diff options
-rw-r--r-- | pimd/pim_igmp.c | 4 | ||||
-rw-r--r-- | pimd/pim_igmpv2.c | 31 | ||||
-rw-r--r-- | pimd/pim_igmpv2.h | 2 |
3 files changed, 31 insertions, 6 deletions
diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index 9924e335b..73e42e9d8 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -558,8 +558,8 @@ int pim_igmp_packet(struct igmp_sock *igmp, char *buf, size_t len) igmp_msg, igmp_msg_len); case PIM_IGMP_V2_LEAVE_GROUP: - return igmp_v2_recv_leave(igmp, ip_hdr->ip_src, from_str, - igmp_msg, igmp_msg_len); + return igmp_v2_recv_leave(igmp, ip_hdr, from_str, igmp_msg, + igmp_msg_len); case PIM_IGMP_MTRACE_RESPONSE: return igmp_mtrace_recv_response(igmp, ip_hdr, ip_hdr->ip_src, diff --git a/pimd/pim_igmpv2.c b/pimd/pim_igmpv2.c index d836c66cb..7f3c7a0f8 100644 --- a/pimd/pim_igmpv2.c +++ b/pimd/pim_igmpv2.c @@ -158,12 +158,13 @@ int igmp_v2_recv_report(struct igmp_sock *igmp, struct in_addr from, return 0; } -int igmp_v2_recv_leave(struct igmp_sock *igmp, struct in_addr from, +int igmp_v2_recv_leave(struct igmp_sock *igmp, struct ip *ip_hdr, const char *from_str, char *igmp_msg, int igmp_msg_len) { struct interface *ifp = igmp->interface; struct in_addr group_addr; char group_str[INET_ADDRSTRLEN]; + struct in_addr from = ip_hdr->ip_src; on_trace(__func__, igmp->interface, from); @@ -184,8 +185,6 @@ int igmp_v2_recv_leave(struct igmp_sock *igmp, struct in_addr from, return -1; } - /* Collecting IGMP Rx stats */ - igmp->rx_stats.leave_v2++; memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr)); @@ -195,6 +194,32 @@ int igmp_v2_recv_leave(struct igmp_sock *igmp, struct in_addr from, zlog_debug("Recv IGMPv2 LEAVE from %s on %s for %s", from_str, ifp->name, group_str); } + /* + * As per RFC 2236, section 9: + Message Type Destination Group + ------------ ----------------- + General Query ALL-SYSTEMS (224.0.0.1) + Group-Specific Query The group being queried + Membership Report The group being reported + Leave Message ALL-ROUTERS (224.0.0.2) + + Note: in older (i.e., non-standard and now obsolete) versions of + IGMPv2, hosts send Leave Messages to the group being left. A + router SHOULD accept Leave Messages addressed to the group being + left in the interests of backwards compatibility with such hosts. + In all cases, however, hosts MUST send to the ALL-ROUTERS address + to be compliant with this specification. + */ + 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) + zlog_debug( + "IGMPv2 Leave message is ignored since received on address other than ALL-ROUTERS or Group-address"); + return -1; + } + + /* Collecting IGMP Rx stats */ + igmp->rx_stats.leave_v2++; /* * RFC 3376 diff --git a/pimd/pim_igmpv2.h b/pimd/pim_igmpv2.h index f0a6fdc5f..29591ff16 100644 --- a/pimd/pim_igmpv2.h +++ b/pimd/pim_igmpv2.h @@ -29,7 +29,7 @@ void igmp_v2_send_query(struct igmp_group *group, int fd, const char *ifname, int igmp_v2_recv_report(struct igmp_sock *igmp, struct in_addr from, const char *from_str, char *igmp_msg, int igmp_msg_len); -int igmp_v2_recv_leave(struct igmp_sock *igmp, struct in_addr from, +int igmp_v2_recv_leave(struct igmp_sock *igmp, struct ip *ip_hdr, const char *from_str, char *igmp_msg, int igmp_msg_len); #endif /* PIM_IGMPV2_H */ |