+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* PIM for Quagga
* Copyright (C) 2016 Cumulus Networks, Inc.
* Daniel Walton
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "zebra.h"
#include "pimd.h"
+#include "pim_instance.h"
#include "pim_igmp.h"
#include "pim_igmpv2.h"
#include "pim_igmpv3.h"
+#include "pim_ssm.h"
#include "pim_str.h"
#include "pim_time.h"
#include "pim_util.h"
static void on_trace(const char *label, struct interface *ifp,
struct in_addr from)
{
- if (PIM_DEBUG_IGMP_TRACE) {
+ if (PIM_DEBUG_GM_TRACE) {
char from_str[INET_ADDRSTRLEN];
pim_inet4_dump("<from?>", from, from_str, sizeof(from_str));
zlog_debug("%s: from %s on %s", label, from_str, ifp->name);
/* max_resp_code must be non-zero else this will look like an IGMP v1
* query */
- max_resp_code = igmp_msg_encode16to8(query_max_response_time_dsec);
+ /* RFC 2236: 2.2. , v2's is equal to it */
+ max_resp_code = query_max_response_time_dsec;
assert(max_resp_code > 0);
query_buf[0] = PIM_IGMP_MEMBERSHIP_QUERY;
checksum = in_cksum(query_buf, msg_size);
*(uint16_t *)(query_buf + IGMP_CHECKSUM_OFFSET) = checksum;
- if (PIM_DEBUG_IGMP_PACKETS) {
+ if (PIM_DEBUG_GM_PACKETS) {
char dst_str[INET_ADDRSTRLEN];
char group_str[INET_ADDRSTRLEN];
pim_inet4_dump("<dst?>", dst_addr, dst_str, sizeof(dst_str));
{
struct interface *ifp = igmp->interface;
struct in_addr group_addr;
+ struct pim_interface *pim_ifp;
char group_str[INET_ADDRSTRLEN];
on_trace(__func__, igmp->interface, from);
+ pim_ifp = ifp->info;
+
if (igmp->mtrace_only)
return 0;
if (igmp_msg_len != IGMP_V12_MSG_SIZE) {
- if (PIM_DEBUG_IGMP_PACKETS)
+ if (PIM_DEBUG_GM_PACKETS)
zlog_debug(
"Recv IGMPv2 REPORT from %s on %s: size=%d other than correct=%d",
from_str, ifp->name, igmp_msg_len,
memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr));
- if (PIM_DEBUG_IGMP_PACKETS) {
+ if (PIM_DEBUG_GM_PACKETS) {
pim_inet4_dump("<dst?>", group_addr, group_str,
sizeof(group_str));
zlog_debug("Recv IGMPv2 REPORT from %s on %s for %s", from_str,
ifp->name, group_str);
}
+ /*
+ * RFC 4604
+ * section 2.2.1
+ * EXCLUDE mode does not apply to SSM addresses, and an SSM-aware router
+ * will ignore MODE_IS_EXCLUDE and CHANGE_TO_EXCLUDE_MODE requests in
+ * the SSM range.
+ */
+ if (pim_is_grp_ssm(pim_ifp->pim, group_addr)) {
+ if (PIM_DEBUG_GM_PACKETS) {
+ zlog_debug(
+ "Ignoring IGMPv2 group record %pI4 from %s on %s exclude mode in SSM range",
+ &group_addr.s_addr, from_str, ifp->name);
+ }
+ return -1;
+ }
+
+
/*
* RFC 3376
* 7.3.2. In the Presence of Older Version Group Members
return 0;
if (igmp_msg_len != IGMP_V12_MSG_SIZE) {
- if (PIM_DEBUG_IGMP_PACKETS)
+ if (PIM_DEBUG_GM_PACKETS)
zlog_debug(
"Recv IGMPv2 LEAVE from %s on %s: size=%d other than correct=%d",
from_str, ifp->name, igmp_msg_len,
memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr));
- if (PIM_DEBUG_IGMP_PACKETS) {
+ if (PIM_DEBUG_GM_PACKETS) {
pim_inet4_dump("<dst?>", group_addr, group_str,
sizeof(group_str));
zlog_debug("Recv IGMPv2 LEAVE from %s on %s for %s", from_str,
*/
if ((ntohl(ip_hdr->ip_dst.s_addr) != INADDR_ALLRTRS_GROUP)
&& (ip_hdr->ip_dst.s_addr != group_addr.s_addr)) {
- if (PIM_DEBUG_IGMP_EVENTS)
+ if (PIM_DEBUG_GM_EVENTS)
zlog_debug(
"IGMPv2 Leave message is ignored since received on address other than ALL-ROUTERS or Group-address");
return -1;