aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/igmp.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/igmp.c')
-rw-r--r--net/ipv4/igmp.c72
1 files changed, 38 insertions, 34 deletions
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index 666cf364df86..a3a697f5ffba 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -97,6 +97,7 @@
97#include <net/route.h> 97#include <net/route.h>
98#include <net/sock.h> 98#include <net/sock.h>
99#include <net/checksum.h> 99#include <net/checksum.h>
100#include <net/inet_common.h>
100#include <linux/netfilter_ipv4.h> 101#include <linux/netfilter_ipv4.h>
101#ifdef CONFIG_IP_MROUTE 102#ifdef CONFIG_IP_MROUTE
102#include <linux/mroute.h> 103#include <linux/mroute.h>
@@ -369,7 +370,7 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, unsigned int mtu)
369 pip->saddr = fl4.saddr; 370 pip->saddr = fl4.saddr;
370 pip->protocol = IPPROTO_IGMP; 371 pip->protocol = IPPROTO_IGMP;
371 pip->tot_len = 0; /* filled in later */ 372 pip->tot_len = 0; /* filled in later */
372 ip_select_ident(skb, NULL); 373 ip_select_ident(net, skb, NULL);
373 ((u8 *)&pip[1])[0] = IPOPT_RA; 374 ((u8 *)&pip[1])[0] = IPOPT_RA;
374 ((u8 *)&pip[1])[1] = 4; 375 ((u8 *)&pip[1])[1] = 4;
375 ((u8 *)&pip[1])[2] = 0; 376 ((u8 *)&pip[1])[2] = 0;
@@ -691,7 +692,7 @@ static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc,
691 hlen = LL_RESERVED_SPACE(dev); 692 hlen = LL_RESERVED_SPACE(dev);
692 tlen = dev->needed_tailroom; 693 tlen = dev->needed_tailroom;
693 skb = alloc_skb(IGMP_SIZE + hlen + tlen, GFP_ATOMIC); 694 skb = alloc_skb(IGMP_SIZE + hlen + tlen, GFP_ATOMIC);
694 if (skb == NULL) { 695 if (!skb) {
695 ip_rt_put(rt); 696 ip_rt_put(rt);
696 return -1; 697 return -1;
697 } 698 }
@@ -713,7 +714,7 @@ static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc,
713 iph->daddr = dst; 714 iph->daddr = dst;
714 iph->saddr = fl4.saddr; 715 iph->saddr = fl4.saddr;
715 iph->protocol = IPPROTO_IGMP; 716 iph->protocol = IPPROTO_IGMP;
716 ip_select_ident(skb, NULL); 717 ip_select_ident(net, skb, NULL);
717 ((u8 *)&iph[1])[0] = IPOPT_RA; 718 ((u8 *)&iph[1])[0] = IPOPT_RA;
718 ((u8 *)&iph[1])[1] = 4; 719 ((u8 *)&iph[1])[1] = 4;
719 ((u8 *)&iph[1])[2] = 0; 720 ((u8 *)&iph[1])[2] = 0;
@@ -980,7 +981,7 @@ int igmp_rcv(struct sk_buff *skb)
980 int len = skb->len; 981 int len = skb->len;
981 bool dropped = true; 982 bool dropped = true;
982 983
983 if (in_dev == NULL) 984 if (!in_dev)
984 goto drop; 985 goto drop;
985 986
986 if (!pskb_may_pull(skb, sizeof(struct igmphdr))) 987 if (!pskb_may_pull(skb, sizeof(struct igmphdr)))
@@ -1849,30 +1850,28 @@ static void ip_mc_clear_src(struct ip_mc_list *pmc)
1849 pmc->sfcount[MCAST_EXCLUDE] = 1; 1850 pmc->sfcount[MCAST_EXCLUDE] = 1;
1850} 1851}
1851 1852
1852 1853/* Join a multicast group
1853/*
1854 * Join a multicast group
1855 */ 1854 */
1856int ip_mc_join_group(struct sock *sk , struct ip_mreqn *imr) 1855
1856int ip_mc_join_group(struct sock *sk, struct ip_mreqn *imr)
1857{ 1857{
1858 int err;
1859 __be32 addr = imr->imr_multiaddr.s_addr; 1858 __be32 addr = imr->imr_multiaddr.s_addr;
1860 struct ip_mc_socklist *iml = NULL, *i; 1859 struct ip_mc_socklist *iml, *i;
1861 struct in_device *in_dev; 1860 struct in_device *in_dev;
1862 struct inet_sock *inet = inet_sk(sk); 1861 struct inet_sock *inet = inet_sk(sk);
1863 struct net *net = sock_net(sk); 1862 struct net *net = sock_net(sk);
1864 int ifindex; 1863 int ifindex;
1865 int count = 0; 1864 int count = 0;
1865 int err;
1866
1867 ASSERT_RTNL();
1866 1868
1867 if (!ipv4_is_multicast(addr)) 1869 if (!ipv4_is_multicast(addr))
1868 return -EINVAL; 1870 return -EINVAL;
1869 1871
1870 rtnl_lock();
1871
1872 in_dev = ip_mc_find_dev(net, imr); 1872 in_dev = ip_mc_find_dev(net, imr);
1873 1873
1874 if (!in_dev) { 1874 if (!in_dev) {
1875 iml = NULL;
1876 err = -ENODEV; 1875 err = -ENODEV;
1877 goto done; 1876 goto done;
1878 } 1877 }
@@ -1889,7 +1888,7 @@ int ip_mc_join_group(struct sock *sk , struct ip_mreqn *imr)
1889 if (count >= sysctl_igmp_max_memberships) 1888 if (count >= sysctl_igmp_max_memberships)
1890 goto done; 1889 goto done;
1891 iml = sock_kmalloc(sk, sizeof(*iml), GFP_KERNEL); 1890 iml = sock_kmalloc(sk, sizeof(*iml), GFP_KERNEL);
1892 if (iml == NULL) 1891 if (!iml)
1893 goto done; 1892 goto done;
1894 1893
1895 memcpy(&iml->multi, imr, sizeof(*imr)); 1894 memcpy(&iml->multi, imr, sizeof(*imr));
@@ -1900,7 +1899,6 @@ int ip_mc_join_group(struct sock *sk , struct ip_mreqn *imr)
1900 ip_mc_inc_group(in_dev, addr); 1899 ip_mc_inc_group(in_dev, addr);
1901 err = 0; 1900 err = 0;
1902done: 1901done:
1903 rtnl_unlock();
1904 return err; 1902 return err;
1905} 1903}
1906EXPORT_SYMBOL(ip_mc_join_group); 1904EXPORT_SYMBOL(ip_mc_join_group);
@@ -1911,7 +1909,7 @@ static int ip_mc_leave_src(struct sock *sk, struct ip_mc_socklist *iml,
1911 struct ip_sf_socklist *psf = rtnl_dereference(iml->sflist); 1909 struct ip_sf_socklist *psf = rtnl_dereference(iml->sflist);
1912 int err; 1910 int err;
1913 1911
1914 if (psf == NULL) { 1912 if (!psf) {
1915 /* any-source empty exclude case */ 1913 /* any-source empty exclude case */
1916 return ip_mc_del_src(in_dev, &iml->multi.imr_multiaddr.s_addr, 1914 return ip_mc_del_src(in_dev, &iml->multi.imr_multiaddr.s_addr,
1917 iml->sfmode, 0, NULL, 0); 1915 iml->sfmode, 0, NULL, 0);
@@ -1925,10 +1923,6 @@ static int ip_mc_leave_src(struct sock *sk, struct ip_mc_socklist *iml,
1925 return err; 1923 return err;
1926} 1924}
1927 1925
1928/*
1929 * Ask a socket to leave a group.
1930 */
1931
1932int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr) 1926int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr)
1933{ 1927{
1934 struct inet_sock *inet = inet_sk(sk); 1928 struct inet_sock *inet = inet_sk(sk);
@@ -1940,7 +1934,8 @@ int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr)
1940 u32 ifindex; 1934 u32 ifindex;
1941 int ret = -EADDRNOTAVAIL; 1935 int ret = -EADDRNOTAVAIL;
1942 1936
1943 rtnl_lock(); 1937 ASSERT_RTNL();
1938
1944 in_dev = ip_mc_find_dev(net, imr); 1939 in_dev = ip_mc_find_dev(net, imr);
1945 if (!in_dev) { 1940 if (!in_dev) {
1946 ret = -ENODEV; 1941 ret = -ENODEV;
@@ -1964,14 +1959,13 @@ int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr)
1964 *imlp = iml->next_rcu; 1959 *imlp = iml->next_rcu;
1965 1960
1966 ip_mc_dec_group(in_dev, group); 1961 ip_mc_dec_group(in_dev, group);
1967 rtnl_unlock(); 1962
1968 /* decrease mem now to avoid the memleak warning */ 1963 /* decrease mem now to avoid the memleak warning */
1969 atomic_sub(sizeof(*iml), &sk->sk_omem_alloc); 1964 atomic_sub(sizeof(*iml), &sk->sk_omem_alloc);
1970 kfree_rcu(iml, rcu); 1965 kfree_rcu(iml, rcu);
1971 return 0; 1966 return 0;
1972 } 1967 }
1973out: 1968out:
1974 rtnl_unlock();
1975 return ret; 1969 return ret;
1976} 1970}
1977EXPORT_SYMBOL(ip_mc_leave_group); 1971EXPORT_SYMBOL(ip_mc_leave_group);
@@ -1993,7 +1987,7 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct
1993 if (!ipv4_is_multicast(addr)) 1987 if (!ipv4_is_multicast(addr))
1994 return -EINVAL; 1988 return -EINVAL;
1995 1989
1996 rtnl_lock(); 1990 ASSERT_RTNL();
1997 1991
1998 imr.imr_multiaddr.s_addr = mreqs->imr_multiaddr; 1992 imr.imr_multiaddr.s_addr = mreqs->imr_multiaddr;
1999 imr.imr_address.s_addr = mreqs->imr_interface; 1993 imr.imr_address.s_addr = mreqs->imr_interface;
@@ -2107,9 +2101,8 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct
2107 ip_mc_add_src(in_dev, &mreqs->imr_multiaddr, omode, 1, 2101 ip_mc_add_src(in_dev, &mreqs->imr_multiaddr, omode, 1,
2108 &mreqs->imr_sourceaddr, 1); 2102 &mreqs->imr_sourceaddr, 1);
2109done: 2103done:
2110 rtnl_unlock();
2111 if (leavegroup) 2104 if (leavegroup)
2112 return ip_mc_leave_group(sk, &imr); 2105 err = ip_mc_leave_group(sk, &imr);
2113 return err; 2106 return err;
2114} 2107}
2115 2108
@@ -2131,7 +2124,7 @@ int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf, int ifindex)
2131 msf->imsf_fmode != MCAST_EXCLUDE) 2124 msf->imsf_fmode != MCAST_EXCLUDE)
2132 return -EINVAL; 2125 return -EINVAL;
2133 2126
2134 rtnl_lock(); 2127 ASSERT_RTNL();
2135 2128
2136 imr.imr_multiaddr.s_addr = msf->imsf_multiaddr; 2129 imr.imr_multiaddr.s_addr = msf->imsf_multiaddr;
2137 imr.imr_address.s_addr = msf->imsf_interface; 2130 imr.imr_address.s_addr = msf->imsf_interface;
@@ -2193,7 +2186,6 @@ int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf, int ifindex)
2193 pmc->sfmode = msf->imsf_fmode; 2186 pmc->sfmode = msf->imsf_fmode;
2194 err = 0; 2187 err = 0;
2195done: 2188done:
2196 rtnl_unlock();
2197 if (leavegroup) 2189 if (leavegroup)
2198 err = ip_mc_leave_group(sk, &imr); 2190 err = ip_mc_leave_group(sk, &imr);
2199 return err; 2191 return err;
@@ -2368,7 +2360,7 @@ void ip_mc_drop_socket(struct sock *sk)
2368 struct ip_mc_socklist *iml; 2360 struct ip_mc_socklist *iml;
2369 struct net *net = sock_net(sk); 2361 struct net *net = sock_net(sk);
2370 2362
2371 if (inet->mc_list == NULL) 2363 if (!inet->mc_list)
2372 return; 2364 return;
2373 2365
2374 rtnl_lock(); 2366 rtnl_lock();
@@ -2378,7 +2370,7 @@ void ip_mc_drop_socket(struct sock *sk)
2378 inet->mc_list = iml->next_rcu; 2370 inet->mc_list = iml->next_rcu;
2379 in_dev = inetdev_by_index(net, iml->multi.imr_ifindex); 2371 in_dev = inetdev_by_index(net, iml->multi.imr_ifindex);
2380 (void) ip_mc_leave_src(sk, iml, in_dev); 2372 (void) ip_mc_leave_src(sk, iml, in_dev);
2381 if (in_dev != NULL) 2373 if (in_dev)
2382 ip_mc_dec_group(in_dev, iml->multi.imr_multiaddr.s_addr); 2374 ip_mc_dec_group(in_dev, iml->multi.imr_multiaddr.s_addr);
2383 /* decrease mem now to avoid the memleak warning */ 2375 /* decrease mem now to avoid the memleak warning */
2384 atomic_sub(sizeof(*iml), &sk->sk_omem_alloc); 2376 atomic_sub(sizeof(*iml), &sk->sk_omem_alloc);
@@ -2595,13 +2587,13 @@ static inline struct ip_sf_list *igmp_mcf_get_first(struct seq_file *seq)
2595 for_each_netdev_rcu(net, state->dev) { 2587 for_each_netdev_rcu(net, state->dev) {
2596 struct in_device *idev; 2588 struct in_device *idev;
2597 idev = __in_dev_get_rcu(state->dev); 2589 idev = __in_dev_get_rcu(state->dev);
2598 if (unlikely(idev == NULL)) 2590 if (unlikely(!idev))
2599 continue; 2591 continue;
2600 im = rcu_dereference(idev->mc_list); 2592 im = rcu_dereference(idev->mc_list);
2601 if (likely(im != NULL)) { 2593 if (likely(im)) {
2602 spin_lock_bh(&im->lock); 2594 spin_lock_bh(&im->lock);
2603 psf = im->sources; 2595 psf = im->sources;
2604 if (likely(psf != NULL)) { 2596 if (likely(psf)) {
2605 state->im = im; 2597 state->im = im;
2606 state->idev = idev; 2598 state->idev = idev;
2607 break; 2599 break;
@@ -2671,7 +2663,7 @@ static void igmp_mcf_seq_stop(struct seq_file *seq, void *v)
2671 __releases(rcu) 2663 __releases(rcu)
2672{ 2664{
2673 struct igmp_mcf_iter_state *state = igmp_mcf_seq_private(seq); 2665 struct igmp_mcf_iter_state *state = igmp_mcf_seq_private(seq);
2674 if (likely(state->im != NULL)) { 2666 if (likely(state->im)) {
2675 spin_unlock_bh(&state->im->lock); 2667 spin_unlock_bh(&state->im->lock);
2676 state->im = NULL; 2668 state->im = NULL;
2677 } 2669 }
@@ -2724,6 +2716,7 @@ static const struct file_operations igmp_mcf_seq_fops = {
2724static int __net_init igmp_net_init(struct net *net) 2716static int __net_init igmp_net_init(struct net *net)
2725{ 2717{
2726 struct proc_dir_entry *pde; 2718 struct proc_dir_entry *pde;
2719 int err;
2727 2720
2728 pde = proc_create("igmp", S_IRUGO, net->proc_net, &igmp_mc_seq_fops); 2721 pde = proc_create("igmp", S_IRUGO, net->proc_net, &igmp_mc_seq_fops);
2729 if (!pde) 2722 if (!pde)
@@ -2732,8 +2725,18 @@ static int __net_init igmp_net_init(struct net *net)
2732 &igmp_mcf_seq_fops); 2725 &igmp_mcf_seq_fops);
2733 if (!pde) 2726 if (!pde)
2734 goto out_mcfilter; 2727 goto out_mcfilter;
2728 err = inet_ctl_sock_create(&net->ipv4.mc_autojoin_sk, AF_INET,
2729 SOCK_DGRAM, 0, net);
2730 if (err < 0) {
2731 pr_err("Failed to initialize the IGMP autojoin socket (err %d)\n",
2732 err);
2733 goto out_sock;
2734 }
2735
2735 return 0; 2736 return 0;
2736 2737
2738out_sock:
2739 remove_proc_entry("mcfilter", net->proc_net);
2737out_mcfilter: 2740out_mcfilter:
2738 remove_proc_entry("igmp", net->proc_net); 2741 remove_proc_entry("igmp", net->proc_net);
2739out_igmp: 2742out_igmp:
@@ -2744,6 +2747,7 @@ static void __net_exit igmp_net_exit(struct net *net)
2744{ 2747{
2745 remove_proc_entry("mcfilter", net->proc_net); 2748 remove_proc_entry("mcfilter", net->proc_net);
2746 remove_proc_entry("igmp", net->proc_net); 2749 remove_proc_entry("igmp", net->proc_net);
2750 inet_ctl_sock_destroy(net->ipv4.mc_autojoin_sk);
2747} 2751}
2748 2752
2749static struct pernet_operations igmp_net_ops = { 2753static struct pernet_operations igmp_net_ops = {