diff options
author | Hangbin Liu <liuhangbin@gmail.com> | 2014-06-27 09:57:53 +0800 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-06-27 00:21:50 -0700 |
commit | e940f5d6ba6a01f8dbb870854d5205d322452730 (patch) | |
tree | 810d25786e16066afb98f59a35e71a837add9f13 /net/ipv6/mcast.c | |
parent | 3e215c8d1b6b772d107f1811b5ee8eae7a046fb4 (diff) | |
download | linux-stable-e940f5d6ba6a01f8dbb870854d5205d322452730.tar.gz linux-stable-e940f5d6ba6a01f8dbb870854d5205d322452730.tar.bz2 linux-stable-e940f5d6ba6a01f8dbb870854d5205d322452730.zip |
ipv6: Fix MLD Query message check
Based on RFC3810 6.2, we also need to check the hop limit and router alert
option besides source address.
Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
Acked-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Acked-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/mcast.c')
-rw-r--r-- | net/ipv6/mcast.c | 13 |
1 files changed, 11 insertions, 2 deletions
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 08b367c6b9cf..617f0958e164 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -1301,8 +1301,17 @@ int igmp6_event_query(struct sk_buff *skb) len = ntohs(ipv6_hdr(skb)->payload_len) + sizeof(struct ipv6hdr); len -= skb_network_header_len(skb); - /* Drop queries with not link local source */ - if (!(ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL)) + /* RFC3810 6.2 + * Upon reception of an MLD message that contains a Query, the node + * checks if the source address of the message is a valid link-local + * address, if the Hop Limit is set to 1, and if the Router Alert + * option is present in the Hop-By-Hop Options header of the IPv6 + * packet. If any of these checks fails, the packet is dropped. + */ + if (!(ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL) || + ipv6_hdr(skb)->hop_limit != 1 || + !(IP6CB(skb)->flags & IP6SKB_ROUTERALERT) || + IP6CB(skb)->ra != htons(IPV6_OPT_ROUTERALERT_MLD)) return -EINVAL; idev = __in6_dev_get(skb->dev); |