aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/ip6_input.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/ip6_input.c')
-rw-r--r--net/ipv6/ip6_input.c35
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 }