netdev
[Top] [All Lists]

multicast loop with include filters fix [PATCH]

To: davem@xxxxxxxxxx, netdev@xxxxxxxxxxx
Subject: multicast loop with include filters fix [PATCH]
From: David Stevens <dlstevens@xxxxxxxxxx>
Date: Thu, 22 Jan 2004 19:02:07 -0700
Cc: stevenh@xxxxxxxxxx
Importance: Normal
Sender: netdev-bounce@xxxxxxxxxxx
Sensitivity:

When sending a multicast and using looping back a copy to the
local machine, the interface filter checks can be done before the
source address is specified. For an INCLUDE filter, this won't match
the allowed sources and the packets won't be delivered locally,
even when the ultimate source address chosen is in the allowed list.

The patch below fixes the filter checks for both IGMPv3 and MLDv2
to only apply when a source address is available.

Thanks to Steven Hessing for reporting the problem and providing
a test case for reproducing it.

+-DLS

[not-whitespace-mangled patch attached]

diff -ruN linux-2.6.2-rc1/net/ipv4/igmp.c linux-2.6.2-rc1F1/net/ipv4/igmp.c
--- linux-2.6.2-rc1/net/ipv4/igmp.c 2004-01-21 14:03:35.000000000 -0800
+++ linux-2.6.2-rc1F1/net/ipv4/igmp.c 2004-01-22 17:11:38.000000000 -0800
@@ -2084,16 +2084,19 @@
if (im && proto == IPPROTO_IGMP) {
rv = 1;
} else if (im) {
- for (psf=im->sources; psf; psf=psf->sf_next) {
- if (psf->sf_inaddr == src_addr)
- break;
- }
- if (psf)
- rv = psf->sf_count[MCAST_INCLUDE] ||
- psf->sf_count[MCAST_EXCLUDE] !=
- im->sfcount[MCAST_EXCLUDE];
- else
- rv = im->sfcount[MCAST_EXCLUDE] != 0;
+ if (src_addr) {
+ for (psf=im->sources; psf; psf=psf->sf_next) {
+ if (psf->sf_inaddr == src_addr)
+ break;
+ }
+ if (psf)
+ rv = psf->sf_count[MCAST_INCLUDE] ||
+ psf->sf_count[MCAST_EXCLUDE] !=
+ im->sfcount[MCAST_EXCLUDE];
+ else
+ rv = im->sfcount[MCAST_EXCLUDE] != 0;
+ } else
+ rv = 1; /* unspecified source; tentatively allow */
}
read_unlock(&in_dev->lock);
return rv;
diff -ruN linux-2.6.2-rc1/net/ipv6/mcast.c linux-2.6.2-rc1F1/net/ipv6/mcast.c
--- linux-2.6.2-rc1/net/ipv6/mcast.c 2004-01-21 14:03:35.000000000 -0800
+++ linux-2.6.2-rc1F1/net/ipv6/mcast.c 2004-01-22 17:29:29.000000000 -0800
@@ -918,20 +918,24 @@
break;
}
if (mc) {
- struct ip6_sf_list *psf;
+ if (ipv6_addr_any(src_addr)) {
+ struct ip6_sf_list *psf;

- spin_lock_bh(&mc->mca_lock);
- for (psf=mc->mca_sources; psf; psf=psf->sf_next) {
- if (ipv6_addr_cmp(&psf->sf_addr, src_addr) == 0)
- break;
- }
- if (psf)
- rv = psf->sf_count[MCAST_INCLUDE] ||
- psf->sf_count[MCAST_EXCLUDE] !=
- mc->mca_sfcount[MCAST_EXCLUDE];
- else
- rv = mc->mca_sfcount[MCAST_EXCLUDE] != 0;
- spin_unlock_bh(&mc->mca_lock);
+ spin_lock_bh(&mc->mca_lock);
+ for (psf=mc->mca_sources;psf;psf=psf->sf_next) {
+ if (ipv6_addr_cmp(&psf->sf_addr,
+ src_addr) == 0)
+ break;
+ }
+ if (psf)
+ rv = psf->sf_count[MCAST_INCLUDE] ||
+ psf->sf_count[MCAST_EXCLUDE] !=
+ mc->mca_sfcount[MCAST_EXCLUDE];
+ else
+ rv = mc->mca_sfcount[MCAST_EXCLUDE] !=0;
+ spin_unlock_bh(&mc->mca_lock);
+ } else
+ rv = 1; /* don't filter unspecified source */
}
read_unlock_bh(&idev->lock);
in6_dev_put(idev);

(See attached file: igmpf1.patch)

Attachment: igmpf1.patch
Description: Binary data

<Prev in Thread] Current Thread [Next in Thread>