diff options
Diffstat (limited to 'net/ipv6/ip6_input.c')
-rw-r--r-- | net/ipv6/ip6_input.c | 35 |
1 files changed, 14 insertions, 21 deletions
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index a52d864d562b..5b10414e619e 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c | |||
@@ -118,6 +118,15 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt | |||
118 | ipv6_addr_loopback(&hdr->daddr)) | 118 | ipv6_addr_loopback(&hdr->daddr)) |
119 | goto err; | 119 | goto err; |
120 | 120 | ||
121 | /* RFC4291 2.7 | ||
122 | * Nodes must not originate a packet to a multicast address whose scope | ||
123 | * field contains the reserved value 0; if such a packet is received, it | ||
124 | * must be silently dropped. | ||
125 | */ | ||
126 | if (ipv6_addr_is_multicast(&hdr->daddr) && | ||
127 | IPV6_ADDR_MC_SCOPE(&hdr->daddr) == 0) | ||
128 | goto err; | ||
129 | |||
121 | /* | 130 | /* |
122 | * RFC4291 2.7 | 131 | * RFC4291 2.7 |
123 | * Multicast addresses must not be used as source addresses in IPv6 | 132 | * Multicast addresses must not be used as source addresses in IPv6 |
@@ -212,7 +221,7 @@ resubmit: | |||
212 | if (ipv6_addr_is_multicast(&hdr->daddr) && | 221 | if (ipv6_addr_is_multicast(&hdr->daddr) && |
213 | !ipv6_chk_mcast_addr(skb->dev, &hdr->daddr, | 222 | !ipv6_chk_mcast_addr(skb->dev, &hdr->daddr, |
214 | &hdr->saddr) && | 223 | &hdr->saddr) && |
215 | !ipv6_is_mld(skb, nexthdr)) | 224 | !ipv6_is_mld(skb, nexthdr, skb_network_header_len(skb))) |
216 | goto discard; | 225 | goto discard; |
217 | } | 226 | } |
218 | if (!(ipprot->flags & INET6_PROTO_NOPOLICY) && | 227 | if (!(ipprot->flags & INET6_PROTO_NOPOLICY) && |
@@ -280,10 +289,8 @@ int ip6_mc_input(struct sk_buff *skb) | |||
280 | struct inet6_skb_parm *opt = IP6CB(skb); | 289 | struct inet6_skb_parm *opt = IP6CB(skb); |
281 | 290 | ||
282 | /* Check for MLD */ | 291 | /* Check for MLD */ |
283 | if (unlikely(opt->ra)) { | 292 | if (unlikely(opt->flags & IP6SKB_ROUTERALERT)) { |
284 | /* Check if this is a mld message */ | 293 | /* Check if this is a mld message */ |
285 | u8 *ptr = skb_network_header(skb) + opt->ra; | ||
286 | struct icmp6hdr *icmp6; | ||
287 | u8 nexthdr = hdr->nexthdr; | 294 | u8 nexthdr = hdr->nexthdr; |
288 | __be16 frag_off; | 295 | __be16 frag_off; |
289 | int offset; | 296 | int offset; |
@@ -291,7 +298,7 @@ int ip6_mc_input(struct sk_buff *skb) | |||
291 | /* Check if the value of Router Alert | 298 | /* Check if the value of Router Alert |
292 | * is for MLD (0x0000). | 299 | * is for MLD (0x0000). |
293 | */ | 300 | */ |
294 | if ((ptr[2] | ptr[3]) == 0) { | 301 | if (opt->ra == htons(IPV6_OPT_ROUTERALERT_MLD)) { |
295 | deliver = false; | 302 | deliver = false; |
296 | 303 | ||
297 | if (!ipv6_ext_hdr(nexthdr)) { | 304 | if (!ipv6_ext_hdr(nexthdr)) { |
@@ -303,24 +310,10 @@ int ip6_mc_input(struct sk_buff *skb) | |||
303 | if (offset < 0) | 310 | if (offset < 0) |
304 | goto out; | 311 | goto out; |
305 | 312 | ||
306 | if (nexthdr != IPPROTO_ICMPV6) | 313 | if (!ipv6_is_mld(skb, nexthdr, offset)) |
307 | goto out; | 314 | goto out; |
308 | 315 | ||
309 | if (!pskb_may_pull(skb, (skb_network_header(skb) + | 316 | deliver = true; |
310 | offset + 1 - skb->data))) | ||
311 | goto out; | ||
312 | |||
313 | icmp6 = (struct icmp6hdr *)(skb_network_header(skb) + offset); | ||
314 | |||
315 | switch (icmp6->icmp6_type) { | ||
316 | case ICMPV6_MGM_QUERY: | ||
317 | case ICMPV6_MGM_REPORT: | ||
318 | case ICMPV6_MGM_REDUCTION: | ||
319 | case ICMPV6_MLD2_REPORT: | ||
320 | deliver = true; | ||
321 | break; | ||
322 | } | ||
323 | goto out; | ||
324 | } | 317 | } |
325 | /* unknown RA - process it normally */ | 318 | /* unknown RA - process it normally */ |
326 | } | 319 | } |