Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

rtnetlink: bridge: mcast: Move MDB handlers out of bridge driver

Currently, the bridge driver registers handlers for MDB netlink
messages, making it impossible for other drivers to implement MDB
support.

As a preparation for VXLAN MDB support, move the MDB handlers out of the
bridge driver to the core rtnetlink code. The rtnetlink code will call
into individual drivers by invoking their previously added MDB net
device operations.

Note that while the diffstat is large, the change is mechanical. It
moves code out of the bridge driver to rtnetlink code. Also note that a
similar change was made in 2012 with commit 77162022ab26 ("net: add
generic PF_BRIDGE:RTM_ FDB hooks") that moved FDB handlers out of the
bridge driver to the core rtnetlink code.

Signed-off-by: Ido Schimmel <idosch@nvidia.com>
Reviewed-by: Nikolay Aleksandrov <razor@blackwall.org>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Ido Schimmel and committed by
David S. Miller
cc7f5022 c009de10

+244 -318
+3 -3
net/bridge/br_device.c
··· 468 468 .ndo_fdb_del_bulk = br_fdb_delete_bulk, 469 469 .ndo_fdb_dump = br_fdb_dump, 470 470 .ndo_fdb_get = br_fdb_get, 471 - .ndo_mdb_add = br_mdb_add_new, 472 - .ndo_mdb_del = br_mdb_del_new, 473 - .ndo_mdb_dump = br_mdb_dump_new, 471 + .ndo_mdb_add = br_mdb_add, 472 + .ndo_mdb_del = br_mdb_del, 473 + .ndo_mdb_dump = br_mdb_dump, 474 474 .ndo_bridge_getlink = br_getlink, 475 475 .ndo_bridge_setlink = br_setlink, 476 476 .ndo_bridge_dellink = br_dellink,
+12 -289
net/bridge/br_mdb.c
··· 380 380 return err; 381 381 } 382 382 383 - static int br_mdb_valid_dump_req(const struct nlmsghdr *nlh, 384 - struct netlink_ext_ack *extack) 385 - { 386 - struct br_port_msg *bpm; 387 - 388 - if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*bpm))) { 389 - NL_SET_ERR_MSG_MOD(extack, "Invalid header for mdb dump request"); 390 - return -EINVAL; 391 - } 392 - 393 - bpm = nlmsg_data(nlh); 394 - if (bpm->ifindex) { 395 - NL_SET_ERR_MSG_MOD(extack, "Filtering by device index is not supported for mdb dump request"); 396 - return -EINVAL; 397 - } 398 - if (nlmsg_attrlen(nlh, sizeof(*bpm))) { 399 - NL_SET_ERR_MSG(extack, "Invalid data after header in mdb dump request"); 400 - return -EINVAL; 401 - } 402 - 403 - return 0; 404 - } 405 - 406 - static int br_mdb_dump(struct sk_buff *skb, struct netlink_callback *cb) 407 - { 408 - struct net_device *dev; 409 - struct net *net = sock_net(skb->sk); 410 - struct nlmsghdr *nlh = NULL; 411 - int idx = 0, s_idx; 412 - 413 - if (cb->strict_check) { 414 - int err = br_mdb_valid_dump_req(cb->nlh, cb->extack); 415 - 416 - if (err < 0) 417 - return err; 418 - } 419 - 420 - s_idx = cb->args[0]; 421 - 422 - rcu_read_lock(); 423 - 424 - for_each_netdev_rcu(net, dev) { 425 - if (netif_is_bridge_master(dev)) { 426 - struct net_bridge *br = netdev_priv(dev); 427 - struct br_port_msg *bpm; 428 - 429 - if (idx < s_idx) 430 - goto skip; 431 - 432 - nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid, 433 - cb->nlh->nlmsg_seq, RTM_GETMDB, 434 - sizeof(*bpm), NLM_F_MULTI); 435 - if (nlh == NULL) 436 - break; 437 - 438 - bpm = nlmsg_data(nlh); 439 - memset(bpm, 0, sizeof(*bpm)); 440 - bpm->ifindex = dev->ifindex; 441 - if (br_mdb_fill_info(skb, cb, dev) < 0) 442 - goto out; 443 - if (br_rports_fill_info(skb, &br->multicast_ctx) < 0) 444 - goto out; 445 - 446 - cb->args[1] = 0; 447 - nlmsg_end(skb, nlh); 448 - skip: 449 - idx++; 450 - } 451 - } 452 - 453 - out: 454 - if (nlh) 455 - nlmsg_end(skb, nlh); 456 - rcu_read_unlock(); 457 - cb->args[0] = idx; 458 - return skb->len; 459 - } 460 - 461 - int br_mdb_dump_new(struct net_device *dev, struct sk_buff *skb, 462 - struct netlink_callback *cb) 383 + int br_mdb_dump(struct net_device *dev, struct sk_buff *skb, 384 + struct netlink_callback *cb) 463 385 { 464 386 struct net_bridge *br = netdev_priv(dev); 465 387 struct br_port_msg *bpm; ··· 637 715 [MDBE_ATTR_SRC_LIST] = NLA_POLICY_NESTED(br_mdbe_src_list_pol), 638 716 [MDBE_ATTR_RTPROT] = NLA_POLICY_MIN(NLA_U8, RTPROT_STATIC), 639 717 }; 640 - 641 - static int validate_mdb_entry(const struct nlattr *attr, 642 - struct netlink_ext_ack *extack) 643 - { 644 - struct br_mdb_entry *entry = nla_data(attr); 645 - 646 - if (nla_len(attr) != sizeof(struct br_mdb_entry)) { 647 - NL_SET_ERR_MSG_MOD(extack, "Invalid MDBA_SET_ENTRY attribute length"); 648 - return -EINVAL; 649 - } 650 - 651 - if (entry->ifindex == 0) { 652 - NL_SET_ERR_MSG_MOD(extack, "Zero entry ifindex is not allowed"); 653 - return -EINVAL; 654 - } 655 - 656 - if (entry->addr.proto == htons(ETH_P_IP)) { 657 - if (!ipv4_is_multicast(entry->addr.u.ip4)) { 658 - NL_SET_ERR_MSG_MOD(extack, "IPv4 entry group address is not multicast"); 659 - return -EINVAL; 660 - } 661 - if (ipv4_is_local_multicast(entry->addr.u.ip4)) { 662 - NL_SET_ERR_MSG_MOD(extack, "IPv4 entry group address is local multicast"); 663 - return -EINVAL; 664 - } 665 - #if IS_ENABLED(CONFIG_IPV6) 666 - } else if (entry->addr.proto == htons(ETH_P_IPV6)) { 667 - if (ipv6_addr_is_ll_all_nodes(&entry->addr.u.ip6)) { 668 - NL_SET_ERR_MSG_MOD(extack, "IPv6 entry group address is link-local all nodes"); 669 - return -EINVAL; 670 - } 671 - #endif 672 - } else if (entry->addr.proto == 0) { 673 - /* L2 mdb */ 674 - if (!is_multicast_ether_addr(entry->addr.u.mac_addr)) { 675 - NL_SET_ERR_MSG_MOD(extack, "L2 entry group is not multicast"); 676 - return -EINVAL; 677 - } 678 - } else { 679 - NL_SET_ERR_MSG_MOD(extack, "Unknown entry protocol"); 680 - return -EINVAL; 681 - } 682 - 683 - if (entry->state != MDB_PERMANENT && entry->state != MDB_TEMPORARY) { 684 - NL_SET_ERR_MSG_MOD(extack, "Unknown entry state"); 685 - return -EINVAL; 686 - } 687 - if (entry->vid >= VLAN_VID_MASK) { 688 - NL_SET_ERR_MSG_MOD(extack, "Invalid entry VLAN id"); 689 - return -EINVAL; 690 - } 691 - 692 - return 0; 693 - } 694 718 695 719 static bool is_valid_mdb_source(struct nlattr *attr, __be16 proto, 696 720 struct netlink_ext_ack *extack) ··· 1200 1332 return 0; 1201 1333 } 1202 1334 1203 - static const struct nla_policy mdba_policy[MDBA_SET_ENTRY_MAX + 1] = { 1204 - [MDBA_SET_ENTRY_UNSPEC] = { .strict_start_type = MDBA_SET_ENTRY_ATTRS + 1 }, 1205 - [MDBA_SET_ENTRY] = NLA_POLICY_VALIDATE_FN(NLA_BINARY, 1206 - validate_mdb_entry, 1207 - sizeof(struct br_mdb_entry)), 1208 - [MDBA_SET_ENTRY_ATTRS] = { .type = NLA_NESTED }, 1209 - }; 1210 - 1211 - static int br_mdb_config_init(struct net *net, const struct nlmsghdr *nlh, 1212 - struct br_mdb_config *cfg, 1335 + static int br_mdb_config_init(struct br_mdb_config *cfg, struct net_device *dev, 1336 + struct nlattr *tb[], u16 nlmsg_flags, 1213 1337 struct netlink_ext_ack *extack) 1214 1338 { 1215 - struct nlattr *tb[MDBA_SET_ENTRY_MAX + 1]; 1216 - struct br_port_msg *bpm; 1217 - struct net_device *dev; 1218 - int err; 1219 - 1220 - err = nlmsg_parse_deprecated(nlh, sizeof(*bpm), tb, 1221 - MDBA_SET_ENTRY_MAX, mdba_policy, extack); 1222 - if (err) 1223 - return err; 1339 + struct net *net = dev_net(dev); 1224 1340 1225 1341 memset(cfg, 0, sizeof(*cfg)); 1226 1342 cfg->filter_mode = MCAST_EXCLUDE; 1227 1343 cfg->rt_protocol = RTPROT_STATIC; 1228 - cfg->nlflags = nlh->nlmsg_flags; 1229 - 1230 - bpm = nlmsg_data(nlh); 1231 - if (!bpm->ifindex) { 1232 - NL_SET_ERR_MSG_MOD(extack, "Invalid bridge ifindex"); 1233 - return -EINVAL; 1234 - } 1235 - 1236 - dev = __dev_get_by_index(net, bpm->ifindex); 1237 - if (!dev) { 1238 - NL_SET_ERR_MSG_MOD(extack, "Bridge device doesn't exist"); 1239 - return -ENODEV; 1240 - } 1241 - 1242 - if (!netif_is_bridge_master(dev)) { 1243 - NL_SET_ERR_MSG_MOD(extack, "Device is not a bridge"); 1244 - return -EOPNOTSUPP; 1245 - } 1344 + cfg->nlflags = nlmsg_flags; 1246 1345 1247 1346 cfg->br = netdev_priv(dev); 1248 1347 ··· 1220 1385 1221 1386 if (!br_opt_get(cfg->br, BROPT_MULTICAST_ENABLED)) { 1222 1387 NL_SET_ERR_MSG_MOD(extack, "Bridge's multicast processing is disabled"); 1223 - return -EINVAL; 1224 - } 1225 - 1226 - if (NL_REQ_ATTR_CHECK(extack, NULL, tb, MDBA_SET_ENTRY)) { 1227 - NL_SET_ERR_MSG_MOD(extack, "Missing MDBA_SET_ENTRY attribute"); 1228 1388 return -EINVAL; 1229 1389 } 1230 1390 ··· 1260 1430 br_mdb_config_src_list_fini(cfg); 1261 1431 } 1262 1432 1263 - static int br_mdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, 1264 - struct netlink_ext_ack *extack) 1433 + int br_mdb_add(struct net_device *dev, struct nlattr *tb[], u16 nlmsg_flags, 1434 + struct netlink_ext_ack *extack) 1265 1435 { 1266 - struct net *net = sock_net(skb->sk); 1267 1436 struct net_bridge_vlan_group *vg; 1268 1437 struct net_bridge_vlan *v; 1269 1438 struct br_mdb_config cfg; 1270 1439 int err; 1271 1440 1272 - err = br_mdb_config_init(net, nlh, &cfg, extack); 1441 + err = br_mdb_config_init(&cfg, dev, tb, nlmsg_flags, extack); 1273 1442 if (err) 1274 1443 return err; 1275 - 1276 - err = -EINVAL; 1277 - /* host join errors which can happen before creating the group */ 1278 - if (!cfg.p && !br_group_is_l2(&cfg.group)) { 1279 - /* don't allow any flags for host-joined IP groups */ 1280 - if (cfg.entry->state) { 1281 - NL_SET_ERR_MSG_MOD(extack, "Flags are not allowed for host groups"); 1282 - goto out; 1283 - } 1284 - if (!br_multicast_is_star_g(&cfg.group)) { 1285 - NL_SET_ERR_MSG_MOD(extack, "Groups with sources cannot be manually host joined"); 1286 - goto out; 1287 - } 1288 - } 1289 - 1290 - if (br_group_is_l2(&cfg.group) && cfg.entry->state != MDB_PERMANENT) { 1291 - NL_SET_ERR_MSG_MOD(extack, "Only permanent L2 entries allowed"); 1292 - goto out; 1293 - } 1294 - 1295 - if (cfg.p) { 1296 - if (cfg.p->state == BR_STATE_DISABLED && cfg.entry->state != MDB_PERMANENT) { 1297 - NL_SET_ERR_MSG_MOD(extack, "Port is in disabled state and entry is not permanent"); 1298 - goto out; 1299 - } 1300 - vg = nbp_vlan_group(cfg.p); 1301 - } else { 1302 - vg = br_vlan_group(cfg.br); 1303 - } 1304 - 1305 - /* If vlan filtering is enabled and VLAN is not specified 1306 - * install mdb entry on all vlans configured on the port. 1307 - */ 1308 - if (br_vlan_enabled(cfg.br->dev) && vg && cfg.entry->vid == 0) { 1309 - list_for_each_entry(v, &vg->vlan_list, vlist) { 1310 - cfg.entry->vid = v->vid; 1311 - cfg.group.vid = v->vid; 1312 - err = __br_mdb_add(&cfg, extack); 1313 - if (err) 1314 - break; 1315 - } 1316 - } else { 1317 - err = __br_mdb_add(&cfg, extack); 1318 - } 1319 - 1320 - out: 1321 - br_mdb_config_fini(&cfg); 1322 - return err; 1323 - } 1324 - 1325 - int br_mdb_add_new(struct net_device *dev, struct nlattr *tb[], u16 nlmsg_flags, 1326 - struct netlink_ext_ack *extack) 1327 - { 1328 - struct net_bridge_vlan_group *vg; 1329 - struct br_mdb_config cfg = {}; 1330 - struct net_bridge_vlan *v; 1331 - int err; 1332 - 1333 - /* Configuration structure will be initialized here. */ 1334 1444 1335 1445 err = -EINVAL; 1336 1446 /* host join errors which can happen before creating the group */ ··· 1362 1592 return err; 1363 1593 } 1364 1594 1365 - static int br_mdb_del(struct sk_buff *skb, struct nlmsghdr *nlh, 1366 - struct netlink_ext_ack *extack) 1595 + int br_mdb_del(struct net_device *dev, struct nlattr *tb[], 1596 + struct netlink_ext_ack *extack) 1367 1597 { 1368 - struct net *net = sock_net(skb->sk); 1369 1598 struct net_bridge_vlan_group *vg; 1370 1599 struct net_bridge_vlan *v; 1371 1600 struct br_mdb_config cfg; 1372 1601 int err; 1373 1602 1374 - err = br_mdb_config_init(net, nlh, &cfg, extack); 1603 + err = br_mdb_config_init(&cfg, dev, tb, 0, extack); 1375 1604 if (err) 1376 1605 return err; 1377 1606 ··· 1394 1625 1395 1626 br_mdb_config_fini(&cfg); 1396 1627 return err; 1397 - } 1398 - 1399 - int br_mdb_del_new(struct net_device *dev, struct nlattr *tb[], 1400 - struct netlink_ext_ack *extack) 1401 - { 1402 - struct net_bridge_vlan_group *vg; 1403 - struct br_mdb_config cfg = {}; 1404 - struct net_bridge_vlan *v; 1405 - int err = 0; 1406 - 1407 - /* Configuration structure will be initialized here. */ 1408 - 1409 - if (cfg.p) 1410 - vg = nbp_vlan_group(cfg.p); 1411 - else 1412 - vg = br_vlan_group(cfg.br); 1413 - 1414 - /* If vlan filtering is enabled and VLAN is not specified 1415 - * delete mdb entry on all vlans configured on the port. 1416 - */ 1417 - if (br_vlan_enabled(cfg.br->dev) && vg && cfg.entry->vid == 0) { 1418 - list_for_each_entry(v, &vg->vlan_list, vlist) { 1419 - cfg.entry->vid = v->vid; 1420 - cfg.group.vid = v->vid; 1421 - err = __br_mdb_del(&cfg); 1422 - } 1423 - } else { 1424 - err = __br_mdb_del(&cfg); 1425 - } 1426 - 1427 - br_mdb_config_fini(&cfg); 1428 - return err; 1429 - } 1430 - 1431 - void br_mdb_init(void) 1432 - { 1433 - rtnl_register_module(THIS_MODULE, PF_BRIDGE, RTM_GETMDB, NULL, br_mdb_dump, 0); 1434 - rtnl_register_module(THIS_MODULE, PF_BRIDGE, RTM_NEWMDB, br_mdb_add, NULL, 0); 1435 - rtnl_register_module(THIS_MODULE, PF_BRIDGE, RTM_DELMDB, br_mdb_del, NULL, 0); 1436 - } 1437 - 1438 - void br_mdb_uninit(void) 1439 - { 1440 - rtnl_unregister(PF_BRIDGE, RTM_GETMDB); 1441 - rtnl_unregister(PF_BRIDGE, RTM_NEWMDB); 1442 - rtnl_unregister(PF_BRIDGE, RTM_DELMDB); 1443 1628 }
-3
net/bridge/br_netlink.c
··· 1886 1886 { 1887 1887 int err; 1888 1888 1889 - br_mdb_init(); 1890 1889 br_vlan_rtnl_init(); 1891 1890 rtnl_af_register(&br_af_ops); 1892 1891 ··· 1897 1898 1898 1899 out_af: 1899 1900 rtnl_af_unregister(&br_af_ops); 1900 - br_mdb_uninit(); 1901 1901 return err; 1902 1902 } 1903 1903 1904 1904 void br_netlink_fini(void) 1905 1905 { 1906 - br_mdb_uninit(); 1907 1906 br_vlan_rtnl_uninit(); 1908 1907 rtnl_af_unregister(&br_af_ops); 1909 1908 rtnl_link_unregister(&br_link_ops);
+12 -23
net/bridge/br_private.h
··· 981 981 u32 br_multicast_ngroups_get(const struct net_bridge_mcast_port *pmctx); 982 982 void br_multicast_ngroups_set_max(struct net_bridge_mcast_port *pmctx, u32 max); 983 983 u32 br_multicast_ngroups_get_max(const struct net_bridge_mcast_port *pmctx); 984 - int br_mdb_add_new(struct net_device *dev, struct nlattr *tb[], u16 nlmsg_flags, 985 - struct netlink_ext_ack *extack); 986 - int br_mdb_del_new(struct net_device *dev, struct nlattr *tb[], 987 - struct netlink_ext_ack *extack); 988 - int br_mdb_dump_new(struct net_device *dev, struct sk_buff *skb, 989 - struct netlink_callback *cb); 990 - void br_mdb_init(void); 991 - void br_mdb_uninit(void); 984 + int br_mdb_add(struct net_device *dev, struct nlattr *tb[], u16 nlmsg_flags, 985 + struct netlink_ext_ack *extack); 986 + int br_mdb_del(struct net_device *dev, struct nlattr *tb[], 987 + struct netlink_ext_ack *extack); 988 + int br_mdb_dump(struct net_device *dev, struct sk_buff *skb, 989 + struct netlink_callback *cb); 992 990 void br_multicast_host_join(const struct net_bridge_mcast *brmctx, 993 991 struct net_bridge_mdb_entry *mp, bool notify); 994 992 void br_multicast_host_leave(struct net_bridge_mdb_entry *mp, bool notify); ··· 1378 1380 return false; 1379 1381 } 1380 1382 1381 - static inline int br_mdb_add_new(struct net_device *dev, struct nlattr *tb[], 1382 - u16 nlmsg_flags, 1383 - struct netlink_ext_ack *extack) 1383 + static inline int br_mdb_add(struct net_device *dev, struct nlattr *tb[], 1384 + u16 nlmsg_flags, struct netlink_ext_ack *extack) 1384 1385 { 1385 1386 return -EOPNOTSUPP; 1386 1387 } 1387 1388 1388 - static inline int br_mdb_del_new(struct net_device *dev, struct nlattr *tb[], 1389 - struct netlink_ext_ack *extack) 1389 + static inline int br_mdb_del(struct net_device *dev, struct nlattr *tb[], 1390 + struct netlink_ext_ack *extack) 1390 1391 { 1391 1392 return -EOPNOTSUPP; 1392 1393 } 1393 1394 1394 - static inline int br_mdb_dump_new(struct net_device *dev, struct sk_buff *skb, 1395 - struct netlink_callback *cb) 1395 + static inline int br_mdb_dump(struct net_device *dev, struct sk_buff *skb, 1396 + struct netlink_callback *cb) 1396 1397 { 1397 1398 return 0; 1398 - } 1399 - 1400 - static inline void br_mdb_init(void) 1401 - { 1402 - } 1403 - 1404 - static inline void br_mdb_uninit(void) 1405 - { 1406 1399 } 1407 1400 1408 1401 static inline int br_mdb_hash_init(struct net_bridge *br)
+217
net/core/rtnetlink.c
··· 54 54 #include <net/rtnetlink.h> 55 55 #include <net/net_namespace.h> 56 56 #include <net/devlink.h> 57 + #if IS_ENABLED(CONFIG_IPV6) 58 + #include <net/addrconf.h> 59 + #endif 57 60 58 61 #include "dev.h" 59 62 ··· 6066 6063 return 0; 6067 6064 } 6068 6065 6066 + static int rtnl_mdb_valid_dump_req(const struct nlmsghdr *nlh, 6067 + struct netlink_ext_ack *extack) 6068 + { 6069 + struct br_port_msg *bpm; 6070 + 6071 + if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*bpm))) { 6072 + NL_SET_ERR_MSG(extack, "Invalid header for mdb dump request"); 6073 + return -EINVAL; 6074 + } 6075 + 6076 + bpm = nlmsg_data(nlh); 6077 + if (bpm->ifindex) { 6078 + NL_SET_ERR_MSG(extack, "Filtering by device index is not supported for mdb dump request"); 6079 + return -EINVAL; 6080 + } 6081 + if (nlmsg_attrlen(nlh, sizeof(*bpm))) { 6082 + NL_SET_ERR_MSG(extack, "Invalid data after header in mdb dump request"); 6083 + return -EINVAL; 6084 + } 6085 + 6086 + return 0; 6087 + } 6088 + 6089 + struct rtnl_mdb_dump_ctx { 6090 + long idx; 6091 + }; 6092 + 6093 + static int rtnl_mdb_dump(struct sk_buff *skb, struct netlink_callback *cb) 6094 + { 6095 + struct rtnl_mdb_dump_ctx *ctx = (void *)cb->ctx; 6096 + struct net *net = sock_net(skb->sk); 6097 + struct net_device *dev; 6098 + int idx, s_idx; 6099 + int err; 6100 + 6101 + NL_ASSERT_DUMP_CTX_FITS(struct rtnl_mdb_dump_ctx); 6102 + 6103 + if (cb->strict_check) { 6104 + err = rtnl_mdb_valid_dump_req(cb->nlh, cb->extack); 6105 + if (err) 6106 + return err; 6107 + } 6108 + 6109 + s_idx = ctx->idx; 6110 + idx = 0; 6111 + 6112 + for_each_netdev(net, dev) { 6113 + if (idx < s_idx) 6114 + goto skip; 6115 + if (!dev->netdev_ops->ndo_mdb_dump) 6116 + goto skip; 6117 + 6118 + err = dev->netdev_ops->ndo_mdb_dump(dev, skb, cb); 6119 + if (err == -EMSGSIZE) 6120 + goto out; 6121 + /* Moving on to next device, reset markers and sequence 6122 + * counters since they are all maintained per-device. 6123 + */ 6124 + memset(cb->ctx, 0, sizeof(cb->ctx)); 6125 + cb->prev_seq = 0; 6126 + cb->seq = 0; 6127 + skip: 6128 + idx++; 6129 + } 6130 + 6131 + out: 6132 + ctx->idx = idx; 6133 + return skb->len; 6134 + } 6135 + 6136 + static int rtnl_validate_mdb_entry(const struct nlattr *attr, 6137 + struct netlink_ext_ack *extack) 6138 + { 6139 + struct br_mdb_entry *entry = nla_data(attr); 6140 + 6141 + if (nla_len(attr) != sizeof(struct br_mdb_entry)) { 6142 + NL_SET_ERR_MSG_ATTR(extack, attr, "Invalid attribute length"); 6143 + return -EINVAL; 6144 + } 6145 + 6146 + if (entry->ifindex == 0) { 6147 + NL_SET_ERR_MSG(extack, "Zero entry ifindex is not allowed"); 6148 + return -EINVAL; 6149 + } 6150 + 6151 + if (entry->addr.proto == htons(ETH_P_IP)) { 6152 + if (!ipv4_is_multicast(entry->addr.u.ip4)) { 6153 + NL_SET_ERR_MSG(extack, "IPv4 entry group address is not multicast"); 6154 + return -EINVAL; 6155 + } 6156 + if (ipv4_is_local_multicast(entry->addr.u.ip4)) { 6157 + NL_SET_ERR_MSG(extack, "IPv4 entry group address is local multicast"); 6158 + return -EINVAL; 6159 + } 6160 + #if IS_ENABLED(CONFIG_IPV6) 6161 + } else if (entry->addr.proto == htons(ETH_P_IPV6)) { 6162 + if (ipv6_addr_is_ll_all_nodes(&entry->addr.u.ip6)) { 6163 + NL_SET_ERR_MSG(extack, "IPv6 entry group address is link-local all nodes"); 6164 + return -EINVAL; 6165 + } 6166 + #endif 6167 + } else if (entry->addr.proto == 0) { 6168 + /* L2 mdb */ 6169 + if (!is_multicast_ether_addr(entry->addr.u.mac_addr)) { 6170 + NL_SET_ERR_MSG(extack, "L2 entry group is not multicast"); 6171 + return -EINVAL; 6172 + } 6173 + } else { 6174 + NL_SET_ERR_MSG(extack, "Unknown entry protocol"); 6175 + return -EINVAL; 6176 + } 6177 + 6178 + if (entry->state != MDB_PERMANENT && entry->state != MDB_TEMPORARY) { 6179 + NL_SET_ERR_MSG(extack, "Unknown entry state"); 6180 + return -EINVAL; 6181 + } 6182 + if (entry->vid >= VLAN_VID_MASK) { 6183 + NL_SET_ERR_MSG(extack, "Invalid entry VLAN id"); 6184 + return -EINVAL; 6185 + } 6186 + 6187 + return 0; 6188 + } 6189 + 6190 + static const struct nla_policy mdba_policy[MDBA_SET_ENTRY_MAX + 1] = { 6191 + [MDBA_SET_ENTRY_UNSPEC] = { .strict_start_type = MDBA_SET_ENTRY_ATTRS + 1 }, 6192 + [MDBA_SET_ENTRY] = NLA_POLICY_VALIDATE_FN(NLA_BINARY, 6193 + rtnl_validate_mdb_entry, 6194 + sizeof(struct br_mdb_entry)), 6195 + [MDBA_SET_ENTRY_ATTRS] = { .type = NLA_NESTED }, 6196 + }; 6197 + 6198 + static int rtnl_mdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, 6199 + struct netlink_ext_ack *extack) 6200 + { 6201 + struct nlattr *tb[MDBA_SET_ENTRY_MAX + 1]; 6202 + struct net *net = sock_net(skb->sk); 6203 + struct br_port_msg *bpm; 6204 + struct net_device *dev; 6205 + int err; 6206 + 6207 + err = nlmsg_parse_deprecated(nlh, sizeof(*bpm), tb, 6208 + MDBA_SET_ENTRY_MAX, mdba_policy, extack); 6209 + if (err) 6210 + return err; 6211 + 6212 + bpm = nlmsg_data(nlh); 6213 + if (!bpm->ifindex) { 6214 + NL_SET_ERR_MSG(extack, "Invalid ifindex"); 6215 + return -EINVAL; 6216 + } 6217 + 6218 + dev = __dev_get_by_index(net, bpm->ifindex); 6219 + if (!dev) { 6220 + NL_SET_ERR_MSG(extack, "Device doesn't exist"); 6221 + return -ENODEV; 6222 + } 6223 + 6224 + if (NL_REQ_ATTR_CHECK(extack, NULL, tb, MDBA_SET_ENTRY)) { 6225 + NL_SET_ERR_MSG(extack, "Missing MDBA_SET_ENTRY attribute"); 6226 + return -EINVAL; 6227 + } 6228 + 6229 + if (!dev->netdev_ops->ndo_mdb_add) { 6230 + NL_SET_ERR_MSG(extack, "Device does not support MDB operations"); 6231 + return -EOPNOTSUPP; 6232 + } 6233 + 6234 + return dev->netdev_ops->ndo_mdb_add(dev, tb, nlh->nlmsg_flags, extack); 6235 + } 6236 + 6237 + static int rtnl_mdb_del(struct sk_buff *skb, struct nlmsghdr *nlh, 6238 + struct netlink_ext_ack *extack) 6239 + { 6240 + struct nlattr *tb[MDBA_SET_ENTRY_MAX + 1]; 6241 + struct net *net = sock_net(skb->sk); 6242 + struct br_port_msg *bpm; 6243 + struct net_device *dev; 6244 + int err; 6245 + 6246 + err = nlmsg_parse_deprecated(nlh, sizeof(*bpm), tb, 6247 + MDBA_SET_ENTRY_MAX, mdba_policy, extack); 6248 + if (err) 6249 + return err; 6250 + 6251 + bpm = nlmsg_data(nlh); 6252 + if (!bpm->ifindex) { 6253 + NL_SET_ERR_MSG(extack, "Invalid ifindex"); 6254 + return -EINVAL; 6255 + } 6256 + 6257 + dev = __dev_get_by_index(net, bpm->ifindex); 6258 + if (!dev) { 6259 + NL_SET_ERR_MSG(extack, "Device doesn't exist"); 6260 + return -ENODEV; 6261 + } 6262 + 6263 + if (NL_REQ_ATTR_CHECK(extack, NULL, tb, MDBA_SET_ENTRY)) { 6264 + NL_SET_ERR_MSG(extack, "Missing MDBA_SET_ENTRY attribute"); 6265 + return -EINVAL; 6266 + } 6267 + 6268 + if (!dev->netdev_ops->ndo_mdb_del) { 6269 + NL_SET_ERR_MSG(extack, "Device does not support MDB operations"); 6270 + return -EOPNOTSUPP; 6271 + } 6272 + 6273 + return dev->netdev_ops->ndo_mdb_del(dev, tb, extack); 6274 + } 6275 + 6069 6276 /* Process one rtnetlink message. */ 6070 6277 6071 6278 static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, ··· 6510 6297 rtnl_register(PF_UNSPEC, RTM_GETSTATS, rtnl_stats_get, rtnl_stats_dump, 6511 6298 0); 6512 6299 rtnl_register(PF_UNSPEC, RTM_SETSTATS, rtnl_stats_set, NULL, 0); 6300 + 6301 + rtnl_register(PF_BRIDGE, RTM_GETMDB, NULL, rtnl_mdb_dump, 0); 6302 + rtnl_register(PF_BRIDGE, RTM_NEWMDB, rtnl_mdb_add, NULL, 0); 6303 + rtnl_register(PF_BRIDGE, RTM_DELMDB, rtnl_mdb_del, NULL, 0); 6513 6304 }