From 5b1207f72c67b65a60959945bb4250409bb8460f Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 12 Jul 2016 11:31:45 -0400 Subject: [PATCH] pimd: Stale IGMP groups left behind When a toin IGMPv3 join is received, the code was always auto creating the igmp group associated with the received packet. The RFC clearly states though that if a INCLUDE is received for a group with 0 sources and we have received nothing the igmpv3 packet should be ignored. Ticket: CM-11260 Signed-off-by: Donald Sharp --- pimd/pim_igmp.c | 8 +++----- pimd/pim_igmp.h | 2 ++ pimd/pim_igmpv3.c | 25 ++++++++++++++++++++----- 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index 6df835e252..440d648723 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -46,9 +46,6 @@ static void group_timer_off(struct igmp_group *group); -static struct igmp_group *find_group_by_addr(struct igmp_sock *igmp, - struct in_addr group_addr); - static int igmp_sock_open(struct in_addr ifaddr, int ifindex, uint32_t pim_options) { int fd; @@ -1358,8 +1355,9 @@ void igmp_group_timer_on(struct igmp_group *group, group, interval_msec); } -static struct igmp_group *find_group_by_addr(struct igmp_sock *igmp, - struct in_addr group_addr) +struct igmp_group * +find_group_by_addr (struct igmp_sock *igmp, + struct in_addr group_addr) { struct igmp_group *group; struct listnode *node; diff --git a/pimd/pim_igmp.h b/pimd/pim_igmp.h index ab396159e3..c6685c2837 100644 --- a/pimd/pim_igmp.h +++ b/pimd/pim_igmp.h @@ -162,6 +162,8 @@ struct igmp_group { int64_t last_igmp_v2_report_dsec; }; +struct igmp_group *find_group_by_addr (struct igmp_sock *igmp, + struct in_addr group_addr); struct igmp_group *igmp_add_group_by_addr(struct igmp_sock *igmp, struct in_addr group_addr); diff --git a/pimd/pim_igmpv3.c b/pimd/pim_igmpv3.c index 0a6b6b3795..7300e6c6b4 100644 --- a/pimd/pim_igmpv3.c +++ b/pimd/pim_igmpv3.c @@ -834,11 +834,26 @@ void igmpv3_report_toin(struct igmp_sock *igmp, struct in_addr from, on_trace(__PRETTY_FUNCTION__, ifp, from, group_addr, num_sources, sources); - /* non-existant group is created as INCLUDE {empty} */ - group = igmp_add_group_by_addr(igmp, group_addr); - if (!group) { - return; - } + /* + * If the requested filter mode is INCLUDE *and* the requested source + * list is empty, then the entry corresponding to the requested + * interface and multicast address is deleted if present. If no such + * entry is present, the request is ignored. + */ + if (num_sources) + { + /* non-existant group is created as INCLUDE {empty} */ + group = igmp_add_group_by_addr(igmp, group_addr); + if (!group) { + return; + } + } + else + { + group = find_group_by_addr (igmp, group_addr); + if (!group) + return; + } if (group->group_filtermode_isexcl) { /* EXCLUDE mode */