.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * Multicast support for IPv6 |
---|
3 | 4 | * Linux INET6 implementation |
---|
.. | .. |
---|
6 | 7 | * Pedro Roque <roque@di.fc.ul.pt> |
---|
7 | 8 | * |
---|
8 | 9 | * Based on linux/ipv4/igmp.c and linux/ipv4/ip_sockglue.c |
---|
9 | | - * |
---|
10 | | - * This program is free software; you can redistribute it and/or |
---|
11 | | - * modify it under the terms of the GNU General Public License |
---|
12 | | - * as published by the Free Software Foundation; either version |
---|
13 | | - * 2 of the License, or (at your option) any later version. |
---|
14 | 10 | */ |
---|
15 | 11 | |
---|
16 | 12 | /* Changes: |
---|
.. | .. |
---|
461 | 457 | return err; |
---|
462 | 458 | } |
---|
463 | 459 | |
---|
464 | | -int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf) |
---|
| 460 | +int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf, |
---|
| 461 | + struct sockaddr_storage *list) |
---|
465 | 462 | { |
---|
466 | 463 | const struct in6_addr *group; |
---|
467 | 464 | struct ipv6_mc_socklist *pmc; |
---|
.. | .. |
---|
513 | 510 | goto done; |
---|
514 | 511 | } |
---|
515 | 512 | newpsl->sl_max = newpsl->sl_count = gsf->gf_numsrc; |
---|
516 | | - for (i = 0; i < newpsl->sl_count; ++i) { |
---|
| 513 | + for (i = 0; i < newpsl->sl_count; ++i, ++list) { |
---|
517 | 514 | struct sockaddr_in6 *psin6; |
---|
518 | 515 | |
---|
519 | | - psin6 = (struct sockaddr_in6 *)&gsf->gf_slist[i]; |
---|
| 516 | + psin6 = (struct sockaddr_in6 *)list; |
---|
520 | 517 | newpsl->sl_addr[i] = psin6->sin6_addr; |
---|
521 | 518 | } |
---|
522 | 519 | err = ip6_mc_add_src(idev, group, gsf->gf_fmode, |
---|
.. | .. |
---|
551 | 548 | } |
---|
552 | 549 | |
---|
553 | 550 | int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf, |
---|
554 | | - struct group_filter __user *optval, int __user *optlen) |
---|
| 551 | + struct sockaddr_storage *p) |
---|
555 | 552 | { |
---|
556 | 553 | int err, i, count, copycount; |
---|
557 | 554 | const struct in6_addr *group; |
---|
.. | .. |
---|
596 | 593 | |
---|
597 | 594 | copycount = count < gsf->gf_numsrc ? count : gsf->gf_numsrc; |
---|
598 | 595 | gsf->gf_numsrc = count; |
---|
599 | | - if (put_user(GROUP_FILTER_SIZE(copycount), optlen) || |
---|
600 | | - copy_to_user(optval, gsf, GROUP_FILTER_SIZE(0))) { |
---|
601 | | - return -EFAULT; |
---|
602 | | - } |
---|
603 | 596 | /* changes to psl require the socket lock, and a write lock |
---|
604 | 597 | * on pmc->sflock. We have the socket lock so reading here is safe. |
---|
605 | 598 | */ |
---|
606 | | - for (i = 0; i < copycount; i++) { |
---|
| 599 | + for (i = 0; i < copycount; i++, p++) { |
---|
607 | 600 | struct sockaddr_in6 *psin6; |
---|
608 | 601 | struct sockaddr_storage ss; |
---|
609 | 602 | |
---|
.. | .. |
---|
611 | 604 | memset(&ss, 0, sizeof(ss)); |
---|
612 | 605 | psin6->sin6_family = AF_INET6; |
---|
613 | 606 | psin6->sin6_addr = psl->sl_addr[i]; |
---|
614 | | - if (copy_to_user(&optval->gf_slist[i], &ss, sizeof(ss))) |
---|
| 607 | + if (copy_to_user(p, &ss, sizeof(ss))) |
---|
615 | 608 | return -EFAULT; |
---|
616 | 609 | } |
---|
617 | 610 | return 0; |
---|
.. | .. |
---|
636 | 629 | } |
---|
637 | 630 | if (!mc) { |
---|
638 | 631 | rcu_read_unlock(); |
---|
639 | | - return true; |
---|
| 632 | + return np->mc_all; |
---|
640 | 633 | } |
---|
641 | 634 | read_lock(&mc->sflock); |
---|
642 | 635 | psl = mc->sflist; |
---|
.. | .. |
---|
941 | 934 | { |
---|
942 | 935 | return __ipv6_dev_mc_inc(dev, addr, MCAST_EXCLUDE); |
---|
943 | 936 | } |
---|
| 937 | +EXPORT_SYMBOL(ipv6_dev_mc_inc); |
---|
944 | 938 | |
---|
945 | 939 | /* |
---|
946 | 940 | * device multicast group del |
---|
.. | .. |
---|
988 | 982 | |
---|
989 | 983 | return err; |
---|
990 | 984 | } |
---|
| 985 | +EXPORT_SYMBOL(ipv6_dev_mc_dec); |
---|
991 | 986 | |
---|
992 | 987 | /* |
---|
993 | 988 | * check if the interface/address pair is valid |
---|