* multicast loop with include filters fix [PATCH]
@ 2004-01-23 2:02 David Stevens
2004-01-23 1:57 ` David S. Miller
0 siblings, 1 reply; 5+ messages in thread
From: David Stevens @ 2004-01-23 2:02 UTC (permalink / raw)
To: davem, netdev; +Cc: stevenh
[-- Attachment #1.1: Type: text/plain, Size: 3995 bytes --]
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 #1.2: Type: text/html, Size: 3469 bytes --]
[-- Attachment #2: igmpf1.patch --]
[-- Type: application/octet-stream, Size: 2287 bytes --]
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);
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: multicast loop with include filters fix [PATCH]
2004-01-23 2:02 multicast loop with include filters fix [PATCH] David Stevens
@ 2004-01-23 1:57 ` David S. Miller
0 siblings, 0 replies; 5+ messages in thread
From: David S. Miller @ 2004-01-23 1:57 UTC (permalink / raw)
To: dlstevens; +Cc: netdev, stevenh
From: David Stevens <dlstevens@us.ibm.com>
Date: Thu, 22 Jan 2004 19:02:07 -0700
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.
Looks good, I guess a 2.4.x variant is forthcoming?
Thanks.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: multicast loop with include filters fix [PATCH]
@ 2004-01-23 20:27 David Stevens
0 siblings, 0 replies; 5+ messages in thread
From: David Stevens @ 2004-01-23 20:27 UTC (permalink / raw)
To: davem; +Cc: netdev, stevenh
[-- Attachment #1.1: Type: text/plain, Size: 673 bytes --]
Dave,
I had a stupid typo in the v6 side of this patch, which
reverses the sense of the check; here's a patch to fix the patch.
Sorry about that.
+-DLS
--- linux-2.6.2-rc1F1/net/ipv6/mcast.c.orig 2004-01-23 12:10:55.615139688 -0800
+++ linux-2.6.2-rc1F1/net/ipv6/mcast.c 2004-01-23 12:11:15.477120208 -0800
@@ -918,7 +918,7 @@
break;
}
if (mc) {
- if (ipv6_addr_any(src_addr)) {
+ if (!ipv6_addr_any(src_addr)) {
struct ip6_sf_list *psf;
spin_lock_bh(&mc->mca_lock);
(See attached file: mldfix.patch)
[-- Attachment #1.2: Type: text/html, Size: 661 bytes --]
[-- Attachment #2: mldfix.patch --]
[-- Type: application/octet-stream, Size: 342 bytes --]
--- linux-2.6.2-rc1F1/net/ipv6/mcast.c.orig 2004-01-23 12:10:55.615139688 -0800
+++ linux-2.6.2-rc1F1/net/ipv6/mcast.c 2004-01-23 12:11:15.477120208 -0800
@@ -918,7 +918,7 @@
break;
}
if (mc) {
- if (ipv6_addr_any(src_addr)) {
+ if (!ipv6_addr_any(src_addr)) {
struct ip6_sf_list *psf;
spin_lock_bh(&mc->mca_lock);
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: multicast loop with include filters fix [PATCH]
@ 2004-01-23 22:39 David Stevens
2004-01-24 18:00 ` David S. Miller
0 siblings, 1 reply; 5+ messages in thread
From: David Stevens @ 2004-01-23 22:39 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, stevenh
[-- Attachment #1.1: Type: text/plain, Size: 3426 bytes --]
Dave,
Here's the 2.4.x version of the patch.
+-DLS
diff -ruN linux-2.4.25-pre7/net/ipv4/igmp.c linux-2.4.25-pre7F1/net/ipv4/igmp.c
--- linux-2.4.25-pre7/net/ipv4/igmp.c 2004-01-23 13:54:35.000000000 -0800
+++ linux-2.4.25-pre7F1/net/ipv4/igmp.c 2004-01-23 13:58:43.000000000 -0800
@@ -2071,16 +2071,19 @@
* Differs from 2.5.x here. +-DLS 4/23/03
*/
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;
}
read_unlock(&in_dev->lock);
return rv;
diff -ruN linux-2.4.25-pre7/net/ipv6/mcast.c linux-2.4.25-pre7F1/net/ipv6/mcast.c
--- linux-2.4.25-pre7/net/ipv6/mcast.c 2004-01-23 13:54:35.000000000 -0800
+++ linux-2.4.25-pre7F1/net/ipv6/mcast.c 2004-01-23 13:56:19.000000000 -0800
@@ -914,20 +914,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: 2.4.25-pre7IGMP.patch)
[-- Attachment #1.2: Type: text/html, Size: 2853 bytes --]
[-- Attachment #2: 2.4.25-pre7IGMP.patch --]
[-- Type: application/octet-stream, Size: 2255 bytes --]
diff -ruN linux-2.4.25-pre7/net/ipv4/igmp.c linux-2.4.25-pre7F1/net/ipv4/igmp.c
--- linux-2.4.25-pre7/net/ipv4/igmp.c 2004-01-23 13:54:35.000000000 -0800
+++ linux-2.4.25-pre7F1/net/ipv4/igmp.c 2004-01-23 13:58:43.000000000 -0800
@@ -2071,16 +2071,19 @@
* Differs from 2.5.x here. +-DLS 4/23/03
*/
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;
}
read_unlock(&in_dev->lock);
return rv;
diff -ruN linux-2.4.25-pre7/net/ipv6/mcast.c linux-2.4.25-pre7F1/net/ipv6/mcast.c
--- linux-2.4.25-pre7/net/ipv6/mcast.c 2004-01-23 13:54:35.000000000 -0800
+++ linux-2.4.25-pre7F1/net/ipv6/mcast.c 2004-01-23 13:56:19.000000000 -0800
@@ -914,20 +914,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);
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2004-01-24 18:00 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-01-23 2:02 multicast loop with include filters fix [PATCH] David Stevens
2004-01-23 1:57 ` David S. Miller
-- strict thread matches above, loose matches on Subject: below --
2004-01-23 20:27 David Stevens
2004-01-23 22:39 David Stevens
2004-01-24 18:00 ` David S. Miller
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).