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.c60
1 files changed, 27 insertions, 33 deletions
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index 2e6a53f3cc38..54f91efdae58 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -127,8 +127,6 @@ static struct in6_addr mld2_all_mcr = MLD2_ALL_MCR_INIT;
127/* Big mc list lock for all the sockets */ 127/* Big mc list lock for all the sockets */
128static DEFINE_RWLOCK(ipv6_sk_mc_lock); 128static DEFINE_RWLOCK(ipv6_sk_mc_lock);
129 129
130int __ipv6_dev_mc_dec(struct inet6_dev *idev, struct in6_addr *addr);
131
132static void igmp6_join_group(struct ifmcaddr6 *ma); 130static void igmp6_join_group(struct ifmcaddr6 *ma);
133static void igmp6_leave_group(struct ifmcaddr6 *ma); 131static void igmp6_leave_group(struct ifmcaddr6 *ma);
134static void igmp6_timer_handler(unsigned long data); 132static void igmp6_timer_handler(unsigned long data);
@@ -177,7 +175,7 @@ int sysctl_mld_max_msf __read_mostly = IPV6_MLD_MAX_MSF;
177 * socket join on multicast group 175 * socket join on multicast group
178 */ 176 */
179 177
180int ipv6_sock_mc_join(struct sock *sk, int ifindex, struct in6_addr *addr) 178int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
181{ 179{
182 struct net_device *dev = NULL; 180 struct net_device *dev = NULL;
183 struct ipv6_mc_socklist *mc_lst; 181 struct ipv6_mc_socklist *mc_lst;
@@ -252,7 +250,7 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, struct in6_addr *addr)
252/* 250/*
253 * socket leave on multicast group 251 * socket leave on multicast group
254 */ 252 */
255int ipv6_sock_mc_drop(struct sock *sk, int ifindex, struct in6_addr *addr) 253int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr)
256{ 254{
257 struct ipv6_pinfo *np = inet6_sk(sk); 255 struct ipv6_pinfo *np = inet6_sk(sk);
258 struct ipv6_mc_socklist *mc_lst, **lnk; 256 struct ipv6_mc_socklist *mc_lst, **lnk;
@@ -664,8 +662,8 @@ done:
664 return err; 662 return err;
665} 663}
666 664
667int inet6_mc_check(struct sock *sk, struct in6_addr *mc_addr, 665int inet6_mc_check(struct sock *sk, const struct in6_addr *mc_addr,
668 struct in6_addr *src_addr) 666 const struct in6_addr *src_addr)
669{ 667{
670 struct ipv6_pinfo *np = inet6_sk(sk); 668 struct ipv6_pinfo *np = inet6_sk(sk);
671 struct ipv6_mc_socklist *mc; 669 struct ipv6_mc_socklist *mc;
@@ -871,7 +869,7 @@ static void mld_clear_delrec(struct inet6_dev *idev)
871/* 869/*
872 * device multicast group inc (add if not found) 870 * device multicast group inc (add if not found)
873 */ 871 */
874int ipv6_dev_mc_inc(struct net_device *dev, struct in6_addr *addr) 872int ipv6_dev_mc_inc(struct net_device *dev, const struct in6_addr *addr)
875{ 873{
876 struct ifmcaddr6 *mc; 874 struct ifmcaddr6 *mc;
877 struct inet6_dev *idev; 875 struct inet6_dev *idev;
@@ -942,7 +940,7 @@ int ipv6_dev_mc_inc(struct net_device *dev, struct in6_addr *addr)
942/* 940/*
943 * device multicast group del 941 * device multicast group del
944 */ 942 */
945int __ipv6_dev_mc_dec(struct inet6_dev *idev, struct in6_addr *addr) 943int __ipv6_dev_mc_dec(struct inet6_dev *idev, const struct in6_addr *addr)
946{ 944{
947 struct ifmcaddr6 *ma, **map; 945 struct ifmcaddr6 *ma, **map;
948 946
@@ -967,7 +965,7 @@ int __ipv6_dev_mc_dec(struct inet6_dev *idev, struct in6_addr *addr)
967 return -ENOENT; 965 return -ENOENT;
968} 966}
969 967
970int ipv6_dev_mc_dec(struct net_device *dev, struct in6_addr *addr) 968int ipv6_dev_mc_dec(struct net_device *dev, const struct in6_addr *addr)
971{ 969{
972 struct inet6_dev *idev = in6_dev_get(dev); 970 struct inet6_dev *idev = in6_dev_get(dev);
973 int err; 971 int err;
@@ -1012,8 +1010,8 @@ int ipv6_is_mld(struct sk_buff *skb, int nexthdr)
1012/* 1010/*
1013 * check if the interface/address pair is valid 1011 * check if the interface/address pair is valid
1014 */ 1012 */
1015int ipv6_chk_mcast_addr(struct net_device *dev, struct in6_addr *group, 1013int ipv6_chk_mcast_addr(struct net_device *dev, const struct in6_addr *group,
1016 struct in6_addr *src_addr) 1014 const struct in6_addr *src_addr)
1017{ 1015{
1018 struct inet6_dev *idev; 1016 struct inet6_dev *idev;
1019 struct ifmcaddr6 *mc; 1017 struct ifmcaddr6 *mc;
@@ -1406,6 +1404,7 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size)
1406 struct sk_buff *skb; 1404 struct sk_buff *skb;
1407 struct mld2_report *pmr; 1405 struct mld2_report *pmr;
1408 struct in6_addr addr_buf; 1406 struct in6_addr addr_buf;
1407 const struct in6_addr *saddr;
1409 int err; 1408 int err;
1410 u8 ra[8] = { IPPROTO_ICMPV6, 0, 1409 u8 ra[8] = { IPPROTO_ICMPV6, 0,
1411 IPV6_TLV_ROUTERALERT, 2, 0, 0, 1410 IPV6_TLV_ROUTERALERT, 2, 0, 0,
@@ -1424,10 +1423,11 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size)
1424 * use unspecified address as the source address 1423 * use unspecified address as the source address
1425 * when a valid link-local address is not available. 1424 * when a valid link-local address is not available.
1426 */ 1425 */
1427 memset(&addr_buf, 0, sizeof(addr_buf)); 1426 saddr = &in6addr_any;
1428 } 1427 } else
1428 saddr = &addr_buf;
1429 1429
1430 ip6_nd_hdr(sk, skb, dev, &addr_buf, &mld2_all_mcr, NEXTHDR_HOP, 0); 1430 ip6_nd_hdr(sk, skb, dev, saddr, &mld2_all_mcr, NEXTHDR_HOP, 0);
1431 1431
1432 memcpy(skb_put(skb, sizeof(ra)), ra, sizeof(ra)); 1432 memcpy(skb_put(skb, sizeof(ra)), ra, sizeof(ra));
1433 1433
@@ -1768,10 +1768,9 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
1768 struct inet6_dev *idev; 1768 struct inet6_dev *idev;
1769 struct sk_buff *skb; 1769 struct sk_buff *skb;
1770 struct icmp6hdr *hdr; 1770 struct icmp6hdr *hdr;
1771 struct in6_addr *snd_addr; 1771 const struct in6_addr *snd_addr, *saddr;
1772 struct in6_addr *addrp; 1772 struct in6_addr *addrp;
1773 struct in6_addr addr_buf; 1773 struct in6_addr addr_buf;
1774 struct in6_addr all_routers;
1775 int err, len, payload_len, full_len; 1774 int err, len, payload_len, full_len;
1776 u8 ra[8] = { IPPROTO_ICMPV6, 0, 1775 u8 ra[8] = { IPPROTO_ICMPV6, 0,
1777 IPV6_TLV_ROUTERALERT, 2, 0, 0, 1776 IPV6_TLV_ROUTERALERT, 2, 0, 0,
@@ -1782,11 +1781,10 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
1782 IP6_INC_STATS(__in6_dev_get(dev), 1781 IP6_INC_STATS(__in6_dev_get(dev),
1783 IPSTATS_MIB_OUTREQUESTS); 1782 IPSTATS_MIB_OUTREQUESTS);
1784 rcu_read_unlock(); 1783 rcu_read_unlock();
1785 snd_addr = addr; 1784 if (type == ICMPV6_MGM_REDUCTION)
1786 if (type == ICMPV6_MGM_REDUCTION) { 1785 snd_addr = &in6addr_linklocal_allrouters;
1787 snd_addr = &all_routers; 1786 else
1788 ipv6_addr_all_routers(&all_routers); 1787 snd_addr = addr;
1789 }
1790 1788
1791 len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr); 1789 len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr);
1792 payload_len = len + sizeof(ra); 1790 payload_len = len + sizeof(ra);
@@ -1809,10 +1807,11 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
1809 * use unspecified address as the source address 1807 * use unspecified address as the source address
1810 * when a valid link-local address is not available. 1808 * when a valid link-local address is not available.
1811 */ 1809 */
1812 memset(&addr_buf, 0, sizeof(addr_buf)); 1810 saddr = &in6addr_any;
1813 } 1811 } else
1812 saddr = &addr_buf;
1814 1813
1815 ip6_nd_hdr(sk, skb, dev, &addr_buf, snd_addr, NEXTHDR_HOP, payload_len); 1814 ip6_nd_hdr(sk, skb, dev, saddr, snd_addr, NEXTHDR_HOP, payload_len);
1816 1815
1817 memcpy(skb_put(skb, sizeof(ra)), ra, sizeof(ra)); 1816 memcpy(skb_put(skb, sizeof(ra)), ra, sizeof(ra));
1818 1817
@@ -1823,7 +1822,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
1823 addrp = (struct in6_addr *) skb_put(skb, sizeof(struct in6_addr)); 1822 addrp = (struct in6_addr *) skb_put(skb, sizeof(struct in6_addr));
1824 ipv6_addr_copy(addrp, addr); 1823 ipv6_addr_copy(addrp, addr);
1825 1824
1826 hdr->icmp6_cksum = csum_ipv6_magic(&addr_buf, snd_addr, len, 1825 hdr->icmp6_cksum = csum_ipv6_magic(saddr, snd_addr, len,
1827 IPPROTO_ICMPV6, 1826 IPPROTO_ICMPV6,
1828 csum_partial((__u8 *) hdr, len, 0)); 1827 csum_partial((__u8 *) hdr, len, 0));
1829 1828
@@ -2311,24 +2310,19 @@ void ipv6_mc_init_dev(struct inet6_dev *idev)
2311void ipv6_mc_destroy_dev(struct inet6_dev *idev) 2310void ipv6_mc_destroy_dev(struct inet6_dev *idev)
2312{ 2311{
2313 struct ifmcaddr6 *i; 2312 struct ifmcaddr6 *i;
2314 struct in6_addr maddr;
2315 2313
2316 /* Deactivate timers */ 2314 /* Deactivate timers */
2317 ipv6_mc_down(idev); 2315 ipv6_mc_down(idev);
2318 2316
2319 /* Delete all-nodes address. */ 2317 /* Delete all-nodes address. */
2320 ipv6_addr_all_nodes(&maddr);
2321
2322 /* We cannot call ipv6_dev_mc_dec() directly, our caller in 2318 /* We cannot call ipv6_dev_mc_dec() directly, our caller in
2323 * addrconf.c has NULL'd out dev->ip6_ptr so in6_dev_get() will 2319 * addrconf.c has NULL'd out dev->ip6_ptr so in6_dev_get() will
2324 * fail. 2320 * fail.
2325 */ 2321 */
2326 __ipv6_dev_mc_dec(idev, &maddr); 2322 __ipv6_dev_mc_dec(idev, &in6addr_linklocal_allnodes);
2327 2323
2328 if (idev->cnf.forwarding) { 2324 if (idev->cnf.forwarding)
2329 ipv6_addr_all_routers(&maddr); 2325 __ipv6_dev_mc_dec(idev, &in6addr_linklocal_allrouters);
2330 __ipv6_dev_mc_dec(idev, &maddr);
2331 }
2332 2326
2333 write_lock_bh(&idev->lock); 2327 write_lock_bh(&idev->lock);
2334 while ((i = idev->mc_list) != NULL) { 2328 while ((i = idev->mc_list) != NULL) {