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.c138
1 files changed, 94 insertions, 44 deletions
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index 76c08402c933..2a4bb76f2132 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -71,6 +71,7 @@
71 */ 71 */
72 72
73#include <linux/module.h> 73#include <linux/module.h>
74#include <linux/slab.h>
74#include <asm/uaccess.h> 75#include <asm/uaccess.h>
75#include <asm/system.h> 76#include <asm/system.h>
76#include <linux/types.h> 77#include <linux/types.h>
@@ -311,7 +312,7 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size)
311 return NULL; 312 return NULL;
312 } 313 }
313 314
314 skb_dst_set(skb, &rt->u.dst); 315 skb_dst_set(skb, &rt->dst);
315 skb->dev = dev; 316 skb->dev = dev;
316 317
317 skb_reserve(skb, LL_RESERVED_SPACE(dev)); 318 skb_reserve(skb, LL_RESERVED_SPACE(dev));
@@ -329,7 +330,7 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size)
329 pip->saddr = rt->rt_src; 330 pip->saddr = rt->rt_src;
330 pip->protocol = IPPROTO_IGMP; 331 pip->protocol = IPPROTO_IGMP;
331 pip->tot_len = 0; /* filled in later */ 332 pip->tot_len = 0; /* filled in later */
332 ip_select_ident(pip, &rt->u.dst, NULL); 333 ip_select_ident(pip, &rt->dst, NULL);
333 ((u8*)&pip[1])[0] = IPOPT_RA; 334 ((u8*)&pip[1])[0] = IPOPT_RA;
334 ((u8*)&pip[1])[1] = 4; 335 ((u8*)&pip[1])[1] = 4;
335 ((u8*)&pip[1])[2] = 0; 336 ((u8*)&pip[1])[2] = 0;
@@ -659,7 +660,7 @@ static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc,
659 return -1; 660 return -1;
660 } 661 }
661 662
662 skb_dst_set(skb, &rt->u.dst); 663 skb_dst_set(skb, &rt->dst);
663 664
664 skb_reserve(skb, LL_RESERVED_SPACE(dev)); 665 skb_reserve(skb, LL_RESERVED_SPACE(dev));
665 666
@@ -675,7 +676,7 @@ static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc,
675 iph->daddr = dst; 676 iph->daddr = dst;
676 iph->saddr = rt->rt_src; 677 iph->saddr = rt->rt_src;
677 iph->protocol = IPPROTO_IGMP; 678 iph->protocol = IPPROTO_IGMP;
678 ip_select_ident(iph, &rt->u.dst, NULL); 679 ip_select_ident(iph, &rt->dst, NULL);
679 ((u8*)&iph[1])[0] = IPOPT_RA; 680 ((u8*)&iph[1])[0] = IPOPT_RA;
680 ((u8*)&iph[1])[1] = 4; 681 ((u8*)&iph[1])[1] = 4;
681 ((u8*)&iph[1])[2] = 0; 682 ((u8*)&iph[1])[2] = 0;
@@ -855,6 +856,18 @@ static void igmp_heard_query(struct in_device *in_dev, struct sk_buff *skb,
855 igmpv3_clear_delrec(in_dev); 856 igmpv3_clear_delrec(in_dev);
856 } else if (len < 12) { 857 } else if (len < 12) {
857 return; /* ignore bogus packet; freed by caller */ 858 return; /* ignore bogus packet; freed by caller */
859 } else if (IGMP_V1_SEEN(in_dev)) {
860 /* This is a v3 query with v1 queriers present */
861 max_delay = IGMP_Query_Response_Interval;
862 group = 0;
863 } else if (IGMP_V2_SEEN(in_dev)) {
864 /* this is a v3 query with v2 queriers present;
865 * Interpretation of the max_delay code is problematic here.
866 * A real v2 host would use ih_code directly, while v3 has a
867 * different encoding. We use the v3 encoding as more likely
868 * to be intended in a v3 query.
869 */
870 max_delay = IGMPV3_MRC(ih3->code)*(HZ/IGMP_TIMER_SCALE);
858 } else { /* v3 */ 871 } else { /* v3 */
859 if (!pskb_may_pull(skb, sizeof(struct igmpv3_query))) 872 if (!pskb_may_pull(skb, sizeof(struct igmpv3_query)))
860 return; 873 return;
@@ -915,18 +928,19 @@ static void igmp_heard_query(struct in_device *in_dev, struct sk_buff *skb,
915 read_unlock(&in_dev->mc_list_lock); 928 read_unlock(&in_dev->mc_list_lock);
916} 929}
917 930
931/* called in rcu_read_lock() section */
918int igmp_rcv(struct sk_buff *skb) 932int igmp_rcv(struct sk_buff *skb)
919{ 933{
920 /* This basically follows the spec line by line -- see RFC1112 */ 934 /* This basically follows the spec line by line -- see RFC1112 */
921 struct igmphdr *ih; 935 struct igmphdr *ih;
922 struct in_device *in_dev = in_dev_get(skb->dev); 936 struct in_device *in_dev = __in_dev_get_rcu(skb->dev);
923 int len = skb->len; 937 int len = skb->len;
924 938
925 if (in_dev == NULL) 939 if (in_dev == NULL)
926 goto drop; 940 goto drop;
927 941
928 if (!pskb_may_pull(skb, sizeof(struct igmphdr))) 942 if (!pskb_may_pull(skb, sizeof(struct igmphdr)))
929 goto drop_ref; 943 goto drop;
930 944
931 switch (skb->ip_summed) { 945 switch (skb->ip_summed) {
932 case CHECKSUM_COMPLETE: 946 case CHECKSUM_COMPLETE:
@@ -936,7 +950,7 @@ int igmp_rcv(struct sk_buff *skb)
936 case CHECKSUM_NONE: 950 case CHECKSUM_NONE:
937 skb->csum = 0; 951 skb->csum = 0;
938 if (__skb_checksum_complete(skb)) 952 if (__skb_checksum_complete(skb))
939 goto drop_ref; 953 goto drop;
940 } 954 }
941 955
942 ih = igmp_hdr(skb); 956 ih = igmp_hdr(skb);
@@ -946,7 +960,6 @@ int igmp_rcv(struct sk_buff *skb)
946 break; 960 break;
947 case IGMP_HOST_MEMBERSHIP_REPORT: 961 case IGMP_HOST_MEMBERSHIP_REPORT:
948 case IGMPV2_HOST_MEMBERSHIP_REPORT: 962 case IGMPV2_HOST_MEMBERSHIP_REPORT:
949 case IGMPV3_HOST_MEMBERSHIP_REPORT:
950 /* Is it our report looped back? */ 963 /* Is it our report looped back? */
951 if (skb_rtable(skb)->fl.iif == 0) 964 if (skb_rtable(skb)->fl.iif == 0)
952 break; 965 break;
@@ -957,9 +970,9 @@ int igmp_rcv(struct sk_buff *skb)
957 break; 970 break;
958 case IGMP_PIM: 971 case IGMP_PIM:
959#ifdef CONFIG_IP_PIMSM_V1 972#ifdef CONFIG_IP_PIMSM_V1
960 in_dev_put(in_dev);
961 return pim_rcv_v1(skb); 973 return pim_rcv_v1(skb);
962#endif 974#endif
975 case IGMPV3_HOST_MEMBERSHIP_REPORT:
963 case IGMP_DVMRP: 976 case IGMP_DVMRP:
964 case IGMP_TRACE: 977 case IGMP_TRACE:
965 case IGMP_HOST_LEAVE_MESSAGE: 978 case IGMP_HOST_LEAVE_MESSAGE:
@@ -970,8 +983,6 @@ int igmp_rcv(struct sk_buff *skb)
970 break; 983 break;
971 } 984 }
972 985
973drop_ref:
974 in_dev_put(in_dev);
975drop: 986drop:
976 kfree_skb(skb); 987 kfree_skb(skb);
977 return 0; 988 return 0;
@@ -997,7 +1008,7 @@ static void ip_mc_filter_add(struct in_device *in_dev, __be32 addr)
997 --ANK 1008 --ANK
998 */ 1009 */
999 if (arp_mc_map(addr, buf, dev, 0) == 0) 1010 if (arp_mc_map(addr, buf, dev, 0) == 0)
1000 dev_mc_add(dev, buf, dev->addr_len, 0); 1011 dev_mc_add(dev, buf);
1001} 1012}
1002 1013
1003/* 1014/*
@@ -1010,7 +1021,7 @@ static void ip_mc_filter_del(struct in_device *in_dev, __be32 addr)
1010 struct net_device *dev = in_dev->dev; 1021 struct net_device *dev = in_dev->dev;
1011 1022
1012 if (arp_mc_map(addr, buf, dev, 0) == 0) 1023 if (arp_mc_map(addr, buf, dev, 0) == 0)
1013 dev_mc_delete(dev, buf, dev->addr_len, 0); 1024 dev_mc_del(dev, buf);
1014} 1025}
1015 1026
1016#ifdef CONFIG_IP_MULTICAST 1027#ifdef CONFIG_IP_MULTICAST
@@ -1245,6 +1256,7 @@ void ip_mc_inc_group(struct in_device *in_dev, __be32 addr)
1245out: 1256out:
1246 return; 1257 return;
1247} 1258}
1259EXPORT_SYMBOL(ip_mc_inc_group);
1248 1260
1249/* 1261/*
1250 * Resend IGMP JOIN report; used for bonding. 1262 * Resend IGMP JOIN report; used for bonding.
@@ -1267,6 +1279,7 @@ void ip_mc_rejoin_group(struct ip_mc_list *im)
1267 igmp_ifc_event(in_dev); 1279 igmp_ifc_event(in_dev);
1268#endif 1280#endif
1269} 1281}
1282EXPORT_SYMBOL(ip_mc_rejoin_group);
1270 1283
1271/* 1284/*
1272 * A socket has left a multicast group on device dev 1285 * A socket has left a multicast group on device dev
@@ -1297,6 +1310,7 @@ void ip_mc_dec_group(struct in_device *in_dev, __be32 addr)
1297 } 1310 }
1298 } 1311 }
1299} 1312}
1313EXPORT_SYMBOL(ip_mc_dec_group);
1300 1314
1301/* Device changing type */ 1315/* Device changing type */
1302 1316
@@ -1426,7 +1440,7 @@ static struct in_device *ip_mc_find_dev(struct net *net, struct ip_mreqn *imr)
1426 } 1440 }
1427 1441
1428 if (!dev && !ip_route_output_key(net, &rt, &fl)) { 1442 if (!dev && !ip_route_output_key(net, &rt, &fl)) {
1429 dev = rt->u.dst.dev; 1443 dev = rt->dst.dev;
1430 ip_rt_put(rt); 1444 ip_rt_put(rt);
1431 } 1445 }
1432 if (dev) { 1446 if (dev) {
@@ -1645,8 +1659,7 @@ static int sf_setstate(struct ip_mc_list *pmc)
1645 if (dpsf->sf_inaddr == psf->sf_inaddr) 1659 if (dpsf->sf_inaddr == psf->sf_inaddr)
1646 break; 1660 break;
1647 if (!dpsf) { 1661 if (!dpsf) {
1648 dpsf = (struct ip_sf_list *) 1662 dpsf = kmalloc(sizeof(*dpsf), GFP_ATOMIC);
1649 kmalloc(sizeof(*dpsf), GFP_ATOMIC);
1650 if (!dpsf) 1663 if (!dpsf)
1651 continue; 1664 continue;
1652 *dpsf = *psf; 1665 *dpsf = *psf;
@@ -1799,32 +1812,55 @@ int ip_mc_join_group(struct sock *sk , struct ip_mreqn *imr)
1799 iml->next = inet->mc_list; 1812 iml->next = inet->mc_list;
1800 iml->sflist = NULL; 1813 iml->sflist = NULL;
1801 iml->sfmode = MCAST_EXCLUDE; 1814 iml->sfmode = MCAST_EXCLUDE;
1802 inet->mc_list = iml; 1815 rcu_assign_pointer(inet->mc_list, iml);
1803 ip_mc_inc_group(in_dev, addr); 1816 ip_mc_inc_group(in_dev, addr);
1804 err = 0; 1817 err = 0;
1805done: 1818done:
1806 rtnl_unlock(); 1819 rtnl_unlock();
1807 return err; 1820 return err;
1808} 1821}
1822EXPORT_SYMBOL(ip_mc_join_group);
1823
1824static void ip_sf_socklist_reclaim(struct rcu_head *rp)
1825{
1826 struct ip_sf_socklist *psf;
1827
1828 psf = container_of(rp, struct ip_sf_socklist, rcu);
1829 /* sk_omem_alloc should have been decreased by the caller*/
1830 kfree(psf);
1831}
1809 1832
1810static int ip_mc_leave_src(struct sock *sk, struct ip_mc_socklist *iml, 1833static int ip_mc_leave_src(struct sock *sk, struct ip_mc_socklist *iml,
1811 struct in_device *in_dev) 1834 struct in_device *in_dev)
1812{ 1835{
1836 struct ip_sf_socklist *psf = iml->sflist;
1813 int err; 1837 int err;
1814 1838
1815 if (iml->sflist == NULL) { 1839 if (psf == NULL) {
1816 /* any-source empty exclude case */ 1840 /* any-source empty exclude case */
1817 return ip_mc_del_src(in_dev, &iml->multi.imr_multiaddr.s_addr, 1841 return ip_mc_del_src(in_dev, &iml->multi.imr_multiaddr.s_addr,
1818 iml->sfmode, 0, NULL, 0); 1842 iml->sfmode, 0, NULL, 0);
1819 } 1843 }
1820 err = ip_mc_del_src(in_dev, &iml->multi.imr_multiaddr.s_addr, 1844 err = ip_mc_del_src(in_dev, &iml->multi.imr_multiaddr.s_addr,
1821 iml->sfmode, iml->sflist->sl_count, 1845 iml->sfmode, psf->sl_count, psf->sl_addr, 0);
1822 iml->sflist->sl_addr, 0); 1846 rcu_assign_pointer(iml->sflist, NULL);
1823 sock_kfree_s(sk, iml->sflist, IP_SFLSIZE(iml->sflist->sl_max)); 1847 /* decrease mem now to avoid the memleak warning */
1824 iml->sflist = NULL; 1848 atomic_sub(IP_SFLSIZE(psf->sl_max), &sk->sk_omem_alloc);
1849 call_rcu(&psf->rcu, ip_sf_socklist_reclaim);
1825 return err; 1850 return err;
1826} 1851}
1827 1852
1853
1854static void ip_mc_socklist_reclaim(struct rcu_head *rp)
1855{
1856 struct ip_mc_socklist *iml;
1857
1858 iml = container_of(rp, struct ip_mc_socklist, rcu);
1859 /* sk_omem_alloc should have been decreased by the caller*/
1860 kfree(iml);
1861}
1862
1863
1828/* 1864/*
1829 * Ask a socket to leave a group. 1865 * Ask a socket to leave a group.
1830 */ 1866 */
@@ -1854,12 +1890,14 @@ int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr)
1854 1890
1855 (void) ip_mc_leave_src(sk, iml, in_dev); 1891 (void) ip_mc_leave_src(sk, iml, in_dev);
1856 1892
1857 *imlp = iml->next; 1893 rcu_assign_pointer(*imlp, iml->next);
1858 1894
1859 if (in_dev) 1895 if (in_dev)
1860 ip_mc_dec_group(in_dev, group); 1896 ip_mc_dec_group(in_dev, group);
1861 rtnl_unlock(); 1897 rtnl_unlock();
1862 sock_kfree_s(sk, iml, sizeof(*iml)); 1898 /* decrease mem now to avoid the memleak warning */
1899 atomic_sub(sizeof(*iml), &sk->sk_omem_alloc);
1900 call_rcu(&iml->rcu, ip_mc_socklist_reclaim);
1863 return 0; 1901 return 0;
1864 } 1902 }
1865 if (!in_dev) 1903 if (!in_dev)
@@ -1974,9 +2012,12 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct
1974 if (psl) { 2012 if (psl) {
1975 for (i=0; i<psl->sl_count; i++) 2013 for (i=0; i<psl->sl_count; i++)
1976 newpsl->sl_addr[i] = psl->sl_addr[i]; 2014 newpsl->sl_addr[i] = psl->sl_addr[i];
1977 sock_kfree_s(sk, psl, IP_SFLSIZE(psl->sl_max)); 2015 /* decrease mem now to avoid the memleak warning */
2016 atomic_sub(IP_SFLSIZE(psl->sl_max), &sk->sk_omem_alloc);
2017 call_rcu(&psl->rcu, ip_sf_socklist_reclaim);
1978 } 2018 }
1979 pmc->sflist = psl = newpsl; 2019 rcu_assign_pointer(pmc->sflist, newpsl);
2020 psl = newpsl;
1980 } 2021 }
1981 rv = 1; /* > 0 for insert logic below if sl_count is 0 */ 2022 rv = 1; /* > 0 for insert logic below if sl_count is 0 */
1982 for (i=0; i<psl->sl_count; i++) { 2023 for (i=0; i<psl->sl_count; i++) {
@@ -2072,11 +2113,13 @@ int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf, int ifindex)
2072 if (psl) { 2113 if (psl) {
2073 (void) ip_mc_del_src(in_dev, &msf->imsf_multiaddr, pmc->sfmode, 2114 (void) ip_mc_del_src(in_dev, &msf->imsf_multiaddr, pmc->sfmode,
2074 psl->sl_count, psl->sl_addr, 0); 2115 psl->sl_count, psl->sl_addr, 0);
2075 sock_kfree_s(sk, psl, IP_SFLSIZE(psl->sl_max)); 2116 /* decrease mem now to avoid the memleak warning */
2117 atomic_sub(IP_SFLSIZE(psl->sl_max), &sk->sk_omem_alloc);
2118 call_rcu(&psl->rcu, ip_sf_socklist_reclaim);
2076 } else 2119 } else
2077 (void) ip_mc_del_src(in_dev, &msf->imsf_multiaddr, pmc->sfmode, 2120 (void) ip_mc_del_src(in_dev, &msf->imsf_multiaddr, pmc->sfmode,
2078 0, NULL, 0); 2121 0, NULL, 0);
2079 pmc->sflist = newpsl; 2122 rcu_assign_pointer(pmc->sflist, newpsl);
2080 pmc->sfmode = msf->imsf_fmode; 2123 pmc->sfmode = msf->imsf_fmode;
2081 err = 0; 2124 err = 0;
2082done: 2125done:
@@ -2209,30 +2252,40 @@ int ip_mc_sf_allow(struct sock *sk, __be32 loc_addr, __be32 rmt_addr, int dif)
2209 struct ip_mc_socklist *pmc; 2252 struct ip_mc_socklist *pmc;
2210 struct ip_sf_socklist *psl; 2253 struct ip_sf_socklist *psl;
2211 int i; 2254 int i;
2255 int ret;
2212 2256
2257 ret = 1;
2213 if (!ipv4_is_multicast(loc_addr)) 2258 if (!ipv4_is_multicast(loc_addr))
2214 return 1; 2259 goto out;
2215 2260
2216 for (pmc=inet->mc_list; pmc; pmc=pmc->next) { 2261 rcu_read_lock();
2262 for (pmc=rcu_dereference(inet->mc_list); pmc; pmc=rcu_dereference(pmc->next)) {
2217 if (pmc->multi.imr_multiaddr.s_addr == loc_addr && 2263 if (pmc->multi.imr_multiaddr.s_addr == loc_addr &&
2218 pmc->multi.imr_ifindex == dif) 2264 pmc->multi.imr_ifindex == dif)
2219 break; 2265 break;
2220 } 2266 }
2267 ret = inet->mc_all;
2221 if (!pmc) 2268 if (!pmc)
2222 return inet->mc_all; 2269 goto unlock;
2223 psl = pmc->sflist; 2270 psl = pmc->sflist;
2271 ret = (pmc->sfmode == MCAST_EXCLUDE);
2224 if (!psl) 2272 if (!psl)
2225 return pmc->sfmode == MCAST_EXCLUDE; 2273 goto unlock;
2226 2274
2227 for (i=0; i<psl->sl_count; i++) { 2275 for (i=0; i<psl->sl_count; i++) {
2228 if (psl->sl_addr[i] == rmt_addr) 2276 if (psl->sl_addr[i] == rmt_addr)
2229 break; 2277 break;
2230 } 2278 }
2279 ret = 0;
2231 if (pmc->sfmode == MCAST_INCLUDE && i >= psl->sl_count) 2280 if (pmc->sfmode == MCAST_INCLUDE && i >= psl->sl_count)
2232 return 0; 2281 goto unlock;
2233 if (pmc->sfmode == MCAST_EXCLUDE && i < psl->sl_count) 2282 if (pmc->sfmode == MCAST_EXCLUDE && i < psl->sl_count)
2234 return 0; 2283 goto unlock;
2235 return 1; 2284 ret = 1;
2285unlock:
2286 rcu_read_unlock();
2287out:
2288 return ret;
2236} 2289}
2237 2290
2238/* 2291/*
@@ -2251,7 +2304,7 @@ void ip_mc_drop_socket(struct sock *sk)
2251 rtnl_lock(); 2304 rtnl_lock();
2252 while ((iml = inet->mc_list) != NULL) { 2305 while ((iml = inet->mc_list) != NULL) {
2253 struct in_device *in_dev; 2306 struct in_device *in_dev;
2254 inet->mc_list = iml->next; 2307 rcu_assign_pointer(inet->mc_list, iml->next);
2255 2308
2256 in_dev = inetdev_by_index(net, iml->multi.imr_ifindex); 2309 in_dev = inetdev_by_index(net, iml->multi.imr_ifindex);
2257 (void) ip_mc_leave_src(sk, iml, in_dev); 2310 (void) ip_mc_leave_src(sk, iml, in_dev);
@@ -2259,7 +2312,9 @@ void ip_mc_drop_socket(struct sock *sk)
2259 ip_mc_dec_group(in_dev, iml->multi.imr_multiaddr.s_addr); 2312 ip_mc_dec_group(in_dev, iml->multi.imr_multiaddr.s_addr);
2260 in_dev_put(in_dev); 2313 in_dev_put(in_dev);
2261 } 2314 }
2262 sock_kfree_s(sk, iml, sizeof(*iml)); 2315 /* decrease mem now to avoid the memleak warning */
2316 atomic_sub(sizeof(*iml), &sk->sk_omem_alloc);
2317 call_rcu(&iml->rcu, ip_mc_socklist_reclaim);
2263 } 2318 }
2264 rtnl_unlock(); 2319 rtnl_unlock();
2265} 2320}
@@ -2603,7 +2658,7 @@ static const struct file_operations igmp_mcf_seq_fops = {
2603 .release = seq_release_net, 2658 .release = seq_release_net,
2604}; 2659};
2605 2660
2606static int igmp_net_init(struct net *net) 2661static int __net_init igmp_net_init(struct net *net)
2607{ 2662{
2608 struct proc_dir_entry *pde; 2663 struct proc_dir_entry *pde;
2609 2664
@@ -2621,7 +2676,7 @@ out_igmp:
2621 return -ENOMEM; 2676 return -ENOMEM;
2622} 2677}
2623 2678
2624static void igmp_net_exit(struct net *net) 2679static void __net_exit igmp_net_exit(struct net *net)
2625{ 2680{
2626 proc_net_remove(net, "mcfilter"); 2681 proc_net_remove(net, "mcfilter");
2627 proc_net_remove(net, "igmp"); 2682 proc_net_remove(net, "igmp");
@@ -2637,8 +2692,3 @@ int __init igmp_mc_proc_init(void)
2637 return register_pernet_subsys(&igmp_net_ops); 2692 return register_pernet_subsys(&igmp_net_ops);
2638} 2693}
2639#endif 2694#endif
2640
2641EXPORT_SYMBOL(ip_mc_dec_group);
2642EXPORT_SYMBOL(ip_mc_inc_group);
2643EXPORT_SYMBOL(ip_mc_join_group);
2644EXPORT_SYMBOL(ip_mc_rejoin_group);