^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Multicast support for IPv6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Linux INET6 implementation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Authors:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Pedro Roque <roque@di.fc.ul.pt>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Based on linux/ipv4/igmp.c and linux/ipv4/ip_sockglue.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) /* Changes:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * yoshfuji : fix format of router-alert option
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * YOSHIFUJI Hideaki @USAGI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * Fixed source address for MLD message based on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * <draft-ietf-magma-mld-source-05.txt>.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * YOSHIFUJI Hideaki @USAGI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * - Ignore Queries for invalid addresses.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * - MLD for link-local addresses.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * David L Stevens <dlstevens@us.ibm.com>:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * - MLDv2 support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/socket.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/sockios.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/jiffies.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/times.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/net.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/in.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/in6.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/netdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <linux/if_arp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <linux/route.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <linux/proc_fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <linux/seq_file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include <linux/pkt_sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #include <net/mld.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #include <linux/netfilter.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #include <linux/netfilter_ipv6.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #include <net/net_namespace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #include <net/sock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #include <net/snmp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #include <net/ipv6.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #include <net/protocol.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #include <net/if_inet6.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #include <net/ndisc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #include <net/addrconf.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #include <net/ip6_route.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #include <net/inet_common.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #include <net/ip6_checksum.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) /* Ensure that we have struct in6_addr aligned on 32bit word. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) static int __mld2_query_bugs[] __attribute__((__unused__)) = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) BUILD_BUG_ON_ZERO(offsetof(struct mld2_query, mld2q_srcs) % 4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) BUILD_BUG_ON_ZERO(offsetof(struct mld2_report, mld2r_grec) % 4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) BUILD_BUG_ON_ZERO(offsetof(struct mld2_grec, grec_mca) % 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) static struct in6_addr mld2_all_mcr = MLD2_ALL_MCR_INIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) static void igmp6_join_group(struct ifmcaddr6 *ma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) static void igmp6_leave_group(struct ifmcaddr6 *ma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) static void igmp6_timer_handler(struct timer_list *t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) static void mld_gq_timer_expire(struct timer_list *t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) static void mld_ifc_timer_expire(struct timer_list *t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) static void mld_ifc_event(struct inet6_dev *idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) static void mld_add_delrec(struct inet6_dev *idev, struct ifmcaddr6 *pmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static void mld_del_delrec(struct inet6_dev *idev, struct ifmcaddr6 *pmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) static void mld_clear_delrec(struct inet6_dev *idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) static bool mld_in_v1_mode(const struct inet6_dev *idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) static int sf_setstate(struct ifmcaddr6 *pmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) static void sf_markstate(struct ifmcaddr6 *pmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) static void ip6_mc_clear_src(struct ifmcaddr6 *pmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) static int ip6_mc_del_src(struct inet6_dev *idev, const struct in6_addr *pmca,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) int sfmode, int sfcount, const struct in6_addr *psfsrc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) int delta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) static int ip6_mc_add_src(struct inet6_dev *idev, const struct in6_addr *pmca,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) int sfmode, int sfcount, const struct in6_addr *psfsrc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) int delta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) static int ip6_mc_leave_src(struct sock *sk, struct ipv6_mc_socklist *iml,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) struct inet6_dev *idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) static int __ipv6_dev_mc_inc(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) const struct in6_addr *addr, unsigned int mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define MLD_QRV_DEFAULT 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) /* RFC3810, 9.2. Query Interval */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define MLD_QI_DEFAULT (125 * HZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) /* RFC3810, 9.3. Query Response Interval */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define MLD_QRI_DEFAULT (10 * HZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) /* RFC3810, 8.1 Query Version Distinctions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define MLD_V1_QUERY_LEN 24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #define MLD_V2_QUERY_LEN_MIN 28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #define IPV6_MLD_MAX_MSF 64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) int sysctl_mld_max_msf __read_mostly = IPV6_MLD_MAX_MSF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) int sysctl_mld_qrv __read_mostly = MLD_QRV_DEFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) * socket join on multicast group
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) #define for_each_pmc_rcu(np, pmc) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) for (pmc = rcu_dereference(np->ipv6_mc_list); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) pmc != NULL; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) pmc = rcu_dereference(pmc->next))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) static int unsolicited_report_interval(struct inet6_dev *idev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) int iv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) if (mld_in_v1_mode(idev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) iv = idev->cnf.mldv1_unsolicited_report_interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) iv = idev->cnf.mldv2_unsolicited_report_interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) return iv > 0 ? iv : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) static int __ipv6_sock_mc_join(struct sock *sk, int ifindex,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) const struct in6_addr *addr, unsigned int mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) struct net_device *dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) struct ipv6_mc_socklist *mc_lst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) struct ipv6_pinfo *np = inet6_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) struct net *net = sock_net(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) if (!ipv6_addr_is_multicast(addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) for_each_pmc_rcu(np, mc_lst) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) if ((ifindex == 0 || mc_lst->ifindex == ifindex) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) ipv6_addr_equal(&mc_lst->addr, addr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) return -EADDRINUSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) mc_lst = sock_kmalloc(sk, sizeof(struct ipv6_mc_socklist), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) if (!mc_lst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) mc_lst->next = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) mc_lst->addr = *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) if (ifindex == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) struct rt6_info *rt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) rt = rt6_lookup(net, addr, NULL, 0, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) if (rt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) dev = rt->dst.dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) ip6_rt_put(rt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) dev = __dev_get_by_index(net, ifindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) if (!dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) sock_kfree_s(sk, mc_lst, sizeof(*mc_lst));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) mc_lst->ifindex = dev->ifindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) mc_lst->sfmode = mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) rwlock_init(&mc_lst->sflock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) mc_lst->sflist = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) * now add/increase the group membership on the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) err = __ipv6_dev_mc_inc(dev, addr, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) sock_kfree_s(sk, mc_lst, sizeof(*mc_lst));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) mc_lst->next = np->ipv6_mc_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) rcu_assign_pointer(np->ipv6_mc_list, mc_lst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) return __ipv6_sock_mc_join(sk, ifindex, addr, MCAST_EXCLUDE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) EXPORT_SYMBOL(ipv6_sock_mc_join);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) int ipv6_sock_mc_join_ssm(struct sock *sk, int ifindex,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) const struct in6_addr *addr, unsigned int mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) return __ipv6_sock_mc_join(sk, ifindex, addr, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) * socket leave on multicast group
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) struct ipv6_pinfo *np = inet6_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) struct ipv6_mc_socklist *mc_lst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) struct ipv6_mc_socklist __rcu **lnk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) struct net *net = sock_net(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) if (!ipv6_addr_is_multicast(addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) for (lnk = &np->ipv6_mc_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) (mc_lst = rtnl_dereference(*lnk)) != NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) lnk = &mc_lst->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if ((ifindex == 0 || mc_lst->ifindex == ifindex) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) ipv6_addr_equal(&mc_lst->addr, addr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) *lnk = mc_lst->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) dev = __dev_get_by_index(net, mc_lst->ifindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) if (dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) struct inet6_dev *idev = __in6_dev_get(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) (void) ip6_mc_leave_src(sk, mc_lst, idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) if (idev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) __ipv6_dev_mc_dec(idev, &mc_lst->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) (void) ip6_mc_leave_src(sk, mc_lst, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) atomic_sub(sizeof(*mc_lst), &sk->sk_omem_alloc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) kfree_rcu(mc_lst, rcu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) return -EADDRNOTAVAIL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) EXPORT_SYMBOL(ipv6_sock_mc_drop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) /* called with rcu_read_lock() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) static struct inet6_dev *ip6_mc_find_dev_rcu(struct net *net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) const struct in6_addr *group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) int ifindex)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) struct net_device *dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) struct inet6_dev *idev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) if (ifindex == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) struct rt6_info *rt = rt6_lookup(net, group, NULL, 0, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) if (rt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) dev = rt->dst.dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) ip6_rt_put(rt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) dev = dev_get_by_index_rcu(net, ifindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) if (!dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) idev = __in6_dev_get(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) if (!idev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) read_lock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) if (idev->dead) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) read_unlock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) return idev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) void __ipv6_sock_mc_close(struct sock *sk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) struct ipv6_pinfo *np = inet6_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) struct ipv6_mc_socklist *mc_lst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) struct net *net = sock_net(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) while ((mc_lst = rtnl_dereference(np->ipv6_mc_list)) != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) np->ipv6_mc_list = mc_lst->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) dev = __dev_get_by_index(net, mc_lst->ifindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) if (dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) struct inet6_dev *idev = __in6_dev_get(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) (void) ip6_mc_leave_src(sk, mc_lst, idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) if (idev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) __ipv6_dev_mc_dec(idev, &mc_lst->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) (void) ip6_mc_leave_src(sk, mc_lst, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) atomic_sub(sizeof(*mc_lst), &sk->sk_omem_alloc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) kfree_rcu(mc_lst, rcu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) void ipv6_sock_mc_close(struct sock *sk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) struct ipv6_pinfo *np = inet6_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) if (!rcu_access_pointer(np->ipv6_mc_list))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) __ipv6_sock_mc_close(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) int ip6_mc_source(int add, int omode, struct sock *sk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) struct group_source_req *pgsr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) struct in6_addr *source, *group;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) struct ipv6_mc_socklist *pmc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) struct inet6_dev *idev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) struct ipv6_pinfo *inet6 = inet6_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) struct ip6_sf_socklist *psl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) struct net *net = sock_net(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) int i, j, rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) int leavegroup = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) int pmclocked = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) source = &((struct sockaddr_in6 *)&pgsr->gsr_source)->sin6_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) group = &((struct sockaddr_in6 *)&pgsr->gsr_group)->sin6_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) if (!ipv6_addr_is_multicast(group))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) idev = ip6_mc_find_dev_rcu(net, group, pgsr->gsr_interface);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) if (!idev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) err = -EADDRNOTAVAIL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) for_each_pmc_rcu(inet6, pmc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) if (pgsr->gsr_interface && pmc->ifindex != pgsr->gsr_interface)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) if (ipv6_addr_equal(&pmc->addr, group))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) if (!pmc) { /* must have a prior join */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) /* if a source filter was set, must be the same mode as before */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) if (pmc->sflist) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) if (pmc->sfmode != omode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) } else if (pmc->sfmode != omode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) /* allow mode switches for empty-set filters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) ip6_mc_add_src(idev, group, omode, 0, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) ip6_mc_del_src(idev, group, pmc->sfmode, 0, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) pmc->sfmode = omode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) write_lock(&pmc->sflock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) pmclocked = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) psl = pmc->sflist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) if (!add) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) if (!psl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) goto done; /* err = -EADDRNOTAVAIL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) rv = !0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) for (i = 0; i < psl->sl_count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) rv = !ipv6_addr_equal(&psl->sl_addr[i], source);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) if (rv == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) if (rv) /* source not found */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) goto done; /* err = -EADDRNOTAVAIL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) /* special case - (INCLUDE, empty) == LEAVE_GROUP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) if (psl->sl_count == 1 && omode == MCAST_INCLUDE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) leavegroup = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) /* update the interface filter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) ip6_mc_del_src(idev, group, omode, 1, source, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) for (j = i+1; j < psl->sl_count; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) psl->sl_addr[j-1] = psl->sl_addr[j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) psl->sl_count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) /* else, add a new source to the filter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) if (psl && psl->sl_count >= sysctl_mld_max_msf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) err = -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) if (!psl || psl->sl_count == psl->sl_max) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) struct ip6_sf_socklist *newpsl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) int count = IP6_SFBLOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) if (psl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) count += psl->sl_max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) newpsl = sock_kmalloc(sk, IP6_SFLSIZE(count), GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) if (!newpsl) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) err = -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) newpsl->sl_max = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) newpsl->sl_count = count - IP6_SFBLOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) if (psl) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) for (i = 0; i < psl->sl_count; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) newpsl->sl_addr[i] = psl->sl_addr[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) sock_kfree_s(sk, psl, IP6_SFLSIZE(psl->sl_max));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) pmc->sflist = psl = newpsl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) rv = 1; /* > 0 for insert logic below if sl_count is 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) for (i = 0; i < psl->sl_count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) rv = !ipv6_addr_equal(&psl->sl_addr[i], source);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) if (rv == 0) /* There is an error in the address. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) for (j = psl->sl_count-1; j >= i; j--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) psl->sl_addr[j+1] = psl->sl_addr[j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) psl->sl_addr[i] = *source;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) psl->sl_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) /* update the interface list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) ip6_mc_add_src(idev, group, omode, 1, source, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) if (pmclocked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) write_unlock(&pmc->sflock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) read_unlock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) if (leavegroup)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) err = ipv6_sock_mc_drop(sk, pgsr->gsr_interface, group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) struct sockaddr_storage *list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) const struct in6_addr *group;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) struct ipv6_mc_socklist *pmc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) struct inet6_dev *idev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) struct ipv6_pinfo *inet6 = inet6_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) struct ip6_sf_socklist *newpsl, *psl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) struct net *net = sock_net(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) int leavegroup = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) int i, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) group = &((struct sockaddr_in6 *)&gsf->gf_group)->sin6_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) if (!ipv6_addr_is_multicast(group))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) if (gsf->gf_fmode != MCAST_INCLUDE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) gsf->gf_fmode != MCAST_EXCLUDE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) idev = ip6_mc_find_dev_rcu(net, group, gsf->gf_interface);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) if (!idev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) if (gsf->gf_fmode == MCAST_INCLUDE && gsf->gf_numsrc == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) leavegroup = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) for_each_pmc_rcu(inet6, pmc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) if (pmc->ifindex != gsf->gf_interface)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) if (ipv6_addr_equal(&pmc->addr, group))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) if (!pmc) { /* must have a prior join */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) if (gsf->gf_numsrc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) newpsl = sock_kmalloc(sk, IP6_SFLSIZE(gsf->gf_numsrc),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) if (!newpsl) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) err = -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) newpsl->sl_max = newpsl->sl_count = gsf->gf_numsrc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) for (i = 0; i < newpsl->sl_count; ++i, ++list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) struct sockaddr_in6 *psin6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) psin6 = (struct sockaddr_in6 *)list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) newpsl->sl_addr[i] = psin6->sin6_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) err = ip6_mc_add_src(idev, group, gsf->gf_fmode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) newpsl->sl_count, newpsl->sl_addr, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) sock_kfree_s(sk, newpsl, IP6_SFLSIZE(newpsl->sl_max));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) newpsl = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) (void) ip6_mc_add_src(idev, group, gsf->gf_fmode, 0, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) write_lock(&pmc->sflock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) psl = pmc->sflist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) if (psl) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) (void) ip6_mc_del_src(idev, group, pmc->sfmode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) psl->sl_count, psl->sl_addr, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) sock_kfree_s(sk, psl, IP6_SFLSIZE(psl->sl_max));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) (void) ip6_mc_del_src(idev, group, pmc->sfmode, 0, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) pmc->sflist = newpsl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) pmc->sfmode = gsf->gf_fmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) write_unlock(&pmc->sflock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) read_unlock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) if (leavegroup)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) err = ipv6_sock_mc_drop(sk, gsf->gf_interface, group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) struct sockaddr_storage *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) int err, i, count, copycount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) const struct in6_addr *group;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) struct ipv6_mc_socklist *pmc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) struct inet6_dev *idev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) struct ipv6_pinfo *inet6 = inet6_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) struct ip6_sf_socklist *psl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) struct net *net = sock_net(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) group = &((struct sockaddr_in6 *)&gsf->gf_group)->sin6_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) if (!ipv6_addr_is_multicast(group))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) idev = ip6_mc_find_dev_rcu(net, group, gsf->gf_interface);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) if (!idev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) err = -EADDRNOTAVAIL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) /* changes to the ipv6_mc_list require the socket lock and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) * rtnl lock. We have the socket lock and rcu read lock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) * so reading the list is safe.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) for_each_pmc_rcu(inet6, pmc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) if (pmc->ifindex != gsf->gf_interface)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) if (ipv6_addr_equal(group, &pmc->addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) if (!pmc) /* must have a prior join */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) gsf->gf_fmode = pmc->sfmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) psl = pmc->sflist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) count = psl ? psl->sl_count : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) read_unlock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) copycount = count < gsf->gf_numsrc ? count : gsf->gf_numsrc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) gsf->gf_numsrc = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) /* changes to psl require the socket lock, and a write lock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) * on pmc->sflock. We have the socket lock so reading here is safe.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) for (i = 0; i < copycount; i++, p++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) struct sockaddr_in6 *psin6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) struct sockaddr_storage ss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) psin6 = (struct sockaddr_in6 *)&ss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) memset(&ss, 0, sizeof(ss));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) psin6->sin6_family = AF_INET6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) psin6->sin6_addr = psl->sl_addr[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) if (copy_to_user(p, &ss, sizeof(ss)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) read_unlock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) bool inet6_mc_check(struct sock *sk, const struct in6_addr *mc_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) const struct in6_addr *src_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) struct ipv6_pinfo *np = inet6_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) struct ipv6_mc_socklist *mc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) struct ip6_sf_socklist *psl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) bool rv = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) for_each_pmc_rcu(np, mc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) if (ipv6_addr_equal(&mc->addr, mc_addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) if (!mc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) return np->mc_all;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) read_lock(&mc->sflock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) psl = mc->sflist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) if (!psl) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) rv = mc->sfmode == MCAST_EXCLUDE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) for (i = 0; i < psl->sl_count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) if (ipv6_addr_equal(&psl->sl_addr[i], src_addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) if (mc->sfmode == MCAST_INCLUDE && i >= psl->sl_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) rv = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) if (mc->sfmode == MCAST_EXCLUDE && i < psl->sl_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) rv = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) read_unlock(&mc->sflock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) static void igmp6_group_added(struct ifmcaddr6 *mc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) struct net_device *dev = mc->idev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) char buf[MAX_ADDR_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) if (IPV6_ADDR_MC_SCOPE(&mc->mca_addr) <
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) IPV6_ADDR_SCOPE_LINKLOCAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) spin_lock_bh(&mc->mca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) if (!(mc->mca_flags&MAF_LOADED)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) mc->mca_flags |= MAF_LOADED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) if (ndisc_mc_map(&mc->mca_addr, buf, dev, 0) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) dev_mc_add(dev, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) spin_unlock_bh(&mc->mca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) if (!(dev->flags & IFF_UP) || (mc->mca_flags & MAF_NOREPORT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) if (mld_in_v1_mode(mc->idev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) igmp6_join_group(mc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) /* else v2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) /* Based on RFC3810 6.1, for newly added INCLUDE SSM, we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) * should not send filter-mode change record as the mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) * should be from IN() to IN(A).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) if (mc->mca_sfmode == MCAST_EXCLUDE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) mc->mca_crcount = mc->idev->mc_qrv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) mld_ifc_event(mc->idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) static void igmp6_group_dropped(struct ifmcaddr6 *mc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) struct net_device *dev = mc->idev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) char buf[MAX_ADDR_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) if (IPV6_ADDR_MC_SCOPE(&mc->mca_addr) <
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) IPV6_ADDR_SCOPE_LINKLOCAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) spin_lock_bh(&mc->mca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) if (mc->mca_flags&MAF_LOADED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) mc->mca_flags &= ~MAF_LOADED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) if (ndisc_mc_map(&mc->mca_addr, buf, dev, 0) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) dev_mc_del(dev, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) spin_unlock_bh(&mc->mca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) if (mc->mca_flags & MAF_NOREPORT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) if (!mc->idev->dead)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) igmp6_leave_group(mc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) spin_lock_bh(&mc->mca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) if (del_timer(&mc->mca_timer))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) refcount_dec(&mc->mca_refcnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) spin_unlock_bh(&mc->mca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) * deleted ifmcaddr6 manipulation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) static void mld_add_delrec(struct inet6_dev *idev, struct ifmcaddr6 *im)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) struct ifmcaddr6 *pmc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) /* this is an "ifmcaddr6" for convenience; only the fields below
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) * are actually used. In particular, the refcnt and users are not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) * used for management of the delete list. Using the same structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) * for deleted items allows change reports to use common code with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) * non-deleted or query-response MCA's.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) pmc = kzalloc(sizeof(*pmc), GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) if (!pmc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) spin_lock_bh(&im->mca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) spin_lock_init(&pmc->mca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) pmc->idev = im->idev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) in6_dev_hold(idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) pmc->mca_addr = im->mca_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) pmc->mca_crcount = idev->mc_qrv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) pmc->mca_sfmode = im->mca_sfmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) if (pmc->mca_sfmode == MCAST_INCLUDE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) struct ip6_sf_list *psf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) pmc->mca_tomb = im->mca_tomb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) pmc->mca_sources = im->mca_sources;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) im->mca_tomb = im->mca_sources = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) for (psf = pmc->mca_sources; psf; psf = psf->sf_next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) psf->sf_crcount = pmc->mca_crcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) spin_unlock_bh(&im->mca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) spin_lock_bh(&idev->mc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) pmc->next = idev->mc_tomb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) idev->mc_tomb = pmc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) spin_unlock_bh(&idev->mc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) static void mld_del_delrec(struct inet6_dev *idev, struct ifmcaddr6 *im)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) struct ifmcaddr6 *pmc, *pmc_prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) struct ip6_sf_list *psf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) struct in6_addr *pmca = &im->mca_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) spin_lock_bh(&idev->mc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) pmc_prev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) for (pmc = idev->mc_tomb; pmc; pmc = pmc->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) if (ipv6_addr_equal(&pmc->mca_addr, pmca))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) pmc_prev = pmc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) if (pmc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) if (pmc_prev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) pmc_prev->next = pmc->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) idev->mc_tomb = pmc->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) spin_unlock_bh(&idev->mc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) spin_lock_bh(&im->mca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) if (pmc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) im->idev = pmc->idev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) if (im->mca_sfmode == MCAST_INCLUDE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) swap(im->mca_tomb, pmc->mca_tomb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) swap(im->mca_sources, pmc->mca_sources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) for (psf = im->mca_sources; psf; psf = psf->sf_next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) psf->sf_crcount = idev->mc_qrv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) im->mca_crcount = idev->mc_qrv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) in6_dev_put(pmc->idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) ip6_mc_clear_src(pmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) kfree(pmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) spin_unlock_bh(&im->mca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) static void mld_clear_delrec(struct inet6_dev *idev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) struct ifmcaddr6 *pmc, *nextpmc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) spin_lock_bh(&idev->mc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) pmc = idev->mc_tomb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) idev->mc_tomb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) spin_unlock_bh(&idev->mc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) for (; pmc; pmc = nextpmc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) nextpmc = pmc->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) ip6_mc_clear_src(pmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) in6_dev_put(pmc->idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) kfree(pmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) /* clear dead sources, too */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) read_lock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) for (pmc = idev->mc_list; pmc; pmc = pmc->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) struct ip6_sf_list *psf, *psf_next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) spin_lock_bh(&pmc->mca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) psf = pmc->mca_tomb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) pmc->mca_tomb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) spin_unlock_bh(&pmc->mca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) for (; psf; psf = psf_next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) psf_next = psf->sf_next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) kfree(psf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) read_unlock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) static void mca_get(struct ifmcaddr6 *mc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) refcount_inc(&mc->mca_refcnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) static void ma_put(struct ifmcaddr6 *mc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) if (refcount_dec_and_test(&mc->mca_refcnt)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) in6_dev_put(mc->idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) kfree(mc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) static struct ifmcaddr6 *mca_alloc(struct inet6_dev *idev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) const struct in6_addr *addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) unsigned int mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) struct ifmcaddr6 *mc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) mc = kzalloc(sizeof(*mc), GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) if (!mc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) timer_setup(&mc->mca_timer, igmp6_timer_handler, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) mc->mca_addr = *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) mc->idev = idev; /* reference taken by caller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) mc->mca_users = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) /* mca_stamp should be updated upon changes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) mc->mca_cstamp = mc->mca_tstamp = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) refcount_set(&mc->mca_refcnt, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) spin_lock_init(&mc->mca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) mc->mca_sfmode = mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) mc->mca_sfcount[mode] = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) if (ipv6_addr_is_ll_all_nodes(&mc->mca_addr) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) IPV6_ADDR_MC_SCOPE(&mc->mca_addr) < IPV6_ADDR_SCOPE_LINKLOCAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) mc->mca_flags |= MAF_NOREPORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) return mc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) * device multicast group inc (add if not found)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) static int __ipv6_dev_mc_inc(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) const struct in6_addr *addr, unsigned int mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) struct ifmcaddr6 *mc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) struct inet6_dev *idev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) /* we need to take a reference on idev */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) idev = in6_dev_get(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) if (!idev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) write_lock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) if (idev->dead) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) write_unlock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) in6_dev_put(idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) for (mc = idev->mc_list; mc; mc = mc->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) if (ipv6_addr_equal(&mc->mca_addr, addr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) mc->mca_users++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) write_unlock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) ip6_mc_add_src(idev, &mc->mca_addr, mode, 0, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) in6_dev_put(idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) mc = mca_alloc(idev, addr, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) if (!mc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) write_unlock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) in6_dev_put(idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) mc->next = idev->mc_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) idev->mc_list = mc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) /* Hold this for the code below before we unlock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) * it is already exposed via idev->mc_list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) mca_get(mc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) write_unlock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) mld_del_delrec(idev, mc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) igmp6_group_added(mc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) ma_put(mc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) int ipv6_dev_mc_inc(struct net_device *dev, const struct in6_addr *addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) return __ipv6_dev_mc_inc(dev, addr, MCAST_EXCLUDE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) EXPORT_SYMBOL(ipv6_dev_mc_inc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) * device multicast group del
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) int __ipv6_dev_mc_dec(struct inet6_dev *idev, const struct in6_addr *addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) struct ifmcaddr6 *ma, **map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) write_lock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) for (map = &idev->mc_list; (ma = *map) != NULL; map = &ma->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) if (ipv6_addr_equal(&ma->mca_addr, addr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) if (--ma->mca_users == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) *map = ma->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) write_unlock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) igmp6_group_dropped(ma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) ip6_mc_clear_src(ma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) ma_put(ma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) write_unlock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) write_unlock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) int ipv6_dev_mc_dec(struct net_device *dev, const struct in6_addr *addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) struct inet6_dev *idev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) idev = __in6_dev_get(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) if (!idev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) err = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) err = __ipv6_dev_mc_dec(idev, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) EXPORT_SYMBOL(ipv6_dev_mc_dec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) * check if the interface/address pair is valid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) bool ipv6_chk_mcast_addr(struct net_device *dev, const struct in6_addr *group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) const struct in6_addr *src_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) struct inet6_dev *idev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) struct ifmcaddr6 *mc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) bool rv = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) idev = __in6_dev_get(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) if (idev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) read_lock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) for (mc = idev->mc_list; mc; mc = mc->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) if (ipv6_addr_equal(&mc->mca_addr, group))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) if (mc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) if (src_addr && !ipv6_addr_any(src_addr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) struct ip6_sf_list *psf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) spin_lock_bh(&mc->mca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) for (psf = mc->mca_sources; psf; psf = psf->sf_next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) if (ipv6_addr_equal(&psf->sf_addr, src_addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) if (psf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) rv = psf->sf_count[MCAST_INCLUDE] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) psf->sf_count[MCAST_EXCLUDE] !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) mc->mca_sfcount[MCAST_EXCLUDE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) rv = mc->mca_sfcount[MCAST_EXCLUDE] != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) spin_unlock_bh(&mc->mca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) rv = true; /* don't filter unspecified source */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) read_unlock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) static void mld_gq_start_timer(struct inet6_dev *idev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) unsigned long tv = prandom_u32() % idev->mc_maxdelay;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) idev->mc_gq_running = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) if (!mod_timer(&idev->mc_gq_timer, jiffies+tv+2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) in6_dev_hold(idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) static void mld_gq_stop_timer(struct inet6_dev *idev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) idev->mc_gq_running = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) if (del_timer(&idev->mc_gq_timer))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) __in6_dev_put(idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) static void mld_ifc_start_timer(struct inet6_dev *idev, unsigned long delay)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) unsigned long tv = prandom_u32() % delay;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) if (!mod_timer(&idev->mc_ifc_timer, jiffies+tv+2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) in6_dev_hold(idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) static void mld_ifc_stop_timer(struct inet6_dev *idev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) idev->mc_ifc_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) if (del_timer(&idev->mc_ifc_timer))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) __in6_dev_put(idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) static void mld_dad_start_timer(struct inet6_dev *idev, unsigned long delay)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) unsigned long tv = prandom_u32() % delay;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) if (!mod_timer(&idev->mc_dad_timer, jiffies+tv+2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) in6_dev_hold(idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) static void mld_dad_stop_timer(struct inet6_dev *idev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) if (del_timer(&idev->mc_dad_timer))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) __in6_dev_put(idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) * IGMP handling (alias multicast ICMPv6 messages)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) static void igmp6_group_queried(struct ifmcaddr6 *ma, unsigned long resptime)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) unsigned long delay = resptime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) /* Do not start timer for these addresses */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) if (ipv6_addr_is_ll_all_nodes(&ma->mca_addr) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) IPV6_ADDR_MC_SCOPE(&ma->mca_addr) < IPV6_ADDR_SCOPE_LINKLOCAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) if (del_timer(&ma->mca_timer)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) refcount_dec(&ma->mca_refcnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) delay = ma->mca_timer.expires - jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) if (delay >= resptime)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) delay = prandom_u32() % resptime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) ma->mca_timer.expires = jiffies + delay;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) if (!mod_timer(&ma->mca_timer, jiffies + delay))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) refcount_inc(&ma->mca_refcnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) ma->mca_flags |= MAF_TIMER_RUNNING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) /* mark EXCLUDE-mode sources */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) static bool mld_xmarksources(struct ifmcaddr6 *pmc, int nsrcs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) const struct in6_addr *srcs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) struct ip6_sf_list *psf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) int i, scount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) scount = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) for (psf = pmc->mca_sources; psf; psf = psf->sf_next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) if (scount == nsrcs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) for (i = 0; i < nsrcs; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) /* skip inactive filters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) if (psf->sf_count[MCAST_INCLUDE] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) pmc->mca_sfcount[MCAST_EXCLUDE] !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) psf->sf_count[MCAST_EXCLUDE])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) if (ipv6_addr_equal(&srcs[i], &psf->sf_addr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) scount++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) pmc->mca_flags &= ~MAF_GSQUERY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) if (scount == nsrcs) /* all sources excluded */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) static bool mld_marksources(struct ifmcaddr6 *pmc, int nsrcs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) const struct in6_addr *srcs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) struct ip6_sf_list *psf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) int i, scount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) if (pmc->mca_sfmode == MCAST_EXCLUDE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) return mld_xmarksources(pmc, nsrcs, srcs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) /* mark INCLUDE-mode sources */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) scount = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) for (psf = pmc->mca_sources; psf; psf = psf->sf_next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) if (scount == nsrcs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) for (i = 0; i < nsrcs; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) if (ipv6_addr_equal(&srcs[i], &psf->sf_addr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) psf->sf_gsresp = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) scount++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) if (!scount) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) pmc->mca_flags &= ~MAF_GSQUERY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) pmc->mca_flags |= MAF_GSQUERY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) static int mld_force_mld_version(const struct inet6_dev *idev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) /* Normally, both are 0 here. If enforcement to a particular is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) * being used, individual device enforcement will have a lower
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) * precedence over 'all' device (.../conf/all/force_mld_version).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) if (dev_net(idev->dev)->ipv6.devconf_all->force_mld_version != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) return dev_net(idev->dev)->ipv6.devconf_all->force_mld_version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) return idev->cnf.force_mld_version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) static bool mld_in_v2_mode_only(const struct inet6_dev *idev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) return mld_force_mld_version(idev) == 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) static bool mld_in_v1_mode_only(const struct inet6_dev *idev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) return mld_force_mld_version(idev) == 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) static bool mld_in_v1_mode(const struct inet6_dev *idev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) if (mld_in_v2_mode_only(idev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) if (mld_in_v1_mode_only(idev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) if (idev->mc_v1_seen && time_before(jiffies, idev->mc_v1_seen))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) static void mld_set_v1_mode(struct inet6_dev *idev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) /* RFC3810, relevant sections:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) * - 9.1. Robustness Variable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) * - 9.2. Query Interval
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) * - 9.3. Query Response Interval
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) * - 9.12. Older Version Querier Present Timeout
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) unsigned long switchback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) switchback = (idev->mc_qrv * idev->mc_qi) + idev->mc_qri;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) idev->mc_v1_seen = jiffies + switchback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) static void mld_update_qrv(struct inet6_dev *idev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) const struct mld2_query *mlh2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) /* RFC3810, relevant sections:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) * - 5.1.8. QRV (Querier's Robustness Variable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) * - 9.1. Robustness Variable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) /* The value of the Robustness Variable MUST NOT be zero,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) * and SHOULD NOT be one. Catch this here if we ever run
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) * into such a case in future.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) const int min_qrv = min(MLD_QRV_DEFAULT, sysctl_mld_qrv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) WARN_ON(idev->mc_qrv == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) if (mlh2->mld2q_qrv > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) idev->mc_qrv = mlh2->mld2q_qrv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) if (unlikely(idev->mc_qrv < min_qrv)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) net_warn_ratelimited("IPv6: MLD: clamping QRV from %u to %u!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) idev->mc_qrv, min_qrv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) idev->mc_qrv = min_qrv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) static void mld_update_qi(struct inet6_dev *idev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) const struct mld2_query *mlh2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) /* RFC3810, relevant sections:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) * - 5.1.9. QQIC (Querier's Query Interval Code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) * - 9.2. Query Interval
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) * - 9.12. Older Version Querier Present Timeout
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) * (the [Query Interval] in the last Query received)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) unsigned long mc_qqi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) if (mlh2->mld2q_qqic < 128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) mc_qqi = mlh2->mld2q_qqic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) unsigned long mc_man, mc_exp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) mc_exp = MLDV2_QQIC_EXP(mlh2->mld2q_qqic);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) mc_man = MLDV2_QQIC_MAN(mlh2->mld2q_qqic);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) mc_qqi = (mc_man | 0x10) << (mc_exp + 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) idev->mc_qi = mc_qqi * HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) static void mld_update_qri(struct inet6_dev *idev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) const struct mld2_query *mlh2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) /* RFC3810, relevant sections:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) * - 5.1.3. Maximum Response Code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) * - 9.3. Query Response Interval
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) idev->mc_qri = msecs_to_jiffies(mldv2_mrc(mlh2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) static int mld_process_v1(struct inet6_dev *idev, struct mld_msg *mld,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) unsigned long *max_delay, bool v1_query)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) unsigned long mldv1_md;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) /* Ignore v1 queries */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) if (mld_in_v2_mode_only(idev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) mldv1_md = ntohs(mld->mld_maxdelay);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) /* When in MLDv1 fallback and a MLDv2 router start-up being
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) * unaware of current MLDv1 operation, the MRC == MRD mapping
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) * only works when the exponential algorithm is not being
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) * used (as MLDv1 is unaware of such things).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) * According to the RFC author, the MLDv2 implementations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) * he's aware of all use a MRC < 32768 on start up queries.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) * Thus, should we *ever* encounter something else larger
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) * than that, just assume the maximum possible within our
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) * reach.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) if (!v1_query)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) mldv1_md = min(mldv1_md, MLDV1_MRD_MAX_COMPAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) *max_delay = max(msecs_to_jiffies(mldv1_md), 1UL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) /* MLDv1 router present: we need to go into v1 mode *only*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) * when an MLDv1 query is received as per section 9.12. of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) * RFC3810! And we know from RFC2710 section 3.7 that MLDv1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) * queries MUST be of exactly 24 octets.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) if (v1_query)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) mld_set_v1_mode(idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) /* cancel MLDv2 report timer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) mld_gq_stop_timer(idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) /* cancel the interface change timer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) mld_ifc_stop_timer(idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) /* clear deleted report items */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) mld_clear_delrec(idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) static int mld_process_v2(struct inet6_dev *idev, struct mld2_query *mld,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) unsigned long *max_delay)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) *max_delay = max(msecs_to_jiffies(mldv2_mrc(mld)), 1UL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) mld_update_qrv(idev, mld);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) mld_update_qi(idev, mld);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) mld_update_qri(idev, mld);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) idev->mc_maxdelay = *max_delay;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) /* called with rcu_read_lock() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) int igmp6_event_query(struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) struct mld2_query *mlh2 = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) struct ifmcaddr6 *ma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) const struct in6_addr *group;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) unsigned long max_delay;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) struct inet6_dev *idev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) struct mld_msg *mld;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) int group_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) int mark = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) int len, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) if (!pskb_may_pull(skb, sizeof(struct in6_addr)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) /* compute payload length excluding extension headers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) len = ntohs(ipv6_hdr(skb)->payload_len) + sizeof(struct ipv6hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) len -= skb_network_header_len(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) /* RFC3810 6.2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) * Upon reception of an MLD message that contains a Query, the node
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) * checks if the source address of the message is a valid link-local
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) * address, if the Hop Limit is set to 1, and if the Router Alert
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) * option is present in the Hop-By-Hop Options header of the IPv6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) * packet. If any of these checks fails, the packet is dropped.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) if (!(ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) ipv6_hdr(skb)->hop_limit != 1 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) !(IP6CB(skb)->flags & IP6SKB_ROUTERALERT) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) IP6CB(skb)->ra != htons(IPV6_OPT_ROUTERALERT_MLD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) idev = __in6_dev_get(skb->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) if (!idev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) mld = (struct mld_msg *)icmp6_hdr(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) group = &mld->mld_mca;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) group_type = ipv6_addr_type(group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) if (group_type != IPV6_ADDR_ANY &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) !(group_type&IPV6_ADDR_MULTICAST))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) if (len < MLD_V1_QUERY_LEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) } else if (len == MLD_V1_QUERY_LEN || mld_in_v1_mode(idev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) err = mld_process_v1(idev, mld, &max_delay,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) len == MLD_V1_QUERY_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) } else if (len >= MLD_V2_QUERY_LEN_MIN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) int srcs_offset = sizeof(struct mld2_query) -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) sizeof(struct icmp6hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) if (!pskb_may_pull(skb, srcs_offset))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) mlh2 = (struct mld2_query *)skb_transport_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) err = mld_process_v2(idev, mlh2, &max_delay);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) if (group_type == IPV6_ADDR_ANY) { /* general query */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) if (mlh2->mld2q_nsrcs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) return -EINVAL; /* no sources allowed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) mld_gq_start_timer(idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) /* mark sources to include, if group & source-specific */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) if (mlh2->mld2q_nsrcs != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) if (!pskb_may_pull(skb, srcs_offset +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) ntohs(mlh2->mld2q_nsrcs) * sizeof(struct in6_addr)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) mlh2 = (struct mld2_query *)skb_transport_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) mark = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) read_lock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) if (group_type == IPV6_ADDR_ANY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) for (ma = idev->mc_list; ma; ma = ma->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) spin_lock_bh(&ma->mca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) igmp6_group_queried(ma, max_delay);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) spin_unlock_bh(&ma->mca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) for (ma = idev->mc_list; ma; ma = ma->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) if (!ipv6_addr_equal(group, &ma->mca_addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) spin_lock_bh(&ma->mca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) if (ma->mca_flags & MAF_TIMER_RUNNING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) /* gsquery <- gsquery && mark */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) if (!mark)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) ma->mca_flags &= ~MAF_GSQUERY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) /* gsquery <- mark */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) if (mark)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) ma->mca_flags |= MAF_GSQUERY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) ma->mca_flags &= ~MAF_GSQUERY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) if (!(ma->mca_flags & MAF_GSQUERY) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) mld_marksources(ma, ntohs(mlh2->mld2q_nsrcs), mlh2->mld2q_srcs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) igmp6_group_queried(ma, max_delay);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) spin_unlock_bh(&ma->mca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) read_unlock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) /* called with rcu_read_lock() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) int igmp6_event_report(struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) struct ifmcaddr6 *ma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) struct inet6_dev *idev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) struct mld_msg *mld;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) int addr_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) /* Our own report looped back. Ignore it. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) if (skb->pkt_type == PACKET_LOOPBACK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) /* send our report if the MC router may not have heard this report */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) if (skb->pkt_type != PACKET_MULTICAST &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) skb->pkt_type != PACKET_BROADCAST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) if (!pskb_may_pull(skb, sizeof(*mld) - sizeof(struct icmp6hdr)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) mld = (struct mld_msg *)icmp6_hdr(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) /* Drop reports with not link local source */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) addr_type = ipv6_addr_type(&ipv6_hdr(skb)->saddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) if (addr_type != IPV6_ADDR_ANY &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) !(addr_type&IPV6_ADDR_LINKLOCAL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) idev = __in6_dev_get(skb->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) if (!idev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) * Cancel the timer for this group
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) read_lock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) for (ma = idev->mc_list; ma; ma = ma->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) if (ipv6_addr_equal(&ma->mca_addr, &mld->mld_mca)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) spin_lock(&ma->mca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) if (del_timer(&ma->mca_timer))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) refcount_dec(&ma->mca_refcnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) ma->mca_flags &= ~(MAF_LAST_REPORTER|MAF_TIMER_RUNNING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) spin_unlock(&ma->mca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) read_unlock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) static bool is_in(struct ifmcaddr6 *pmc, struct ip6_sf_list *psf, int type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) int gdeleted, int sdeleted)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) case MLD2_MODE_IS_INCLUDE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) case MLD2_MODE_IS_EXCLUDE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) if (gdeleted || sdeleted)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) if (!((pmc->mca_flags & MAF_GSQUERY) && !psf->sf_gsresp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) if (pmc->mca_sfmode == MCAST_INCLUDE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) /* don't include if this source is excluded
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) * in all filters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) if (psf->sf_count[MCAST_INCLUDE])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) return type == MLD2_MODE_IS_INCLUDE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) return pmc->mca_sfcount[MCAST_EXCLUDE] ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) psf->sf_count[MCAST_EXCLUDE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) case MLD2_CHANGE_TO_INCLUDE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) if (gdeleted || sdeleted)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) return psf->sf_count[MCAST_INCLUDE] != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) case MLD2_CHANGE_TO_EXCLUDE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) if (gdeleted || sdeleted)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) if (pmc->mca_sfcount[MCAST_EXCLUDE] == 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) psf->sf_count[MCAST_INCLUDE])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) return pmc->mca_sfcount[MCAST_EXCLUDE] ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) psf->sf_count[MCAST_EXCLUDE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) case MLD2_ALLOW_NEW_SOURCES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) if (gdeleted || !psf->sf_crcount)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) return (pmc->mca_sfmode == MCAST_INCLUDE) ^ sdeleted;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) case MLD2_BLOCK_OLD_SOURCES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) if (pmc->mca_sfmode == MCAST_INCLUDE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) return gdeleted || (psf->sf_crcount && sdeleted);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) return psf->sf_crcount && !gdeleted && !sdeleted;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) mld_scount(struct ifmcaddr6 *pmc, int type, int gdeleted, int sdeleted)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) struct ip6_sf_list *psf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) int scount = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) for (psf = pmc->mca_sources; psf; psf = psf->sf_next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) if (!is_in(pmc, psf, type, gdeleted, sdeleted))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) scount++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) return scount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) static void ip6_mc_hdr(struct sock *sk, struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) const struct in6_addr *saddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) const struct in6_addr *daddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) int proto, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) struct ipv6hdr *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) skb->protocol = htons(ETH_P_IPV6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) skb->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) skb_reset_network_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) skb_put(skb, sizeof(struct ipv6hdr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) hdr = ipv6_hdr(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) ip6_flow_hdr(hdr, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) hdr->payload_len = htons(len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) hdr->nexthdr = proto;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) hdr->hop_limit = inet6_sk(sk)->hop_limit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) hdr->saddr = *saddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) hdr->daddr = *daddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) static struct sk_buff *mld_newpack(struct inet6_dev *idev, unsigned int mtu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) struct net_device *dev = idev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) struct net *net = dev_net(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) struct sock *sk = net->ipv6.igmp_sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) struct mld2_report *pmr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) struct in6_addr addr_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) const struct in6_addr *saddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) int hlen = LL_RESERVED_SPACE(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) int tlen = dev->needed_tailroom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) unsigned int size = mtu + hlen + tlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) u8 ra[8] = { IPPROTO_ICMPV6, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) IPV6_TLV_ROUTERALERT, 2, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) IPV6_TLV_PADN, 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) /* we assume size > sizeof(ra) here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) skb = sock_alloc_send_skb(sk, size, 1, &err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) if (!skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) skb->priority = TC_PRIO_CONTROL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) skb_reserve(skb, hlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) skb_tailroom_reserve(skb, mtu, tlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) if (__ipv6_get_lladdr(idev, &addr_buf, IFA_F_TENTATIVE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) /* <draft-ietf-magma-mld-source-05.txt>:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) * use unspecified address as the source address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) * when a valid link-local address is not available.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) saddr = &in6addr_any;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) saddr = &addr_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) ip6_mc_hdr(sk, skb, dev, saddr, &mld2_all_mcr, NEXTHDR_HOP, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) skb_put_data(skb, ra, sizeof(ra));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) skb_set_transport_header(skb, skb_tail_pointer(skb) - skb->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) skb_put(skb, sizeof(*pmr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) pmr = (struct mld2_report *)skb_transport_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) pmr->mld2r_type = ICMPV6_MLD2_REPORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) pmr->mld2r_resv1 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) pmr->mld2r_cksum = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) pmr->mld2r_resv2 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) pmr->mld2r_ngrec = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) return skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) static void mld_sendpack(struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) struct ipv6hdr *pip6 = ipv6_hdr(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) struct mld2_report *pmr =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) (struct mld2_report *)skb_transport_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) int payload_len, mldlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) struct inet6_dev *idev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) struct net *net = dev_net(skb->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) struct flowi6 fl6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) struct dst_entry *dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) idev = __in6_dev_get(skb->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) payload_len = (skb_tail_pointer(skb) - skb_network_header(skb)) -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) sizeof(*pip6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) mldlen = skb_tail_pointer(skb) - skb_transport_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) pip6->payload_len = htons(payload_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) pmr->mld2r_cksum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) IPPROTO_ICMPV6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) csum_partial(skb_transport_header(skb),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) mldlen, 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) icmpv6_flow_init(net->ipv6.igmp_sk, &fl6, ICMPV6_MLD2_REPORT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) skb->dev->ifindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) dst = icmp6_dst_alloc(skb->dev, &fl6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) if (IS_ERR(dst)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) err = PTR_ERR(dst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) dst = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) skb_dst_set(skb, dst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) goto err_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) net, net->ipv6.igmp_sk, skb, NULL, skb->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) dst_output);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) if (!err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) ICMP6MSGOUT_INC_STATS(net, idev, ICMPV6_MLD2_REPORT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) err_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) static int grec_size(struct ifmcaddr6 *pmc, int type, int gdel, int sdel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) return sizeof(struct mld2_grec) + 16 * mld_scount(pmc,type,gdel,sdel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) static struct sk_buff *add_grhead(struct sk_buff *skb, struct ifmcaddr6 *pmc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) int type, struct mld2_grec **ppgr, unsigned int mtu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) struct mld2_report *pmr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) struct mld2_grec *pgr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) if (!skb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) skb = mld_newpack(pmc->idev, mtu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) if (!skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) pgr = skb_put(skb, sizeof(struct mld2_grec));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) pgr->grec_type = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) pgr->grec_auxwords = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) pgr->grec_nsrcs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) pgr->grec_mca = pmc->mca_addr; /* structure copy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) pmr = (struct mld2_report *)skb_transport_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) pmr->mld2r_ngrec = htons(ntohs(pmr->mld2r_ngrec)+1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) *ppgr = pgr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) return skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) #define AVAILABLE(skb) ((skb) ? skb_availroom(skb) : 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) static struct sk_buff *add_grec(struct sk_buff *skb, struct ifmcaddr6 *pmc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) int type, int gdeleted, int sdeleted, int crsend)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) struct inet6_dev *idev = pmc->idev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) struct net_device *dev = idev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) struct mld2_report *pmr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) struct mld2_grec *pgr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) struct ip6_sf_list *psf, *psf_next, *psf_prev, **psf_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) int scount, stotal, first, isquery, truncate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) unsigned int mtu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) if (pmc->mca_flags & MAF_NOREPORT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) return skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) mtu = READ_ONCE(dev->mtu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) if (mtu < IPV6_MIN_MTU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) return skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) isquery = type == MLD2_MODE_IS_INCLUDE ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) type == MLD2_MODE_IS_EXCLUDE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) truncate = type == MLD2_MODE_IS_EXCLUDE ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) type == MLD2_CHANGE_TO_EXCLUDE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) stotal = scount = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) psf_list = sdeleted ? &pmc->mca_tomb : &pmc->mca_sources;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) if (!*psf_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) goto empty_source;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) pmr = skb ? (struct mld2_report *)skb_transport_header(skb) : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) /* EX and TO_EX get a fresh packet, if needed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) if (truncate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) if (pmr && pmr->mld2r_ngrec &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) AVAILABLE(skb) < grec_size(pmc, type, gdeleted, sdeleted)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) if (skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) mld_sendpack(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) skb = mld_newpack(idev, mtu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) first = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) psf_prev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) for (psf = *psf_list; psf; psf = psf_next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) struct in6_addr *psrc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) psf_next = psf->sf_next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) if (!is_in(pmc, psf, type, gdeleted, sdeleted) && !crsend) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) psf_prev = psf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) /* Based on RFC3810 6.1. Should not send source-list change
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) * records when there is a filter mode change.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) if (((gdeleted && pmc->mca_sfmode == MCAST_EXCLUDE) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) (!gdeleted && pmc->mca_crcount)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) (type == MLD2_ALLOW_NEW_SOURCES ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) type == MLD2_BLOCK_OLD_SOURCES) && psf->sf_crcount)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) goto decrease_sf_crcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) /* clear marks on query responses */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) if (isquery)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) psf->sf_gsresp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) if (AVAILABLE(skb) < sizeof(*psrc) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) first*sizeof(struct mld2_grec)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) if (truncate && !first)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) break; /* truncate these */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) if (pgr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) pgr->grec_nsrcs = htons(scount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) if (skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) mld_sendpack(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) skb = mld_newpack(idev, mtu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) first = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) scount = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) if (first) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) skb = add_grhead(skb, pmc, type, &pgr, mtu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) first = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) if (!skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) psrc = skb_put(skb, sizeof(*psrc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) *psrc = psf->sf_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) scount++; stotal++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) if ((type == MLD2_ALLOW_NEW_SOURCES ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) type == MLD2_BLOCK_OLD_SOURCES) && psf->sf_crcount) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) decrease_sf_crcount:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) psf->sf_crcount--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) if ((sdeleted || gdeleted) && psf->sf_crcount == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) if (psf_prev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) psf_prev->sf_next = psf->sf_next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) *psf_list = psf->sf_next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) kfree(psf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) psf_prev = psf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) empty_source:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) if (!stotal) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) if (type == MLD2_ALLOW_NEW_SOURCES ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) type == MLD2_BLOCK_OLD_SOURCES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) return skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) if (pmc->mca_crcount || isquery || crsend) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) /* make sure we have room for group header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) if (skb && AVAILABLE(skb) < sizeof(struct mld2_grec)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) mld_sendpack(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) skb = NULL; /* add_grhead will get a new one */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) skb = add_grhead(skb, pmc, type, &pgr, mtu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) if (pgr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) pgr->grec_nsrcs = htons(scount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) if (isquery)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) pmc->mca_flags &= ~MAF_GSQUERY; /* clear query state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) return skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) static void mld_send_report(struct inet6_dev *idev, struct ifmcaddr6 *pmc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) struct sk_buff *skb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) int type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) read_lock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) if (!pmc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) for (pmc = idev->mc_list; pmc; pmc = pmc->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) if (pmc->mca_flags & MAF_NOREPORT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) spin_lock_bh(&pmc->mca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) if (pmc->mca_sfcount[MCAST_EXCLUDE])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) type = MLD2_MODE_IS_EXCLUDE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) type = MLD2_MODE_IS_INCLUDE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) skb = add_grec(skb, pmc, type, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) spin_unlock_bh(&pmc->mca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) spin_lock_bh(&pmc->mca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) if (pmc->mca_sfcount[MCAST_EXCLUDE])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) type = MLD2_MODE_IS_EXCLUDE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) type = MLD2_MODE_IS_INCLUDE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) skb = add_grec(skb, pmc, type, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) spin_unlock_bh(&pmc->mca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) read_unlock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) if (skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) mld_sendpack(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) * remove zero-count source records from a source filter list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) static void mld_clear_zeros(struct ip6_sf_list **ppsf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) struct ip6_sf_list *psf_prev, *psf_next, *psf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) psf_prev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) for (psf = *ppsf; psf; psf = psf_next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) psf_next = psf->sf_next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) if (psf->sf_crcount == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) if (psf_prev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) psf_prev->sf_next = psf->sf_next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) *ppsf = psf->sf_next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) kfree(psf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) psf_prev = psf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) static void mld_send_cr(struct inet6_dev *idev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) struct ifmcaddr6 *pmc, *pmc_prev, *pmc_next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) struct sk_buff *skb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) int type, dtype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) read_lock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) spin_lock(&idev->mc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) /* deleted MCA's */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) pmc_prev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) for (pmc = idev->mc_tomb; pmc; pmc = pmc_next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) pmc_next = pmc->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) if (pmc->mca_sfmode == MCAST_INCLUDE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) type = MLD2_BLOCK_OLD_SOURCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) dtype = MLD2_BLOCK_OLD_SOURCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) skb = add_grec(skb, pmc, type, 1, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) skb = add_grec(skb, pmc, dtype, 1, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) if (pmc->mca_crcount) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) if (pmc->mca_sfmode == MCAST_EXCLUDE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) type = MLD2_CHANGE_TO_INCLUDE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) skb = add_grec(skb, pmc, type, 1, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) pmc->mca_crcount--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) if (pmc->mca_crcount == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) mld_clear_zeros(&pmc->mca_tomb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) mld_clear_zeros(&pmc->mca_sources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) if (pmc->mca_crcount == 0 && !pmc->mca_tomb &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) !pmc->mca_sources) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) if (pmc_prev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) pmc_prev->next = pmc_next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) idev->mc_tomb = pmc_next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) in6_dev_put(pmc->idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) kfree(pmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) pmc_prev = pmc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) spin_unlock(&idev->mc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) /* change recs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) for (pmc = idev->mc_list; pmc; pmc = pmc->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) spin_lock_bh(&pmc->mca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) if (pmc->mca_sfcount[MCAST_EXCLUDE]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) type = MLD2_BLOCK_OLD_SOURCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) dtype = MLD2_ALLOW_NEW_SOURCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) type = MLD2_ALLOW_NEW_SOURCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) dtype = MLD2_BLOCK_OLD_SOURCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) skb = add_grec(skb, pmc, type, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) skb = add_grec(skb, pmc, dtype, 0, 1, 0); /* deleted sources */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) /* filter mode changes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) if (pmc->mca_crcount) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) if (pmc->mca_sfmode == MCAST_EXCLUDE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) type = MLD2_CHANGE_TO_EXCLUDE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) type = MLD2_CHANGE_TO_INCLUDE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) skb = add_grec(skb, pmc, type, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) pmc->mca_crcount--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) spin_unlock_bh(&pmc->mca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) read_unlock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) if (!skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) (void) mld_sendpack(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) struct net *net = dev_net(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) struct sock *sk = net->ipv6.igmp_sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) struct inet6_dev *idev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) struct mld_msg *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) const struct in6_addr *snd_addr, *saddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) struct in6_addr addr_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) int hlen = LL_RESERVED_SPACE(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) int tlen = dev->needed_tailroom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) int err, len, payload_len, full_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) u8 ra[8] = { IPPROTO_ICMPV6, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) IPV6_TLV_ROUTERALERT, 2, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) IPV6_TLV_PADN, 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) struct flowi6 fl6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) struct dst_entry *dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) if (type == ICMPV6_MGM_REDUCTION)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) snd_addr = &in6addr_linklocal_allrouters;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) snd_addr = addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999) payload_len = len + sizeof(ra);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) full_len = sizeof(struct ipv6hdr) + payload_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) IP6_UPD_PO_STATS(net, __in6_dev_get(dev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) IPSTATS_MIB_OUT, full_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) skb = sock_alloc_send_skb(sk, hlen + tlen + full_len, 1, &err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) if (!skb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) IP6_INC_STATS(net, __in6_dev_get(dev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) IPSTATS_MIB_OUTDISCARDS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) skb->priority = TC_PRIO_CONTROL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) skb_reserve(skb, hlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) if (ipv6_get_lladdr(dev, &addr_buf, IFA_F_TENTATIVE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) /* <draft-ietf-magma-mld-source-05.txt>:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) * use unspecified address as the source address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) * when a valid link-local address is not available.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) saddr = &in6addr_any;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) saddr = &addr_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) ip6_mc_hdr(sk, skb, dev, saddr, snd_addr, NEXTHDR_HOP, payload_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) skb_put_data(skb, ra, sizeof(ra));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) hdr = skb_put_zero(skb, sizeof(struct mld_msg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) hdr->mld_type = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) hdr->mld_mca = *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) hdr->mld_cksum = csum_ipv6_magic(saddr, snd_addr, len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) IPPROTO_ICMPV6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038) csum_partial(hdr, len, 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041) idev = __in6_dev_get(skb->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043) icmpv6_flow_init(sk, &fl6, type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) skb->dev->ifindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046) dst = icmp6_dst_alloc(skb->dev, &fl6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) if (IS_ERR(dst)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) err = PTR_ERR(dst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) goto err_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) skb_dst_set(skb, dst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) net, sk, skb, NULL, skb->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) dst_output);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) if (!err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) ICMP6MSGOUT_INC_STATS(net, idev, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059) ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) err_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) static void mld_send_initial_cr(struct inet6_dev *idev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) struct ifmcaddr6 *pmc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075) int type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) if (mld_in_v1_mode(idev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) skb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) read_lock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082) for (pmc = idev->mc_list; pmc; pmc = pmc->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083) spin_lock_bh(&pmc->mca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) if (pmc->mca_sfcount[MCAST_EXCLUDE])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) type = MLD2_CHANGE_TO_EXCLUDE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) type = MLD2_ALLOW_NEW_SOURCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088) skb = add_grec(skb, pmc, type, 0, 0, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) spin_unlock_bh(&pmc->mca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) read_unlock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092) if (skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) mld_sendpack(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096) void ipv6_mc_dad_complete(struct inet6_dev *idev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) idev->mc_dad_count = idev->mc_qrv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) if (idev->mc_dad_count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) mld_send_initial_cr(idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) idev->mc_dad_count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) if (idev->mc_dad_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103) mld_dad_start_timer(idev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) unsolicited_report_interval(idev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108) static void mld_dad_timer_expire(struct timer_list *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) struct inet6_dev *idev = from_timer(idev, t, mc_dad_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) mld_send_initial_cr(idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113) if (idev->mc_dad_count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114) idev->mc_dad_count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) if (idev->mc_dad_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116) mld_dad_start_timer(idev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117) unsolicited_report_interval(idev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119) in6_dev_put(idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122) static int ip6_mc_del1_src(struct ifmcaddr6 *pmc, int sfmode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123) const struct in6_addr *psfsrc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125) struct ip6_sf_list *psf, *psf_prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126) int rv = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128) psf_prev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129) for (psf = pmc->mca_sources; psf; psf = psf->sf_next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130) if (ipv6_addr_equal(&psf->sf_addr, psfsrc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132) psf_prev = psf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134) if (!psf || psf->sf_count[sfmode] == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) /* source filter not found, or count wrong => bug */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) return -ESRCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138) psf->sf_count[sfmode]--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139) if (!psf->sf_count[MCAST_INCLUDE] && !psf->sf_count[MCAST_EXCLUDE]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140) struct inet6_dev *idev = pmc->idev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142) /* no more filters for this source */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) if (psf_prev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144) psf_prev->sf_next = psf->sf_next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146) pmc->mca_sources = psf->sf_next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147) if (psf->sf_oldin && !(pmc->mca_flags & MAF_NOREPORT) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148) !mld_in_v1_mode(idev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) psf->sf_crcount = idev->mc_qrv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) psf->sf_next = pmc->mca_tomb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151) pmc->mca_tomb = psf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152) rv = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) kfree(psf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) static int ip6_mc_del_src(struct inet6_dev *idev, const struct in6_addr *pmca,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160) int sfmode, int sfcount, const struct in6_addr *psfsrc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161) int delta)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163) struct ifmcaddr6 *pmc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164) int changerec = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165) int i, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167) if (!idev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169) read_lock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170) for (pmc = idev->mc_list; pmc; pmc = pmc->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171) if (ipv6_addr_equal(pmca, &pmc->mca_addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) if (!pmc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175) /* MCA not found?? bug */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176) read_unlock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177) return -ESRCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179) spin_lock_bh(&pmc->mca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180) sf_markstate(pmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181) if (!delta) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182) if (!pmc->mca_sfcount[sfmode]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183) spin_unlock_bh(&pmc->mca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184) read_unlock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187) pmc->mca_sfcount[sfmode]--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190) for (i = 0; i < sfcount; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191) int rv = ip6_mc_del1_src(pmc, sfmode, &psfsrc[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193) changerec |= rv > 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194) if (!err && rv < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195) err = rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197) if (pmc->mca_sfmode == MCAST_EXCLUDE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198) pmc->mca_sfcount[MCAST_EXCLUDE] == 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199) pmc->mca_sfcount[MCAST_INCLUDE]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200) struct ip6_sf_list *psf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202) /* filter mode change */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203) pmc->mca_sfmode = MCAST_INCLUDE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204) pmc->mca_crcount = idev->mc_qrv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205) idev->mc_ifc_count = pmc->mca_crcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206) for (psf = pmc->mca_sources; psf; psf = psf->sf_next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207) psf->sf_crcount = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208) mld_ifc_event(pmc->idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209) } else if (sf_setstate(pmc) || changerec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210) mld_ifc_event(pmc->idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211) spin_unlock_bh(&pmc->mca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212) read_unlock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217) * Add multicast single-source filter to the interface list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219) static int ip6_mc_add1_src(struct ifmcaddr6 *pmc, int sfmode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220) const struct in6_addr *psfsrc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222) struct ip6_sf_list *psf, *psf_prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224) psf_prev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225) for (psf = pmc->mca_sources; psf; psf = psf->sf_next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226) if (ipv6_addr_equal(&psf->sf_addr, psfsrc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228) psf_prev = psf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230) if (!psf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231) psf = kzalloc(sizeof(*psf), GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232) if (!psf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2233) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2235) psf->sf_addr = *psfsrc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2236) if (psf_prev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2237) psf_prev->sf_next = psf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2238) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2239) pmc->mca_sources = psf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2241) psf->sf_count[sfmode]++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2242) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2245) static void sf_markstate(struct ifmcaddr6 *pmc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2246) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2247) struct ip6_sf_list *psf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2248) int mca_xcount = pmc->mca_sfcount[MCAST_EXCLUDE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2250) for (psf = pmc->mca_sources; psf; psf = psf->sf_next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2251) if (pmc->mca_sfcount[MCAST_EXCLUDE]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2252) psf->sf_oldin = mca_xcount ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2253) psf->sf_count[MCAST_EXCLUDE] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2254) !psf->sf_count[MCAST_INCLUDE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2255) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2256) psf->sf_oldin = psf->sf_count[MCAST_INCLUDE] != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2259) static int sf_setstate(struct ifmcaddr6 *pmc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2260) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2261) struct ip6_sf_list *psf, *dpsf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2262) int mca_xcount = pmc->mca_sfcount[MCAST_EXCLUDE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2263) int qrv = pmc->idev->mc_qrv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2264) int new_in, rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2266) rv = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2267) for (psf = pmc->mca_sources; psf; psf = psf->sf_next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2268) if (pmc->mca_sfcount[MCAST_EXCLUDE]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2269) new_in = mca_xcount == psf->sf_count[MCAST_EXCLUDE] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2270) !psf->sf_count[MCAST_INCLUDE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2271) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2272) new_in = psf->sf_count[MCAST_INCLUDE] != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2273) if (new_in) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2274) if (!psf->sf_oldin) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2275) struct ip6_sf_list *prev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2277) for (dpsf = pmc->mca_tomb; dpsf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2278) dpsf = dpsf->sf_next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2279) if (ipv6_addr_equal(&dpsf->sf_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2280) &psf->sf_addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2281) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2282) prev = dpsf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2284) if (dpsf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2285) if (prev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2286) prev->sf_next = dpsf->sf_next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2287) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2288) pmc->mca_tomb = dpsf->sf_next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2289) kfree(dpsf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2291) psf->sf_crcount = qrv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2292) rv++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294) } else if (psf->sf_oldin) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2295) psf->sf_crcount = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2296) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2297) * add or update "delete" records if an active filter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298) * is now inactive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2299) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2300) for (dpsf = pmc->mca_tomb; dpsf; dpsf = dpsf->sf_next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2301) if (ipv6_addr_equal(&dpsf->sf_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2302) &psf->sf_addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2303) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2304) if (!dpsf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2305) dpsf = kmalloc(sizeof(*dpsf), GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2306) if (!dpsf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2307) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2308) *dpsf = *psf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2309) /* pmc->mca_lock held by callers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2310) dpsf->sf_next = pmc->mca_tomb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2311) pmc->mca_tomb = dpsf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2313) dpsf->sf_crcount = qrv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2314) rv++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2317) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2320) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2321) * Add multicast source filter list to the interface list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2322) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2323) static int ip6_mc_add_src(struct inet6_dev *idev, const struct in6_addr *pmca,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2324) int sfmode, int sfcount, const struct in6_addr *psfsrc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2325) int delta)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2326) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2327) struct ifmcaddr6 *pmc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2328) int isexclude;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2329) int i, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2331) if (!idev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2332) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2333) read_lock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2334) for (pmc = idev->mc_list; pmc; pmc = pmc->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2335) if (ipv6_addr_equal(pmca, &pmc->mca_addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2336) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2338) if (!pmc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2339) /* MCA not found?? bug */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2340) read_unlock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2341) return -ESRCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2342) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2343) spin_lock_bh(&pmc->mca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2345) sf_markstate(pmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2346) isexclude = pmc->mca_sfmode == MCAST_EXCLUDE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2347) if (!delta)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2348) pmc->mca_sfcount[sfmode]++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2349) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2350) for (i = 0; i < sfcount; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2351) err = ip6_mc_add1_src(pmc, sfmode, &psfsrc[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2352) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2353) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2355) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2356) int j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2358) if (!delta)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2359) pmc->mca_sfcount[sfmode]--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2360) for (j = 0; j < i; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2361) ip6_mc_del1_src(pmc, sfmode, &psfsrc[j]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2362) } else if (isexclude != (pmc->mca_sfcount[MCAST_EXCLUDE] != 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2363) struct ip6_sf_list *psf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2365) /* filter mode change */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2366) if (pmc->mca_sfcount[MCAST_EXCLUDE])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2367) pmc->mca_sfmode = MCAST_EXCLUDE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2368) else if (pmc->mca_sfcount[MCAST_INCLUDE])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2369) pmc->mca_sfmode = MCAST_INCLUDE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2370) /* else no filters; keep old mode for reports */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2372) pmc->mca_crcount = idev->mc_qrv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2373) idev->mc_ifc_count = pmc->mca_crcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2374) for (psf = pmc->mca_sources; psf; psf = psf->sf_next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2375) psf->sf_crcount = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2376) mld_ifc_event(idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2377) } else if (sf_setstate(pmc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2378) mld_ifc_event(idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2379) spin_unlock_bh(&pmc->mca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2380) read_unlock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2381) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2384) static void ip6_mc_clear_src(struct ifmcaddr6 *pmc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2385) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2386) struct ip6_sf_list *psf, *nextpsf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2388) for (psf = pmc->mca_tomb; psf; psf = nextpsf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2389) nextpsf = psf->sf_next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2390) kfree(psf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2392) pmc->mca_tomb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2393) for (psf = pmc->mca_sources; psf; psf = nextpsf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2394) nextpsf = psf->sf_next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2395) kfree(psf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2397) pmc->mca_sources = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2398) pmc->mca_sfmode = MCAST_EXCLUDE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2399) pmc->mca_sfcount[MCAST_INCLUDE] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2400) pmc->mca_sfcount[MCAST_EXCLUDE] = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2404) static void igmp6_join_group(struct ifmcaddr6 *ma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2405) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2406) unsigned long delay;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2408) if (ma->mca_flags & MAF_NOREPORT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2409) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2411) igmp6_send(&ma->mca_addr, ma->idev->dev, ICMPV6_MGM_REPORT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2413) delay = prandom_u32() % unsolicited_report_interval(ma->idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2415) spin_lock_bh(&ma->mca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2416) if (del_timer(&ma->mca_timer)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2417) refcount_dec(&ma->mca_refcnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2418) delay = ma->mca_timer.expires - jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2421) if (!mod_timer(&ma->mca_timer, jiffies + delay))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2422) refcount_inc(&ma->mca_refcnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2423) ma->mca_flags |= MAF_TIMER_RUNNING | MAF_LAST_REPORTER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2424) spin_unlock_bh(&ma->mca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2427) static int ip6_mc_leave_src(struct sock *sk, struct ipv6_mc_socklist *iml,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2428) struct inet6_dev *idev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2429) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2430) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2432) write_lock_bh(&iml->sflock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2433) if (!iml->sflist) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2434) /* any-source empty exclude case */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2435) err = ip6_mc_del_src(idev, &iml->addr, iml->sfmode, 0, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2436) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2437) err = ip6_mc_del_src(idev, &iml->addr, iml->sfmode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2438) iml->sflist->sl_count, iml->sflist->sl_addr, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2439) sock_kfree_s(sk, iml->sflist, IP6_SFLSIZE(iml->sflist->sl_max));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2440) iml->sflist = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2442) write_unlock_bh(&iml->sflock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2443) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2446) static void igmp6_leave_group(struct ifmcaddr6 *ma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2447) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2448) if (mld_in_v1_mode(ma->idev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2449) if (ma->mca_flags & MAF_LAST_REPORTER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2450) igmp6_send(&ma->mca_addr, ma->idev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2451) ICMPV6_MGM_REDUCTION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2452) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2453) mld_add_delrec(ma->idev, ma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2454) mld_ifc_event(ma->idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2455) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2456) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2458) static void mld_gq_timer_expire(struct timer_list *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2459) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2460) struct inet6_dev *idev = from_timer(idev, t, mc_gq_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2462) idev->mc_gq_running = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2463) mld_send_report(idev, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2464) in6_dev_put(idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2465) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2467) static void mld_ifc_timer_expire(struct timer_list *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2468) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2469) struct inet6_dev *idev = from_timer(idev, t, mc_ifc_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2471) mld_send_cr(idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2472) if (idev->mc_ifc_count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2473) idev->mc_ifc_count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2474) if (idev->mc_ifc_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2475) mld_ifc_start_timer(idev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2476) unsolicited_report_interval(idev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2477) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2478) in6_dev_put(idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2479) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2481) static void mld_ifc_event(struct inet6_dev *idev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2482) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2483) if (mld_in_v1_mode(idev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2484) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2485) idev->mc_ifc_count = idev->mc_qrv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2486) mld_ifc_start_timer(idev, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2489) static void igmp6_timer_handler(struct timer_list *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2490) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2491) struct ifmcaddr6 *ma = from_timer(ma, t, mca_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2493) if (mld_in_v1_mode(ma->idev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2494) igmp6_send(&ma->mca_addr, ma->idev->dev, ICMPV6_MGM_REPORT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2495) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2496) mld_send_report(ma->idev, ma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2498) spin_lock(&ma->mca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2499) ma->mca_flags |= MAF_LAST_REPORTER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2500) ma->mca_flags &= ~MAF_TIMER_RUNNING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2501) spin_unlock(&ma->mca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2502) ma_put(ma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2503) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2505) /* Device changing type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2507) void ipv6_mc_unmap(struct inet6_dev *idev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2508) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2509) struct ifmcaddr6 *i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2511) /* Install multicast list, except for all-nodes (already installed) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2513) read_lock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2514) for (i = idev->mc_list; i; i = i->next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2515) igmp6_group_dropped(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2516) read_unlock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2517) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2519) void ipv6_mc_remap(struct inet6_dev *idev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2520) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2521) ipv6_mc_up(idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2522) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2524) /* Device going down */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2526) void ipv6_mc_down(struct inet6_dev *idev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2527) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2528) struct ifmcaddr6 *i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2530) /* Withdraw multicast list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2532) read_lock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2534) for (i = idev->mc_list; i; i = i->next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2535) igmp6_group_dropped(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2537) /* Should stop timer after group drop. or we will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2538) * start timer again in mld_ifc_event()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2539) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2540) mld_ifc_stop_timer(idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2541) mld_gq_stop_timer(idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2542) mld_dad_stop_timer(idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2543) read_unlock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2544) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2546) static void ipv6_mc_reset(struct inet6_dev *idev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2547) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2548) idev->mc_qrv = sysctl_mld_qrv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2549) idev->mc_qi = MLD_QI_DEFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2550) idev->mc_qri = MLD_QRI_DEFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2551) idev->mc_v1_seen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2552) idev->mc_maxdelay = unsolicited_report_interval(idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2553) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2555) /* Device going up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2557) void ipv6_mc_up(struct inet6_dev *idev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2558) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2559) struct ifmcaddr6 *i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2561) /* Install multicast list, except for all-nodes (already installed) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2563) read_lock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2564) ipv6_mc_reset(idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2565) for (i = idev->mc_list; i; i = i->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2566) mld_del_delrec(idev, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2567) igmp6_group_added(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2568) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2569) read_unlock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2570) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2572) /* IPv6 device initialization. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2574) void ipv6_mc_init_dev(struct inet6_dev *idev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2575) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2576) write_lock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2577) spin_lock_init(&idev->mc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2578) idev->mc_gq_running = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2579) timer_setup(&idev->mc_gq_timer, mld_gq_timer_expire, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2580) idev->mc_tomb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2581) idev->mc_ifc_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2582) timer_setup(&idev->mc_ifc_timer, mld_ifc_timer_expire, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2583) timer_setup(&idev->mc_dad_timer, mld_dad_timer_expire, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2584) ipv6_mc_reset(idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2585) write_unlock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2586) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2588) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2589) * Device is about to be destroyed: clean up.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2590) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2592) void ipv6_mc_destroy_dev(struct inet6_dev *idev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2593) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2594) struct ifmcaddr6 *i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2596) /* Deactivate timers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2597) ipv6_mc_down(idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2598) mld_clear_delrec(idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2600) /* Delete all-nodes address. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2601) /* We cannot call ipv6_dev_mc_dec() directly, our caller in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2602) * addrconf.c has NULL'd out dev->ip6_ptr so in6_dev_get() will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2603) * fail.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2604) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2605) __ipv6_dev_mc_dec(idev, &in6addr_linklocal_allnodes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2607) if (idev->cnf.forwarding)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2608) __ipv6_dev_mc_dec(idev, &in6addr_linklocal_allrouters);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2610) write_lock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2611) while ((i = idev->mc_list) != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2612) idev->mc_list = i->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2614) write_unlock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2615) ip6_mc_clear_src(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2616) ma_put(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2617) write_lock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2618) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2619) write_unlock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2620) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2622) static void ipv6_mc_rejoin_groups(struct inet6_dev *idev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2623) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2624) struct ifmcaddr6 *pmc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2626) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2628) if (mld_in_v1_mode(idev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2629) read_lock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2630) for (pmc = idev->mc_list; pmc; pmc = pmc->next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2631) igmp6_join_group(pmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2632) read_unlock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2633) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2634) mld_send_report(idev, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2635) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2637) static int ipv6_mc_netdev_event(struct notifier_block *this,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2638) unsigned long event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2639) void *ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2640) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2641) struct net_device *dev = netdev_notifier_info_to_dev(ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2642) struct inet6_dev *idev = __in6_dev_get(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2644) switch (event) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2645) case NETDEV_RESEND_IGMP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2646) if (idev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2647) ipv6_mc_rejoin_groups(idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2648) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2649) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2650) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2651) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2653) return NOTIFY_DONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2654) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2656) static struct notifier_block igmp6_netdev_notifier = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2657) .notifier_call = ipv6_mc_netdev_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2658) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2660) #ifdef CONFIG_PROC_FS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2661) struct igmp6_mc_iter_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2662) struct seq_net_private p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2663) struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2664) struct inet6_dev *idev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2665) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2667) #define igmp6_mc_seq_private(seq) ((struct igmp6_mc_iter_state *)(seq)->private)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2669) static inline struct ifmcaddr6 *igmp6_mc_get_first(struct seq_file *seq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2670) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2671) struct ifmcaddr6 *im = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2672) struct igmp6_mc_iter_state *state = igmp6_mc_seq_private(seq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2673) struct net *net = seq_file_net(seq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2675) state->idev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2676) for_each_netdev_rcu(net, state->dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2677) struct inet6_dev *idev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2678) idev = __in6_dev_get(state->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2679) if (!idev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2680) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2681) read_lock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2682) im = idev->mc_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2683) if (im) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2684) state->idev = idev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2685) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2686) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2687) read_unlock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2688) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2689) return im;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2690) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2692) static struct ifmcaddr6 *igmp6_mc_get_next(struct seq_file *seq, struct ifmcaddr6 *im)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2693) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2694) struct igmp6_mc_iter_state *state = igmp6_mc_seq_private(seq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2696) im = im->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2697) while (!im) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2698) if (likely(state->idev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2699) read_unlock_bh(&state->idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2701) state->dev = next_net_device_rcu(state->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2702) if (!state->dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2703) state->idev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2704) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2705) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2706) state->idev = __in6_dev_get(state->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2707) if (!state->idev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2708) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2709) read_lock_bh(&state->idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2710) im = state->idev->mc_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2711) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2712) return im;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2713) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2715) static struct ifmcaddr6 *igmp6_mc_get_idx(struct seq_file *seq, loff_t pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2716) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2717) struct ifmcaddr6 *im = igmp6_mc_get_first(seq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2718) if (im)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2719) while (pos && (im = igmp6_mc_get_next(seq, im)) != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2720) --pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2721) return pos ? NULL : im;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2722) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2724) static void *igmp6_mc_seq_start(struct seq_file *seq, loff_t *pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2725) __acquires(RCU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2726) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2727) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2728) return igmp6_mc_get_idx(seq, *pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2729) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2731) static void *igmp6_mc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2732) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2733) struct ifmcaddr6 *im = igmp6_mc_get_next(seq, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2735) ++*pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2736) return im;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2739) static void igmp6_mc_seq_stop(struct seq_file *seq, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2740) __releases(RCU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2741) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2742) struct igmp6_mc_iter_state *state = igmp6_mc_seq_private(seq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2744) if (likely(state->idev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2745) read_unlock_bh(&state->idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2746) state->idev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2747) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2748) state->dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2749) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2750) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2752) static int igmp6_mc_seq_show(struct seq_file *seq, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2753) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2754) struct ifmcaddr6 *im = (struct ifmcaddr6 *)v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2755) struct igmp6_mc_iter_state *state = igmp6_mc_seq_private(seq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2757) seq_printf(seq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2758) "%-4d %-15s %pi6 %5d %08X %ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2759) state->dev->ifindex, state->dev->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2760) &im->mca_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2761) im->mca_users, im->mca_flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2762) (im->mca_flags&MAF_TIMER_RUNNING) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2763) jiffies_to_clock_t(im->mca_timer.expires-jiffies) : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2764) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2765) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2767) static const struct seq_operations igmp6_mc_seq_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2768) .start = igmp6_mc_seq_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2769) .next = igmp6_mc_seq_next,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2770) .stop = igmp6_mc_seq_stop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2771) .show = igmp6_mc_seq_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2772) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2774) struct igmp6_mcf_iter_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2775) struct seq_net_private p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2776) struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2777) struct inet6_dev *idev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2778) struct ifmcaddr6 *im;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2779) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2781) #define igmp6_mcf_seq_private(seq) ((struct igmp6_mcf_iter_state *)(seq)->private)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2783) static inline struct ip6_sf_list *igmp6_mcf_get_first(struct seq_file *seq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2784) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2785) struct ip6_sf_list *psf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2786) struct ifmcaddr6 *im = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2787) struct igmp6_mcf_iter_state *state = igmp6_mcf_seq_private(seq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2788) struct net *net = seq_file_net(seq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2790) state->idev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2791) state->im = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2792) for_each_netdev_rcu(net, state->dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2793) struct inet6_dev *idev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2794) idev = __in6_dev_get(state->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2795) if (unlikely(idev == NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2796) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2797) read_lock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2798) im = idev->mc_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2799) if (likely(im)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2800) spin_lock_bh(&im->mca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2801) psf = im->mca_sources;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2802) if (likely(psf)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2803) state->im = im;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2804) state->idev = idev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2805) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2806) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2807) spin_unlock_bh(&im->mca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2808) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2809) read_unlock_bh(&idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2810) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2811) return psf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2812) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2814) static struct ip6_sf_list *igmp6_mcf_get_next(struct seq_file *seq, struct ip6_sf_list *psf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2815) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2816) struct igmp6_mcf_iter_state *state = igmp6_mcf_seq_private(seq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2818) psf = psf->sf_next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2819) while (!psf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2820) spin_unlock_bh(&state->im->mca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2821) state->im = state->im->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2822) while (!state->im) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2823) if (likely(state->idev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2824) read_unlock_bh(&state->idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2826) state->dev = next_net_device_rcu(state->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2827) if (!state->dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2828) state->idev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2829) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2830) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2831) state->idev = __in6_dev_get(state->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2832) if (!state->idev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2833) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2834) read_lock_bh(&state->idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2835) state->im = state->idev->mc_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2836) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2837) if (!state->im)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2838) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2839) spin_lock_bh(&state->im->mca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2840) psf = state->im->mca_sources;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2841) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2842) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2843) return psf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2844) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2846) static struct ip6_sf_list *igmp6_mcf_get_idx(struct seq_file *seq, loff_t pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2847) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2848) struct ip6_sf_list *psf = igmp6_mcf_get_first(seq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2849) if (psf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2850) while (pos && (psf = igmp6_mcf_get_next(seq, psf)) != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2851) --pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2852) return pos ? NULL : psf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2853) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2855) static void *igmp6_mcf_seq_start(struct seq_file *seq, loff_t *pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2856) __acquires(RCU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2857) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2858) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2859) return *pos ? igmp6_mcf_get_idx(seq, *pos - 1) : SEQ_START_TOKEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2860) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2862) static void *igmp6_mcf_seq_next(struct seq_file *seq, void *v, loff_t *pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2863) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2864) struct ip6_sf_list *psf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2865) if (v == SEQ_START_TOKEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2866) psf = igmp6_mcf_get_first(seq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2867) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2868) psf = igmp6_mcf_get_next(seq, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2869) ++*pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2870) return psf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2871) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2873) static void igmp6_mcf_seq_stop(struct seq_file *seq, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2874) __releases(RCU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2875) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2876) struct igmp6_mcf_iter_state *state = igmp6_mcf_seq_private(seq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2877) if (likely(state->im)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2878) spin_unlock_bh(&state->im->mca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2879) state->im = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2880) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2881) if (likely(state->idev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2882) read_unlock_bh(&state->idev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2883) state->idev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2884) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2885) state->dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2886) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2887) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2889) static int igmp6_mcf_seq_show(struct seq_file *seq, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2890) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2891) struct ip6_sf_list *psf = (struct ip6_sf_list *)v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2892) struct igmp6_mcf_iter_state *state = igmp6_mcf_seq_private(seq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2894) if (v == SEQ_START_TOKEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2895) seq_puts(seq, "Idx Device Multicast Address Source Address INC EXC\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2896) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2897) seq_printf(seq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2898) "%3d %6.6s %pi6 %pi6 %6lu %6lu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2899) state->dev->ifindex, state->dev->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2900) &state->im->mca_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2901) &psf->sf_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2902) psf->sf_count[MCAST_INCLUDE],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2903) psf->sf_count[MCAST_EXCLUDE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2904) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2905) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2906) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2908) static const struct seq_operations igmp6_mcf_seq_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2909) .start = igmp6_mcf_seq_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2910) .next = igmp6_mcf_seq_next,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2911) .stop = igmp6_mcf_seq_stop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2912) .show = igmp6_mcf_seq_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2913) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2915) static int __net_init igmp6_proc_init(struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2916) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2917) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2919) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2920) if (!proc_create_net("igmp6", 0444, net->proc_net, &igmp6_mc_seq_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2921) sizeof(struct igmp6_mc_iter_state)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2922) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2923) if (!proc_create_net("mcfilter6", 0444, net->proc_net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2924) &igmp6_mcf_seq_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2925) sizeof(struct igmp6_mcf_iter_state)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2926) goto out_proc_net_igmp6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2928) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2929) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2930) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2932) out_proc_net_igmp6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2933) remove_proc_entry("igmp6", net->proc_net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2934) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2935) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2937) static void __net_exit igmp6_proc_exit(struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2938) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2939) remove_proc_entry("mcfilter6", net->proc_net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2940) remove_proc_entry("igmp6", net->proc_net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2941) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2942) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2943) static inline int igmp6_proc_init(struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2944) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2945) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2946) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2947) static inline void igmp6_proc_exit(struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2948) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2949) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2950) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2952) static int __net_init igmp6_net_init(struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2953) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2954) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2956) err = inet_ctl_sock_create(&net->ipv6.igmp_sk, PF_INET6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2957) SOCK_RAW, IPPROTO_ICMPV6, net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2958) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2959) pr_err("Failed to initialize the IGMP6 control socket (err %d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2960) err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2961) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2962) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2964) inet6_sk(net->ipv6.igmp_sk)->hop_limit = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2966) err = inet_ctl_sock_create(&net->ipv6.mc_autojoin_sk, PF_INET6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2967) SOCK_RAW, IPPROTO_ICMPV6, net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2968) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2969) pr_err("Failed to initialize the IGMP6 autojoin socket (err %d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2970) err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2971) goto out_sock_create;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2972) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2974) err = igmp6_proc_init(net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2975) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2976) goto out_sock_create_autojoin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2978) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2979)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2980) out_sock_create_autojoin:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2981) inet_ctl_sock_destroy(net->ipv6.mc_autojoin_sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2982) out_sock_create:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2983) inet_ctl_sock_destroy(net->ipv6.igmp_sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2984) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2985) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2986) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2988) static void __net_exit igmp6_net_exit(struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2989) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2990) inet_ctl_sock_destroy(net->ipv6.igmp_sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2991) inet_ctl_sock_destroy(net->ipv6.mc_autojoin_sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2992) igmp6_proc_exit(net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2993) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2994)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2995) static struct pernet_operations igmp6_net_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2996) .init = igmp6_net_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2997) .exit = igmp6_net_exit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2998) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3000) int __init igmp6_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3001) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3002) return register_pernet_subsys(&igmp6_net_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3003) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3005) int __init igmp6_late_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3006) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3007) return register_netdevice_notifier(&igmp6_netdev_notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3008) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3010) void igmp6_cleanup(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3011) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3012) unregister_pernet_subsys(&igmp6_net_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3013) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3015) void igmp6_late_cleanup(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3016) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3017) unregister_netdevice_notifier(&igmp6_netdev_notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3018) }