diff options
Diffstat (limited to 'net/ipv6/mcast.c')
-rw-r--r-- | net/ipv6/mcast.c | 60 |
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 */ |
128 | static DEFINE_RWLOCK(ipv6_sk_mc_lock); | 128 | static DEFINE_RWLOCK(ipv6_sk_mc_lock); |
129 | 129 | ||
130 | int __ipv6_dev_mc_dec(struct inet6_dev *idev, struct in6_addr *addr); | ||
131 | |||
132 | static void igmp6_join_group(struct ifmcaddr6 *ma); | 130 | static void igmp6_join_group(struct ifmcaddr6 *ma); |
133 | static void igmp6_leave_group(struct ifmcaddr6 *ma); | 131 | static void igmp6_leave_group(struct ifmcaddr6 *ma); |
134 | static void igmp6_timer_handler(unsigned long data); | 132 | static 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 | ||
180 | int ipv6_sock_mc_join(struct sock *sk, int ifindex, struct in6_addr *addr) | 178 | int 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 | */ |
255 | int ipv6_sock_mc_drop(struct sock *sk, int ifindex, struct in6_addr *addr) | 253 | int 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 | ||
667 | int inet6_mc_check(struct sock *sk, struct in6_addr *mc_addr, | 665 | int 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 | */ |
874 | int ipv6_dev_mc_inc(struct net_device *dev, struct in6_addr *addr) | 872 | int 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 | */ |
945 | int __ipv6_dev_mc_dec(struct inet6_dev *idev, struct in6_addr *addr) | 943 | int __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 | ||
970 | int ipv6_dev_mc_dec(struct net_device *dev, struct in6_addr *addr) | 968 | int 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 | */ |
1015 | int ipv6_chk_mcast_addr(struct net_device *dev, struct in6_addr *group, | 1013 | int 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) | |||
2311 | void ipv6_mc_destroy_dev(struct inet6_dev *idev) | 2310 | void 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) { |