From d1b61cb92dfdb4815d5f729a8f89ceb6eaee7ba6 Mon Sep 17 00:00:00 2001 From: Mobashshera Rasool Date: Thu, 17 Dec 2020 11:40:13 +0000 Subject: [PATCH] pimd: IGMP conformance 5.10 test case is failing Test case 5.10 sends leave message to unicast address, the leave packet is accepted and a query message is sent in response to this. No validation for address is present in the function Add check for addresses as per RFC. Leave messages are allowed only sent to either ALL-ROUTERS (224.0.0.2) or group address. Signed-off-by: Mobashshera Rasool --- pimd/pim_igmp.c | 4 ++-- pimd/pim_igmpv2.c | 31 ++++++++++++++++++++++++++++--- 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 9924e335b0..73e42e9d83 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 d836c66cbb..7f3c7a0f8c 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 f0a6fdc5fb..29591ff16c 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 */