]> git.proxmox.com Git - mirror_frr.git/blobdiff - pimd/pim_igmpv2.c
Merge pull request #13646 from donaldsharp/logically_illogical
[mirror_frr.git] / pimd / pim_igmpv2.c
index 09a82069a2f8695b5d3787a857e1fe42cc93050f..944dffdc338942fe2303526fde385ac3c9e49e9b 100644 (file)
@@ -1,29 +1,18 @@
+// 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"
@@ -32,7 +21,7 @@
 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);
@@ -53,7 +42,8 @@ void igmp_v2_send_query(struct gm_group *group, int fd, const char *ifname,
 
        /* 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;
@@ -65,7 +55,7 @@ void igmp_v2_send_query(struct gm_group *group, int fd, const char *ifname,
        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));
@@ -107,15 +97,18 @@ int igmp_v2_recv_report(struct gm_sock *igmp, struct in_addr from,
 {
        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,
@@ -134,13 +127,30 @@ int igmp_v2_recv_report(struct gm_sock *igmp, struct in_addr from,
 
        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
@@ -173,7 +183,7 @@ int igmp_v2_recv_leave(struct gm_sock *igmp, struct ip *ip_hdr,
                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,
@@ -190,7 +200,7 @@ int igmp_v2_recv_leave(struct gm_sock *igmp, struct ip *ip_hdr,
 
        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,
@@ -214,7 +224,7 @@ int igmp_v2_recv_leave(struct gm_sock *igmp, struct ip *ip_hdr,
        */
        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;