| .. | .. |
|---|
| 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 |
|---|