^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <linux/igmp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/netdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/rculist.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/if_ether.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <net/ip.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <net/netlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <net/switchdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <net/ipv6.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <net/addrconf.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "br_private.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) static int br_rports_fill_info(struct sk_buff *skb, struct netlink_callback *cb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) struct net_bridge *br = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) struct net_bridge_port *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) struct nlattr *nest, *port_nest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) if (!br->multicast_router || hlist_empty(&br->router_list))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) nest = nla_nest_start_noflag(skb, MDBA_ROUTER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) if (nest == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) hlist_for_each_entry_rcu(p, &br->router_list, rlist) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) if (!p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) port_nest = nla_nest_start_noflag(skb, MDBA_ROUTER_PORT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) if (!port_nest)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) if (nla_put_nohdr(skb, sizeof(u32), &p->dev->ifindex) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) nla_put_u32(skb, MDBA_ROUTER_PATTR_TIMER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) br_timer_value(&p->multicast_router_timer)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) nla_put_u8(skb, MDBA_ROUTER_PATTR_TYPE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) p->multicast_router)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) nla_nest_cancel(skb, port_nest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) nla_nest_end(skb, port_nest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) nla_nest_end(skb, nest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) nla_nest_cancel(skb, nest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) static void __mdb_entry_fill_flags(struct br_mdb_entry *e, unsigned char flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) e->state = flags & MDB_PG_FLAGS_PERMANENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) e->flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) if (flags & MDB_PG_FLAGS_OFFLOAD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) e->flags |= MDB_FLAGS_OFFLOAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) if (flags & MDB_PG_FLAGS_FAST_LEAVE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) e->flags |= MDB_FLAGS_FAST_LEAVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) if (flags & MDB_PG_FLAGS_STAR_EXCL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) e->flags |= MDB_FLAGS_STAR_EXCL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if (flags & MDB_PG_FLAGS_BLOCKED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) e->flags |= MDB_FLAGS_BLOCKED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) static void __mdb_entry_to_br_ip(struct br_mdb_entry *entry, struct br_ip *ip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) struct nlattr **mdb_attrs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) memset(ip, 0, sizeof(struct br_ip));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) ip->vid = entry->vid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) ip->proto = entry->addr.proto;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) switch (ip->proto) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) case htons(ETH_P_IP):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) ip->dst.ip4 = entry->addr.u.ip4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) if (mdb_attrs && mdb_attrs[MDBE_ATTR_SOURCE])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) ip->src.ip4 = nla_get_in_addr(mdb_attrs[MDBE_ATTR_SOURCE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) case htons(ETH_P_IPV6):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) ip->dst.ip6 = entry->addr.u.ip6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) if (mdb_attrs && mdb_attrs[MDBE_ATTR_SOURCE])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) ip->src.ip6 = nla_get_in6_addr(mdb_attrs[MDBE_ATTR_SOURCE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) static int __mdb_fill_srcs(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) struct net_bridge_port_group *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) struct net_bridge_group_src *ent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) struct nlattr *nest, *nest_ent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (hlist_empty(&p->src_list))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) nest = nla_nest_start(skb, MDBA_MDB_EATTR_SRC_LIST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) if (!nest)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) hlist_for_each_entry_rcu(ent, &p->src_list, node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) lockdep_is_held(&p->key.port->br->multicast_lock)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) nest_ent = nla_nest_start(skb, MDBA_MDB_SRCLIST_ENTRY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) if (!nest_ent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) goto out_cancel_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) switch (ent->addr.proto) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) case htons(ETH_P_IP):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if (nla_put_in_addr(skb, MDBA_MDB_SRCATTR_ADDRESS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) ent->addr.src.ip4)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) nla_nest_cancel(skb, nest_ent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) goto out_cancel_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) case htons(ETH_P_IPV6):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) if (nla_put_in6_addr(skb, MDBA_MDB_SRCATTR_ADDRESS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) &ent->addr.src.ip6)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) nla_nest_cancel(skb, nest_ent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) goto out_cancel_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) nla_nest_cancel(skb, nest_ent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) if (nla_put_u32(skb, MDBA_MDB_SRCATTR_TIMER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) br_timer_value(&ent->timer))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) nla_nest_cancel(skb, nest_ent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) goto out_cancel_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) nla_nest_end(skb, nest_ent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) nla_nest_end(skb, nest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) out_cancel_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) nla_nest_cancel(skb, nest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) static int __mdb_fill_info(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) struct net_bridge_mdb_entry *mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) struct net_bridge_port_group *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) bool dump_srcs_mode = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) struct timer_list *mtimer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) struct nlattr *nest_ent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) struct br_mdb_entry e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) u8 flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) int ifindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) memset(&e, 0, sizeof(e));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if (p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) ifindex = p->key.port->dev->ifindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) mtimer = &p->timer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) flags = p->flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) ifindex = mp->br->dev->ifindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) mtimer = &mp->timer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) __mdb_entry_fill_flags(&e, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) e.ifindex = ifindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) e.vid = mp->addr.vid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) if (mp->addr.proto == htons(ETH_P_IP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) e.addr.u.ip4 = mp->addr.dst.ip4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) if (mp->addr.proto == htons(ETH_P_IPV6))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) e.addr.u.ip6 = mp->addr.dst.ip6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) e.addr.proto = mp->addr.proto;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) nest_ent = nla_nest_start_noflag(skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) MDBA_MDB_ENTRY_INFO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (!nest_ent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) if (nla_put_nohdr(skb, sizeof(e), &e) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) nla_put_u32(skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) MDBA_MDB_EATTR_TIMER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) br_timer_value(mtimer)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) goto nest_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) switch (mp->addr.proto) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) case htons(ETH_P_IP):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) dump_srcs_mode = !!(mp->br->multicast_igmp_version == 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) if (mp->addr.src.ip4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) if (nla_put_in_addr(skb, MDBA_MDB_EATTR_SOURCE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) mp->addr.src.ip4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) goto nest_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) case htons(ETH_P_IPV6):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) dump_srcs_mode = !!(mp->br->multicast_mld_version == 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) if (!ipv6_addr_any(&mp->addr.src.ip6)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (nla_put_in6_addr(skb, MDBA_MDB_EATTR_SOURCE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) &mp->addr.src.ip6))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) goto nest_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) if (p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) if (nla_put_u8(skb, MDBA_MDB_EATTR_RTPROT, p->rt_protocol))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) goto nest_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) if (dump_srcs_mode &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) (__mdb_fill_srcs(skb, p) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) nla_put_u8(skb, MDBA_MDB_EATTR_GROUP_MODE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) p->filter_mode)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) goto nest_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) nla_nest_end(skb, nest_ent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) nest_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) nla_nest_cancel(skb, nest_ent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) static int br_mdb_fill_info(struct sk_buff *skb, struct netlink_callback *cb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) int idx = 0, s_idx = cb->args[1], err = 0, pidx = 0, s_pidx = cb->args[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) struct net_bridge *br = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) struct net_bridge_mdb_entry *mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) struct nlattr *nest, *nest2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) if (!br_opt_get(br, BROPT_MULTICAST_ENABLED))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) nest = nla_nest_start_noflag(skb, MDBA_MDB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) if (nest == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) hlist_for_each_entry_rcu(mp, &br->mdb_list, mdb_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) struct net_bridge_port_group *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) struct net_bridge_port_group __rcu **pp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) if (idx < s_idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) goto skip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) nest2 = nla_nest_start_noflag(skb, MDBA_MDB_ENTRY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) if (!nest2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) err = -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) if (!s_pidx && mp->host_joined) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) err = __mdb_fill_info(skb, mp, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) nla_nest_cancel(skb, nest2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) for (pp = &mp->ports; (p = rcu_dereference(*pp)) != NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) pp = &p->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) if (!p->key.port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) if (pidx < s_pidx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) goto skip_pg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) err = __mdb_fill_info(skb, mp, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) nla_nest_end(skb, nest2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) skip_pg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) pidx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) pidx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) s_pidx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) nla_nest_end(skb, nest2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) skip:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) idx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) cb->args[1] = idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) cb->args[2] = pidx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) nla_nest_end(skb, nest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) static int br_mdb_valid_dump_req(const struct nlmsghdr *nlh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) struct netlink_ext_ack *extack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) struct br_port_msg *bpm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*bpm))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) NL_SET_ERR_MSG_MOD(extack, "Invalid header for mdb dump request");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) bpm = nlmsg_data(nlh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if (bpm->ifindex) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) NL_SET_ERR_MSG_MOD(extack, "Filtering by device index is not supported for mdb dump request");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) if (nlmsg_attrlen(nlh, sizeof(*bpm))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) NL_SET_ERR_MSG(extack, "Invalid data after header in mdb dump request");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) return -EINVAL;
^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) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) static int br_mdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) struct net *net = sock_net(skb->sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) struct nlmsghdr *nlh = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) int idx = 0, s_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) if (cb->strict_check) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) int err = br_mdb_valid_dump_req(cb->nlh, cb->extack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) s_idx = cb->args[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) cb->seq = net->dev_base_seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) for_each_netdev_rcu(net, dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) if (dev->priv_flags & IFF_EBRIDGE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) struct br_port_msg *bpm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) if (idx < s_idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) goto skip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) cb->nlh->nlmsg_seq, RTM_GETMDB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) sizeof(*bpm), NLM_F_MULTI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) if (nlh == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) bpm = nlmsg_data(nlh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) memset(bpm, 0, sizeof(*bpm));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) bpm->ifindex = dev->ifindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) if (br_mdb_fill_info(skb, cb, dev) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) if (br_rports_fill_info(skb, cb, dev) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) cb->args[1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) nlmsg_end(skb, nlh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) skip:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) idx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) if (nlh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) nlmsg_end(skb, nlh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) cb->args[0] = idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) return skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) static int nlmsg_populate_mdb_fill(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) struct net_bridge_mdb_entry *mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) struct net_bridge_port_group *pg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) int type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) struct nlmsghdr *nlh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) struct br_port_msg *bpm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) struct nlattr *nest, *nest2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) nlh = nlmsg_put(skb, 0, 0, type, sizeof(*bpm), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) if (!nlh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) bpm = nlmsg_data(nlh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) memset(bpm, 0, sizeof(*bpm));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) bpm->family = AF_BRIDGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) bpm->ifindex = dev->ifindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) nest = nla_nest_start_noflag(skb, MDBA_MDB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) if (nest == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) goto cancel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) nest2 = nla_nest_start_noflag(skb, MDBA_MDB_ENTRY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) if (nest2 == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) if (__mdb_fill_info(skb, mp, pg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) nla_nest_end(skb, nest2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) nla_nest_end(skb, nest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) nlmsg_end(skb, nlh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) nla_nest_end(skb, nest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) cancel:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) nlmsg_cancel(skb, nlh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) static size_t rtnl_mdb_nlmsg_size(struct net_bridge_port_group *pg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) size_t nlmsg_size = NLMSG_ALIGN(sizeof(struct br_port_msg)) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) nla_total_size(sizeof(struct br_mdb_entry)) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) nla_total_size(sizeof(u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) struct net_bridge_group_src *ent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) size_t addr_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) if (!pg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) /* MDBA_MDB_EATTR_RTPROT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) nlmsg_size += nla_total_size(sizeof(u8));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) switch (pg->key.addr.proto) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) case htons(ETH_P_IP):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) /* MDBA_MDB_EATTR_SOURCE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) if (pg->key.addr.src.ip4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) nlmsg_size += nla_total_size(sizeof(__be32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) if (pg->key.port->br->multicast_igmp_version == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) addr_size = sizeof(__be32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) case htons(ETH_P_IPV6):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) /* MDBA_MDB_EATTR_SOURCE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) if (!ipv6_addr_any(&pg->key.addr.src.ip6))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) nlmsg_size += nla_total_size(sizeof(struct in6_addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) if (pg->key.port->br->multicast_mld_version == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) addr_size = sizeof(struct in6_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) /* MDBA_MDB_EATTR_GROUP_MODE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) nlmsg_size += nla_total_size(sizeof(u8));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) /* MDBA_MDB_EATTR_SRC_LIST nested attr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) if (!hlist_empty(&pg->src_list))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) nlmsg_size += nla_total_size(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) hlist_for_each_entry(ent, &pg->src_list, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) /* MDBA_MDB_SRCLIST_ENTRY nested attr +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) * MDBA_MDB_SRCATTR_ADDRESS + MDBA_MDB_SRCATTR_TIMER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) nlmsg_size += nla_total_size(0) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) nla_total_size(addr_size) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) nla_total_size(sizeof(u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) return nlmsg_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) struct br_mdb_complete_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) struct net_bridge_port *port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) struct br_ip ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) static void br_mdb_complete(struct net_device *dev, int err, void *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) struct br_mdb_complete_info *data = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) struct net_bridge_port_group __rcu **pp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) struct net_bridge_port_group *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) struct net_bridge_mdb_entry *mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) struct net_bridge_port *port = data->port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) struct net_bridge *br = port->br;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) spin_lock_bh(&br->multicast_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) mp = br_mdb_ip_get(br, &data->ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) if (!mp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) for (pp = &mp->ports; (p = mlock_dereference(*pp, br)) != NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) pp = &p->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) if (p->key.port != port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) p->flags |= MDB_PG_FLAGS_OFFLOAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) spin_unlock_bh(&br->multicast_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) kfree(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) static void br_mdb_switchdev_host_port(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) struct net_device *lower_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) struct net_bridge_mdb_entry *mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) int type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) struct switchdev_obj_port_mdb mdb = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) .obj = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) .id = SWITCHDEV_OBJ_ID_HOST_MDB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) .flags = SWITCHDEV_F_DEFER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) .vid = mp->addr.vid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) if (mp->addr.proto == htons(ETH_P_IP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) ip_eth_mc_map(mp->addr.dst.ip4, mdb.addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) ipv6_eth_mc_map(&mp->addr.dst.ip6, mdb.addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) mdb.obj.orig_dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) case RTM_NEWMDB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) switchdev_port_obj_add(lower_dev, &mdb.obj, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) case RTM_DELMDB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) switchdev_port_obj_del(lower_dev, &mdb.obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) static void br_mdb_switchdev_host(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) struct net_bridge_mdb_entry *mp, int type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) struct net_device *lower_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) struct list_head *iter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) netdev_for_each_lower_dev(dev, lower_dev, iter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) br_mdb_switchdev_host_port(dev, lower_dev, mp, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) void br_mdb_notify(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) struct net_bridge_mdb_entry *mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) struct net_bridge_port_group *pg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) int type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) struct br_mdb_complete_info *complete_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) struct switchdev_obj_port_mdb mdb = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) .obj = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) .id = SWITCHDEV_OBJ_ID_PORT_MDB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) .flags = SWITCHDEV_F_DEFER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) .vid = mp->addr.vid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) struct net *net = dev_net(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) int err = -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) if (pg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) if (mp->addr.proto == htons(ETH_P_IP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) ip_eth_mc_map(mp->addr.dst.ip4, mdb.addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) ipv6_eth_mc_map(&mp->addr.dst.ip6, mdb.addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) mdb.obj.orig_dev = pg->key.port->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) case RTM_NEWMDB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) complete_info = kmalloc(sizeof(*complete_info), GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) if (!complete_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) complete_info->port = pg->key.port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) complete_info->ip = mp->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) mdb.obj.complete_priv = complete_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) mdb.obj.complete = br_mdb_complete;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) if (switchdev_port_obj_add(pg->key.port->dev, &mdb.obj, NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) kfree(complete_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) case RTM_DELMDB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) switchdev_port_obj_del(pg->key.port->dev, &mdb.obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) br_mdb_switchdev_host(dev, mp, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) skb = nlmsg_new(rtnl_mdb_nlmsg_size(pg), GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) if (!skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) goto errout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) err = nlmsg_populate_mdb_fill(skb, dev, mp, pg, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) goto errout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) rtnl_notify(skb, net, 0, RTNLGRP_MDB, NULL, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) errout:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) rtnl_set_sk_err(net, RTNLGRP_MDB, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) static int nlmsg_populate_rtr_fill(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) int ifindex, u32 pid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) u32 seq, int type, unsigned int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) struct br_port_msg *bpm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) struct nlmsghdr *nlh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) struct nlattr *nest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) nlh = nlmsg_put(skb, pid, seq, type, sizeof(*bpm), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) if (!nlh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) bpm = nlmsg_data(nlh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) memset(bpm, 0, sizeof(*bpm));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) bpm->family = AF_BRIDGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) bpm->ifindex = dev->ifindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) nest = nla_nest_start_noflag(skb, MDBA_ROUTER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) if (!nest)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) goto cancel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) if (nla_put_u32(skb, MDBA_ROUTER_PORT, ifindex))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) nla_nest_end(skb, nest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) nlmsg_end(skb, nlh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) nla_nest_end(skb, nest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) cancel:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) nlmsg_cancel(skb, nlh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) static inline size_t rtnl_rtr_nlmsg_size(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) return NLMSG_ALIGN(sizeof(struct br_port_msg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) + nla_total_size(sizeof(__u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) void br_rtr_notify(struct net_device *dev, struct net_bridge_port *port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) int type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) struct net *net = dev_net(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) int err = -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) int ifindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) ifindex = port ? port->dev->ifindex : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) skb = nlmsg_new(rtnl_rtr_nlmsg_size(), GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) if (!skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) goto errout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) err = nlmsg_populate_rtr_fill(skb, dev, ifindex, 0, 0, type, NTF_SELF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) goto errout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) rtnl_notify(skb, net, 0, RTNLGRP_MDB, NULL, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) errout:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) rtnl_set_sk_err(net, RTNLGRP_MDB, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) static bool is_valid_mdb_entry(struct br_mdb_entry *entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) struct netlink_ext_ack *extack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) if (entry->ifindex == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) NL_SET_ERR_MSG_MOD(extack, "Zero entry ifindex is not allowed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) if (entry->addr.proto == htons(ETH_P_IP)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) if (!ipv4_is_multicast(entry->addr.u.ip4)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) NL_SET_ERR_MSG_MOD(extack, "IPv4 entry group address is not multicast");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) if (ipv4_is_local_multicast(entry->addr.u.ip4)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) NL_SET_ERR_MSG_MOD(extack, "IPv4 entry group address is local multicast");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) } else if (entry->addr.proto == htons(ETH_P_IPV6)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) if (ipv6_addr_is_ll_all_nodes(&entry->addr.u.ip6)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) NL_SET_ERR_MSG_MOD(extack, "IPv6 entry group address is link-local all nodes");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) NL_SET_ERR_MSG_MOD(extack, "Unknown entry protocol");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) if (entry->state != MDB_PERMANENT && entry->state != MDB_TEMPORARY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) NL_SET_ERR_MSG_MOD(extack, "Unknown entry state");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) if (entry->vid >= VLAN_VID_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) NL_SET_ERR_MSG_MOD(extack, "Invalid entry VLAN id");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) static bool is_valid_mdb_source(struct nlattr *attr, __be16 proto,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) struct netlink_ext_ack *extack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) switch (proto) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) case htons(ETH_P_IP):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) if (nla_len(attr) != sizeof(struct in_addr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) NL_SET_ERR_MSG_MOD(extack, "IPv4 invalid source address length");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) if (ipv4_is_multicast(nla_get_in_addr(attr))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) NL_SET_ERR_MSG_MOD(extack, "IPv4 multicast source address is not allowed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) case htons(ETH_P_IPV6): {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) struct in6_addr src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) if (nla_len(attr) != sizeof(struct in6_addr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) NL_SET_ERR_MSG_MOD(extack, "IPv6 invalid source address length");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) src = nla_get_in6_addr(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) if (ipv6_addr_is_multicast(&src)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) NL_SET_ERR_MSG_MOD(extack, "IPv6 multicast source address is not allowed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) NL_SET_ERR_MSG_MOD(extack, "Invalid protocol used with source address");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) static const struct nla_policy br_mdbe_attrs_pol[MDBE_ATTR_MAX + 1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) [MDBE_ATTR_SOURCE] = NLA_POLICY_RANGE(NLA_BINARY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) sizeof(struct in_addr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) sizeof(struct in6_addr)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) static int br_mdb_parse(struct sk_buff *skb, struct nlmsghdr *nlh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) struct net_device **pdev, struct br_mdb_entry **pentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) struct nlattr **mdb_attrs, struct netlink_ext_ack *extack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) struct net *net = sock_net(skb->sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) struct br_mdb_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) struct br_port_msg *bpm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) struct nlattr *tb[MDBA_SET_ENTRY_MAX+1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) err = nlmsg_parse_deprecated(nlh, sizeof(*bpm), tb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) MDBA_SET_ENTRY_MAX, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) bpm = nlmsg_data(nlh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) if (bpm->ifindex == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) NL_SET_ERR_MSG_MOD(extack, "Invalid bridge ifindex");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) dev = __dev_get_by_index(net, bpm->ifindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) if (dev == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) NL_SET_ERR_MSG_MOD(extack, "Bridge device doesn't exist");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) if (!(dev->priv_flags & IFF_EBRIDGE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) NL_SET_ERR_MSG_MOD(extack, "Device is not a bridge");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) *pdev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) if (!tb[MDBA_SET_ENTRY]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) NL_SET_ERR_MSG_MOD(extack, "Missing MDBA_SET_ENTRY attribute");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) if (nla_len(tb[MDBA_SET_ENTRY]) != sizeof(struct br_mdb_entry)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) NL_SET_ERR_MSG_MOD(extack, "Invalid MDBA_SET_ENTRY attribute length");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) return -EINVAL;
^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) entry = nla_data(tb[MDBA_SET_ENTRY]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) if (!is_valid_mdb_entry(entry, extack))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) *pentry = entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) if (tb[MDBA_SET_ENTRY_ATTRS]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) err = nla_parse_nested(mdb_attrs, MDBE_ATTR_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) tb[MDBA_SET_ENTRY_ATTRS],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) br_mdbe_attrs_pol, extack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) if (mdb_attrs[MDBE_ATTR_SOURCE] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) !is_valid_mdb_source(mdb_attrs[MDBE_ATTR_SOURCE],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) entry->addr.proto, extack))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) memset(mdb_attrs, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) sizeof(struct nlattr *) * (MDBE_ATTR_MAX + 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) static int br_mdb_add_group(struct net_bridge *br, struct net_bridge_port *port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) struct br_mdb_entry *entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) struct nlattr **mdb_attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) struct netlink_ext_ack *extack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) struct net_bridge_mdb_entry *mp, *star_mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) struct net_bridge_port_group *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) struct net_bridge_port_group __rcu **pp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) struct br_ip group, star_group;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) unsigned long now = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) u8 filter_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) __mdb_entry_to_br_ip(entry, &group, mdb_attrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) /* host join errors which can happen before creating the group */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) if (!port) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) /* don't allow any flags for host-joined groups */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) if (entry->state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) NL_SET_ERR_MSG_MOD(extack, "Flags are not allowed for host groups");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) if (!br_multicast_is_star_g(&group)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) NL_SET_ERR_MSG_MOD(extack, "Groups with sources cannot be manually host joined");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) mp = br_mdb_ip_get(br, &group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) if (!mp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) mp = br_multicast_new_group(br, &group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) err = PTR_ERR_OR_ZERO(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) /* host join */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) if (!port) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) if (mp->host_joined) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) NL_SET_ERR_MSG_MOD(extack, "Group is already joined by host");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) return -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) br_multicast_host_join(mp, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) br_mdb_notify(br->dev, mp, NULL, RTM_NEWMDB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) for (pp = &mp->ports;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) (p = mlock_dereference(*pp, br)) != NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) pp = &p->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) if (p->key.port == port) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) NL_SET_ERR_MSG_MOD(extack, "Group is already joined by port");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) return -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) if ((unsigned long)p->key.port < (unsigned long)port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) filter_mode = br_multicast_is_star_g(&group) ? MCAST_EXCLUDE :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) MCAST_INCLUDE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) p = br_multicast_new_port_group(port, &group, *pp, entry->state, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) filter_mode, RTPROT_STATIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) if (unlikely(!p)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) NL_SET_ERR_MSG_MOD(extack, "Couldn't allocate new port group");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) rcu_assign_pointer(*pp, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) if (entry->state == MDB_TEMPORARY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) mod_timer(&p->timer, now + br->multicast_membership_interval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) br_mdb_notify(br->dev, mp, p, RTM_NEWMDB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) /* if we are adding a new EXCLUDE port group (*,G) it needs to be also
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) * added to all S,G entries for proper replication, if we are adding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) * a new INCLUDE port (S,G) then all of *,G EXCLUDE ports need to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) * added to it for proper replication
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) if (br_multicast_should_handle_mode(br, group.proto)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) switch (filter_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) case MCAST_EXCLUDE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) br_multicast_star_g_handle_mode(p, MCAST_EXCLUDE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) case MCAST_INCLUDE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) star_group = p->key.addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) memset(&star_group.src, 0, sizeof(star_group.src));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) star_mp = br_mdb_ip_get(br, &star_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) if (star_mp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) br_multicast_sg_add_exclude_ports(star_mp, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) static int __br_mdb_add(struct net *net, struct net_bridge *br,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) struct net_bridge_port *p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) struct br_mdb_entry *entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) struct nlattr **mdb_attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) struct netlink_ext_ack *extack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) spin_lock_bh(&br->multicast_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) ret = br_mdb_add_group(br, p, entry, mdb_attrs, extack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) spin_unlock_bh(&br->multicast_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) static int br_mdb_add(struct sk_buff *skb, struct nlmsghdr *nlh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) struct netlink_ext_ack *extack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) struct nlattr *mdb_attrs[MDBE_ATTR_MAX + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) struct net *net = sock_net(skb->sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) struct net_bridge_vlan_group *vg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) struct net_bridge_port *p = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) struct net_device *dev, *pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) struct br_mdb_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) struct net_bridge_vlan *v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) struct net_bridge *br;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) err = br_mdb_parse(skb, nlh, &dev, &entry, mdb_attrs, extack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) br = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) if (!netif_running(br->dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) NL_SET_ERR_MSG_MOD(extack, "Bridge device is not running");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) if (!br_opt_get(br, BROPT_MULTICAST_ENABLED)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) NL_SET_ERR_MSG_MOD(extack, "Bridge's multicast processing is disabled");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) if (entry->ifindex != br->dev->ifindex) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) pdev = __dev_get_by_index(net, entry->ifindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) if (!pdev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) NL_SET_ERR_MSG_MOD(extack, "Port net device doesn't exist");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) p = br_port_get_rtnl(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) if (!p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) NL_SET_ERR_MSG_MOD(extack, "Net device is not a bridge port");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) if (p->br != br) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) NL_SET_ERR_MSG_MOD(extack, "Port belongs to a different bridge device");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) if (p->state == BR_STATE_DISABLED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) NL_SET_ERR_MSG_MOD(extack, "Port is in disabled state");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) vg = nbp_vlan_group(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) vg = br_vlan_group(br);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) /* If vlan filtering is enabled and VLAN is not specified
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) * install mdb entry on all vlans configured on the port.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) if (br_vlan_enabled(br->dev) && vg && entry->vid == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) list_for_each_entry(v, &vg->vlan_list, vlist) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) entry->vid = v->vid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) err = __br_mdb_add(net, br, p, entry, mdb_attrs, extack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) err = __br_mdb_add(net, br, p, entry, mdb_attrs, extack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) static int __br_mdb_del(struct net_bridge *br, struct br_mdb_entry *entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) struct nlattr **mdb_attrs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) struct net_bridge_mdb_entry *mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) struct net_bridge_port_group *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) struct net_bridge_port_group __rcu **pp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) struct br_ip ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) int err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) if (!netif_running(br->dev) || !br_opt_get(br, BROPT_MULTICAST_ENABLED))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) __mdb_entry_to_br_ip(entry, &ip, mdb_attrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) spin_lock_bh(&br->multicast_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) mp = br_mdb_ip_get(br, &ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) if (!mp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) /* host leave */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) if (entry->ifindex == mp->br->dev->ifindex && mp->host_joined) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) br_multicast_host_leave(mp, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) br_mdb_notify(br->dev, mp, NULL, RTM_DELMDB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) if (!mp->ports && netif_running(br->dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) mod_timer(&mp->timer, jiffies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) for (pp = &mp->ports;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) (p = mlock_dereference(*pp, br)) != NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) pp = &p->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) if (!p->key.port || p->key.port->dev->ifindex != entry->ifindex)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) if (p->key.port->state == BR_STATE_DISABLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) br_multicast_del_pg(mp, p, pp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) spin_unlock_bh(&br->multicast_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) static int br_mdb_del(struct sk_buff *skb, struct nlmsghdr *nlh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) struct netlink_ext_ack *extack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) struct nlattr *mdb_attrs[MDBE_ATTR_MAX + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) struct net *net = sock_net(skb->sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) struct net_bridge_vlan_group *vg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) struct net_bridge_port *p = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) struct net_device *dev, *pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) struct br_mdb_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) struct net_bridge_vlan *v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) struct net_bridge *br;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) err = br_mdb_parse(skb, nlh, &dev, &entry, mdb_attrs, extack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) br = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) if (entry->ifindex != br->dev->ifindex) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) pdev = __dev_get_by_index(net, entry->ifindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) if (!pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) p = br_port_get_rtnl(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) if (!p || p->br != br || p->state == BR_STATE_DISABLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) vg = nbp_vlan_group(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) vg = br_vlan_group(br);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) /* If vlan filtering is enabled and VLAN is not specified
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) * delete mdb entry on all vlans configured on the port.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) if (br_vlan_enabled(br->dev) && vg && entry->vid == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) list_for_each_entry(v, &vg->vlan_list, vlist) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) entry->vid = v->vid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) err = __br_mdb_del(br, entry, mdb_attrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) err = __br_mdb_del(br, entry, mdb_attrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) return err;
^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) void br_mdb_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) rtnl_register_module(THIS_MODULE, PF_BRIDGE, RTM_GETMDB, NULL, br_mdb_dump, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) rtnl_register_module(THIS_MODULE, PF_BRIDGE, RTM_NEWMDB, br_mdb_add, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) rtnl_register_module(THIS_MODULE, PF_BRIDGE, RTM_DELMDB, br_mdb_del, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) void br_mdb_uninit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) rtnl_unregister(PF_BRIDGE, RTM_GETMDB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) rtnl_unregister(PF_BRIDGE, RTM_NEWMDB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) rtnl_unregister(PF_BRIDGE, RTM_DELMDB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) }