Merge branch 'master' into for-4.4-fixes
[firefly-linux-kernel-4.4.55.git] / net / ipv4 / igmp.c
index 64aaf3522a59f30672689f7309987606773ccb0c..05e4cba14162f3583ec588657af7e8b68546b111 100644 (file)
@@ -2126,7 +2126,7 @@ int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr)
        ASSERT_RTNL();
 
        in_dev = ip_mc_find_dev(net, imr);
-       if (!in_dev) {
+       if (!imr->imr_ifindex && !imr->imr_address.s_addr && !in_dev) {
                ret = -ENODEV;
                goto out;
        }
@@ -2147,7 +2147,8 @@ int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr)
 
                *imlp = iml->next_rcu;
 
-               ip_mc_dec_group(in_dev, group);
+               if (in_dev)
+                       ip_mc_dec_group(in_dev, group);
 
                /* decrease mem now to avoid the memleak warning */
                atomic_sub(sizeof(*iml), &sk->sk_omem_alloc);
@@ -2392,11 +2393,11 @@ int ip_mc_msfget(struct sock *sk, struct ip_msfilter *msf,
        struct ip_sf_socklist *psl;
        struct net *net = sock_net(sk);
 
+       ASSERT_RTNL();
+
        if (!ipv4_is_multicast(addr))
                return -EINVAL;
 
-       rtnl_lock();
-
        imr.imr_multiaddr.s_addr = msf->imsf_multiaddr;
        imr.imr_address.s_addr = msf->imsf_interface;
        imr.imr_ifindex = 0;
@@ -2417,7 +2418,6 @@ int ip_mc_msfget(struct sock *sk, struct ip_msfilter *msf,
                goto done;
        msf->imsf_fmode = pmc->sfmode;
        psl = rtnl_dereference(pmc->sflist);
-       rtnl_unlock();
        if (!psl) {
                len = 0;
                count = 0;
@@ -2436,7 +2436,6 @@ int ip_mc_msfget(struct sock *sk, struct ip_msfilter *msf,
                return -EFAULT;
        return 0;
 done:
-       rtnl_unlock();
        return err;
 }
 
@@ -2450,6 +2449,8 @@ int ip_mc_gsfget(struct sock *sk, struct group_filter *gsf,
        struct inet_sock *inet = inet_sk(sk);
        struct ip_sf_socklist *psl;
 
+       ASSERT_RTNL();
+
        psin = (struct sockaddr_in *)&gsf->gf_group;
        if (psin->sin_family != AF_INET)
                return -EINVAL;
@@ -2457,8 +2458,6 @@ int ip_mc_gsfget(struct sock *sk, struct group_filter *gsf,
        if (!ipv4_is_multicast(addr))
                return -EINVAL;
 
-       rtnl_lock();
-
        err = -EADDRNOTAVAIL;
 
        for_each_pmc_rtnl(inet, pmc) {
@@ -2470,7 +2469,6 @@ int ip_mc_gsfget(struct sock *sk, struct group_filter *gsf,
                goto done;
        gsf->gf_fmode = pmc->sfmode;
        psl = rtnl_dereference(pmc->sflist);
-       rtnl_unlock();
        count = psl ? psl->sl_count : 0;
        copycount = count < gsf->gf_numsrc ? count : gsf->gf_numsrc;
        gsf->gf_numsrc = count;
@@ -2490,7 +2488,6 @@ int ip_mc_gsfget(struct sock *sk, struct group_filter *gsf,
        }
        return 0;
 done:
-       rtnl_unlock();
        return err;
 }