diff options
author | David Stevens <dlstevens@us.ibm.com> | 2005-12-02 20:32:59 -0800 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2005-12-02 20:32:59 -0800 |
commit | 24c6927505ca77ee4ac25fb31dcd56f6506979ed (patch) | |
tree | 17d873b63f0ce24b81e184f2515f2b643143e48e /net | |
parent | bf031fff1fac77775b2cd2c72ad8b017f4c0af13 (diff) | |
download | linux-24c6927505ca77ee4ac25fb31dcd56f6506979ed.tar.gz linux-24c6927505ca77ee4ac25fb31dcd56f6506979ed.tar.bz2 linux-24c6927505ca77ee4ac25fb31dcd56f6506979ed.zip |
[IGMP]: workaround for IGMP v1/v2 bug
From: David Stevens <dlstevens@us.ibm.com>
As explained at:
http://www.cs.ucsb.edu/~krishna/igmp_dos/
With IGMP version 1 and 2 it is possible to inject a unicast
report to a client which will make it ignore multicast
reports sent later by the router.
The fix is to only accept the report if is was sent to a
multicast or unicast address.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/igmp.c | 5 | ||||
-rw-r--r-- | net/ipv6/mcast.c | 5 |
2 files changed, 9 insertions, 1 deletions
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index c04607b49212..4a195c724f01 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -897,7 +897,10 @@ int igmp_rcv(struct sk_buff *skb) /* Is it our report looped back? */ if (((struct rtable*)skb->dst)->fl.iif == 0) break; - igmp_heard_report(in_dev, ih->group); + /* don't rely on MC router hearing unicast reports */ + if (skb->pkt_type == PACKET_MULTICAST || + skb->pkt_type == PACKET_BROADCAST) + igmp_heard_report(in_dev, ih->group); break; case IGMP_PIM: #ifdef CONFIG_IP_PIMSM_V1 diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index f15e04ad026e..fd939da090c4 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -1231,6 +1231,11 @@ int igmp6_event_report(struct sk_buff *skb) if (skb->pkt_type == PACKET_LOOPBACK) return 0; + /* send our report if the MC router may not have heard this report */ + if (skb->pkt_type != PACKET_MULTICAST && + skb->pkt_type != PACKET_BROADCAST) + return 0; + if (!pskb_may_pull(skb, sizeof(struct in6_addr))) return -EINVAL; |