Merge tag 'mfd-3.9-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6
[pandora-kernel.git] / net / ipv6 / ip6_input.c
index a52d864..5b10414 100644 (file)
@@ -118,6 +118,15 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
            ipv6_addr_loopback(&hdr->daddr))
                goto err;
 
+       /* RFC4291 2.7
+        * Nodes must not originate a packet to a multicast address whose scope
+        * field contains the reserved value 0; if such a packet is received, it
+        * must be silently dropped.
+        */
+       if (ipv6_addr_is_multicast(&hdr->daddr) &&
+           IPV6_ADDR_MC_SCOPE(&hdr->daddr) == 0)
+               goto err;
+
        /*
         * RFC4291 2.7
         * Multicast addresses must not be used as source addresses in IPv6
@@ -212,7 +221,7 @@ resubmit:
                        if (ipv6_addr_is_multicast(&hdr->daddr) &&
                            !ipv6_chk_mcast_addr(skb->dev, &hdr->daddr,
                            &hdr->saddr) &&
-                           !ipv6_is_mld(skb, nexthdr))
+                           !ipv6_is_mld(skb, nexthdr, skb_network_header_len(skb)))
                                goto discard;
                }
                if (!(ipprot->flags & INET6_PROTO_NOPOLICY) &&
@@ -280,10 +289,8 @@ int ip6_mc_input(struct sk_buff *skb)
                struct inet6_skb_parm *opt = IP6CB(skb);
 
                /* Check for MLD */
-               if (unlikely(opt->ra)) {
+               if (unlikely(opt->flags & IP6SKB_ROUTERALERT)) {
                        /* Check if this is a mld message */
-                       u8 *ptr = skb_network_header(skb) + opt->ra;
-                       struct icmp6hdr *icmp6;
                        u8 nexthdr = hdr->nexthdr;
                        __be16 frag_off;
                        int offset;
@@ -291,7 +298,7 @@ int ip6_mc_input(struct sk_buff *skb)
                        /* Check if the value of Router Alert
                         * is for MLD (0x0000).
                         */
-                       if ((ptr[2] | ptr[3]) == 0) {
+                       if (opt->ra == htons(IPV6_OPT_ROUTERALERT_MLD)) {
                                deliver = false;
 
                                if (!ipv6_ext_hdr(nexthdr)) {
@@ -303,24 +310,10 @@ int ip6_mc_input(struct sk_buff *skb)
                                if (offset < 0)
                                        goto out;
 
-                               if (nexthdr != IPPROTO_ICMPV6)
+                               if (!ipv6_is_mld(skb, nexthdr, offset))
                                        goto out;
 
-                               if (!pskb_may_pull(skb, (skb_network_header(skb) +
-                                                  offset + 1 - skb->data)))
-                                       goto out;
-
-                               icmp6 = (struct icmp6hdr *)(skb_network_header(skb) + offset);
-
-                               switch (icmp6->icmp6_type) {
-                               case ICMPV6_MGM_QUERY:
-                               case ICMPV6_MGM_REPORT:
-                               case ICMPV6_MGM_REDUCTION:
-                               case ICMPV6_MLD2_REPORT:
-                                       deliver = true;
-                                       break;
-                               }
-                               goto out;
+                               deliver = true;
                        }
                        /* unknown RA - process it normally */
                }