diff options
Diffstat (limited to 'net/ipv6/mcast.c')
-rw-r--r-- | net/ipv6/mcast.c | 136 |
1 files changed, 73 insertions, 63 deletions
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index d1444b95ad7e..3e6ebcdb4779 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
@@ -82,7 +82,7 @@ static void *__mld2_query_bugs[] __attribute__((__unused__)) = { | |||
82 | static struct in6_addr mld2_all_mcr = MLD2_ALL_MCR_INIT; | 82 | static struct in6_addr mld2_all_mcr = MLD2_ALL_MCR_INIT; |
83 | 83 | ||
84 | /* Big mc list lock for all the sockets */ | 84 | /* Big mc list lock for all the sockets */ |
85 | static DEFINE_RWLOCK(ipv6_sk_mc_lock); | 85 | static DEFINE_SPINLOCK(ipv6_sk_mc_lock); |
86 | 86 | ||
87 | static void igmp6_join_group(struct ifmcaddr6 *ma); | 87 | static void igmp6_join_group(struct ifmcaddr6 *ma); |
88 | static void igmp6_leave_group(struct ifmcaddr6 *ma); | 88 | static void igmp6_leave_group(struct ifmcaddr6 *ma); |
@@ -92,16 +92,16 @@ static void mld_gq_timer_expire(unsigned long data); | |||
92 | static void mld_ifc_timer_expire(unsigned long data); | 92 | static void mld_ifc_timer_expire(unsigned long data); |
93 | static void mld_ifc_event(struct inet6_dev *idev); | 93 | static void mld_ifc_event(struct inet6_dev *idev); |
94 | static void mld_add_delrec(struct inet6_dev *idev, struct ifmcaddr6 *pmc); | 94 | static void mld_add_delrec(struct inet6_dev *idev, struct ifmcaddr6 *pmc); |
95 | static void mld_del_delrec(struct inet6_dev *idev, struct in6_addr *addr); | 95 | static void mld_del_delrec(struct inet6_dev *idev, const struct in6_addr *addr); |
96 | static void mld_clear_delrec(struct inet6_dev *idev); | 96 | static void mld_clear_delrec(struct inet6_dev *idev); |
97 | static int sf_setstate(struct ifmcaddr6 *pmc); | 97 | static int sf_setstate(struct ifmcaddr6 *pmc); |
98 | static void sf_markstate(struct ifmcaddr6 *pmc); | 98 | static void sf_markstate(struct ifmcaddr6 *pmc); |
99 | static void ip6_mc_clear_src(struct ifmcaddr6 *pmc); | 99 | static void ip6_mc_clear_src(struct ifmcaddr6 *pmc); |
100 | static int ip6_mc_del_src(struct inet6_dev *idev, struct in6_addr *pmca, | 100 | static 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); |
103 | static int ip6_mc_add_src(struct inet6_dev *idev, struct in6_addr *pmca, | 103 | static 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); |
106 | static int ip6_mc_leave_src(struct sock *sk, struct ipv6_mc_socklist *iml, | 106 | static int ip6_mc_leave_src(struct sock *sk, struct ipv6_mc_socklist *iml, |
107 | struct inet6_dev *idev); | 107 | struct inet6_dev *idev); |
@@ -123,6 +123,11 @@ int sysctl_mld_max_msf __read_mostly = IPV6_MLD_MAX_MSF; | |||
123 | * socket join on multicast group | 123 | * socket join on multicast group |
124 | */ | 124 | */ |
125 | 125 | ||
126 | #define for_each_pmc_rcu(np, pmc) \ | ||
127 | for (pmc = rcu_dereference(np->ipv6_mc_list); \ | ||
128 | pmc != NULL; \ | ||
129 | pmc = rcu_dereference(pmc->next)) | ||
130 | |||
126 | int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr) | 131 | int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr) |
127 | { | 132 | { |
128 | struct net_device *dev = NULL; | 133 | struct net_device *dev = NULL; |
@@ -134,15 +139,15 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr) | |||
134 | if (!ipv6_addr_is_multicast(addr)) | 139 | if (!ipv6_addr_is_multicast(addr)) |
135 | return -EINVAL; | 140 | return -EINVAL; |
136 | 141 | ||
137 | read_lock_bh(&ipv6_sk_mc_lock); | 142 | rcu_read_lock(); |
138 | for (mc_lst=np->ipv6_mc_list; mc_lst; mc_lst=mc_lst->next) { | 143 | for_each_pmc_rcu(np, mc_lst) { |
139 | if ((ifindex == 0 || mc_lst->ifindex == ifindex) && | 144 | if ((ifindex == 0 || mc_lst->ifindex == ifindex) && |
140 | ipv6_addr_equal(&mc_lst->addr, addr)) { | 145 | ipv6_addr_equal(&mc_lst->addr, addr)) { |
141 | read_unlock_bh(&ipv6_sk_mc_lock); | 146 | rcu_read_unlock(); |
142 | return -EADDRINUSE; | 147 | return -EADDRINUSE; |
143 | } | 148 | } |
144 | } | 149 | } |
145 | read_unlock_bh(&ipv6_sk_mc_lock); | 150 | rcu_read_unlock(); |
146 | 151 | ||
147 | mc_lst = sock_kmalloc(sk, sizeof(struct ipv6_mc_socklist), GFP_KERNEL); | 152 | mc_lst = sock_kmalloc(sk, sizeof(struct ipv6_mc_socklist), GFP_KERNEL); |
148 | 153 | ||
@@ -186,10 +191,10 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr) | |||
186 | return err; | 191 | return err; |
187 | } | 192 | } |
188 | 193 | ||
189 | write_lock_bh(&ipv6_sk_mc_lock); | 194 | spin_lock(&ipv6_sk_mc_lock); |
190 | mc_lst->next = np->ipv6_mc_list; | 195 | mc_lst->next = np->ipv6_mc_list; |
191 | np->ipv6_mc_list = mc_lst; | 196 | rcu_assign_pointer(np->ipv6_mc_list, mc_lst); |
192 | write_unlock_bh(&ipv6_sk_mc_lock); | 197 | spin_unlock(&ipv6_sk_mc_lock); |
193 | 198 | ||
194 | rcu_read_unlock(); | 199 | rcu_read_unlock(); |
195 | 200 | ||
@@ -202,17 +207,21 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr) | |||
202 | int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr) | 207 | int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr) |
203 | { | 208 | { |
204 | struct ipv6_pinfo *np = inet6_sk(sk); | 209 | struct ipv6_pinfo *np = inet6_sk(sk); |
205 | struct ipv6_mc_socklist *mc_lst, **lnk; | 210 | struct ipv6_mc_socklist *mc_lst; |
211 | struct ipv6_mc_socklist __rcu **lnk; | ||
206 | struct net *net = sock_net(sk); | 212 | struct net *net = sock_net(sk); |
207 | 213 | ||
208 | write_lock_bh(&ipv6_sk_mc_lock); | 214 | spin_lock(&ipv6_sk_mc_lock); |
209 | for (lnk = &np->ipv6_mc_list; (mc_lst = *lnk) !=NULL ; lnk = &mc_lst->next) { | 215 | for (lnk = &np->ipv6_mc_list; |
216 | (mc_lst = rcu_dereference_protected(*lnk, | ||
217 | lockdep_is_held(&ipv6_sk_mc_lock))) !=NULL ; | ||
218 | lnk = &mc_lst->next) { | ||
210 | if ((ifindex == 0 || mc_lst->ifindex == ifindex) && | 219 | if ((ifindex == 0 || mc_lst->ifindex == ifindex) && |
211 | ipv6_addr_equal(&mc_lst->addr, addr)) { | 220 | ipv6_addr_equal(&mc_lst->addr, addr)) { |
212 | struct net_device *dev; | 221 | struct net_device *dev; |
213 | 222 | ||
214 | *lnk = mc_lst->next; | 223 | *lnk = mc_lst->next; |
215 | write_unlock_bh(&ipv6_sk_mc_lock); | 224 | spin_unlock(&ipv6_sk_mc_lock); |
216 | 225 | ||
217 | rcu_read_lock(); | 226 | rcu_read_lock(); |
218 | dev = dev_get_by_index_rcu(net, mc_lst->ifindex); | 227 | dev = dev_get_by_index_rcu(net, mc_lst->ifindex); |
@@ -225,18 +234,19 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr) | |||
225 | } else | 234 | } else |
226 | (void) ip6_mc_leave_src(sk, mc_lst, NULL); | 235 | (void) ip6_mc_leave_src(sk, mc_lst, NULL); |
227 | rcu_read_unlock(); | 236 | rcu_read_unlock(); |
228 | sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); | 237 | atomic_sub(sizeof(*mc_lst), &sk->sk_omem_alloc); |
238 | kfree_rcu(mc_lst, rcu); | ||
229 | return 0; | 239 | return 0; |
230 | } | 240 | } |
231 | } | 241 | } |
232 | write_unlock_bh(&ipv6_sk_mc_lock); | 242 | spin_unlock(&ipv6_sk_mc_lock); |
233 | 243 | ||
234 | return -EADDRNOTAVAIL; | 244 | return -EADDRNOTAVAIL; |
235 | } | 245 | } |
236 | 246 | ||
237 | /* called with rcu_read_lock() */ | 247 | /* called with rcu_read_lock() */ |
238 | static struct inet6_dev *ip6_mc_find_dev_rcu(struct net *net, | 248 | static struct inet6_dev *ip6_mc_find_dev_rcu(struct net *net, |
239 | struct in6_addr *group, | 249 | const struct in6_addr *group, |
240 | int ifindex) | 250 | int ifindex) |
241 | { | 251 | { |
242 | struct net_device *dev = NULL; | 252 | struct net_device *dev = NULL; |
@@ -257,7 +267,7 @@ static struct inet6_dev *ip6_mc_find_dev_rcu(struct net *net, | |||
257 | return NULL; | 267 | return NULL; |
258 | idev = __in6_dev_get(dev); | 268 | idev = __in6_dev_get(dev); |
259 | if (!idev) | 269 | if (!idev) |
260 | return NULL;; | 270 | return NULL; |
261 | read_lock_bh(&idev->lock); | 271 | read_lock_bh(&idev->lock); |
262 | if (idev->dead) { | 272 | if (idev->dead) { |
263 | read_unlock_bh(&idev->lock); | 273 | read_unlock_bh(&idev->lock); |
@@ -272,12 +282,13 @@ void ipv6_sock_mc_close(struct sock *sk) | |||
272 | struct ipv6_mc_socklist *mc_lst; | 282 | struct ipv6_mc_socklist *mc_lst; |
273 | struct net *net = sock_net(sk); | 283 | struct net *net = sock_net(sk); |
274 | 284 | ||
275 | write_lock_bh(&ipv6_sk_mc_lock); | 285 | spin_lock(&ipv6_sk_mc_lock); |
276 | while ((mc_lst = np->ipv6_mc_list) != NULL) { | 286 | while ((mc_lst = rcu_dereference_protected(np->ipv6_mc_list, |
287 | lockdep_is_held(&ipv6_sk_mc_lock))) != NULL) { | ||
277 | struct net_device *dev; | 288 | struct net_device *dev; |
278 | 289 | ||
279 | np->ipv6_mc_list = mc_lst->next; | 290 | np->ipv6_mc_list = mc_lst->next; |
280 | write_unlock_bh(&ipv6_sk_mc_lock); | 291 | spin_unlock(&ipv6_sk_mc_lock); |
281 | 292 | ||
282 | rcu_read_lock(); | 293 | rcu_read_lock(); |
283 | dev = dev_get_by_index_rcu(net, mc_lst->ifindex); | 294 | dev = dev_get_by_index_rcu(net, mc_lst->ifindex); |
@@ -290,11 +301,13 @@ void ipv6_sock_mc_close(struct sock *sk) | |||
290 | } else | 301 | } else |
291 | (void) ip6_mc_leave_src(sk, mc_lst, NULL); | 302 | (void) ip6_mc_leave_src(sk, mc_lst, NULL); |
292 | rcu_read_unlock(); | 303 | rcu_read_unlock(); |
293 | sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); | ||
294 | 304 | ||
295 | write_lock_bh(&ipv6_sk_mc_lock); | 305 | atomic_sub(sizeof(*mc_lst), &sk->sk_omem_alloc); |
306 | kfree_rcu(mc_lst, rcu); | ||
307 | |||
308 | spin_lock(&ipv6_sk_mc_lock); | ||
296 | } | 309 | } |
297 | write_unlock_bh(&ipv6_sk_mc_lock); | 310 | spin_unlock(&ipv6_sk_mc_lock); |
298 | } | 311 | } |
299 | 312 | ||
300 | int ip6_mc_source(int add, int omode, struct sock *sk, | 313 | int ip6_mc_source(int add, int omode, struct sock *sk, |
@@ -302,7 +315,6 @@ int ip6_mc_source(int add, int omode, struct sock *sk, | |||
302 | { | 315 | { |
303 | struct in6_addr *source, *group; | 316 | struct in6_addr *source, *group; |
304 | struct ipv6_mc_socklist *pmc; | 317 | struct ipv6_mc_socklist *pmc; |
305 | struct net_device *dev; | ||
306 | struct inet6_dev *idev; | 318 | struct inet6_dev *idev; |
307 | struct ipv6_pinfo *inet6 = inet6_sk(sk); | 319 | struct ipv6_pinfo *inet6 = inet6_sk(sk); |
308 | struct ip6_sf_socklist *psl; | 320 | struct ip6_sf_socklist *psl; |
@@ -324,12 +336,10 @@ int ip6_mc_source(int add, int omode, struct sock *sk, | |||
324 | rcu_read_unlock(); | 336 | rcu_read_unlock(); |
325 | return -ENODEV; | 337 | return -ENODEV; |
326 | } | 338 | } |
327 | dev = idev->dev; | ||
328 | 339 | ||
329 | err = -EADDRNOTAVAIL; | 340 | err = -EADDRNOTAVAIL; |
330 | 341 | ||
331 | read_lock(&ipv6_sk_mc_lock); | 342 | for_each_pmc_rcu(inet6, pmc) { |
332 | for (pmc=inet6->ipv6_mc_list; pmc; pmc=pmc->next) { | ||
333 | if (pgsr->gsr_interface && pmc->ifindex != pgsr->gsr_interface) | 343 | if (pgsr->gsr_interface && pmc->ifindex != pgsr->gsr_interface) |
334 | continue; | 344 | continue; |
335 | if (ipv6_addr_equal(&pmc->addr, group)) | 345 | if (ipv6_addr_equal(&pmc->addr, group)) |
@@ -428,7 +438,6 @@ int ip6_mc_source(int add, int omode, struct sock *sk, | |||
428 | done: | 438 | done: |
429 | if (pmclocked) | 439 | if (pmclocked) |
430 | write_unlock(&pmc->sflock); | 440 | write_unlock(&pmc->sflock); |
431 | read_unlock(&ipv6_sk_mc_lock); | ||
432 | read_unlock_bh(&idev->lock); | 441 | read_unlock_bh(&idev->lock); |
433 | rcu_read_unlock(); | 442 | rcu_read_unlock(); |
434 | if (leavegroup) | 443 | if (leavegroup) |
@@ -438,9 +447,8 @@ done: | |||
438 | 447 | ||
439 | int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf) | 448 | int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf) |
440 | { | 449 | { |
441 | struct in6_addr *group; | 450 | const struct in6_addr *group; |
442 | struct ipv6_mc_socklist *pmc; | 451 | struct ipv6_mc_socklist *pmc; |
443 | struct net_device *dev; | ||
444 | struct inet6_dev *idev; | 452 | struct inet6_dev *idev; |
445 | struct ipv6_pinfo *inet6 = inet6_sk(sk); | 453 | struct ipv6_pinfo *inet6 = inet6_sk(sk); |
446 | struct ip6_sf_socklist *newpsl, *psl; | 454 | struct ip6_sf_socklist *newpsl, *psl; |
@@ -463,17 +471,15 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf) | |||
463 | rcu_read_unlock(); | 471 | rcu_read_unlock(); |
464 | return -ENODEV; | 472 | return -ENODEV; |
465 | } | 473 | } |
466 | dev = idev->dev; | ||
467 | 474 | ||
468 | err = 0; | 475 | err = 0; |
469 | read_lock(&ipv6_sk_mc_lock); | ||
470 | 476 | ||
471 | if (gsf->gf_fmode == MCAST_INCLUDE && gsf->gf_numsrc == 0) { | 477 | if (gsf->gf_fmode == MCAST_INCLUDE && gsf->gf_numsrc == 0) { |
472 | leavegroup = 1; | 478 | leavegroup = 1; |
473 | goto done; | 479 | goto done; |
474 | } | 480 | } |
475 | 481 | ||
476 | for (pmc=inet6->ipv6_mc_list; pmc; pmc=pmc->next) { | 482 | for_each_pmc_rcu(inet6, pmc) { |
477 | if (pmc->ifindex != gsf->gf_interface) | 483 | if (pmc->ifindex != gsf->gf_interface) |
478 | continue; | 484 | continue; |
479 | if (ipv6_addr_equal(&pmc->addr, group)) | 485 | if (ipv6_addr_equal(&pmc->addr, group)) |
@@ -521,7 +527,6 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf) | |||
521 | write_unlock(&pmc->sflock); | 527 | write_unlock(&pmc->sflock); |
522 | err = 0; | 528 | err = 0; |
523 | done: | 529 | done: |
524 | read_unlock(&ipv6_sk_mc_lock); | ||
525 | read_unlock_bh(&idev->lock); | 530 | read_unlock_bh(&idev->lock); |
526 | rcu_read_unlock(); | 531 | rcu_read_unlock(); |
527 | if (leavegroup) | 532 | if (leavegroup) |
@@ -533,10 +538,9 @@ int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf, | |||
533 | struct group_filter __user *optval, int __user *optlen) | 538 | struct group_filter __user *optval, int __user *optlen) |
534 | { | 539 | { |
535 | int err, i, count, copycount; | 540 | int err, i, count, copycount; |
536 | struct in6_addr *group; | 541 | const struct in6_addr *group; |
537 | struct ipv6_mc_socklist *pmc; | 542 | struct ipv6_mc_socklist *pmc; |
538 | struct inet6_dev *idev; | 543 | struct inet6_dev *idev; |
539 | struct net_device *dev; | ||
540 | struct ipv6_pinfo *inet6 = inet6_sk(sk); | 544 | struct ipv6_pinfo *inet6 = inet6_sk(sk); |
541 | struct ip6_sf_socklist *psl; | 545 | struct ip6_sf_socklist *psl; |
542 | struct net *net = sock_net(sk); | 546 | struct net *net = sock_net(sk); |
@@ -553,7 +557,6 @@ int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf, | |||
553 | rcu_read_unlock(); | 557 | rcu_read_unlock(); |
554 | return -ENODEV; | 558 | return -ENODEV; |
555 | } | 559 | } |
556 | dev = idev->dev; | ||
557 | 560 | ||
558 | err = -EADDRNOTAVAIL; | 561 | err = -EADDRNOTAVAIL; |
559 | /* | 562 | /* |
@@ -562,7 +565,7 @@ int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf, | |||
562 | * so reading the list is safe. | 565 | * so reading the list is safe. |
563 | */ | 566 | */ |
564 | 567 | ||
565 | for (pmc=inet6->ipv6_mc_list; pmc; pmc=pmc->next) { | 568 | for_each_pmc_rcu(inet6, pmc) { |
566 | if (pmc->ifindex != gsf->gf_interface) | 569 | if (pmc->ifindex != gsf->gf_interface) |
567 | continue; | 570 | continue; |
568 | if (ipv6_addr_equal(group, &pmc->addr)) | 571 | if (ipv6_addr_equal(group, &pmc->addr)) |
@@ -612,13 +615,13 @@ int inet6_mc_check(struct sock *sk, const struct in6_addr *mc_addr, | |||
612 | struct ip6_sf_socklist *psl; | 615 | struct ip6_sf_socklist *psl; |
613 | int rv = 1; | 616 | int rv = 1; |
614 | 617 | ||
615 | read_lock(&ipv6_sk_mc_lock); | 618 | rcu_read_lock(); |
616 | for (mc = np->ipv6_mc_list; mc; mc = mc->next) { | 619 | for_each_pmc_rcu(np, mc) { |
617 | if (ipv6_addr_equal(&mc->addr, mc_addr)) | 620 | if (ipv6_addr_equal(&mc->addr, mc_addr)) |
618 | break; | 621 | break; |
619 | } | 622 | } |
620 | if (!mc) { | 623 | if (!mc) { |
621 | read_unlock(&ipv6_sk_mc_lock); | 624 | rcu_read_unlock(); |
622 | return 1; | 625 | return 1; |
623 | } | 626 | } |
624 | read_lock(&mc->sflock); | 627 | read_lock(&mc->sflock); |
@@ -638,7 +641,7 @@ int inet6_mc_check(struct sock *sk, const struct in6_addr *mc_addr, | |||
638 | rv = 0; | 641 | rv = 0; |
639 | } | 642 | } |
640 | read_unlock(&mc->sflock); | 643 | read_unlock(&mc->sflock); |
641 | read_unlock(&ipv6_sk_mc_lock); | 644 | rcu_read_unlock(); |
642 | 645 | ||
643 | return rv; | 646 | return rv; |
644 | } | 647 | } |
@@ -745,7 +748,7 @@ static void mld_add_delrec(struct inet6_dev *idev, struct ifmcaddr6 *im) | |||
745 | spin_unlock_bh(&idev->mc_lock); | 748 | spin_unlock_bh(&idev->mc_lock); |
746 | } | 749 | } |
747 | 750 | ||
748 | static void mld_del_delrec(struct inet6_dev *idev, struct in6_addr *pmca) | 751 | static void mld_del_delrec(struct inet6_dev *idev, const struct in6_addr *pmca) |
749 | { | 752 | { |
750 | struct ifmcaddr6 *pmc, *pmc_prev; | 753 | struct ifmcaddr6 *pmc, *pmc_prev; |
751 | struct ip6_sf_list *psf, *psf_next; | 754 | struct ip6_sf_list *psf, *psf_next; |
@@ -1045,7 +1048,7 @@ static void igmp6_group_queried(struct ifmcaddr6 *ma, unsigned long resptime) | |||
1045 | 1048 | ||
1046 | /* mark EXCLUDE-mode sources */ | 1049 | /* mark EXCLUDE-mode sources */ |
1047 | static int mld_xmarksources(struct ifmcaddr6 *pmc, int nsrcs, | 1050 | static int mld_xmarksources(struct ifmcaddr6 *pmc, int nsrcs, |
1048 | struct in6_addr *srcs) | 1051 | const struct in6_addr *srcs) |
1049 | { | 1052 | { |
1050 | struct ip6_sf_list *psf; | 1053 | struct ip6_sf_list *psf; |
1051 | int i, scount; | 1054 | int i, scount; |
@@ -1073,7 +1076,7 @@ static int mld_xmarksources(struct ifmcaddr6 *pmc, int nsrcs, | |||
1073 | } | 1076 | } |
1074 | 1077 | ||
1075 | static int mld_marksources(struct ifmcaddr6 *pmc, int nsrcs, | 1078 | static int mld_marksources(struct ifmcaddr6 *pmc, int nsrcs, |
1076 | struct in6_addr *srcs) | 1079 | const struct in6_addr *srcs) |
1077 | { | 1080 | { |
1078 | struct ip6_sf_list *psf; | 1081 | struct ip6_sf_list *psf; |
1079 | int i, scount; | 1082 | int i, scount; |
@@ -1108,7 +1111,7 @@ int igmp6_event_query(struct sk_buff *skb) | |||
1108 | { | 1111 | { |
1109 | struct mld2_query *mlh2 = NULL; | 1112 | struct mld2_query *mlh2 = NULL; |
1110 | struct ifmcaddr6 *ma; | 1113 | struct ifmcaddr6 *ma; |
1111 | struct in6_addr *group; | 1114 | const struct in6_addr *group; |
1112 | unsigned long max_delay; | 1115 | unsigned long max_delay; |
1113 | struct inet6_dev *idev; | 1116 | struct inet6_dev *idev; |
1114 | struct mld_msg *mld; | 1117 | struct mld_msg *mld; |
@@ -1389,7 +1392,7 @@ static void mld_sendpack(struct sk_buff *skb) | |||
1389 | struct inet6_dev *idev; | 1392 | struct inet6_dev *idev; |
1390 | struct net *net = dev_net(skb->dev); | 1393 | struct net *net = dev_net(skb->dev); |
1391 | int err; | 1394 | int err; |
1392 | struct flowi fl; | 1395 | struct flowi6 fl6; |
1393 | struct dst_entry *dst; | 1396 | struct dst_entry *dst; |
1394 | 1397 | ||
1395 | rcu_read_lock(); | 1398 | rcu_read_lock(); |
@@ -1412,11 +1415,16 @@ static void mld_sendpack(struct sk_buff *skb) | |||
1412 | goto err_out; | 1415 | goto err_out; |
1413 | } | 1416 | } |
1414 | 1417 | ||
1415 | icmpv6_flow_init(net->ipv6.igmp_sk, &fl, ICMPV6_MLD2_REPORT, | 1418 | icmpv6_flow_init(net->ipv6.igmp_sk, &fl6, ICMPV6_MLD2_REPORT, |
1416 | &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, | 1419 | &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, |
1417 | skb->dev->ifindex); | 1420 | skb->dev->ifindex); |
1418 | 1421 | ||
1419 | 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 | } | ||
1420 | skb_dst_set(skb, dst); | 1428 | skb_dst_set(skb, dst); |
1421 | if (err) | 1429 | if (err) |
1422 | goto err_out; | 1430 | goto err_out; |
@@ -1719,7 +1727,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) | |||
1719 | u8 ra[8] = { IPPROTO_ICMPV6, 0, | 1727 | u8 ra[8] = { IPPROTO_ICMPV6, 0, |
1720 | IPV6_TLV_ROUTERALERT, 2, 0, 0, | 1728 | IPV6_TLV_ROUTERALERT, 2, 0, 0, |
1721 | IPV6_TLV_PADN, 0 }; | 1729 | IPV6_TLV_PADN, 0 }; |
1722 | struct flowi fl; | 1730 | struct flowi6 fl6; |
1723 | struct dst_entry *dst; | 1731 | struct dst_entry *dst; |
1724 | 1732 | ||
1725 | if (type == ICMPV6_MGM_REDUCTION) | 1733 | if (type == ICMPV6_MGM_REDUCTION) |
@@ -1779,13 +1787,15 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) | |||
1779 | goto err_out; | 1787 | goto err_out; |
1780 | } | 1788 | } |
1781 | 1789 | ||
1782 | icmpv6_flow_init(sk, &fl, type, | 1790 | icmpv6_flow_init(sk, &fl6, type, |
1783 | &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, | 1791 | &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, |
1784 | skb->dev->ifindex); | 1792 | skb->dev->ifindex); |
1785 | 1793 | ||
1786 | err = xfrm_lookup(net, &dst, &fl, NULL, 0); | 1794 | dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0); |
1787 | if (err) | 1795 | if (IS_ERR(dst)) { |
1796 | err = PTR_ERR(dst); | ||
1788 | goto err_out; | 1797 | goto err_out; |
1798 | } | ||
1789 | 1799 | ||
1790 | skb_dst_set(skb, dst); | 1800 | skb_dst_set(skb, dst); |
1791 | 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, |
@@ -1807,7 +1817,7 @@ err_out: | |||
1807 | } | 1817 | } |
1808 | 1818 | ||
1809 | static int ip6_mc_del1_src(struct ifmcaddr6 *pmc, int sfmode, | 1819 | static int ip6_mc_del1_src(struct ifmcaddr6 *pmc, int sfmode, |
1810 | struct in6_addr *psfsrc) | 1820 | const struct in6_addr *psfsrc) |
1811 | { | 1821 | { |
1812 | struct ip6_sf_list *psf, *psf_prev; | 1822 | struct ip6_sf_list *psf, *psf_prev; |
1813 | int rv = 0; | 1823 | int rv = 0; |
@@ -1843,8 +1853,8 @@ static int ip6_mc_del1_src(struct ifmcaddr6 *pmc, int sfmode, | |||
1843 | return rv; | 1853 | return rv; |
1844 | } | 1854 | } |
1845 | 1855 | ||
1846 | static int ip6_mc_del_src(struct inet6_dev *idev, struct in6_addr *pmca, | 1856 | static int ip6_mc_del_src(struct inet6_dev *idev, const struct in6_addr *pmca, |
1847 | int sfmode, int sfcount, struct in6_addr *psfsrc, | 1857 | int sfmode, int sfcount, const struct in6_addr *psfsrc, |
1848 | int delta) | 1858 | int delta) |
1849 | { | 1859 | { |
1850 | struct ifmcaddr6 *pmc; | 1860 | struct ifmcaddr6 *pmc; |
@@ -1904,7 +1914,7 @@ static int ip6_mc_del_src(struct inet6_dev *idev, struct in6_addr *pmca, | |||
1904 | * Add multicast single-source filter to the interface list | 1914 | * Add multicast single-source filter to the interface list |
1905 | */ | 1915 | */ |
1906 | static int ip6_mc_add1_src(struct ifmcaddr6 *pmc, int sfmode, | 1916 | static int ip6_mc_add1_src(struct ifmcaddr6 *pmc, int sfmode, |
1907 | struct in6_addr *psfsrc, int delta) | 1917 | const struct in6_addr *psfsrc, int delta) |
1908 | { | 1918 | { |
1909 | struct ip6_sf_list *psf, *psf_prev; | 1919 | struct ip6_sf_list *psf, *psf_prev; |
1910 | 1920 | ||
@@ -2007,8 +2017,8 @@ static int sf_setstate(struct ifmcaddr6 *pmc) | |||
2007 | /* | 2017 | /* |
2008 | * Add multicast source filter list to the interface list | 2018 | * Add multicast source filter list to the interface list |
2009 | */ | 2019 | */ |
2010 | static int ip6_mc_add_src(struct inet6_dev *idev, struct in6_addr *pmca, | 2020 | static int ip6_mc_add_src(struct inet6_dev *idev, const struct in6_addr *pmca, |
2011 | int sfmode, int sfcount, struct in6_addr *psfsrc, | 2021 | int sfmode, int sfcount, const struct in6_addr *psfsrc, |
2012 | int delta) | 2022 | int delta) |
2013 | { | 2023 | { |
2014 | struct ifmcaddr6 *pmc; | 2024 | struct ifmcaddr6 *pmc; |