aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/mcast.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/mcast.c')
-rw-r--r--net/ipv6/mcast.c71
1 files changed, 34 insertions, 37 deletions
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index 49f986d626a0..3e6ebcdb4779 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -92,16 +92,16 @@ static void mld_gq_timer_expire(unsigned long data);
92static void mld_ifc_timer_expire(unsigned long data); 92static void mld_ifc_timer_expire(unsigned long data);
93static void mld_ifc_event(struct inet6_dev *idev); 93static void mld_ifc_event(struct inet6_dev *idev);
94static void mld_add_delrec(struct inet6_dev *idev, struct ifmcaddr6 *pmc); 94static void mld_add_delrec(struct inet6_dev *idev, struct ifmcaddr6 *pmc);
95static void mld_del_delrec(struct inet6_dev *idev, struct in6_addr *addr); 95static void mld_del_delrec(struct inet6_dev *idev, const struct in6_addr *addr);
96static void mld_clear_delrec(struct inet6_dev *idev); 96static void mld_clear_delrec(struct inet6_dev *idev);
97static int sf_setstate(struct ifmcaddr6 *pmc); 97static int sf_setstate(struct ifmcaddr6 *pmc);
98static void sf_markstate(struct ifmcaddr6 *pmc); 98static void sf_markstate(struct ifmcaddr6 *pmc);
99static void ip6_mc_clear_src(struct ifmcaddr6 *pmc); 99static void ip6_mc_clear_src(struct ifmcaddr6 *pmc);
100static int ip6_mc_del_src(struct inet6_dev *idev, struct in6_addr *pmca, 100static int ip6_mc_del_src(struct inet6_dev *idev, const struct in6_addr *pmca,
101 int sfmode, int sfcount, struct in6_addr *psfsrc, 101 int sfmode, int sfcount, const struct in6_addr *psfsrc,
102 int delta); 102 int delta);
103static int ip6_mc_add_src(struct inet6_dev *idev, struct in6_addr *pmca, 103static int ip6_mc_add_src(struct inet6_dev *idev, const struct in6_addr *pmca,
104 int sfmode, int sfcount, struct in6_addr *psfsrc, 104 int sfmode, int sfcount, const struct in6_addr *psfsrc,
105 int delta); 105 int delta);
106static int ip6_mc_leave_src(struct sock *sk, struct ipv6_mc_socklist *iml, 106static int ip6_mc_leave_src(struct sock *sk, struct ipv6_mc_socklist *iml,
107 struct inet6_dev *idev); 107 struct inet6_dev *idev);
@@ -201,10 +201,6 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
201 return 0; 201 return 0;
202} 202}
203 203
204static void ipv6_mc_socklist_reclaim(struct rcu_head *head)
205{
206 kfree(container_of(head, struct ipv6_mc_socklist, rcu));
207}
208/* 204/*
209 * socket leave on multicast group 205 * socket leave on multicast group
210 */ 206 */
@@ -239,7 +235,7 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr)
239 (void) ip6_mc_leave_src(sk, mc_lst, NULL); 235 (void) ip6_mc_leave_src(sk, mc_lst, NULL);
240 rcu_read_unlock(); 236 rcu_read_unlock();
241 atomic_sub(sizeof(*mc_lst), &sk->sk_omem_alloc); 237 atomic_sub(sizeof(*mc_lst), &sk->sk_omem_alloc);
242 call_rcu(&mc_lst->rcu, ipv6_mc_socklist_reclaim); 238 kfree_rcu(mc_lst, rcu);
243 return 0; 239 return 0;
244 } 240 }
245 } 241 }
@@ -250,7 +246,7 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr)
250 246
251/* called with rcu_read_lock() */ 247/* called with rcu_read_lock() */
252static struct inet6_dev *ip6_mc_find_dev_rcu(struct net *net, 248static struct inet6_dev *ip6_mc_find_dev_rcu(struct net *net,
253 struct in6_addr *group, 249 const struct in6_addr *group,
254 int ifindex) 250 int ifindex)
255{ 251{
256 struct net_device *dev = NULL; 252 struct net_device *dev = NULL;
@@ -307,7 +303,7 @@ void ipv6_sock_mc_close(struct sock *sk)
307 rcu_read_unlock(); 303 rcu_read_unlock();
308 304
309 atomic_sub(sizeof(*mc_lst), &sk->sk_omem_alloc); 305 atomic_sub(sizeof(*mc_lst), &sk->sk_omem_alloc);
310 call_rcu(&mc_lst->rcu, ipv6_mc_socklist_reclaim); 306 kfree_rcu(mc_lst, rcu);
311 307
312 spin_lock(&ipv6_sk_mc_lock); 308 spin_lock(&ipv6_sk_mc_lock);
313 } 309 }
@@ -319,7 +315,6 @@ int ip6_mc_source(int add, int omode, struct sock *sk,
319{ 315{
320 struct in6_addr *source, *group; 316 struct in6_addr *source, *group;
321 struct ipv6_mc_socklist *pmc; 317 struct ipv6_mc_socklist *pmc;
322 struct net_device *dev;
323 struct inet6_dev *idev; 318 struct inet6_dev *idev;
324 struct ipv6_pinfo *inet6 = inet6_sk(sk); 319 struct ipv6_pinfo *inet6 = inet6_sk(sk);
325 struct ip6_sf_socklist *psl; 320 struct ip6_sf_socklist *psl;
@@ -341,7 +336,6 @@ int ip6_mc_source(int add, int omode, struct sock *sk,
341 rcu_read_unlock(); 336 rcu_read_unlock();
342 return -ENODEV; 337 return -ENODEV;
343 } 338 }
344 dev = idev->dev;
345 339
346 err = -EADDRNOTAVAIL; 340 err = -EADDRNOTAVAIL;
347 341
@@ -453,9 +447,8 @@ done:
453 447
454int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf) 448int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf)
455{ 449{
456 struct in6_addr *group; 450 const struct in6_addr *group;
457 struct ipv6_mc_socklist *pmc; 451 struct ipv6_mc_socklist *pmc;
458 struct net_device *dev;
459 struct inet6_dev *idev; 452 struct inet6_dev *idev;
460 struct ipv6_pinfo *inet6 = inet6_sk(sk); 453 struct ipv6_pinfo *inet6 = inet6_sk(sk);
461 struct ip6_sf_socklist *newpsl, *psl; 454 struct ip6_sf_socklist *newpsl, *psl;
@@ -478,7 +471,6 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf)
478 rcu_read_unlock(); 471 rcu_read_unlock();
479 return -ENODEV; 472 return -ENODEV;
480 } 473 }
481 dev = idev->dev;
482 474
483 err = 0; 475 err = 0;
484 476
@@ -546,10 +538,9 @@ int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf,
546 struct group_filter __user *optval, int __user *optlen) 538 struct group_filter __user *optval, int __user *optlen)
547{ 539{
548 int err, i, count, copycount; 540 int err, i, count, copycount;
549 struct in6_addr *group; 541 const struct in6_addr *group;
550 struct ipv6_mc_socklist *pmc; 542 struct ipv6_mc_socklist *pmc;
551 struct inet6_dev *idev; 543 struct inet6_dev *idev;
552 struct net_device *dev;
553 struct ipv6_pinfo *inet6 = inet6_sk(sk); 544 struct ipv6_pinfo *inet6 = inet6_sk(sk);
554 struct ip6_sf_socklist *psl; 545 struct ip6_sf_socklist *psl;
555 struct net *net = sock_net(sk); 546 struct net *net = sock_net(sk);
@@ -566,7 +557,6 @@ int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf,
566 rcu_read_unlock(); 557 rcu_read_unlock();
567 return -ENODEV; 558 return -ENODEV;
568 } 559 }
569 dev = idev->dev;
570 560
571 err = -EADDRNOTAVAIL; 561 err = -EADDRNOTAVAIL;
572 /* 562 /*
@@ -758,7 +748,7 @@ static void mld_add_delrec(struct inet6_dev *idev, struct ifmcaddr6 *im)
758 spin_unlock_bh(&idev->mc_lock); 748 spin_unlock_bh(&idev->mc_lock);
759} 749}
760 750
761static void mld_del_delrec(struct inet6_dev *idev, struct in6_addr *pmca) 751static void mld_del_delrec(struct inet6_dev *idev, const struct in6_addr *pmca)
762{ 752{
763 struct ifmcaddr6 *pmc, *pmc_prev; 753 struct ifmcaddr6 *pmc, *pmc_prev;
764 struct ip6_sf_list *psf, *psf_next; 754 struct ip6_sf_list *psf, *psf_next;
@@ -1058,7 +1048,7 @@ static void igmp6_group_queried(struct ifmcaddr6 *ma, unsigned long resptime)
1058 1048
1059/* mark EXCLUDE-mode sources */ 1049/* mark EXCLUDE-mode sources */
1060static int mld_xmarksources(struct ifmcaddr6 *pmc, int nsrcs, 1050static int mld_xmarksources(struct ifmcaddr6 *pmc, int nsrcs,
1061 struct in6_addr *srcs) 1051 const struct in6_addr *srcs)
1062{ 1052{
1063 struct ip6_sf_list *psf; 1053 struct ip6_sf_list *psf;
1064 int i, scount; 1054 int i, scount;
@@ -1086,7 +1076,7 @@ static int mld_xmarksources(struct ifmcaddr6 *pmc, int nsrcs,
1086} 1076}
1087 1077
1088static int mld_marksources(struct ifmcaddr6 *pmc, int nsrcs, 1078static int mld_marksources(struct ifmcaddr6 *pmc, int nsrcs,
1089 struct in6_addr *srcs) 1079 const struct in6_addr *srcs)
1090{ 1080{
1091 struct ip6_sf_list *psf; 1081 struct ip6_sf_list *psf;
1092 int i, scount; 1082 int i, scount;
@@ -1121,7 +1111,7 @@ int igmp6_event_query(struct sk_buff *skb)
1121{ 1111{
1122 struct mld2_query *mlh2 = NULL; 1112 struct mld2_query *mlh2 = NULL;
1123 struct ifmcaddr6 *ma; 1113 struct ifmcaddr6 *ma;
1124 struct in6_addr *group; 1114 const struct in6_addr *group;
1125 unsigned long max_delay; 1115 unsigned long max_delay;
1126 struct inet6_dev *idev; 1116 struct inet6_dev *idev;
1127 struct mld_msg *mld; 1117 struct mld_msg *mld;
@@ -1402,7 +1392,7 @@ static void mld_sendpack(struct sk_buff *skb)
1402 struct inet6_dev *idev; 1392 struct inet6_dev *idev;
1403 struct net *net = dev_net(skb->dev); 1393 struct net *net = dev_net(skb->dev);
1404 int err; 1394 int err;
1405 struct flowi fl; 1395 struct flowi6 fl6;
1406 struct dst_entry *dst; 1396 struct dst_entry *dst;
1407 1397
1408 rcu_read_lock(); 1398 rcu_read_lock();
@@ -1425,11 +1415,16 @@ static void mld_sendpack(struct sk_buff *skb)
1425 goto err_out; 1415 goto err_out;
1426 } 1416 }
1427 1417
1428 icmpv6_flow_init(net->ipv6.igmp_sk, &fl, ICMPV6_MLD2_REPORT, 1418 icmpv6_flow_init(net->ipv6.igmp_sk, &fl6, ICMPV6_MLD2_REPORT,
1429 &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, 1419 &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
1430 skb->dev->ifindex); 1420 skb->dev->ifindex);
1431 1421
1432 err = xfrm_lookup(net, &dst, &fl, NULL, 0); 1422 dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0);
1423 err = 0;
1424 if (IS_ERR(dst)) {
1425 err = PTR_ERR(dst);
1426 dst = NULL;
1427 }
1433 skb_dst_set(skb, dst); 1428 skb_dst_set(skb, dst);
1434 if (err) 1429 if (err)
1435 goto err_out; 1430 goto err_out;
@@ -1732,7 +1727,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
1732 u8 ra[8] = { IPPROTO_ICMPV6, 0, 1727 u8 ra[8] = { IPPROTO_ICMPV6, 0,
1733 IPV6_TLV_ROUTERALERT, 2, 0, 0, 1728 IPV6_TLV_ROUTERALERT, 2, 0, 0,
1734 IPV6_TLV_PADN, 0 }; 1729 IPV6_TLV_PADN, 0 };
1735 struct flowi fl; 1730 struct flowi6 fl6;
1736 struct dst_entry *dst; 1731 struct dst_entry *dst;
1737 1732
1738 if (type == ICMPV6_MGM_REDUCTION) 1733 if (type == ICMPV6_MGM_REDUCTION)
@@ -1792,13 +1787,15 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
1792 goto err_out; 1787 goto err_out;
1793 } 1788 }
1794 1789
1795 icmpv6_flow_init(sk, &fl, type, 1790 icmpv6_flow_init(sk, &fl6, type,
1796 &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, 1791 &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
1797 skb->dev->ifindex); 1792 skb->dev->ifindex);
1798 1793
1799 err = xfrm_lookup(net, &dst, &fl, NULL, 0); 1794 dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0);
1800 if (err) 1795 if (IS_ERR(dst)) {
1796 err = PTR_ERR(dst);
1801 goto err_out; 1797 goto err_out;
1798 }
1802 1799
1803 skb_dst_set(skb, dst); 1800 skb_dst_set(skb, dst);
1804 err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, skb, NULL, skb->dev, 1801 err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, skb, NULL, skb->dev,
@@ -1820,7 +1817,7 @@ err_out:
1820} 1817}
1821 1818
1822static int ip6_mc_del1_src(struct ifmcaddr6 *pmc, int sfmode, 1819static int ip6_mc_del1_src(struct ifmcaddr6 *pmc, int sfmode,
1823 struct in6_addr *psfsrc) 1820 const struct in6_addr *psfsrc)
1824{ 1821{
1825 struct ip6_sf_list *psf, *psf_prev; 1822 struct ip6_sf_list *psf, *psf_prev;
1826 int rv = 0; 1823 int rv = 0;
@@ -1856,8 +1853,8 @@ static int ip6_mc_del1_src(struct ifmcaddr6 *pmc, int sfmode,
1856 return rv; 1853 return rv;
1857} 1854}
1858 1855
1859static int ip6_mc_del_src(struct inet6_dev *idev, struct in6_addr *pmca, 1856static int ip6_mc_del_src(struct inet6_dev *idev, const struct in6_addr *pmca,
1860 int sfmode, int sfcount, struct in6_addr *psfsrc, 1857 int sfmode, int sfcount, const struct in6_addr *psfsrc,
1861 int delta) 1858 int delta)
1862{ 1859{
1863 struct ifmcaddr6 *pmc; 1860 struct ifmcaddr6 *pmc;
@@ -1917,7 +1914,7 @@ static int ip6_mc_del_src(struct inet6_dev *idev, struct in6_addr *pmca,
1917 * Add multicast single-source filter to the interface list 1914 * Add multicast single-source filter to the interface list
1918 */ 1915 */
1919static int ip6_mc_add1_src(struct ifmcaddr6 *pmc, int sfmode, 1916static int ip6_mc_add1_src(struct ifmcaddr6 *pmc, int sfmode,
1920 struct in6_addr *psfsrc, int delta) 1917 const struct in6_addr *psfsrc, int delta)
1921{ 1918{
1922 struct ip6_sf_list *psf, *psf_prev; 1919 struct ip6_sf_list *psf, *psf_prev;
1923 1920
@@ -2020,8 +2017,8 @@ static int sf_setstate(struct ifmcaddr6 *pmc)
2020/* 2017/*
2021 * Add multicast source filter list to the interface list 2018 * Add multicast source filter list to the interface list
2022 */ 2019 */
2023static int ip6_mc_add_src(struct inet6_dev *idev, struct in6_addr *pmca, 2020static int ip6_mc_add_src(struct inet6_dev *idev, const struct in6_addr *pmca,
2024 int sfmode, int sfcount, struct in6_addr *psfsrc, 2021 int sfmode, int sfcount, const struct in6_addr *psfsrc,
2025 int delta) 2022 int delta)
2026{ 2023{
2027 struct ifmcaddr6 *pmc; 2024 struct ifmcaddr6 *pmc;