Merge tag 'ktest-v3.9' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux...
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / net / ipv6 / mcast.c
index 28dfa5f3801febb37cfd4ab17e010be4cc936e24..bfa6cc36ef2ab33e6e2894e03bb07c50f56a5804 100644 (file)
@@ -376,8 +376,7 @@ int ip6_mc_source(int add, int omode, struct sock *sk,
                        goto done;      /* err = -EADDRNOTAVAIL */
                rv = !0;
                for (i=0; i<psl->sl_count; i++) {
-                       rv = memcmp(&psl->sl_addr[i], source,
-                               sizeof(struct in6_addr));
+                       rv = !ipv6_addr_equal(&psl->sl_addr[i], source);
                        if (rv == 0)
                                break;
                }
@@ -427,12 +426,10 @@ int ip6_mc_source(int add, int omode, struct sock *sk,
        }
        rv = 1; /* > 0 for insert logic below if sl_count is 0 */
        for (i=0; i<psl->sl_count; i++) {
-               rv = memcmp(&psl->sl_addr[i], source, sizeof(struct in6_addr));
-               if (rv == 0)
-                       break;
+               rv = !ipv6_addr_equal(&psl->sl_addr[i], source);
+               if (rv == 0) /* There is an error in the address. */
+                       goto done;
        }
-       if (rv == 0)            /* address already there is an error */
-               goto done;
        for (j=psl->sl_count-1; j>=i; j--)
                psl->sl_addr[j+1] = psl->sl_addr[j];
        psl->sl_addr[i] = *source;
@@ -664,6 +661,10 @@ static void igmp6_group_added(struct ifmcaddr6 *mc)
        struct net_device *dev = mc->idev->dev;
        char buf[MAX_ADDR_LEN];
 
+       if (IPV6_ADDR_MC_SCOPE(&mc->mca_addr) <
+           IPV6_ADDR_SCOPE_LINKLOCAL)
+               return;
+
        spin_lock_bh(&mc->mca_lock);
        if (!(mc->mca_flags&MAF_LOADED)) {
                mc->mca_flags |= MAF_LOADED;
@@ -690,6 +691,10 @@ static void igmp6_group_dropped(struct ifmcaddr6 *mc)
        struct net_device *dev = mc->idev->dev;
        char buf[MAX_ADDR_LEN];
 
+       if (IPV6_ADDR_MC_SCOPE(&mc->mca_addr) <
+           IPV6_ADDR_SCOPE_LINKLOCAL)
+               return;
+
        spin_lock_bh(&mc->mca_lock);
        if (mc->mca_flags&MAF_LOADED) {
                mc->mca_flags &= ~MAF_LOADED;
@@ -934,33 +939,6 @@ int ipv6_dev_mc_dec(struct net_device *dev, const struct in6_addr *addr)
        return err;
 }
 
-/*
- * identify MLD packets for MLD filter exceptions
- */
-bool ipv6_is_mld(struct sk_buff *skb, int nexthdr)
-{
-       struct icmp6hdr *pic;
-
-       if (nexthdr != IPPROTO_ICMPV6)
-               return false;
-
-       if (!pskb_may_pull(skb, sizeof(struct icmp6hdr)))
-               return false;
-
-       pic = icmp6_hdr(skb);
-
-       switch (pic->icmp6_type) {
-       case ICMPV6_MGM_QUERY:
-       case ICMPV6_MGM_REPORT:
-       case ICMPV6_MGM_REDUCTION:
-       case ICMPV6_MLD2_REPORT:
-               return true;
-       default:
-               break;
-       }
-       return false;
-}
-
 /*
  *     check if the interface/address pair is valid
  */
@@ -1340,6 +1318,31 @@ mld_scount(struct ifmcaddr6 *pmc, int type, int gdeleted, int sdeleted)
        return scount;
 }
 
+static void ip6_mc_hdr(struct sock *sk, struct sk_buff *skb,
+                      struct net_device *dev,
+                      const struct in6_addr *saddr,
+                      const struct in6_addr *daddr,
+                      int proto, int len)
+{
+       struct ipv6hdr *hdr;
+
+       skb->protocol = htons(ETH_P_IPV6);
+       skb->dev = dev;
+
+       skb_reset_network_header(skb);
+       skb_put(skb, sizeof(struct ipv6hdr));
+       hdr = ipv6_hdr(skb);
+
+       ip6_flow_hdr(hdr, 0, 0);
+
+       hdr->payload_len = htons(len);
+       hdr->nexthdr = proto;
+       hdr->hop_limit = inet6_sk(sk)->hop_limit;
+
+       hdr->saddr = *saddr;
+       hdr->daddr = *daddr;
+}
+
 static struct sk_buff *mld_newpack(struct net_device *dev, int size)
 {
        struct net *net = dev_net(dev);
@@ -1375,7 +1378,7 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size)
        } else
                saddr = &addr_buf;
 
-       ip6_nd_hdr(sk, skb, dev, saddr, &mld2_all_mcr, NEXTHDR_HOP, 0);
+       ip6_mc_hdr(sk, skb, dev, saddr, &mld2_all_mcr, NEXTHDR_HOP, 0);
 
        memcpy(skb_put(skb, sizeof(ra)), ra, sizeof(ra));
 
@@ -1418,7 +1421,7 @@ static void mld_sendpack(struct sk_buff *skb)
        icmpv6_flow_init(net->ipv6.igmp_sk, &fl6, ICMPV6_MLD2_REPORT,
                         &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
                         skb->dev->ifindex);
-       dst = icmp6_dst_alloc(skb->dev, NULL, &fl6);
+       dst = icmp6_dst_alloc(skb->dev, &fl6);
 
        err = 0;
        if (IS_ERR(dst)) {
@@ -1767,7 +1770,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
        } else
                saddr = &addr_buf;
 
-       ip6_nd_hdr(sk, skb, dev, saddr, snd_addr, NEXTHDR_HOP, payload_len);
+       ip6_mc_hdr(sk, skb, dev, saddr, snd_addr, NEXTHDR_HOP, payload_len);
 
        memcpy(skb_put(skb, sizeof(ra)), ra, sizeof(ra));
 
@@ -1786,7 +1789,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
        icmpv6_flow_init(sk, &fl6, type,
                         &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
                         skb->dev->ifindex);
-       dst = icmp6_dst_alloc(skb->dev, NULL, &fl6);
+       dst = icmp6_dst_alloc(skb->dev, &fl6);
        if (IS_ERR(dst)) {
                err = PTR_ERR(dst);
                goto err_out;
@@ -2596,10 +2599,10 @@ static int __net_init igmp6_proc_init(struct net *net)
        int err;
 
        err = -ENOMEM;
-       if (!proc_net_fops_create(net, "igmp6", S_IRUGO, &igmp6_mc_seq_fops))
+       if (!proc_create("igmp6", S_IRUGO, net->proc_net, &igmp6_mc_seq_fops))
                goto out;
-       if (!proc_net_fops_create(net, "mcfilter6", S_IRUGO,
-                                 &igmp6_mcf_seq_fops))
+       if (!proc_create("mcfilter6", S_IRUGO, net->proc_net,
+                        &igmp6_mcf_seq_fops))
                goto out_proc_net_igmp6;
 
        err = 0;
@@ -2607,14 +2610,14 @@ out:
        return err;
 
 out_proc_net_igmp6:
-       proc_net_remove(net, "igmp6");
+       remove_proc_entry("igmp6", net->proc_net);
        goto out;
 }
 
 static void __net_exit igmp6_proc_exit(struct net *net)
 {
-       proc_net_remove(net, "mcfilter6");
-       proc_net_remove(net, "igmp6");
+       remove_proc_entry("mcfilter6", net->proc_net);
+       remove_proc_entry("igmp6", net->proc_net);
 }
 #else
 static inline int igmp6_proc_init(struct net *net)