hc
2024-05-10 9999e48639b3cecb08ffb37358bcba3b48161b29
kernel/net/core/rtnetlink.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * INET An implementation of the TCP/IP protocol suite for the LINUX
34 * operating system. INET is implemented using the BSD Socket
....@@ -6,11 +7,6 @@
67 * Routing netlink socket interface: protocol independent part.
78 *
89 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
9
- *
10
- * This program is free software; you can redistribute it and/or
11
- * modify it under the terms of the GNU General Public License
12
- * as published by the Free Software Foundation; either version
13
- * 2 of the License, or (at your option) any later version.
1410 *
1511 * Fixes:
1612 * Vitaly E. Lavrov RTA_OK arithmetics was wrong.
....@@ -46,7 +42,6 @@
4642
4743 #include <linux/inet.h>
4844 #include <linux/netdevice.h>
49
-#include <net/switchdev.h>
5045 #include <net/ip.h>
5146 #include <net/protocol.h>
5247 #include <net/arp.h>
....@@ -59,7 +54,7 @@
5954 #include <net/rtnetlink.h>
6055 #include <net/net_namespace.h>
6156
62
-#define RTNL_MAX_TYPE 48
57
+#define RTNL_MAX_TYPE 50
6358 #define RTNL_SLAVE_MAX_TYPE 36
6459
6560 struct rtnl_link {
....@@ -635,7 +630,7 @@
635630 if (nla_put_string(skb, IFLA_INFO_SLAVE_KIND, ops->kind) < 0)
636631 return -EMSGSIZE;
637632 if (ops->fill_slave_info) {
638
- slave_data = nla_nest_start(skb, IFLA_INFO_SLAVE_DATA);
633
+ slave_data = nla_nest_start_noflag(skb, IFLA_INFO_SLAVE_DATA);
639634 if (!slave_data)
640635 return -EMSGSIZE;
641636 err = ops->fill_slave_info(skb, master_dev, dev);
....@@ -667,7 +662,7 @@
667662 return err;
668663 }
669664 if (ops->fill_info) {
670
- data = nla_nest_start(skb, IFLA_INFO_DATA);
665
+ data = nla_nest_start_noflag(skb, IFLA_INFO_DATA);
671666 if (data == NULL)
672667 return -EMSGSIZE;
673668 err = ops->fill_info(skb, dev);
....@@ -687,7 +682,7 @@
687682 struct nlattr *linkinfo;
688683 int err = -EMSGSIZE;
689684
690
- linkinfo = nla_nest_start(skb, IFLA_LINKINFO);
685
+ linkinfo = nla_nest_start_noflag(skb, IFLA_LINKINFO);
691686 if (linkinfo == NULL)
692687 goto out;
693688
....@@ -756,7 +751,11 @@
756751 struct nlattr *mx;
757752 int i, valid = 0;
758753
759
- mx = nla_nest_start(skb, RTA_METRICS);
754
+ /* nothing is dumped for dst_default_metrics, so just skip the loop */
755
+ if (metrics == dst_default_metrics.metrics)
756
+ return 0;
757
+
758
+ mx = nla_nest_start_noflag(skb, RTA_METRICS);
760759 if (mx == NULL)
761760 return -ENOBUFS;
762761
....@@ -830,9 +829,16 @@
830829 switch (transition) {
831830 case IF_OPER_UP:
832831 if ((operstate == IF_OPER_DORMANT ||
832
+ operstate == IF_OPER_TESTING ||
833833 operstate == IF_OPER_UNKNOWN) &&
834
- !netif_dormant(dev))
834
+ !netif_dormant(dev) && !netif_testing(dev))
835835 operstate = IF_OPER_UP;
836
+ break;
837
+
838
+ case IF_OPER_TESTING:
839
+ if (operstate == IF_OPER_UP ||
840
+ operstate == IF_OPER_UNKNOWN)
841
+ operstate = IF_OPER_TESTING;
836842 break;
837843
838844 case IF_OPER_DORMANT:
....@@ -913,6 +919,7 @@
913919 size += num_vfs *
914920 (nla_total_size(0) +
915921 nla_total_size(sizeof(struct ifla_vf_mac)) +
922
+ nla_total_size(sizeof(struct ifla_vf_broadcast)) +
916923 nla_total_size(sizeof(struct ifla_vf_vlan)) +
917924 nla_total_size(0) + /* nest IFLA_VF_VLAN_LIST */
918925 nla_total_size(MAX_VLAN_LIST_LEN *
....@@ -922,24 +929,27 @@
922929 nla_total_size(sizeof(struct ifla_vf_rate)) +
923930 nla_total_size(sizeof(struct ifla_vf_link_state)) +
924931 nla_total_size(sizeof(struct ifla_vf_rss_query_en)) +
925
- nla_total_size(0) + /* nest IFLA_VF_STATS */
926
- /* IFLA_VF_STATS_RX_PACKETS */
927
- nla_total_size_64bit(sizeof(__u64)) +
928
- /* IFLA_VF_STATS_TX_PACKETS */
929
- nla_total_size_64bit(sizeof(__u64)) +
930
- /* IFLA_VF_STATS_RX_BYTES */
931
- nla_total_size_64bit(sizeof(__u64)) +
932
- /* IFLA_VF_STATS_TX_BYTES */
933
- nla_total_size_64bit(sizeof(__u64)) +
934
- /* IFLA_VF_STATS_BROADCAST */
935
- nla_total_size_64bit(sizeof(__u64)) +
936
- /* IFLA_VF_STATS_MULTICAST */
937
- nla_total_size_64bit(sizeof(__u64)) +
938
- /* IFLA_VF_STATS_RX_DROPPED */
939
- nla_total_size_64bit(sizeof(__u64)) +
940
- /* IFLA_VF_STATS_TX_DROPPED */
941
- nla_total_size_64bit(sizeof(__u64)) +
942932 nla_total_size(sizeof(struct ifla_vf_trust)));
933
+ if (~ext_filter_mask & RTEXT_FILTER_SKIP_STATS) {
934
+ size += num_vfs *
935
+ (nla_total_size(0) + /* nest IFLA_VF_STATS */
936
+ /* IFLA_VF_STATS_RX_PACKETS */
937
+ nla_total_size_64bit(sizeof(__u64)) +
938
+ /* IFLA_VF_STATS_TX_PACKETS */
939
+ nla_total_size_64bit(sizeof(__u64)) +
940
+ /* IFLA_VF_STATS_RX_BYTES */
941
+ nla_total_size_64bit(sizeof(__u64)) +
942
+ /* IFLA_VF_STATS_TX_BYTES */
943
+ nla_total_size_64bit(sizeof(__u64)) +
944
+ /* IFLA_VF_STATS_BROADCAST */
945
+ nla_total_size_64bit(sizeof(__u64)) +
946
+ /* IFLA_VF_STATS_MULTICAST */
947
+ nla_total_size_64bit(sizeof(__u64)) +
948
+ /* IFLA_VF_STATS_RX_DROPPED */
949
+ nla_total_size_64bit(sizeof(__u64)) +
950
+ /* IFLA_VF_STATS_TX_DROPPED */
951
+ nla_total_size_64bit(sizeof(__u64)));
952
+ }
943953 return size;
944954 } else
945955 return 0;
....@@ -978,6 +988,29 @@
978988 nla_total_size(4); /* XDP_<mode>_PROG_ID */
979989
980990 return xdp_size;
991
+}
992
+
993
+static size_t rtnl_prop_list_size(const struct net_device *dev)
994
+{
995
+ struct netdev_name_node *name_node;
996
+ size_t size;
997
+
998
+ if (list_empty(&dev->name_node->list))
999
+ return 0;
1000
+ size = nla_total_size(0);
1001
+ list_for_each_entry(name_node, &dev->name_node->list, list)
1002
+ size += nla_total_size(ALTIFNAMSIZ);
1003
+ return size;
1004
+}
1005
+
1006
+static size_t rtnl_proto_down_size(const struct net_device *dev)
1007
+{
1008
+ size_t size = nla_total_size(1);
1009
+
1010
+ if (dev->proto_down_reason)
1011
+ size += nla_total_size(0) + nla_total_size(4);
1012
+
1013
+ return size;
9811014 }
9821015
9831016 static noinline size_t if_nlmsg_size(const struct net_device *dev,
....@@ -1021,12 +1054,14 @@
10211054 + nla_total_size(4) /* IFLA_EVENT */
10221055 + nla_total_size(4) /* IFLA_NEW_NETNSID */
10231056 + nla_total_size(4) /* IFLA_NEW_IFINDEX */
1024
- + nla_total_size(1) /* IFLA_PROTO_DOWN */
1025
- + nla_total_size(4) /* IFLA_IF_NETNSID */
1057
+ + rtnl_proto_down_size(dev) /* proto down */
1058
+ + nla_total_size(4) /* IFLA_TARGET_NETNSID */
10261059 + nla_total_size(4) /* IFLA_CARRIER_UP_COUNT */
10271060 + nla_total_size(4) /* IFLA_CARRIER_DOWN_COUNT */
10281061 + nla_total_size(4) /* IFLA_MIN_MTU */
10291062 + nla_total_size(4) /* IFLA_MAX_MTU */
1063
+ + rtnl_prop_list_size(dev)
1064
+ + nla_total_size(MAX_ADDR_LEN) /* IFLA_PERM_ADDRESS */
10301065 + 0;
10311066 }
10321067
....@@ -1037,12 +1072,12 @@
10371072 int vf;
10381073 int err;
10391074
1040
- vf_ports = nla_nest_start(skb, IFLA_VF_PORTS);
1075
+ vf_ports = nla_nest_start_noflag(skb, IFLA_VF_PORTS);
10411076 if (!vf_ports)
10421077 return -EMSGSIZE;
10431078
10441079 for (vf = 0; vf < dev_num_vf(dev->dev.parent); vf++) {
1045
- vf_port = nla_nest_start(skb, IFLA_VF_PORT);
1080
+ vf_port = nla_nest_start_noflag(skb, IFLA_VF_PORT);
10461081 if (!vf_port)
10471082 goto nla_put_failure;
10481083 if (nla_put_u32(skb, IFLA_PORT_VF, vf))
....@@ -1071,7 +1106,7 @@
10711106 struct nlattr *port_self;
10721107 int err;
10731108
1074
- port_self = nla_nest_start(skb, IFLA_PORT_SELF);
1109
+ port_self = nla_nest_start_noflag(skb, IFLA_PORT_SELF);
10751110 if (!port_self)
10761111 return -EMSGSIZE;
10771112
....@@ -1146,22 +1181,17 @@
11461181
11471182 static int rtnl_phys_switch_id_fill(struct sk_buff *skb, struct net_device *dev)
11481183 {
1184
+ struct netdev_phys_item_id ppid = { };
11491185 int err;
1150
- struct switchdev_attr attr = {
1151
- .orig_dev = dev,
1152
- .id = SWITCHDEV_ATTR_ID_PORT_PARENT_ID,
1153
- .flags = SWITCHDEV_F_NO_RECURSE,
1154
- };
11551186
1156
- err = switchdev_port_attr_get(dev, &attr);
1187
+ err = dev_get_port_parent_id(dev, &ppid, false);
11571188 if (err) {
11581189 if (err == -EOPNOTSUPP)
11591190 return 0;
11601191 return err;
11611192 }
11621193
1163
- if (nla_put(skb, IFLA_PHYS_SWITCH_ID, attr.u.ppid.id_len,
1164
- attr.u.ppid.id))
1194
+ if (nla_put(skb, IFLA_PHYS_SWITCH_ID, ppid.id_len, ppid.id))
11651195 return -EMSGSIZE;
11661196
11671197 return 0;
....@@ -1194,7 +1224,8 @@
11941224 static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb,
11951225 struct net_device *dev,
11961226 int vfs_num,
1197
- struct nlattr *vfinfo)
1227
+ struct nlattr *vfinfo,
1228
+ u32 ext_filter_mask)
11981229 {
11991230 struct ifla_vf_rss_query_en vf_rss_query_en;
12001231 struct nlattr *vf, *vfstats, *vfvlanlist;
....@@ -1207,7 +1238,10 @@
12071238 struct ifla_vf_vlan vf_vlan;
12081239 struct ifla_vf_rate vf_rate;
12091240 struct ifla_vf_mac vf_mac;
1241
+ struct ifla_vf_broadcast vf_broadcast;
12101242 struct ifla_vf_info ivi;
1243
+ struct ifla_vf_guid node_guid;
1244
+ struct ifla_vf_guid port_guid;
12111245
12121246 memset(&ivi, 0, sizeof(ivi));
12131247
....@@ -1229,6 +1263,8 @@
12291263 return 0;
12301264
12311265 memset(&vf_vlan_info, 0, sizeof(vf_vlan_info));
1266
+ memset(&node_guid, 0, sizeof(node_guid));
1267
+ memset(&port_guid, 0, sizeof(port_guid));
12321268
12331269 vf_mac.vf =
12341270 vf_vlan.vf =
....@@ -1238,9 +1274,12 @@
12381274 vf_spoofchk.vf =
12391275 vf_linkstate.vf =
12401276 vf_rss_query_en.vf =
1241
- vf_trust.vf = ivi.vf;
1277
+ vf_trust.vf =
1278
+ node_guid.vf =
1279
+ port_guid.vf = ivi.vf;
12421280
12431281 memcpy(vf_mac.mac, ivi.mac, sizeof(ivi.mac));
1282
+ memcpy(vf_broadcast.broadcast, dev->broadcast, dev->addr_len);
12441283 vf_vlan.vlan = ivi.vlan;
12451284 vf_vlan.qos = ivi.qos;
12461285 vf_vlan_info.vlan = ivi.vlan;
....@@ -1253,10 +1292,11 @@
12531292 vf_linkstate.link_state = ivi.linkstate;
12541293 vf_rss_query_en.setting = ivi.rss_query_en;
12551294 vf_trust.setting = ivi.trusted;
1256
- vf = nla_nest_start(skb, IFLA_VF_INFO);
1295
+ vf = nla_nest_start_noflag(skb, IFLA_VF_INFO);
12571296 if (!vf)
12581297 goto nla_put_vfinfo_failure;
12591298 if (nla_put(skb, IFLA_VF_MAC, sizeof(vf_mac), &vf_mac) ||
1299
+ nla_put(skb, IFLA_VF_BROADCAST, sizeof(vf_broadcast), &vf_broadcast) ||
12601300 nla_put(skb, IFLA_VF_VLAN, sizeof(vf_vlan), &vf_vlan) ||
12611301 nla_put(skb, IFLA_VF_RATE, sizeof(vf_rate),
12621302 &vf_rate) ||
....@@ -1272,7 +1312,17 @@
12721312 nla_put(skb, IFLA_VF_TRUST,
12731313 sizeof(vf_trust), &vf_trust))
12741314 goto nla_put_vf_failure;
1275
- vfvlanlist = nla_nest_start(skb, IFLA_VF_VLAN_LIST);
1315
+
1316
+ if (dev->netdev_ops->ndo_get_vf_guid &&
1317
+ !dev->netdev_ops->ndo_get_vf_guid(dev, vfs_num, &node_guid,
1318
+ &port_guid)) {
1319
+ if (nla_put(skb, IFLA_VF_IB_NODE_GUID, sizeof(node_guid),
1320
+ &node_guid) ||
1321
+ nla_put(skb, IFLA_VF_IB_PORT_GUID, sizeof(port_guid),
1322
+ &port_guid))
1323
+ goto nla_put_vf_failure;
1324
+ }
1325
+ vfvlanlist = nla_nest_start_noflag(skb, IFLA_VF_VLAN_LIST);
12761326 if (!vfvlanlist)
12771327 goto nla_put_vf_failure;
12781328 if (nla_put(skb, IFLA_VF_VLAN_INFO, sizeof(vf_vlan_info),
....@@ -1281,33 +1331,35 @@
12811331 goto nla_put_vf_failure;
12821332 }
12831333 nla_nest_end(skb, vfvlanlist);
1284
- memset(&vf_stats, 0, sizeof(vf_stats));
1285
- if (dev->netdev_ops->ndo_get_vf_stats)
1286
- dev->netdev_ops->ndo_get_vf_stats(dev, vfs_num,
1287
- &vf_stats);
1288
- vfstats = nla_nest_start(skb, IFLA_VF_STATS);
1289
- if (!vfstats)
1290
- goto nla_put_vf_failure;
1291
- if (nla_put_u64_64bit(skb, IFLA_VF_STATS_RX_PACKETS,
1292
- vf_stats.rx_packets, IFLA_VF_STATS_PAD) ||
1293
- nla_put_u64_64bit(skb, IFLA_VF_STATS_TX_PACKETS,
1294
- vf_stats.tx_packets, IFLA_VF_STATS_PAD) ||
1295
- nla_put_u64_64bit(skb, IFLA_VF_STATS_RX_BYTES,
1296
- vf_stats.rx_bytes, IFLA_VF_STATS_PAD) ||
1297
- nla_put_u64_64bit(skb, IFLA_VF_STATS_TX_BYTES,
1298
- vf_stats.tx_bytes, IFLA_VF_STATS_PAD) ||
1299
- nla_put_u64_64bit(skb, IFLA_VF_STATS_BROADCAST,
1300
- vf_stats.broadcast, IFLA_VF_STATS_PAD) ||
1301
- nla_put_u64_64bit(skb, IFLA_VF_STATS_MULTICAST,
1302
- vf_stats.multicast, IFLA_VF_STATS_PAD) ||
1303
- nla_put_u64_64bit(skb, IFLA_VF_STATS_RX_DROPPED,
1304
- vf_stats.rx_dropped, IFLA_VF_STATS_PAD) ||
1305
- nla_put_u64_64bit(skb, IFLA_VF_STATS_TX_DROPPED,
1306
- vf_stats.tx_dropped, IFLA_VF_STATS_PAD)) {
1307
- nla_nest_cancel(skb, vfstats);
1308
- goto nla_put_vf_failure;
1334
+ if (~ext_filter_mask & RTEXT_FILTER_SKIP_STATS) {
1335
+ memset(&vf_stats, 0, sizeof(vf_stats));
1336
+ if (dev->netdev_ops->ndo_get_vf_stats)
1337
+ dev->netdev_ops->ndo_get_vf_stats(dev, vfs_num,
1338
+ &vf_stats);
1339
+ vfstats = nla_nest_start_noflag(skb, IFLA_VF_STATS);
1340
+ if (!vfstats)
1341
+ goto nla_put_vf_failure;
1342
+ if (nla_put_u64_64bit(skb, IFLA_VF_STATS_RX_PACKETS,
1343
+ vf_stats.rx_packets, IFLA_VF_STATS_PAD) ||
1344
+ nla_put_u64_64bit(skb, IFLA_VF_STATS_TX_PACKETS,
1345
+ vf_stats.tx_packets, IFLA_VF_STATS_PAD) ||
1346
+ nla_put_u64_64bit(skb, IFLA_VF_STATS_RX_BYTES,
1347
+ vf_stats.rx_bytes, IFLA_VF_STATS_PAD) ||
1348
+ nla_put_u64_64bit(skb, IFLA_VF_STATS_TX_BYTES,
1349
+ vf_stats.tx_bytes, IFLA_VF_STATS_PAD) ||
1350
+ nla_put_u64_64bit(skb, IFLA_VF_STATS_BROADCAST,
1351
+ vf_stats.broadcast, IFLA_VF_STATS_PAD) ||
1352
+ nla_put_u64_64bit(skb, IFLA_VF_STATS_MULTICAST,
1353
+ vf_stats.multicast, IFLA_VF_STATS_PAD) ||
1354
+ nla_put_u64_64bit(skb, IFLA_VF_STATS_RX_DROPPED,
1355
+ vf_stats.rx_dropped, IFLA_VF_STATS_PAD) ||
1356
+ nla_put_u64_64bit(skb, IFLA_VF_STATS_TX_DROPPED,
1357
+ vf_stats.tx_dropped, IFLA_VF_STATS_PAD)) {
1358
+ nla_nest_cancel(skb, vfstats);
1359
+ goto nla_put_vf_failure;
1360
+ }
1361
+ nla_nest_end(skb, vfstats);
13091362 }
1310
- nla_nest_end(skb, vfstats);
13111363 nla_nest_end(skb, vf);
13121364 return 0;
13131365
....@@ -1335,12 +1387,12 @@
13351387 if (!dev->netdev_ops->ndo_get_vf_config)
13361388 return 0;
13371389
1338
- vfinfo = nla_nest_start(skb, IFLA_VFINFO_LIST);
1390
+ vfinfo = nla_nest_start_noflag(skb, IFLA_VFINFO_LIST);
13391391 if (!vfinfo)
13401392 return -EMSGSIZE;
13411393
13421394 for (i = 0; i < num_vfs; i++) {
1343
- if (rtnl_fill_vfinfo(skb, dev, i, vfinfo))
1395
+ if (rtnl_fill_vfinfo(skb, dev, i, vfinfo, ext_filter_mask))
13441396 return -EMSGSIZE;
13451397 }
13461398
....@@ -1380,13 +1432,12 @@
13801432
13811433 static u32 rtnl_xdp_prog_drv(struct net_device *dev)
13821434 {
1383
- return __dev_xdp_query(dev, dev->netdev_ops->ndo_bpf, XDP_QUERY_PROG);
1435
+ return dev_xdp_prog_id(dev, XDP_MODE_DRV);
13841436 }
13851437
13861438 static u32 rtnl_xdp_prog_hw(struct net_device *dev)
13871439 {
1388
- return __dev_xdp_query(dev, dev->netdev_ops->ndo_bpf,
1389
- XDP_QUERY_PROG_HW);
1440
+ return dev_xdp_prog_id(dev, XDP_MODE_HW);
13901441 }
13911442
13921443 static int rtnl_xdp_report_one(struct sk_buff *skb, struct net_device *dev,
....@@ -1420,7 +1471,7 @@
14201471 int err;
14211472 u8 mode;
14221473
1423
- xdp = nla_nest_start(skb, IFLA_XDP);
1474
+ xdp = nla_nest_start_noflag(skb, IFLA_XDP);
14241475 if (!xdp)
14251476 return -EMSGSIZE;
14261477
....@@ -1552,7 +1603,7 @@
15521603 const struct rtnl_af_ops *af_ops;
15531604 struct nlattr *af_spec;
15541605
1555
- af_spec = nla_nest_start(skb, IFLA_AF_SPEC);
1606
+ af_spec = nla_nest_start_noflag(skb, IFLA_AF_SPEC);
15561607 if (!af_spec)
15571608 return -EMSGSIZE;
15581609
....@@ -1563,7 +1614,7 @@
15631614 if (!af_ops->fill_link_af)
15641615 continue;
15651616
1566
- af = nla_nest_start(skb, af_ops->family);
1617
+ af = nla_nest_start_noflag(skb, af_ops->family);
15671618 if (!af)
15681619 return -EMSGSIZE;
15691620
....@@ -1586,6 +1637,71 @@
15861637 return 0;
15871638 }
15881639
1640
+static int rtnl_fill_alt_ifnames(struct sk_buff *skb,
1641
+ const struct net_device *dev)
1642
+{
1643
+ struct netdev_name_node *name_node;
1644
+ int count = 0;
1645
+
1646
+ list_for_each_entry(name_node, &dev->name_node->list, list) {
1647
+ if (nla_put_string(skb, IFLA_ALT_IFNAME, name_node->name))
1648
+ return -EMSGSIZE;
1649
+ count++;
1650
+ }
1651
+ return count;
1652
+}
1653
+
1654
+static int rtnl_fill_prop_list(struct sk_buff *skb,
1655
+ const struct net_device *dev)
1656
+{
1657
+ struct nlattr *prop_list;
1658
+ int ret;
1659
+
1660
+ prop_list = nla_nest_start(skb, IFLA_PROP_LIST);
1661
+ if (!prop_list)
1662
+ return -EMSGSIZE;
1663
+
1664
+ ret = rtnl_fill_alt_ifnames(skb, dev);
1665
+ if (ret <= 0)
1666
+ goto nest_cancel;
1667
+
1668
+ nla_nest_end(skb, prop_list);
1669
+ return 0;
1670
+
1671
+nest_cancel:
1672
+ nla_nest_cancel(skb, prop_list);
1673
+ return ret;
1674
+}
1675
+
1676
+static int rtnl_fill_proto_down(struct sk_buff *skb,
1677
+ const struct net_device *dev)
1678
+{
1679
+ struct nlattr *pr;
1680
+ u32 preason;
1681
+
1682
+ if (nla_put_u8(skb, IFLA_PROTO_DOWN, dev->proto_down))
1683
+ goto nla_put_failure;
1684
+
1685
+ preason = dev->proto_down_reason;
1686
+ if (!preason)
1687
+ return 0;
1688
+
1689
+ pr = nla_nest_start(skb, IFLA_PROTO_DOWN_REASON);
1690
+ if (!pr)
1691
+ return -EMSGSIZE;
1692
+
1693
+ if (nla_put_u32(skb, IFLA_PROTO_DOWN_REASON_VALUE, preason)) {
1694
+ nla_nest_cancel(skb, pr);
1695
+ goto nla_put_failure;
1696
+ }
1697
+
1698
+ nla_nest_end(skb, pr);
1699
+ return 0;
1700
+
1701
+nla_put_failure:
1702
+ return -EMSGSIZE;
1703
+}
1704
+
15891705 static int rtnl_fill_ifinfo(struct sk_buff *skb,
15901706 struct net_device *dev, struct net *src_net,
15911707 int type, u32 pid, u32 seq, u32 change,
....@@ -1595,6 +1711,7 @@
15951711 {
15961712 struct ifinfomsg *ifm;
15971713 struct nlmsghdr *nlh;
1714
+ struct Qdisc *qdisc;
15981715
15991716 ASSERT_RTNL();
16001717 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ifm), flags);
....@@ -1609,9 +1726,10 @@
16091726 ifm->ifi_flags = dev_get_flags(dev);
16101727 ifm->ifi_change = change;
16111728
1612
- if (tgt_netnsid >= 0 && nla_put_s32(skb, IFLA_IF_NETNSID, tgt_netnsid))
1729
+ if (tgt_netnsid >= 0 && nla_put_s32(skb, IFLA_TARGET_NETNSID, tgt_netnsid))
16131730 goto nla_put_failure;
16141731
1732
+ qdisc = rtnl_dereference(dev->qdisc);
16151733 if (nla_put_string(skb, IFLA_IFNAME, dev->name) ||
16161734 nla_put_u32(skb, IFLA_TXQLEN, dev->tx_queue_len) ||
16171735 nla_put_u8(skb, IFLA_OPERSTATE,
....@@ -1630,17 +1748,19 @@
16301748 #endif
16311749 put_master_ifindex(skb, dev) ||
16321750 nla_put_u8(skb, IFLA_CARRIER, netif_carrier_ok(dev)) ||
1633
- (dev->qdisc &&
1634
- nla_put_string(skb, IFLA_QDISC, dev->qdisc->ops->id)) ||
1751
+ (qdisc &&
1752
+ nla_put_string(skb, IFLA_QDISC, qdisc->ops->id)) ||
16351753 nla_put_ifalias(skb, dev) ||
16361754 nla_put_u32(skb, IFLA_CARRIER_CHANGES,
16371755 atomic_read(&dev->carrier_up_count) +
16381756 atomic_read(&dev->carrier_down_count)) ||
1639
- nla_put_u8(skb, IFLA_PROTO_DOWN, dev->proto_down) ||
16401757 nla_put_u32(skb, IFLA_CARRIER_UP_COUNT,
16411758 atomic_read(&dev->carrier_up_count)) ||
16421759 nla_put_u32(skb, IFLA_CARRIER_DOWN_COUNT,
16431760 atomic_read(&dev->carrier_down_count)))
1761
+ goto nla_put_failure;
1762
+
1763
+ if (rtnl_fill_proto_down(skb, dev))
16441764 goto nla_put_failure;
16451765
16461766 if (event != IFLA_EVENT_NONE) {
....@@ -1693,11 +1813,17 @@
16931813 nla_put_s32(skb, IFLA_NEW_IFINDEX, new_ifindex) < 0)
16941814 goto nla_put_failure;
16951815
1816
+ if (memchr_inv(dev->perm_addr, '\0', dev->addr_len) &&
1817
+ nla_put(skb, IFLA_PERM_ADDRESS, dev->addr_len, dev->perm_addr))
1818
+ goto nla_put_failure;
16961819
16971820 rcu_read_lock();
16981821 if (rtnl_fill_link_af(skb, dev, ext_filter_mask))
16991822 goto nla_put_failure_rcu;
17001823 rcu_read_unlock();
1824
+
1825
+ if (rtnl_fill_prop_list(skb, dev))
1826
+ goto nla_put_failure;
17011827
17021828 nlmsg_end(skb, nlh);
17031829 return 0;
....@@ -1747,11 +1873,16 @@
17471873 [IFLA_XDP] = { .type = NLA_NESTED },
17481874 [IFLA_EVENT] = { .type = NLA_U32 },
17491875 [IFLA_GROUP] = { .type = NLA_U32 },
1750
- [IFLA_IF_NETNSID] = { .type = NLA_S32 },
1876
+ [IFLA_TARGET_NETNSID] = { .type = NLA_S32 },
17511877 [IFLA_CARRIER_UP_COUNT] = { .type = NLA_U32 },
17521878 [IFLA_CARRIER_DOWN_COUNT] = { .type = NLA_U32 },
17531879 [IFLA_MIN_MTU] = { .type = NLA_U32 },
17541880 [IFLA_MAX_MTU] = { .type = NLA_U32 },
1881
+ [IFLA_PROP_LIST] = { .type = NLA_NESTED },
1882
+ [IFLA_ALT_IFNAME] = { .type = NLA_STRING,
1883
+ .len = ALTIFNAMSIZ - 1 },
1884
+ [IFLA_PERM_ADDRESS] = { .type = NLA_REJECT },
1885
+ [IFLA_PROTO_DOWN_REASON] = { .type = NLA_NESTED },
17551886 };
17561887
17571888 static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
....@@ -1763,6 +1894,7 @@
17631894
17641895 static const struct nla_policy ifla_vf_policy[IFLA_VF_MAX+1] = {
17651896 [IFLA_VF_MAC] = { .len = sizeof(struct ifla_vf_mac) },
1897
+ [IFLA_VF_BROADCAST] = { .type = NLA_REJECT },
17661898 [IFLA_VF_VLAN] = { .len = sizeof(struct ifla_vf_vlan) },
17671899 [IFLA_VF_VLAN_LIST] = { .type = NLA_NESTED },
17681900 [IFLA_VF_TX_RATE] = { .len = sizeof(struct ifla_vf_tx_rate) },
....@@ -1796,7 +1928,9 @@
17961928 };
17971929
17981930 static const struct nla_policy ifla_xdp_policy[IFLA_XDP_MAX + 1] = {
1931
+ [IFLA_XDP_UNSPEC] = { .strict_start_type = IFLA_XDP_EXPECTED_FD },
17991932 [IFLA_XDP_FD] = { .type = NLA_S32 },
1933
+ [IFLA_XDP_EXPECTED_FD] = { .type = NLA_S32 },
18001934 [IFLA_XDP_ATTACHED] = { .type = NLA_U8 },
18011935 [IFLA_XDP_FLAGS] = { .type = NLA_U32 },
18021936 [IFLA_XDP_PROG_ID] = { .type = NLA_U32 },
....@@ -1807,8 +1941,7 @@
18071941 const struct rtnl_link_ops *ops = NULL;
18081942 struct nlattr *linfo[IFLA_INFO_MAX + 1];
18091943
1810
- if (nla_parse_nested(linfo, IFLA_INFO_MAX, nla,
1811
- ifla_info_policy, NULL) < 0)
1944
+ if (nla_parse_nested_deprecated(linfo, IFLA_INFO_MAX, nla, ifla_info_policy, NULL) < 0)
18121945 return NULL;
18131946
18141947 if (linfo[IFLA_INFO_KIND]) {
....@@ -1855,7 +1988,15 @@
18551988 return false;
18561989 }
18571990
1858
-static struct net *get_target_net(struct sock *sk, int netnsid)
1991
+/**
1992
+ * rtnl_get_net_ns_capable - Get netns if sufficiently privileged.
1993
+ * @sk: netlink socket
1994
+ * @netnsid: network namespace identifier
1995
+ *
1996
+ * Returns the network namespace identified by netnsid on success or an error
1997
+ * pointer on failure.
1998
+ */
1999
+struct net *rtnl_get_net_ns_capable(struct sock *sk, int netnsid)
18592000 {
18602001 struct net *net;
18612002
....@@ -1872,9 +2013,56 @@
18722013 }
18732014 return net;
18742015 }
2016
+EXPORT_SYMBOL_GPL(rtnl_get_net_ns_capable);
2017
+
2018
+static int rtnl_valid_dump_ifinfo_req(const struct nlmsghdr *nlh,
2019
+ bool strict_check, struct nlattr **tb,
2020
+ struct netlink_ext_ack *extack)
2021
+{
2022
+ int hdrlen;
2023
+
2024
+ if (strict_check) {
2025
+ struct ifinfomsg *ifm;
2026
+
2027
+ if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ifm))) {
2028
+ NL_SET_ERR_MSG(extack, "Invalid header for link dump");
2029
+ return -EINVAL;
2030
+ }
2031
+
2032
+ ifm = nlmsg_data(nlh);
2033
+ if (ifm->__ifi_pad || ifm->ifi_type || ifm->ifi_flags ||
2034
+ ifm->ifi_change) {
2035
+ NL_SET_ERR_MSG(extack, "Invalid values in header for link dump request");
2036
+ return -EINVAL;
2037
+ }
2038
+ if (ifm->ifi_index) {
2039
+ NL_SET_ERR_MSG(extack, "Filter by device index not supported for link dumps");
2040
+ return -EINVAL;
2041
+ }
2042
+
2043
+ return nlmsg_parse_deprecated_strict(nlh, sizeof(*ifm), tb,
2044
+ IFLA_MAX, ifla_policy,
2045
+ extack);
2046
+ }
2047
+
2048
+ /* A hack to preserve kernel<->userspace interface.
2049
+ * The correct header is ifinfomsg. It is consistent with rtnl_getlink.
2050
+ * However, before Linux v3.9 the code here assumed rtgenmsg and that's
2051
+ * what iproute2 < v3.9.0 used.
2052
+ * We can detect the old iproute2. Even including the IFLA_EXT_MASK
2053
+ * attribute, its netlink message is shorter than struct ifinfomsg.
2054
+ */
2055
+ hdrlen = nlmsg_len(nlh) < sizeof(struct ifinfomsg) ?
2056
+ sizeof(struct rtgenmsg) : sizeof(struct ifinfomsg);
2057
+
2058
+ return nlmsg_parse_deprecated(nlh, hdrlen, tb, IFLA_MAX, ifla_policy,
2059
+ extack);
2060
+}
18752061
18762062 static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
18772063 {
2064
+ struct netlink_ext_ack *extack = cb->extack;
2065
+ const struct nlmsghdr *nlh = cb->nlh;
18782066 struct net *net = sock_net(skb->sk);
18792067 struct net *tgt_net = net;
18802068 int h, s_h;
....@@ -1887,44 +2075,54 @@
18872075 unsigned int flags = NLM_F_MULTI;
18882076 int master_idx = 0;
18892077 int netnsid = -1;
1890
- int err;
1891
- int hdrlen;
2078
+ int err, i;
18922079
18932080 s_h = cb->args[0];
18942081 s_idx = cb->args[1];
18952082
1896
- /* A hack to preserve kernel<->userspace interface.
1897
- * The correct header is ifinfomsg. It is consistent with rtnl_getlink.
1898
- * However, before Linux v3.9 the code here assumed rtgenmsg and that's
1899
- * what iproute2 < v3.9.0 used.
1900
- * We can detect the old iproute2. Even including the IFLA_EXT_MASK
1901
- * attribute, its netlink message is shorter than struct ifinfomsg.
1902
- */
1903
- hdrlen = nlmsg_len(cb->nlh) < sizeof(struct ifinfomsg) ?
1904
- sizeof(struct rtgenmsg) : sizeof(struct ifinfomsg);
2083
+ err = rtnl_valid_dump_ifinfo_req(nlh, cb->strict_check, tb, extack);
2084
+ if (err < 0) {
2085
+ if (cb->strict_check)
2086
+ return err;
19052087
1906
- if (nlmsg_parse(cb->nlh, hdrlen, tb, IFLA_MAX,
1907
- ifla_policy, NULL) >= 0) {
1908
- if (tb[IFLA_IF_NETNSID]) {
1909
- netnsid = nla_get_s32(tb[IFLA_IF_NETNSID]);
1910
- tgt_net = get_target_net(skb->sk, netnsid);
1911
- if (IS_ERR(tgt_net))
1912
- return PTR_ERR(tgt_net);
1913
- }
1914
-
1915
- if (tb[IFLA_EXT_MASK])
1916
- ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]);
1917
-
1918
- if (tb[IFLA_MASTER])
1919
- master_idx = nla_get_u32(tb[IFLA_MASTER]);
1920
-
1921
- if (tb[IFLA_LINKINFO])
1922
- kind_ops = linkinfo_to_kind_ops(tb[IFLA_LINKINFO]);
1923
-
1924
- if (master_idx || kind_ops)
1925
- flags |= NLM_F_DUMP_FILTERED;
2088
+ goto walk_entries;
19262089 }
19272090
2091
+ for (i = 0; i <= IFLA_MAX; ++i) {
2092
+ if (!tb[i])
2093
+ continue;
2094
+
2095
+ /* new attributes should only be added with strict checking */
2096
+ switch (i) {
2097
+ case IFLA_TARGET_NETNSID:
2098
+ netnsid = nla_get_s32(tb[i]);
2099
+ tgt_net = rtnl_get_net_ns_capable(skb->sk, netnsid);
2100
+ if (IS_ERR(tgt_net)) {
2101
+ NL_SET_ERR_MSG(extack, "Invalid target network namespace id");
2102
+ return PTR_ERR(tgt_net);
2103
+ }
2104
+ break;
2105
+ case IFLA_EXT_MASK:
2106
+ ext_filter_mask = nla_get_u32(tb[i]);
2107
+ break;
2108
+ case IFLA_MASTER:
2109
+ master_idx = nla_get_u32(tb[i]);
2110
+ break;
2111
+ case IFLA_LINKINFO:
2112
+ kind_ops = linkinfo_to_kind_ops(tb[i]);
2113
+ break;
2114
+ default:
2115
+ if (cb->strict_check) {
2116
+ NL_SET_ERR_MSG(extack, "Unsupported attribute in link dump request");
2117
+ return -EINVAL;
2118
+ }
2119
+ }
2120
+ }
2121
+
2122
+ if (master_idx || kind_ops)
2123
+ flags |= NLM_F_DUMP_FILTERED;
2124
+
2125
+walk_entries:
19282126 for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
19292127 idx = 0;
19302128 head = &tgt_net->dev_index_head[h];
....@@ -1936,8 +2134,7 @@
19362134 err = rtnl_fill_ifinfo(skb, dev, net,
19372135 RTM_NEWLINK,
19382136 NETLINK_CB(cb->skb).portid,
1939
- cb->nlh->nlmsg_seq, 0,
1940
- flags,
2137
+ nlh->nlmsg_seq, 0, flags,
19412138 ext_filter_mask, 0, NULL, 0,
19422139 netnsid, GFP_KERNEL);
19432140
....@@ -1964,12 +2161,27 @@
19642161 return err;
19652162 }
19662163
1967
-int rtnl_nla_parse_ifla(struct nlattr **tb, const struct nlattr *head, int len,
1968
- struct netlink_ext_ack *exterr)
2164
+int rtnl_nla_parse_ifinfomsg(struct nlattr **tb, const struct nlattr *nla_peer,
2165
+ struct netlink_ext_ack *exterr)
19692166 {
1970
- return nla_parse(tb, IFLA_MAX, head, len, ifla_policy, exterr);
2167
+ const struct ifinfomsg *ifmp;
2168
+ const struct nlattr *attrs;
2169
+ size_t len;
2170
+
2171
+ ifmp = nla_data(nla_peer);
2172
+ attrs = nla_data(nla_peer) + sizeof(struct ifinfomsg);
2173
+ len = nla_len(nla_peer) - sizeof(struct ifinfomsg);
2174
+
2175
+ if (ifmp->ifi_index < 0) {
2176
+ NL_SET_ERR_MSG_ATTR(exterr, nla_peer,
2177
+ "ifindex can't be negative");
2178
+ return -EINVAL;
2179
+ }
2180
+
2181
+ return nla_parse_deprecated(tb, IFLA_MAX, attrs, len, ifla_policy,
2182
+ exterr);
19712183 }
1972
-EXPORT_SYMBOL(rtnl_nla_parse_ifla);
2184
+EXPORT_SYMBOL(rtnl_nla_parse_ifinfomsg);
19732185
19742186 struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[])
19752187 {
....@@ -1992,7 +2204,7 @@
19922204 *
19932205 * 1. IFLA_NET_NS_PID
19942206 * 2. IFLA_NET_NS_FD
1995
- * 3. IFLA_IF_NETNSID
2207
+ * 3. IFLA_TARGET_NETNSID
19962208 */
19972209 static struct net *rtnl_link_get_net_by_nlattr(struct net *src_net,
19982210 struct nlattr *tb[])
....@@ -2002,10 +2214,10 @@
20022214 if (tb[IFLA_NET_NS_PID] || tb[IFLA_NET_NS_FD])
20032215 return rtnl_link_get_net(src_net, tb);
20042216
2005
- if (!tb[IFLA_IF_NETNSID])
2217
+ if (!tb[IFLA_TARGET_NETNSID])
20062218 return get_net(src_net);
20072219
2008
- net = get_net_ns_by_id(src_net, nla_get_u32(tb[IFLA_IF_NETNSID]));
2220
+ net = get_net_ns_by_id(src_net, nla_get_u32(tb[IFLA_TARGET_NETNSID]));
20092221 if (!net)
20102222 return ERR_PTR(-EINVAL);
20112223
....@@ -2046,13 +2258,13 @@
20462258 return -EOPNOTSUPP;
20472259 }
20482260
2049
- if (tb[IFLA_IF_NETNSID] && (tb[IFLA_NET_NS_PID] || tb[IFLA_NET_NS_FD]))
2261
+ if (tb[IFLA_TARGET_NETNSID] && (tb[IFLA_NET_NS_PID] || tb[IFLA_NET_NS_FD]))
20502262 goto invalid_attr;
20512263
2052
- if (tb[IFLA_NET_NS_PID] && (tb[IFLA_IF_NETNSID] || tb[IFLA_NET_NS_FD]))
2264
+ if (tb[IFLA_NET_NS_PID] && (tb[IFLA_TARGET_NETNSID] || tb[IFLA_NET_NS_FD]))
20532265 goto invalid_attr;
20542266
2055
- if (tb[IFLA_NET_NS_FD] && (tb[IFLA_IF_NETNSID] || tb[IFLA_NET_NS_PID]))
2267
+ if (tb[IFLA_NET_NS_FD] && (tb[IFLA_TARGET_NETNSID] || tb[IFLA_NET_NS_PID]))
20562268 goto invalid_attr;
20572269
20582270 return 0;
....@@ -2334,6 +2546,67 @@
23342546 return 0;
23352547 }
23362548
2549
+static const struct nla_policy ifla_proto_down_reason_policy[IFLA_PROTO_DOWN_REASON_VALUE + 1] = {
2550
+ [IFLA_PROTO_DOWN_REASON_MASK] = { .type = NLA_U32 },
2551
+ [IFLA_PROTO_DOWN_REASON_VALUE] = { .type = NLA_U32 },
2552
+};
2553
+
2554
+static int do_set_proto_down(struct net_device *dev,
2555
+ struct nlattr *nl_proto_down,
2556
+ struct nlattr *nl_proto_down_reason,
2557
+ struct netlink_ext_ack *extack)
2558
+{
2559
+ struct nlattr *pdreason[IFLA_PROTO_DOWN_REASON_MAX + 1];
2560
+ const struct net_device_ops *ops = dev->netdev_ops;
2561
+ unsigned long mask = 0;
2562
+ u32 value;
2563
+ bool proto_down;
2564
+ int err;
2565
+
2566
+ if (!ops->ndo_change_proto_down) {
2567
+ NL_SET_ERR_MSG(extack, "Protodown not supported by device");
2568
+ return -EOPNOTSUPP;
2569
+ }
2570
+
2571
+ if (nl_proto_down_reason) {
2572
+ err = nla_parse_nested_deprecated(pdreason,
2573
+ IFLA_PROTO_DOWN_REASON_MAX,
2574
+ nl_proto_down_reason,
2575
+ ifla_proto_down_reason_policy,
2576
+ NULL);
2577
+ if (err < 0)
2578
+ return err;
2579
+
2580
+ if (!pdreason[IFLA_PROTO_DOWN_REASON_VALUE]) {
2581
+ NL_SET_ERR_MSG(extack, "Invalid protodown reason value");
2582
+ return -EINVAL;
2583
+ }
2584
+
2585
+ value = nla_get_u32(pdreason[IFLA_PROTO_DOWN_REASON_VALUE]);
2586
+
2587
+ if (pdreason[IFLA_PROTO_DOWN_REASON_MASK])
2588
+ mask = nla_get_u32(pdreason[IFLA_PROTO_DOWN_REASON_MASK]);
2589
+
2590
+ dev_change_proto_down_reason(dev, mask, value);
2591
+ }
2592
+
2593
+ if (nl_proto_down) {
2594
+ proto_down = nla_get_u8(nl_proto_down);
2595
+
2596
+ /* Dont turn off protodown if there are active reasons */
2597
+ if (!proto_down && dev->proto_down_reason) {
2598
+ NL_SET_ERR_MSG(extack, "Cannot clear protodown, active reasons");
2599
+ return -EBUSY;
2600
+ }
2601
+ err = dev_change_proto_down(dev,
2602
+ proto_down);
2603
+ if (err)
2604
+ return err;
2605
+ }
2606
+
2607
+ return 0;
2608
+}
2609
+
23372610 #define DO_SETLINK_MODIFIED 0x01
23382611 /* notify flag means notify + modified. */
23392612 #define DO_SETLINK_NOTIFY 0x03
....@@ -2349,7 +2622,8 @@
23492622 if (err < 0)
23502623 return err;
23512624
2352
- if (tb[IFLA_NET_NS_PID] || tb[IFLA_NET_NS_FD] || tb[IFLA_IF_NETNSID]) {
2625
+ if (tb[IFLA_NET_NS_PID] || tb[IFLA_NET_NS_FD] || tb[IFLA_TARGET_NETNSID]) {
2626
+ const char *pat = ifname && ifname[0] ? ifname : NULL;
23532627 struct net *net = rtnl_link_get_net_capable(skb, dev_net(dev),
23542628 tb, CAP_NET_ADMIN);
23552629 if (IS_ERR(net)) {
....@@ -2357,7 +2631,7 @@
23572631 goto errout;
23582632 }
23592633
2360
- err = dev_change_net_namespace(dev, net, ifname);
2634
+ err = dev_change_net_namespace(dev, net, pat);
23612635 put_net(net);
23622636 if (err)
23632637 goto errout;
....@@ -2407,7 +2681,7 @@
24072681 sa->sa_family = dev->type;
24082682 memcpy(sa->sa_data, nla_data(tb[IFLA_ADDRESS]),
24092683 dev->addr_len);
2410
- err = dev_set_mac_address(dev, sa);
2684
+ err = dev_set_mac_address_user(dev, sa, extack);
24112685 kfree(sa);
24122686 if (err)
24132687 goto errout;
....@@ -2452,7 +2726,8 @@
24522726 }
24532727
24542728 if (ifm->ifi_flags || ifm->ifi_change) {
2455
- err = dev_change_flags(dev, rtnl_dev_combine_flags(dev, ifm));
2729
+ err = dev_change_flags(dev, rtnl_dev_combine_flags(dev, ifm),
2730
+ extack);
24562731 if (err < 0)
24572732 goto errout;
24582733 }
....@@ -2532,8 +2807,10 @@
25322807 err = -EINVAL;
25332808 goto errout;
25342809 }
2535
- err = nla_parse_nested(vfinfo, IFLA_VF_MAX, attr,
2536
- ifla_vf_policy, NULL);
2810
+ err = nla_parse_nested_deprecated(vfinfo, IFLA_VF_MAX,
2811
+ attr,
2812
+ ifla_vf_policy,
2813
+ NULL);
25372814 if (err < 0)
25382815 goto errout;
25392816 err = do_setvfinfo(dev, vfinfo);
....@@ -2560,8 +2837,10 @@
25602837 err = -EINVAL;
25612838 goto errout;
25622839 }
2563
- err = nla_parse_nested(port, IFLA_PORT_MAX, attr,
2564
- ifla_port_policy, NULL);
2840
+ err = nla_parse_nested_deprecated(port, IFLA_PORT_MAX,
2841
+ attr,
2842
+ ifla_port_policy,
2843
+ NULL);
25652844 if (err < 0)
25662845 goto errout;
25672846 if (!port[IFLA_PORT_VF]) {
....@@ -2580,9 +2859,9 @@
25802859 if (tb[IFLA_PORT_SELF]) {
25812860 struct nlattr *port[IFLA_PORT_MAX+1];
25822861
2583
- err = nla_parse_nested(port, IFLA_PORT_MAX,
2584
- tb[IFLA_PORT_SELF], ifla_port_policy,
2585
- NULL);
2862
+ err = nla_parse_nested_deprecated(port, IFLA_PORT_MAX,
2863
+ tb[IFLA_PORT_SELF],
2864
+ ifla_port_policy, NULL);
25862865 if (err < 0)
25872866 goto errout;
25882867
....@@ -2617,9 +2896,9 @@
26172896 }
26182897 err = 0;
26192898
2620
- if (tb[IFLA_PROTO_DOWN]) {
2621
- err = dev_change_proto_down(dev,
2622
- nla_get_u8(tb[IFLA_PROTO_DOWN]));
2899
+ if (tb[IFLA_PROTO_DOWN] || tb[IFLA_PROTO_DOWN_REASON]) {
2900
+ err = do_set_proto_down(dev, tb[IFLA_PROTO_DOWN],
2901
+ tb[IFLA_PROTO_DOWN_REASON], extack);
26232902 if (err)
26242903 goto errout;
26252904 status |= DO_SETLINK_NOTIFY;
....@@ -2629,8 +2908,9 @@
26292908 struct nlattr *xdp[IFLA_XDP_MAX + 1];
26302909 u32 xdp_flags = 0;
26312910
2632
- err = nla_parse_nested(xdp, IFLA_XDP_MAX, tb[IFLA_XDP],
2633
- ifla_xdp_policy, NULL);
2911
+ err = nla_parse_nested_deprecated(xdp, IFLA_XDP_MAX,
2912
+ tb[IFLA_XDP],
2913
+ ifla_xdp_policy, NULL);
26342914 if (err < 0)
26352915 goto errout;
26362916
....@@ -2652,8 +2932,20 @@
26522932 }
26532933
26542934 if (xdp[IFLA_XDP_FD]) {
2935
+ int expected_fd = -1;
2936
+
2937
+ if (xdp_flags & XDP_FLAGS_REPLACE) {
2938
+ if (!xdp[IFLA_XDP_EXPECTED_FD]) {
2939
+ err = -EINVAL;
2940
+ goto errout;
2941
+ }
2942
+ expected_fd =
2943
+ nla_get_s32(xdp[IFLA_XDP_EXPECTED_FD]);
2944
+ }
2945
+
26552946 err = dev_change_xdp_fd(dev, extack,
26562947 nla_get_s32(xdp[IFLA_XDP_FD]),
2948
+ expected_fd,
26572949 xdp_flags);
26582950 if (err)
26592951 goto errout;
....@@ -2674,6 +2966,26 @@
26742966 return err;
26752967 }
26762968
2969
+static struct net_device *rtnl_dev_get(struct net *net,
2970
+ struct nlattr *ifname_attr,
2971
+ struct nlattr *altifname_attr,
2972
+ char *ifname)
2973
+{
2974
+ char buffer[ALTIFNAMSIZ];
2975
+
2976
+ if (!ifname) {
2977
+ ifname = buffer;
2978
+ if (ifname_attr)
2979
+ nla_strlcpy(ifname, ifname_attr, IFNAMSIZ);
2980
+ else if (altifname_attr)
2981
+ nla_strlcpy(ifname, altifname_attr, ALTIFNAMSIZ);
2982
+ else
2983
+ return NULL;
2984
+ }
2985
+
2986
+ return __dev_get_by_name(net, ifname);
2987
+}
2988
+
26772989 static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh,
26782990 struct netlink_ext_ack *extack)
26792991 {
....@@ -2684,8 +2996,8 @@
26842996 struct nlattr *tb[IFLA_MAX+1];
26852997 char ifname[IFNAMSIZ];
26862998
2687
- err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy,
2688
- extack);
2999
+ err = nlmsg_parse_deprecated(nlh, sizeof(*ifm), tb, IFLA_MAX,
3000
+ ifla_policy, extack);
26893001 if (err < 0)
26903002 goto errout;
26913003
....@@ -2702,8 +3014,8 @@
27023014 ifm = nlmsg_data(nlh);
27033015 if (ifm->ifi_index > 0)
27043016 dev = __dev_get_by_index(net, ifm->ifi_index);
2705
- else if (tb[IFLA_IFNAME])
2706
- dev = __dev_get_by_name(net, ifname);
3017
+ else if (tb[IFLA_IFNAME] || tb[IFLA_ALT_IFNAME])
3018
+ dev = rtnl_dev_get(net, NULL, tb[IFLA_ALT_IFNAME], ifname);
27073019 else
27083020 goto errout;
27093021
....@@ -2776,12 +3088,12 @@
27763088 struct net *tgt_net = net;
27773089 struct net_device *dev = NULL;
27783090 struct ifinfomsg *ifm;
2779
- char ifname[IFNAMSIZ];
27803091 struct nlattr *tb[IFLA_MAX+1];
27813092 int err;
27823093 int netnsid = -1;
27833094
2784
- err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy, extack);
3095
+ err = nlmsg_parse_deprecated(nlh, sizeof(*ifm), tb, IFLA_MAX,
3096
+ ifla_policy, extack);
27853097 if (err < 0)
27863098 return err;
27873099
....@@ -2789,12 +3101,9 @@
27893101 if (err < 0)
27903102 return err;
27913103
2792
- if (tb[IFLA_IFNAME])
2793
- nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ);
2794
-
2795
- if (tb[IFLA_IF_NETNSID]) {
2796
- netnsid = nla_get_s32(tb[IFLA_IF_NETNSID]);
2797
- tgt_net = get_target_net(NETLINK_CB(skb).sk, netnsid);
3104
+ if (tb[IFLA_TARGET_NETNSID]) {
3105
+ netnsid = nla_get_s32(tb[IFLA_TARGET_NETNSID]);
3106
+ tgt_net = rtnl_get_net_ns_capable(NETLINK_CB(skb).sk, netnsid);
27983107 if (IS_ERR(tgt_net))
27993108 return PTR_ERR(tgt_net);
28003109 }
....@@ -2803,8 +3112,9 @@
28033112 ifm = nlmsg_data(nlh);
28043113 if (ifm->ifi_index > 0)
28053114 dev = __dev_get_by_index(tgt_net, ifm->ifi_index);
2806
- else if (tb[IFLA_IFNAME])
2807
- dev = __dev_get_by_name(tgt_net, ifname);
3115
+ else if (tb[IFLA_IFNAME] || tb[IFLA_ALT_IFNAME])
3116
+ dev = rtnl_dev_get(net, tb[IFLA_IFNAME],
3117
+ tb[IFLA_ALT_IFNAME], NULL);
28083118 else if (tb[IFLA_GROUP])
28093119 err = rtnl_group_dellink(tgt_net, nla_get_u32(tb[IFLA_GROUP]));
28103120 else
....@@ -2833,7 +3143,8 @@
28333143
28343144 old_flags = dev->flags;
28353145 if (ifm && (ifm->ifi_flags || ifm->ifi_change)) {
2836
- err = __dev_change_flags(dev, rtnl_dev_combine_flags(dev, ifm));
3146
+ err = __dev_change_flags(dev, rtnl_dev_combine_flags(dev, ifm),
3147
+ NULL);
28373148 if (err < 0)
28383149 return err;
28393150 }
....@@ -2848,9 +3159,11 @@
28483159 }
28493160 EXPORT_SYMBOL(rtnl_configure_link);
28503161
2851
-struct net_device *rtnl_create_link(struct net *net,
2852
- const char *ifname, unsigned char name_assign_type,
2853
- const struct rtnl_link_ops *ops, struct nlattr *tb[])
3162
+struct net_device *rtnl_create_link(struct net *net, const char *ifname,
3163
+ unsigned char name_assign_type,
3164
+ const struct rtnl_link_ops *ops,
3165
+ struct nlattr *tb[],
3166
+ struct netlink_ext_ack *extack)
28543167 {
28553168 struct net_device *dev;
28563169 unsigned int num_tx_queues = 1;
....@@ -2866,11 +3179,15 @@
28663179 else if (ops->get_num_rx_queues)
28673180 num_rx_queues = ops->get_num_rx_queues();
28683181
2869
- if (num_tx_queues < 1 || num_tx_queues > 4096)
3182
+ if (num_tx_queues < 1 || num_tx_queues > 4096) {
3183
+ NL_SET_ERR_MSG(extack, "Invalid number of transmit queues");
28703184 return ERR_PTR(-EINVAL);
3185
+ }
28713186
2872
- if (num_rx_queues < 1 || num_rx_queues > 4096)
3187
+ if (num_rx_queues < 1 || num_rx_queues > 4096) {
3188
+ NL_SET_ERR_MSG(extack, "Invalid number of receive queues");
28733189 return ERR_PTR(-EINVAL);
3190
+ }
28743191
28753192 dev = alloc_netdev_mqs(ops->priv_size, ifname, name_assign_type,
28763193 ops->setup, num_tx_queues, num_rx_queues);
....@@ -2885,7 +3202,7 @@
28853202 u32 mtu = nla_get_u32(tb[IFLA_MTU]);
28863203 int err;
28873204
2888
- err = dev_validate_mtu(dev, mtu, NULL);
3205
+ err = dev_validate_mtu(dev, mtu, extack);
28893206 if (err) {
28903207 free_netdev(dev);
28913208 return ERR_PTR(err);
....@@ -2937,26 +3254,32 @@
29373254 return 0;
29383255 }
29393256
2940
-static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh,
2941
- struct netlink_ext_ack *extack)
3257
+static int __rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh,
3258
+ struct nlattr **attr, struct netlink_ext_ack *extack)
29423259 {
3260
+ struct nlattr *slave_attr[RTNL_SLAVE_MAX_TYPE + 1];
3261
+ unsigned char name_assign_type = NET_NAME_USER;
3262
+ struct nlattr *linkinfo[IFLA_INFO_MAX + 1];
3263
+ const struct rtnl_link_ops *m_ops;
3264
+ struct net_device *master_dev;
29433265 struct net *net = sock_net(skb->sk);
29443266 const struct rtnl_link_ops *ops;
2945
- const struct rtnl_link_ops *m_ops;
2946
- struct net_device *dev;
2947
- struct net_device *master_dev;
2948
- struct ifinfomsg *ifm;
3267
+ struct nlattr *tb[IFLA_MAX + 1];
3268
+ struct net *dest_net, *link_net;
3269
+ struct nlattr **slave_data;
29493270 char kind[MODULE_NAME_LEN];
3271
+ struct net_device *dev;
3272
+ struct ifinfomsg *ifm;
29503273 char ifname[IFNAMSIZ];
2951
- struct nlattr *tb[IFLA_MAX+1];
2952
- struct nlattr *linkinfo[IFLA_INFO_MAX+1];
2953
- unsigned char name_assign_type = NET_NAME_USER;
3274
+ struct nlattr **data;
3275
+ bool link_specified;
29543276 int err;
29553277
29563278 #ifdef CONFIG_MODULES
29573279 replay:
29583280 #endif
2959
- err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy, extack);
3281
+ err = nlmsg_parse_deprecated(nlh, sizeof(*ifm), tb, IFLA_MAX,
3282
+ ifla_policy, extack);
29603283 if (err < 0)
29613284 return err;
29623285
....@@ -2970,13 +3293,18 @@
29703293 ifname[0] = '\0';
29713294
29723295 ifm = nlmsg_data(nlh);
2973
- if (ifm->ifi_index > 0)
3296
+ if (ifm->ifi_index > 0) {
3297
+ link_specified = true;
29743298 dev = __dev_get_by_index(net, ifm->ifi_index);
2975
- else {
2976
- if (ifname[0])
2977
- dev = __dev_get_by_name(net, ifname);
2978
- else
2979
- dev = NULL;
3299
+ } else if (ifm->ifi_index < 0) {
3300
+ NL_SET_ERR_MSG(extack, "ifindex can't be negative");
3301
+ return -EINVAL;
3302
+ } else if (tb[IFLA_IFNAME] || tb[IFLA_ALT_IFNAME]) {
3303
+ link_specified = true;
3304
+ dev = rtnl_dev_get(net, NULL, tb[IFLA_ALT_IFNAME], ifname);
3305
+ } else {
3306
+ link_specified = false;
3307
+ dev = NULL;
29803308 }
29813309
29823310 master_dev = NULL;
....@@ -2992,9 +3320,9 @@
29923320 return err;
29933321
29943322 if (tb[IFLA_LINKINFO]) {
2995
- err = nla_parse_nested(linkinfo, IFLA_INFO_MAX,
2996
- tb[IFLA_LINKINFO], ifla_info_policy,
2997
- NULL);
3323
+ err = nla_parse_nested_deprecated(linkinfo, IFLA_INFO_MAX,
3324
+ tb[IFLA_LINKINFO],
3325
+ ifla_info_policy, NULL);
29983326 if (err < 0)
29993327 return err;
30003328 } else
....@@ -3008,194 +3336,245 @@
30083336 ops = NULL;
30093337 }
30103338
3011
- if (1) {
3012
- struct nlattr *attr[RTNL_MAX_TYPE + 1];
3013
- struct nlattr *slave_attr[RTNL_SLAVE_MAX_TYPE + 1];
3014
- struct nlattr **data = NULL;
3015
- struct nlattr **slave_data = NULL;
3016
- struct net *dest_net, *link_net = NULL;
3339
+ data = NULL;
3340
+ if (ops) {
3341
+ if (ops->maxtype > RTNL_MAX_TYPE)
3342
+ return -EINVAL;
30173343
3018
- if (ops) {
3019
- if (ops->maxtype > RTNL_MAX_TYPE)
3020
- return -EINVAL;
3021
-
3022
- if (ops->maxtype && linkinfo[IFLA_INFO_DATA]) {
3023
- err = nla_parse_nested(attr, ops->maxtype,
3024
- linkinfo[IFLA_INFO_DATA],
3025
- ops->policy, NULL);
3026
- if (err < 0)
3027
- return err;
3028
- data = attr;
3029
- }
3030
- if (ops->validate) {
3031
- err = ops->validate(tb, data, extack);
3032
- if (err < 0)
3033
- return err;
3034
- }
3344
+ if (ops->maxtype && linkinfo[IFLA_INFO_DATA]) {
3345
+ err = nla_parse_nested_deprecated(attr, ops->maxtype,
3346
+ linkinfo[IFLA_INFO_DATA],
3347
+ ops->policy, extack);
3348
+ if (err < 0)
3349
+ return err;
3350
+ data = attr;
30353351 }
3036
-
3037
- if (m_ops) {
3038
- if (m_ops->slave_maxtype > RTNL_SLAVE_MAX_TYPE)
3039
- return -EINVAL;
3040
-
3041
- if (m_ops->slave_maxtype &&
3042
- linkinfo[IFLA_INFO_SLAVE_DATA]) {
3043
- err = nla_parse_nested(slave_attr,
3044
- m_ops->slave_maxtype,
3045
- linkinfo[IFLA_INFO_SLAVE_DATA],
3046
- m_ops->slave_policy,
3047
- NULL);
3048
- if (err < 0)
3049
- return err;
3050
- slave_data = slave_attr;
3051
- }
3352
+ if (ops->validate) {
3353
+ err = ops->validate(tb, data, extack);
3354
+ if (err < 0)
3355
+ return err;
30523356 }
3357
+ }
30533358
3054
- if (dev) {
3055
- int status = 0;
3359
+ slave_data = NULL;
3360
+ if (m_ops) {
3361
+ if (m_ops->slave_maxtype > RTNL_SLAVE_MAX_TYPE)
3362
+ return -EINVAL;
30563363
3057
- if (nlh->nlmsg_flags & NLM_F_EXCL)
3058
- return -EEXIST;
3059
- if (nlh->nlmsg_flags & NLM_F_REPLACE)
3364
+ if (m_ops->slave_maxtype &&
3365
+ linkinfo[IFLA_INFO_SLAVE_DATA]) {
3366
+ err = nla_parse_nested_deprecated(slave_attr,
3367
+ m_ops->slave_maxtype,
3368
+ linkinfo[IFLA_INFO_SLAVE_DATA],
3369
+ m_ops->slave_policy,
3370
+ extack);
3371
+ if (err < 0)
3372
+ return err;
3373
+ slave_data = slave_attr;
3374
+ }
3375
+ }
3376
+
3377
+ if (dev) {
3378
+ int status = 0;
3379
+
3380
+ if (nlh->nlmsg_flags & NLM_F_EXCL)
3381
+ return -EEXIST;
3382
+ if (nlh->nlmsg_flags & NLM_F_REPLACE)
3383
+ return -EOPNOTSUPP;
3384
+
3385
+ if (linkinfo[IFLA_INFO_DATA]) {
3386
+ if (!ops || ops != dev->rtnl_link_ops ||
3387
+ !ops->changelink)
30603388 return -EOPNOTSUPP;
30613389
3062
- if (linkinfo[IFLA_INFO_DATA]) {
3063
- if (!ops || ops != dev->rtnl_link_ops ||
3064
- !ops->changelink)
3065
- return -EOPNOTSUPP;
3066
-
3067
- err = ops->changelink(dev, tb, data, extack);
3068
- if (err < 0)
3069
- return err;
3070
- status |= DO_SETLINK_NOTIFY;
3071
- }
3072
-
3073
- if (linkinfo[IFLA_INFO_SLAVE_DATA]) {
3074
- if (!m_ops || !m_ops->slave_changelink)
3075
- return -EOPNOTSUPP;
3076
-
3077
- err = m_ops->slave_changelink(master_dev, dev,
3078
- tb, slave_data,
3079
- extack);
3080
- if (err < 0)
3081
- return err;
3082
- status |= DO_SETLINK_NOTIFY;
3083
- }
3084
-
3085
- return do_setlink(skb, dev, ifm, extack, tb, ifname,
3086
- status);
3390
+ err = ops->changelink(dev, tb, data, extack);
3391
+ if (err < 0)
3392
+ return err;
3393
+ status |= DO_SETLINK_NOTIFY;
30873394 }
30883395
3089
- if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
3090
- if (ifm->ifi_index == 0 && tb[IFLA_GROUP])
3091
- return rtnl_group_changelink(skb, net,
3396
+ if (linkinfo[IFLA_INFO_SLAVE_DATA]) {
3397
+ if (!m_ops || !m_ops->slave_changelink)
3398
+ return -EOPNOTSUPP;
3399
+
3400
+ err = m_ops->slave_changelink(master_dev, dev, tb,
3401
+ slave_data, extack);
3402
+ if (err < 0)
3403
+ return err;
3404
+ status |= DO_SETLINK_NOTIFY;
3405
+ }
3406
+
3407
+ return do_setlink(skb, dev, ifm, extack, tb, ifname, status);
3408
+ }
3409
+
3410
+ if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
3411
+ /* No dev found and NLM_F_CREATE not set. Requested dev does not exist,
3412
+ * or it's for a group
3413
+ */
3414
+ if (link_specified)
3415
+ return -ENODEV;
3416
+ if (tb[IFLA_GROUP])
3417
+ return rtnl_group_changelink(skb, net,
30923418 nla_get_u32(tb[IFLA_GROUP]),
30933419 ifm, extack, tb);
3094
- return -ENODEV;
3095
- }
3420
+ return -ENODEV;
3421
+ }
30963422
3097
- if (tb[IFLA_MAP] || tb[IFLA_PROTINFO])
3098
- return -EOPNOTSUPP;
3423
+ if (tb[IFLA_MAP] || tb[IFLA_PROTINFO])
3424
+ return -EOPNOTSUPP;
30993425
3100
- if (!ops) {
3426
+ if (!ops) {
31013427 #ifdef CONFIG_MODULES
3102
- if (kind[0]) {
3103
- __rtnl_unlock();
3104
- request_module("rtnl-link-%s", kind);
3105
- rtnl_lock();
3106
- ops = rtnl_link_ops_get(kind);
3107
- if (ops)
3108
- goto replay;
3109
- }
3428
+ if (kind[0]) {
3429
+ __rtnl_unlock();
3430
+ request_module("rtnl-link-%s", kind);
3431
+ rtnl_lock();
3432
+ ops = rtnl_link_ops_get(kind);
3433
+ if (ops)
3434
+ goto replay;
3435
+ }
31103436 #endif
3111
- return -EOPNOTSUPP;
3112
- }
3437
+ NL_SET_ERR_MSG(extack, "Unknown device type");
3438
+ return -EOPNOTSUPP;
3439
+ }
31133440
3114
- if (!ops->setup)
3115
- return -EOPNOTSUPP;
3441
+ if (!ops->setup)
3442
+ return -EOPNOTSUPP;
31163443
3117
- if (!ifname[0]) {
3118
- snprintf(ifname, IFNAMSIZ, "%s%%d", ops->kind);
3119
- name_assign_type = NET_NAME_ENUM;
3120
- }
3444
+ if (!ifname[0]) {
3445
+ snprintf(ifname, IFNAMSIZ, "%s%%d", ops->kind);
3446
+ name_assign_type = NET_NAME_ENUM;
3447
+ }
31213448
3122
- dest_net = rtnl_link_get_net_capable(skb, net, tb, CAP_NET_ADMIN);
3123
- if (IS_ERR(dest_net))
3124
- return PTR_ERR(dest_net);
3449
+ dest_net = rtnl_link_get_net_capable(skb, net, tb, CAP_NET_ADMIN);
3450
+ if (IS_ERR(dest_net))
3451
+ return PTR_ERR(dest_net);
31253452
3126
- if (tb[IFLA_LINK_NETNSID]) {
3127
- int id = nla_get_s32(tb[IFLA_LINK_NETNSID]);
3453
+ if (tb[IFLA_LINK_NETNSID]) {
3454
+ int id = nla_get_s32(tb[IFLA_LINK_NETNSID]);
31283455
3129
- link_net = get_net_ns_by_id(dest_net, id);
3130
- if (!link_net) {
3131
- err = -EINVAL;
3132
- goto out;
3133
- }
3134
- err = -EPERM;
3135
- if (!netlink_ns_capable(skb, link_net->user_ns, CAP_NET_ADMIN))
3136
- goto out;
3137
- }
3138
-
3139
- dev = rtnl_create_link(link_net ? : dest_net, ifname,
3140
- name_assign_type, ops, tb);
3141
- if (IS_ERR(dev)) {
3142
- err = PTR_ERR(dev);
3456
+ link_net = get_net_ns_by_id(dest_net, id);
3457
+ if (!link_net) {
3458
+ NL_SET_ERR_MSG(extack, "Unknown network namespace id");
3459
+ err = -EINVAL;
31433460 goto out;
31443461 }
3462
+ err = -EPERM;
3463
+ if (!netlink_ns_capable(skb, link_net->user_ns, CAP_NET_ADMIN))
3464
+ goto out;
3465
+ } else {
3466
+ link_net = NULL;
3467
+ }
31453468
3146
- dev->ifindex = ifm->ifi_index;
3147
-
3148
- if (ops->newlink) {
3149
- err = ops->newlink(link_net ? : net, dev, tb, data,
3150
- extack);
3151
- /* Drivers should call free_netdev() in ->destructor
3152
- * and unregister it on failure after registration
3153
- * so that device could be finally freed in rtnl_unlock.
3154
- */
3155
- if (err < 0) {
3156
- /* If device is not registered at all, free it now */
3157
- if (dev->reg_state == NETREG_UNINITIALIZED ||
3158
- dev->reg_state == NETREG_UNREGISTERED)
3159
- free_netdev(dev);
3160
- goto out;
3161
- }
3162
- } else {
3163
- err = register_netdevice(dev);
3164
- if (err < 0) {
3165
- free_netdev(dev);
3166
- goto out;
3167
- }
3168
- }
3169
- err = rtnl_configure_link(dev, ifm);
3170
- if (err < 0)
3171
- goto out_unregister;
3172
- if (link_net) {
3173
- err = dev_change_net_namespace(dev, dest_net, ifname);
3174
- if (err < 0)
3175
- goto out_unregister;
3176
- }
3177
- if (tb[IFLA_MASTER]) {
3178
- err = do_set_master(dev, nla_get_u32(tb[IFLA_MASTER]),
3179
- extack);
3180
- if (err)
3181
- goto out_unregister;
3182
- }
3183
-out:
3184
- if (link_net)
3185
- put_net(link_net);
3186
- put_net(dest_net);
3187
- return err;
3188
-out_unregister:
3189
- if (ops->newlink) {
3190
- LIST_HEAD(list_kill);
3191
-
3192
- ops->dellink(dev, &list_kill);
3193
- unregister_netdevice_many(&list_kill);
3194
- } else {
3195
- unregister_netdevice(dev);
3196
- }
3469
+ dev = rtnl_create_link(link_net ? : dest_net, ifname,
3470
+ name_assign_type, ops, tb, extack);
3471
+ if (IS_ERR(dev)) {
3472
+ err = PTR_ERR(dev);
31973473 goto out;
31983474 }
3475
+
3476
+ dev->ifindex = ifm->ifi_index;
3477
+
3478
+ if (ops->newlink)
3479
+ err = ops->newlink(link_net ? : net, dev, tb, data, extack);
3480
+ else
3481
+ err = register_netdevice(dev);
3482
+ if (err < 0) {
3483
+ free_netdev(dev);
3484
+ goto out;
3485
+ }
3486
+
3487
+ err = rtnl_configure_link(dev, ifm);
3488
+ if (err < 0)
3489
+ goto out_unregister;
3490
+ if (link_net) {
3491
+ err = dev_change_net_namespace(dev, dest_net, ifname);
3492
+ if (err < 0)
3493
+ goto out_unregister;
3494
+ }
3495
+ if (tb[IFLA_MASTER]) {
3496
+ err = do_set_master(dev, nla_get_u32(tb[IFLA_MASTER]), extack);
3497
+ if (err)
3498
+ goto out_unregister;
3499
+ }
3500
+out:
3501
+ if (link_net)
3502
+ put_net(link_net);
3503
+ put_net(dest_net);
3504
+ return err;
3505
+out_unregister:
3506
+ if (ops->newlink) {
3507
+ LIST_HEAD(list_kill);
3508
+
3509
+ ops->dellink(dev, &list_kill);
3510
+ unregister_netdevice_many(&list_kill);
3511
+ } else {
3512
+ unregister_netdevice(dev);
3513
+ }
3514
+ goto out;
3515
+}
3516
+
3517
+static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh,
3518
+ struct netlink_ext_ack *extack)
3519
+{
3520
+ struct nlattr **attr;
3521
+ int ret;
3522
+
3523
+ attr = kmalloc_array(RTNL_MAX_TYPE + 1, sizeof(*attr), GFP_KERNEL);
3524
+ if (!attr)
3525
+ return -ENOMEM;
3526
+
3527
+ ret = __rtnl_newlink(skb, nlh, attr, extack);
3528
+ kfree(attr);
3529
+ return ret;
3530
+}
3531
+
3532
+static int rtnl_valid_getlink_req(struct sk_buff *skb,
3533
+ const struct nlmsghdr *nlh,
3534
+ struct nlattr **tb,
3535
+ struct netlink_ext_ack *extack)
3536
+{
3537
+ struct ifinfomsg *ifm;
3538
+ int i, err;
3539
+
3540
+ if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ifm))) {
3541
+ NL_SET_ERR_MSG(extack, "Invalid header for get link");
3542
+ return -EINVAL;
3543
+ }
3544
+
3545
+ if (!netlink_strict_get_check(skb))
3546
+ return nlmsg_parse_deprecated(nlh, sizeof(*ifm), tb, IFLA_MAX,
3547
+ ifla_policy, extack);
3548
+
3549
+ ifm = nlmsg_data(nlh);
3550
+ if (ifm->__ifi_pad || ifm->ifi_type || ifm->ifi_flags ||
3551
+ ifm->ifi_change) {
3552
+ NL_SET_ERR_MSG(extack, "Invalid values in header for get link request");
3553
+ return -EINVAL;
3554
+ }
3555
+
3556
+ err = nlmsg_parse_deprecated_strict(nlh, sizeof(*ifm), tb, IFLA_MAX,
3557
+ ifla_policy, extack);
3558
+ if (err)
3559
+ return err;
3560
+
3561
+ for (i = 0; i <= IFLA_MAX; i++) {
3562
+ if (!tb[i])
3563
+ continue;
3564
+
3565
+ switch (i) {
3566
+ case IFLA_IFNAME:
3567
+ case IFLA_ALT_IFNAME:
3568
+ case IFLA_EXT_MASK:
3569
+ case IFLA_TARGET_NETNSID:
3570
+ break;
3571
+ default:
3572
+ NL_SET_ERR_MSG(extack, "Unsupported attribute in get link request");
3573
+ return -EINVAL;
3574
+ }
3575
+ }
3576
+
3577
+ return 0;
31993578 }
32003579
32013580 static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr *nlh,
....@@ -3204,7 +3583,6 @@
32043583 struct net *net = sock_net(skb->sk);
32053584 struct net *tgt_net = net;
32063585 struct ifinfomsg *ifm;
3207
- char ifname[IFNAMSIZ];
32083586 struct nlattr *tb[IFLA_MAX+1];
32093587 struct net_device *dev = NULL;
32103588 struct sk_buff *nskb;
....@@ -3212,7 +3590,7 @@
32123590 int err;
32133591 u32 ext_filter_mask = 0;
32143592
3215
- err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy, extack);
3593
+ err = rtnl_valid_getlink_req(skb, nlh, tb, extack);
32163594 if (err < 0)
32173595 return err;
32183596
....@@ -3220,15 +3598,12 @@
32203598 if (err < 0)
32213599 return err;
32223600
3223
- if (tb[IFLA_IF_NETNSID]) {
3224
- netnsid = nla_get_s32(tb[IFLA_IF_NETNSID]);
3225
- tgt_net = get_target_net(NETLINK_CB(skb).sk, netnsid);
3601
+ if (tb[IFLA_TARGET_NETNSID]) {
3602
+ netnsid = nla_get_s32(tb[IFLA_TARGET_NETNSID]);
3603
+ tgt_net = rtnl_get_net_ns_capable(NETLINK_CB(skb).sk, netnsid);
32263604 if (IS_ERR(tgt_net))
32273605 return PTR_ERR(tgt_net);
32283606 }
3229
-
3230
- if (tb[IFLA_IFNAME])
3231
- nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ);
32323607
32333608 if (tb[IFLA_EXT_MASK])
32343609 ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]);
....@@ -3237,8 +3612,9 @@
32373612 ifm = nlmsg_data(nlh);
32383613 if (ifm->ifi_index > 0)
32393614 dev = __dev_get_by_index(tgt_net, ifm->ifi_index);
3240
- else if (tb[IFLA_IFNAME])
3241
- dev = __dev_get_by_name(tgt_net, ifname);
3615
+ else if (tb[IFLA_IFNAME] || tb[IFLA_ALT_IFNAME])
3616
+ dev = rtnl_dev_get(tgt_net, tb[IFLA_IFNAME],
3617
+ tb[IFLA_ALT_IFNAME], NULL);
32423618 else
32433619 goto out;
32443620
....@@ -3268,20 +3644,123 @@
32683644 return err;
32693645 }
32703646
3271
-static u16 rtnl_calcit(struct sk_buff *skb, struct nlmsghdr *nlh)
3647
+static int rtnl_alt_ifname(int cmd, struct net_device *dev, struct nlattr *attr,
3648
+ bool *changed, struct netlink_ext_ack *extack)
3649
+{
3650
+ char *alt_ifname;
3651
+ size_t size;
3652
+ int err;
3653
+
3654
+ err = nla_validate(attr, attr->nla_len, IFLA_MAX, ifla_policy, extack);
3655
+ if (err)
3656
+ return err;
3657
+
3658
+ if (cmd == RTM_NEWLINKPROP) {
3659
+ size = rtnl_prop_list_size(dev);
3660
+ size += nla_total_size(ALTIFNAMSIZ);
3661
+ if (size >= U16_MAX) {
3662
+ NL_SET_ERR_MSG(extack,
3663
+ "effective property list too long");
3664
+ return -EINVAL;
3665
+ }
3666
+ }
3667
+
3668
+ alt_ifname = nla_strdup(attr, GFP_KERNEL_ACCOUNT);
3669
+ if (!alt_ifname)
3670
+ return -ENOMEM;
3671
+
3672
+ if (cmd == RTM_NEWLINKPROP) {
3673
+ err = netdev_name_node_alt_create(dev, alt_ifname);
3674
+ if (!err)
3675
+ alt_ifname = NULL;
3676
+ } else if (cmd == RTM_DELLINKPROP) {
3677
+ err = netdev_name_node_alt_destroy(dev, alt_ifname);
3678
+ } else {
3679
+ WARN_ON_ONCE(1);
3680
+ err = -EINVAL;
3681
+ }
3682
+
3683
+ kfree(alt_ifname);
3684
+ if (!err)
3685
+ *changed = true;
3686
+ return err;
3687
+}
3688
+
3689
+static int rtnl_linkprop(int cmd, struct sk_buff *skb, struct nlmsghdr *nlh,
3690
+ struct netlink_ext_ack *extack)
32723691 {
32733692 struct net *net = sock_net(skb->sk);
3693
+ struct nlattr *tb[IFLA_MAX + 1];
32743694 struct net_device *dev;
3695
+ struct ifinfomsg *ifm;
3696
+ bool changed = false;
3697
+ struct nlattr *attr;
3698
+ int err, rem;
3699
+
3700
+ err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy, extack);
3701
+ if (err)
3702
+ return err;
3703
+
3704
+ err = rtnl_ensure_unique_netns(tb, extack, true);
3705
+ if (err)
3706
+ return err;
3707
+
3708
+ ifm = nlmsg_data(nlh);
3709
+ if (ifm->ifi_index > 0)
3710
+ dev = __dev_get_by_index(net, ifm->ifi_index);
3711
+ else if (tb[IFLA_IFNAME] || tb[IFLA_ALT_IFNAME])
3712
+ dev = rtnl_dev_get(net, tb[IFLA_IFNAME],
3713
+ tb[IFLA_ALT_IFNAME], NULL);
3714
+ else
3715
+ return -EINVAL;
3716
+
3717
+ if (!dev)
3718
+ return -ENODEV;
3719
+
3720
+ if (!tb[IFLA_PROP_LIST])
3721
+ return 0;
3722
+
3723
+ nla_for_each_nested(attr, tb[IFLA_PROP_LIST], rem) {
3724
+ switch (nla_type(attr)) {
3725
+ case IFLA_ALT_IFNAME:
3726
+ err = rtnl_alt_ifname(cmd, dev, attr, &changed, extack);
3727
+ if (err)
3728
+ return err;
3729
+ break;
3730
+ }
3731
+ }
3732
+
3733
+ if (changed)
3734
+ netdev_state_change(dev);
3735
+ return 0;
3736
+}
3737
+
3738
+static int rtnl_newlinkprop(struct sk_buff *skb, struct nlmsghdr *nlh,
3739
+ struct netlink_ext_ack *extack)
3740
+{
3741
+ return rtnl_linkprop(RTM_NEWLINKPROP, skb, nlh, extack);
3742
+}
3743
+
3744
+static int rtnl_dellinkprop(struct sk_buff *skb, struct nlmsghdr *nlh,
3745
+ struct netlink_ext_ack *extack)
3746
+{
3747
+ return rtnl_linkprop(RTM_DELLINKPROP, skb, nlh, extack);
3748
+}
3749
+
3750
+static u32 rtnl_calcit(struct sk_buff *skb, struct nlmsghdr *nlh)
3751
+{
3752
+ struct net *net = sock_net(skb->sk);
3753
+ size_t min_ifinfo_dump_size = 0;
32753754 struct nlattr *tb[IFLA_MAX+1];
32763755 u32 ext_filter_mask = 0;
3277
- u16 min_ifinfo_dump_size = 0;
3756
+ struct net_device *dev;
32783757 int hdrlen;
32793758
32803759 /* Same kernel<->userspace interface hack as in rtnl_dump_ifinfo. */
32813760 hdrlen = nlmsg_len(nlh) < sizeof(struct ifinfomsg) ?
32823761 sizeof(struct rtgenmsg) : sizeof(struct ifinfomsg);
32833762
3284
- if (nlmsg_parse(nlh, hdrlen, tb, IFLA_MAX, ifla_policy, NULL) >= 0) {
3763
+ if (nlmsg_parse_deprecated(nlh, hdrlen, tb, IFLA_MAX, ifla_policy, NULL) >= 0) {
32853764 if (tb[IFLA_EXT_MASK])
32863765 ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]);
32873766 }
....@@ -3294,9 +3773,8 @@
32943773 */
32953774 rcu_read_lock();
32963775 for_each_netdev_rcu(net, dev) {
3297
- min_ifinfo_dump_size = max_t(u16, min_ifinfo_dump_size,
3298
- if_nlmsg_size(dev,
3299
- ext_filter_mask));
3776
+ min_ifinfo_dump_size = max(min_ifinfo_dump_size,
3777
+ if_nlmsg_size(dev, ext_filter_mask));
33003778 }
33013779 rcu_read_unlock();
33023780
....@@ -3308,6 +3786,7 @@
33083786 int idx;
33093787 int s_idx = cb->family;
33103788 int type = cb->nlh->nlmsg_type - RTM_BASE;
3789
+ int ret = 0;
33113790
33123791 if (s_idx == 0)
33133792 s_idx = 1;
....@@ -3340,12 +3819,13 @@
33403819 cb->prev_seq = 0;
33413820 cb->seq = 0;
33423821 }
3343
- if (dumpit(skb, cb))
3822
+ ret = dumpit(skb, cb);
3823
+ if (ret)
33443824 break;
33453825 }
33463826 cb->family = idx;
33473827
3348
- return skb->len;
3828
+ return skb->len ? : ret;
33493829 }
33503830
33513831 struct sk_buff *rtmsg_ifinfo_build_skb(int type, struct net_device *dev,
....@@ -3436,7 +3916,7 @@
34363916 ndm->ndm_ifindex = dev->ifindex;
34373917 ndm->ndm_state = ndm_state;
34383918
3439
- if (nla_put(skb, NDA_LLADDR, ETH_ALEN, addr))
3919
+ if (nla_put(skb, NDA_LLADDR, dev->addr_len, addr))
34403920 goto nla_put_failure;
34413921 if (vid)
34423922 if (nla_put(skb, NDA_VLAN, sizeof(u16), &vid))
....@@ -3450,10 +3930,10 @@
34503930 return -EMSGSIZE;
34513931 }
34523932
3453
-static inline size_t rtnl_fdb_nlmsg_size(void)
3933
+static inline size_t rtnl_fdb_nlmsg_size(const struct net_device *dev)
34543934 {
34553935 return NLMSG_ALIGN(sizeof(struct ndmsg)) +
3456
- nla_total_size(ETH_ALEN) + /* NDA_LLADDR */
3936
+ nla_total_size(dev->addr_len) + /* NDA_LLADDR */
34573937 nla_total_size(sizeof(u16)) + /* NDA_VLAN */
34583938 0;
34593939 }
....@@ -3465,7 +3945,7 @@
34653945 struct sk_buff *skb;
34663946 int err = -ENOBUFS;
34673947
3468
- skb = nlmsg_new(rtnl_fdb_nlmsg_size(), GFP_ATOMIC);
3948
+ skb = nlmsg_new(rtnl_fdb_nlmsg_size(dev), GFP_ATOMIC);
34693949 if (!skb)
34703950 goto errout;
34713951
....@@ -3482,7 +3962,7 @@
34823962 rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);
34833963 }
34843964
3485
-/**
3965
+/*
34863966 * ndo_dflt_fdb_add - default netdevice operation to add an FDB entry
34873967 */
34883968 int ndo_dflt_fdb_add(struct ndmsg *ndm,
....@@ -3552,116 +4032,8 @@
35524032 u16 vid;
35534033 int err;
35544034
3555
- err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL, extack);
3556
- if (err < 0)
3557
- return err;
3558
-
3559
- ndm = nlmsg_data(nlh);
3560
- if (ndm->ndm_ifindex == 0) {
3561
- NL_SET_ERR_MSG(extack, "invalid ifindex");
3562
- return -EINVAL;
3563
- }
3564
-
3565
- dev = __dev_get_by_index(net, ndm->ndm_ifindex);
3566
- if (dev == NULL) {
3567
- NL_SET_ERR_MSG(extack, "unknown ifindex");
3568
- return -ENODEV;
3569
- }
3570
-
3571
- if (!tb[NDA_LLADDR] || nla_len(tb[NDA_LLADDR]) != ETH_ALEN) {
3572
- NL_SET_ERR_MSG(extack, "invalid address");
3573
- return -EINVAL;
3574
- }
3575
-
3576
- if (dev->type != ARPHRD_ETHER) {
3577
- NL_SET_ERR_MSG(extack, "FDB delete only supported for Ethernet devices");
3578
- return -EINVAL;
3579
- }
3580
-
3581
- addr = nla_data(tb[NDA_LLADDR]);
3582
-
3583
- err = fdb_vid_parse(tb[NDA_VLAN], &vid, extack);
3584
- if (err)
3585
- return err;
3586
-
3587
- err = -EOPNOTSUPP;
3588
-
3589
- /* Support fdb on master device the net/bridge default case */
3590
- if ((!ndm->ndm_flags || ndm->ndm_flags & NTF_MASTER) &&
3591
- (dev->priv_flags & IFF_BRIDGE_PORT)) {
3592
- struct net_device *br_dev = netdev_master_upper_dev_get(dev);
3593
- const struct net_device_ops *ops = br_dev->netdev_ops;
3594
-
3595
- err = ops->ndo_fdb_add(ndm, tb, dev, addr, vid,
3596
- nlh->nlmsg_flags);
3597
- if (err)
3598
- goto out;
3599
- else
3600
- ndm->ndm_flags &= ~NTF_MASTER;
3601
- }
3602
-
3603
- /* Embedded bridge, macvlan, and any other device support */
3604
- if ((ndm->ndm_flags & NTF_SELF)) {
3605
- if (dev->netdev_ops->ndo_fdb_add)
3606
- err = dev->netdev_ops->ndo_fdb_add(ndm, tb, dev, addr,
3607
- vid,
3608
- nlh->nlmsg_flags);
3609
- else
3610
- err = ndo_dflt_fdb_add(ndm, tb, dev, addr, vid,
3611
- nlh->nlmsg_flags);
3612
-
3613
- if (!err) {
3614
- rtnl_fdb_notify(dev, addr, vid, RTM_NEWNEIGH,
3615
- ndm->ndm_state);
3616
- ndm->ndm_flags &= ~NTF_SELF;
3617
- }
3618
- }
3619
-out:
3620
- return err;
3621
-}
3622
-
3623
-/**
3624
- * ndo_dflt_fdb_del - default netdevice operation to delete an FDB entry
3625
- */
3626
-int ndo_dflt_fdb_del(struct ndmsg *ndm,
3627
- struct nlattr *tb[],
3628
- struct net_device *dev,
3629
- const unsigned char *addr, u16 vid)
3630
-{
3631
- int err = -EINVAL;
3632
-
3633
- /* If aging addresses are supported device will need to
3634
- * implement its own handler for this.
3635
- */
3636
- if (!(ndm->ndm_state & NUD_PERMANENT)) {
3637
- pr_info("%s: FDB only supports static addresses\n", dev->name);
3638
- return err;
3639
- }
3640
-
3641
- if (is_unicast_ether_addr(addr) || is_link_local_ether_addr(addr))
3642
- err = dev_uc_del(dev, addr);
3643
- else if (is_multicast_ether_addr(addr))
3644
- err = dev_mc_del(dev, addr);
3645
-
3646
- return err;
3647
-}
3648
-EXPORT_SYMBOL(ndo_dflt_fdb_del);
3649
-
3650
-static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh,
3651
- struct netlink_ext_ack *extack)
3652
-{
3653
- struct net *net = sock_net(skb->sk);
3654
- struct ndmsg *ndm;
3655
- struct nlattr *tb[NDA_MAX+1];
3656
- struct net_device *dev;
3657
- int err = -EINVAL;
3658
- __u8 *addr;
3659
- u16 vid;
3660
-
3661
- if (!netlink_capable(skb, CAP_NET_ADMIN))
3662
- return -EPERM;
3663
-
3664
- err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL, extack);
4035
+ err = nlmsg_parse_deprecated(nlh, sizeof(*ndm), tb, NDA_MAX, NULL,
4036
+ extack);
36654037 if (err < 0)
36664038 return err;
36674039
....@@ -3697,7 +4069,118 @@
36974069
36984070 /* Support fdb on master device the net/bridge default case */
36994071 if ((!ndm->ndm_flags || ndm->ndm_flags & NTF_MASTER) &&
3700
- (dev->priv_flags & IFF_BRIDGE_PORT)) {
4072
+ netif_is_bridge_port(dev)) {
4073
+ struct net_device *br_dev = netdev_master_upper_dev_get(dev);
4074
+ const struct net_device_ops *ops = br_dev->netdev_ops;
4075
+
4076
+ err = ops->ndo_fdb_add(ndm, tb, dev, addr, vid,
4077
+ nlh->nlmsg_flags, extack);
4078
+ if (err)
4079
+ goto out;
4080
+ else
4081
+ ndm->ndm_flags &= ~NTF_MASTER;
4082
+ }
4083
+
4084
+ /* Embedded bridge, macvlan, and any other device support */
4085
+ if ((ndm->ndm_flags & NTF_SELF)) {
4086
+ if (dev->netdev_ops->ndo_fdb_add)
4087
+ err = dev->netdev_ops->ndo_fdb_add(ndm, tb, dev, addr,
4088
+ vid,
4089
+ nlh->nlmsg_flags,
4090
+ extack);
4091
+ else
4092
+ err = ndo_dflt_fdb_add(ndm, tb, dev, addr, vid,
4093
+ nlh->nlmsg_flags);
4094
+
4095
+ if (!err) {
4096
+ rtnl_fdb_notify(dev, addr, vid, RTM_NEWNEIGH,
4097
+ ndm->ndm_state);
4098
+ ndm->ndm_flags &= ~NTF_SELF;
4099
+ }
4100
+ }
4101
+out:
4102
+ return err;
4103
+}
4104
+
4105
+/*
4106
+ * ndo_dflt_fdb_del - default netdevice operation to delete an FDB entry
4107
+ */
4108
+int ndo_dflt_fdb_del(struct ndmsg *ndm,
4109
+ struct nlattr *tb[],
4110
+ struct net_device *dev,
4111
+ const unsigned char *addr, u16 vid)
4112
+{
4113
+ int err = -EINVAL;
4114
+
4115
+ /* If aging addresses are supported device will need to
4116
+ * implement its own handler for this.
4117
+ */
4118
+ if (!(ndm->ndm_state & NUD_PERMANENT)) {
4119
+ pr_info("%s: FDB only supports static addresses\n", dev->name);
4120
+ return err;
4121
+ }
4122
+
4123
+ if (is_unicast_ether_addr(addr) || is_link_local_ether_addr(addr))
4124
+ err = dev_uc_del(dev, addr);
4125
+ else if (is_multicast_ether_addr(addr))
4126
+ err = dev_mc_del(dev, addr);
4127
+
4128
+ return err;
4129
+}
4130
+EXPORT_SYMBOL(ndo_dflt_fdb_del);
4131
+
4132
+static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh,
4133
+ struct netlink_ext_ack *extack)
4134
+{
4135
+ struct net *net = sock_net(skb->sk);
4136
+ struct ndmsg *ndm;
4137
+ struct nlattr *tb[NDA_MAX+1];
4138
+ struct net_device *dev;
4139
+ __u8 *addr;
4140
+ int err;
4141
+ u16 vid;
4142
+
4143
+ if (!netlink_capable(skb, CAP_NET_ADMIN))
4144
+ return -EPERM;
4145
+
4146
+ err = nlmsg_parse_deprecated(nlh, sizeof(*ndm), tb, NDA_MAX, NULL,
4147
+ extack);
4148
+ if (err < 0)
4149
+ return err;
4150
+
4151
+ ndm = nlmsg_data(nlh);
4152
+ if (ndm->ndm_ifindex == 0) {
4153
+ NL_SET_ERR_MSG(extack, "invalid ifindex");
4154
+ return -EINVAL;
4155
+ }
4156
+
4157
+ dev = __dev_get_by_index(net, ndm->ndm_ifindex);
4158
+ if (dev == NULL) {
4159
+ NL_SET_ERR_MSG(extack, "unknown ifindex");
4160
+ return -ENODEV;
4161
+ }
4162
+
4163
+ if (!tb[NDA_LLADDR] || nla_len(tb[NDA_LLADDR]) != ETH_ALEN) {
4164
+ NL_SET_ERR_MSG(extack, "invalid address");
4165
+ return -EINVAL;
4166
+ }
4167
+
4168
+ if (dev->type != ARPHRD_ETHER) {
4169
+ NL_SET_ERR_MSG(extack, "FDB delete only supported for Ethernet devices");
4170
+ return -EINVAL;
4171
+ }
4172
+
4173
+ addr = nla_data(tb[NDA_LLADDR]);
4174
+
4175
+ err = fdb_vid_parse(tb[NDA_VLAN], &vid, extack);
4176
+ if (err)
4177
+ return err;
4178
+
4179
+ err = -EOPNOTSUPP;
4180
+
4181
+ /* Support fdb on master device the net/bridge default case */
4182
+ if ((!ndm->ndm_flags || ndm->ndm_flags & NTF_MASTER) &&
4183
+ netif_is_bridge_port(dev)) {
37014184 struct net_device *br_dev = netdev_master_upper_dev_get(dev);
37024185 const struct net_device_ops *ops = br_dev->netdev_ops;
37034186
....@@ -3759,8 +4242,11 @@
37594242
37604243 /**
37614244 * ndo_dflt_fdb_dump - default netdevice operation to dump an FDB table.
3762
- * @nlh: netlink message header
4245
+ * @skb: socket buffer to store message in
4246
+ * @cb: netlink callback
37634247 * @dev: netdevice
4248
+ * @filter_dev: ignored
4249
+ * @idx: the number of FDB table entries dumped is added to *@idx
37644250 *
37654251 * Default netdevice operation to dump the existing unicast address list.
37664252 * Returns number of addresses from list put in skb.
....@@ -3787,14 +4273,101 @@
37874273 }
37884274 EXPORT_SYMBOL(ndo_dflt_fdb_dump);
37894275
4276
+static int valid_fdb_dump_strict(const struct nlmsghdr *nlh,
4277
+ int *br_idx, int *brport_idx,
4278
+ struct netlink_ext_ack *extack)
4279
+{
4280
+ struct nlattr *tb[NDA_MAX + 1];
4281
+ struct ndmsg *ndm;
4282
+ int err, i;
4283
+
4284
+ if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ndm))) {
4285
+ NL_SET_ERR_MSG(extack, "Invalid header for fdb dump request");
4286
+ return -EINVAL;
4287
+ }
4288
+
4289
+ ndm = nlmsg_data(nlh);
4290
+ if (ndm->ndm_pad1 || ndm->ndm_pad2 || ndm->ndm_state ||
4291
+ ndm->ndm_flags || ndm->ndm_type) {
4292
+ NL_SET_ERR_MSG(extack, "Invalid values in header for fdb dump request");
4293
+ return -EINVAL;
4294
+ }
4295
+
4296
+ err = nlmsg_parse_deprecated_strict(nlh, sizeof(struct ndmsg), tb,
4297
+ NDA_MAX, NULL, extack);
4298
+ if (err < 0)
4299
+ return err;
4300
+
4301
+ *brport_idx = ndm->ndm_ifindex;
4302
+ for (i = 0; i <= NDA_MAX; ++i) {
4303
+ if (!tb[i])
4304
+ continue;
4305
+
4306
+ switch (i) {
4307
+ case NDA_IFINDEX:
4308
+ if (nla_len(tb[i]) != sizeof(u32)) {
4309
+ NL_SET_ERR_MSG(extack, "Invalid IFINDEX attribute in fdb dump request");
4310
+ return -EINVAL;
4311
+ }
4312
+ *brport_idx = nla_get_u32(tb[NDA_IFINDEX]);
4313
+ break;
4314
+ case NDA_MASTER:
4315
+ if (nla_len(tb[i]) != sizeof(u32)) {
4316
+ NL_SET_ERR_MSG(extack, "Invalid MASTER attribute in fdb dump request");
4317
+ return -EINVAL;
4318
+ }
4319
+ *br_idx = nla_get_u32(tb[NDA_MASTER]);
4320
+ break;
4321
+ default:
4322
+ NL_SET_ERR_MSG(extack, "Unsupported attribute in fdb dump request");
4323
+ return -EINVAL;
4324
+ }
4325
+ }
4326
+
4327
+ return 0;
4328
+}
4329
+
4330
+static int valid_fdb_dump_legacy(const struct nlmsghdr *nlh,
4331
+ int *br_idx, int *brport_idx,
4332
+ struct netlink_ext_ack *extack)
4333
+{
4334
+ struct nlattr *tb[IFLA_MAX+1];
4335
+ int err;
4336
+
4337
+ /* A hack to preserve kernel<->userspace interface.
4338
+ * Before Linux v4.12 this code accepted ndmsg since iproute2 v3.3.0.
4339
+ * However, ndmsg is shorter than ifinfomsg thus nlmsg_parse() bails.
4340
+ * So, check for ndmsg with an optional u32 attribute (not used here).
4341
+ * Fortunately these sizes don't conflict with the size of ifinfomsg
4342
+ * with an optional attribute.
4343
+ */
4344
+ if (nlmsg_len(nlh) != sizeof(struct ndmsg) &&
4345
+ (nlmsg_len(nlh) != sizeof(struct ndmsg) +
4346
+ nla_attr_size(sizeof(u32)))) {
4347
+ struct ifinfomsg *ifm;
4348
+
4349
+ err = nlmsg_parse_deprecated(nlh, sizeof(struct ifinfomsg),
4350
+ tb, IFLA_MAX, ifla_policy,
4351
+ extack);
4352
+ if (err < 0) {
4353
+ return -EINVAL;
4354
+ } else if (err == 0) {
4355
+ if (tb[IFLA_MASTER])
4356
+ *br_idx = nla_get_u32(tb[IFLA_MASTER]);
4357
+ }
4358
+
4359
+ ifm = nlmsg_data(nlh);
4360
+ *brport_idx = ifm->ifi_index;
4361
+ }
4362
+ return 0;
4363
+}
4364
+
37904365 static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
37914366 {
37924367 struct net_device *dev;
3793
- struct nlattr *tb[IFLA_MAX+1];
37944368 struct net_device *br_dev = NULL;
37954369 const struct net_device_ops *ops = NULL;
37964370 const struct net_device_ops *cops = NULL;
3797
- struct ifinfomsg *ifm = nlmsg_data(cb->nlh);
37984371 struct net *net = sock_net(skb->sk);
37994372 struct hlist_head *head;
38004373 int brport_idx = 0;
....@@ -3804,27 +4377,14 @@
38044377 int err = 0;
38054378 int fidx = 0;
38064379
3807
- /* A hack to preserve kernel<->userspace interface.
3808
- * Before Linux v4.12 this code accepted ndmsg since iproute2 v3.3.0.
3809
- * However, ndmsg is shorter than ifinfomsg thus nlmsg_parse() bails.
3810
- * So, check for ndmsg with an optional u32 attribute (not used here).
3811
- * Fortunately these sizes don't conflict with the size of ifinfomsg
3812
- * with an optional attribute.
3813
- */
3814
- if (nlmsg_len(cb->nlh) != sizeof(struct ndmsg) &&
3815
- (nlmsg_len(cb->nlh) != sizeof(struct ndmsg) +
3816
- nla_attr_size(sizeof(u32)))) {
3817
- err = nlmsg_parse(cb->nlh, sizeof(struct ifinfomsg), tb,
3818
- IFLA_MAX, ifla_policy, NULL);
3819
- if (err < 0) {
3820
- return -EINVAL;
3821
- } else if (err == 0) {
3822
- if (tb[IFLA_MASTER])
3823
- br_idx = nla_get_u32(tb[IFLA_MASTER]);
3824
- }
3825
-
3826
- brport_idx = ifm->ifi_index;
3827
- }
4380
+ if (cb->strict_check)
4381
+ err = valid_fdb_dump_strict(cb->nlh, &br_idx, &brport_idx,
4382
+ cb->extack);
4383
+ else
4384
+ err = valid_fdb_dump_legacy(cb->nlh, &br_idx, &brport_idx,
4385
+ cb->extack);
4386
+ if (err < 0)
4387
+ return err;
38284388
38294389 if (br_idx) {
38304390 br_dev = __dev_get_by_index(net, br_idx);
....@@ -3846,13 +4406,13 @@
38464406 continue;
38474407
38484408 if (!br_idx) { /* user did not specify a specific bridge */
3849
- if (dev->priv_flags & IFF_BRIDGE_PORT) {
4409
+ if (netif_is_bridge_port(dev)) {
38504410 br_dev = netdev_master_upper_dev_get(dev);
38514411 cops = br_dev->netdev_ops;
38524412 }
38534413 } else {
38544414 if (dev != br_dev &&
3855
- !(dev->priv_flags & IFF_BRIDGE_PORT))
4415
+ !netif_is_bridge_port(dev))
38564416 continue;
38574417
38584418 if (br_dev != netdev_master_upper_dev_get(dev) &&
....@@ -3864,7 +4424,7 @@
38644424 if (idx < s_idx)
38654425 goto cont;
38664426
3867
- if (dev->priv_flags & IFF_BRIDGE_PORT) {
4427
+ if (netif_is_bridge_port(dev)) {
38684428 if (cops && cops->ndo_fdb_dump) {
38694429 err = cops->ndo_fdb_dump(skb, cb,
38704430 br_dev, dev,
....@@ -3900,6 +4460,165 @@
39004460 cb->args[2] = fidx;
39014461
39024462 return skb->len;
4463
+}
4464
+
4465
+static int valid_fdb_get_strict(const struct nlmsghdr *nlh,
4466
+ struct nlattr **tb, u8 *ndm_flags,
4467
+ int *br_idx, int *brport_idx, u8 **addr,
4468
+ u16 *vid, struct netlink_ext_ack *extack)
4469
+{
4470
+ struct ndmsg *ndm;
4471
+ int err, i;
4472
+
4473
+ if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ndm))) {
4474
+ NL_SET_ERR_MSG(extack, "Invalid header for fdb get request");
4475
+ return -EINVAL;
4476
+ }
4477
+
4478
+ ndm = nlmsg_data(nlh);
4479
+ if (ndm->ndm_pad1 || ndm->ndm_pad2 || ndm->ndm_state ||
4480
+ ndm->ndm_type) {
4481
+ NL_SET_ERR_MSG(extack, "Invalid values in header for fdb get request");
4482
+ return -EINVAL;
4483
+ }
4484
+
4485
+ if (ndm->ndm_flags & ~(NTF_MASTER | NTF_SELF)) {
4486
+ NL_SET_ERR_MSG(extack, "Invalid flags in header for fdb get request");
4487
+ return -EINVAL;
4488
+ }
4489
+
4490
+ err = nlmsg_parse_deprecated_strict(nlh, sizeof(struct ndmsg), tb,
4491
+ NDA_MAX, nda_policy, extack);
4492
+ if (err < 0)
4493
+ return err;
4494
+
4495
+ *ndm_flags = ndm->ndm_flags;
4496
+ *brport_idx = ndm->ndm_ifindex;
4497
+ for (i = 0; i <= NDA_MAX; ++i) {
4498
+ if (!tb[i])
4499
+ continue;
4500
+
4501
+ switch (i) {
4502
+ case NDA_MASTER:
4503
+ *br_idx = nla_get_u32(tb[i]);
4504
+ break;
4505
+ case NDA_LLADDR:
4506
+ if (nla_len(tb[i]) != ETH_ALEN) {
4507
+ NL_SET_ERR_MSG(extack, "Invalid address in fdb get request");
4508
+ return -EINVAL;
4509
+ }
4510
+ *addr = nla_data(tb[i]);
4511
+ break;
4512
+ case NDA_VLAN:
4513
+ err = fdb_vid_parse(tb[i], vid, extack);
4514
+ if (err)
4515
+ return err;
4516
+ break;
4517
+ case NDA_VNI:
4518
+ break;
4519
+ default:
4520
+ NL_SET_ERR_MSG(extack, "Unsupported attribute in fdb get request");
4521
+ return -EINVAL;
4522
+ }
4523
+ }
4524
+
4525
+ return 0;
4526
+}
4527
+
4528
+static int rtnl_fdb_get(struct sk_buff *in_skb, struct nlmsghdr *nlh,
4529
+ struct netlink_ext_ack *extack)
4530
+{
4531
+ struct net_device *dev = NULL, *br_dev = NULL;
4532
+ const struct net_device_ops *ops = NULL;
4533
+ struct net *net = sock_net(in_skb->sk);
4534
+ struct nlattr *tb[NDA_MAX + 1];
4535
+ struct sk_buff *skb;
4536
+ int brport_idx = 0;
4537
+ u8 ndm_flags = 0;
4538
+ int br_idx = 0;
4539
+ u8 *addr = NULL;
4540
+ u16 vid = 0;
4541
+ int err;
4542
+
4543
+ err = valid_fdb_get_strict(nlh, tb, &ndm_flags, &br_idx,
4544
+ &brport_idx, &addr, &vid, extack);
4545
+ if (err < 0)
4546
+ return err;
4547
+
4548
+ if (!addr) {
4549
+ NL_SET_ERR_MSG(extack, "Missing lookup address for fdb get request");
4550
+ return -EINVAL;
4551
+ }
4552
+
4553
+ if (brport_idx) {
4554
+ dev = __dev_get_by_index(net, brport_idx);
4555
+ if (!dev) {
4556
+ NL_SET_ERR_MSG(extack, "Unknown device ifindex");
4557
+ return -ENODEV;
4558
+ }
4559
+ }
4560
+
4561
+ if (br_idx) {
4562
+ if (dev) {
4563
+ NL_SET_ERR_MSG(extack, "Master and device are mutually exclusive");
4564
+ return -EINVAL;
4565
+ }
4566
+
4567
+ br_dev = __dev_get_by_index(net, br_idx);
4568
+ if (!br_dev) {
4569
+ NL_SET_ERR_MSG(extack, "Invalid master ifindex");
4570
+ return -EINVAL;
4571
+ }
4572
+ ops = br_dev->netdev_ops;
4573
+ }
4574
+
4575
+ if (dev) {
4576
+ if (!ndm_flags || (ndm_flags & NTF_MASTER)) {
4577
+ if (!netif_is_bridge_port(dev)) {
4578
+ NL_SET_ERR_MSG(extack, "Device is not a bridge port");
4579
+ return -EINVAL;
4580
+ }
4581
+ br_dev = netdev_master_upper_dev_get(dev);
4582
+ if (!br_dev) {
4583
+ NL_SET_ERR_MSG(extack, "Master of device not found");
4584
+ return -EINVAL;
4585
+ }
4586
+ ops = br_dev->netdev_ops;
4587
+ } else {
4588
+ if (!(ndm_flags & NTF_SELF)) {
4589
+ NL_SET_ERR_MSG(extack, "Missing NTF_SELF");
4590
+ return -EINVAL;
4591
+ }
4592
+ ops = dev->netdev_ops;
4593
+ }
4594
+ }
4595
+
4596
+ if (!br_dev && !dev) {
4597
+ NL_SET_ERR_MSG(extack, "No device specified");
4598
+ return -ENODEV;
4599
+ }
4600
+
4601
+ if (!ops || !ops->ndo_fdb_get) {
4602
+ NL_SET_ERR_MSG(extack, "Fdb get operation not supported by device");
4603
+ return -EOPNOTSUPP;
4604
+ }
4605
+
4606
+ skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
4607
+ if (!skb)
4608
+ return -ENOBUFS;
4609
+
4610
+ if (br_dev)
4611
+ dev = br_dev;
4612
+ err = ops->ndo_fdb_get(skb, tb, dev, addr, vid,
4613
+ NETLINK_CB(in_skb).portid,
4614
+ nlh->nlmsg_seq, extack);
4615
+ if (err)
4616
+ goto out;
4617
+
4618
+ return rtnl_unicast(skb, net, NETLINK_CB(in_skb).portid);
4619
+out:
4620
+ kfree_skb(skb);
4621
+ return err;
39034622 }
39044623
39054624 static int brport_nla_put_flag(struct sk_buff *skb, u32 flags, u32 mask,
....@@ -3950,7 +4669,7 @@
39504669 nla_put_u32(skb, IFLA_LINK, dev_get_iflink(dev))))
39514670 goto nla_put_failure;
39524671
3953
- br_afspec = nla_nest_start(skb, IFLA_AF_SPEC);
4672
+ br_afspec = nla_nest_start_noflag(skb, IFLA_AF_SPEC);
39544673 if (!br_afspec)
39554674 goto nla_put_failure;
39564675
....@@ -3974,7 +4693,7 @@
39744693 }
39754694 nla_nest_end(skb, br_afspec);
39764695
3977
- protinfo = nla_nest_start(skb, IFLA_PROTINFO | NLA_F_NESTED);
4696
+ protinfo = nla_nest_start(skb, IFLA_PROTINFO);
39784697 if (!protinfo)
39794698 goto nla_put_failure;
39804699
....@@ -3994,7 +4713,11 @@
39944713 brport_nla_put_flag(skb, flags, mask,
39954714 IFLA_BRPORT_UNICAST_FLOOD, BR_FLOOD) ||
39964715 brport_nla_put_flag(skb, flags, mask,
3997
- IFLA_BRPORT_PROXYARP, BR_PROXYARP)) {
4716
+ IFLA_BRPORT_PROXYARP, BR_PROXYARP) ||
4717
+ brport_nla_put_flag(skb, flags, mask,
4718
+ IFLA_BRPORT_MCAST_FLOOD, BR_MCAST_FLOOD) ||
4719
+ brport_nla_put_flag(skb, flags, mask,
4720
+ IFLA_BRPORT_BCAST_FLOOD, BR_BCAST_FLOOD)) {
39984721 nla_nest_cancel(skb, protinfo);
39994722 goto nla_put_failure;
40004723 }
....@@ -4009,28 +4732,75 @@
40094732 }
40104733 EXPORT_SYMBOL_GPL(ndo_dflt_bridge_getlink);
40114734
4735
+static int valid_bridge_getlink_req(const struct nlmsghdr *nlh,
4736
+ bool strict_check, u32 *filter_mask,
4737
+ struct netlink_ext_ack *extack)
4738
+{
4739
+ struct nlattr *tb[IFLA_MAX+1];
4740
+ int err, i;
4741
+
4742
+ if (strict_check) {
4743
+ struct ifinfomsg *ifm;
4744
+
4745
+ if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ifm))) {
4746
+ NL_SET_ERR_MSG(extack, "Invalid header for bridge link dump");
4747
+ return -EINVAL;
4748
+ }
4749
+
4750
+ ifm = nlmsg_data(nlh);
4751
+ if (ifm->__ifi_pad || ifm->ifi_type || ifm->ifi_flags ||
4752
+ ifm->ifi_change || ifm->ifi_index) {
4753
+ NL_SET_ERR_MSG(extack, "Invalid values in header for bridge link dump request");
4754
+ return -EINVAL;
4755
+ }
4756
+
4757
+ err = nlmsg_parse_deprecated_strict(nlh,
4758
+ sizeof(struct ifinfomsg),
4759
+ tb, IFLA_MAX, ifla_policy,
4760
+ extack);
4761
+ } else {
4762
+ err = nlmsg_parse_deprecated(nlh, sizeof(struct ifinfomsg),
4763
+ tb, IFLA_MAX, ifla_policy,
4764
+ extack);
4765
+ }
4766
+ if (err < 0)
4767
+ return err;
4768
+
4769
+ /* new attributes should only be added with strict checking */
4770
+ for (i = 0; i <= IFLA_MAX; ++i) {
4771
+ if (!tb[i])
4772
+ continue;
4773
+
4774
+ switch (i) {
4775
+ case IFLA_EXT_MASK:
4776
+ *filter_mask = nla_get_u32(tb[i]);
4777
+ break;
4778
+ default:
4779
+ if (strict_check) {
4780
+ NL_SET_ERR_MSG(extack, "Unsupported attribute in bridge link dump request");
4781
+ return -EINVAL;
4782
+ }
4783
+ }
4784
+ }
4785
+
4786
+ return 0;
4787
+}
4788
+
40124789 static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb)
40134790 {
4791
+ const struct nlmsghdr *nlh = cb->nlh;
40144792 struct net *net = sock_net(skb->sk);
40154793 struct net_device *dev;
40164794 int idx = 0;
40174795 u32 portid = NETLINK_CB(cb->skb).portid;
4018
- u32 seq = cb->nlh->nlmsg_seq;
4796
+ u32 seq = nlh->nlmsg_seq;
40194797 u32 filter_mask = 0;
40204798 int err;
40214799
4022
- if (nlmsg_len(cb->nlh) > sizeof(struct ifinfomsg)) {
4023
- struct nlattr *extfilt;
4024
-
4025
- extfilt = nlmsg_find_attr(cb->nlh, sizeof(struct ifinfomsg),
4026
- IFLA_EXT_MASK);
4027
- if (extfilt) {
4028
- if (nla_len(extfilt) < sizeof(filter_mask))
4029
- return -EINVAL;
4030
-
4031
- filter_mask = nla_get_u32(extfilt);
4032
- }
4033
- }
4800
+ err = valid_bridge_getlink_req(nlh, cb->strict_check, &filter_mask,
4801
+ cb->extack);
4802
+ if (err < 0 && cb->strict_check)
4803
+ return err;
40344804
40354805 rcu_read_lock();
40364806 for_each_netdev_rcu(net, dev) {
....@@ -4154,13 +4924,17 @@
41544924 br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
41554925 if (br_spec) {
41564926 nla_for_each_nested(attr, br_spec, rem) {
4157
- if (nla_type(attr) == IFLA_BRIDGE_FLAGS) {
4927
+ if (nla_type(attr) == IFLA_BRIDGE_FLAGS && !have_flags) {
41584928 if (nla_len(attr) < sizeof(flags))
41594929 return -EINVAL;
41604930
41614931 have_flags = true;
41624932 flags = nla_get_u16(attr);
4163
- break;
4933
+ }
4934
+
4935
+ if (nla_type(attr) == IFLA_BRIDGE_MODE) {
4936
+ if (nla_len(attr) < sizeof(u16))
4937
+ return -EINVAL;
41644938 }
41654939 }
41664940 }
....@@ -4173,7 +4947,8 @@
41734947 goto out;
41744948 }
41754949
4176
- err = br_dev->netdev_ops->ndo_bridge_setlink(dev, nlh, flags);
4950
+ err = br_dev->netdev_ops->ndo_bridge_setlink(dev, nlh, flags,
4951
+ extack);
41774952 if (err)
41784953 goto out;
41794954
....@@ -4185,7 +4960,8 @@
41854960 err = -EOPNOTSUPP;
41864961 else
41874962 err = dev->netdev_ops->ndo_bridge_setlink(dev, nlh,
4188
- flags);
4963
+ flags,
4964
+ extack);
41894965 if (!err) {
41904966 flags &= ~BRIDGE_FLAGS_SELF;
41914967
....@@ -4411,8 +5187,8 @@
44115187
44125188 if (ops && ops->fill_linkxstats) {
44135189 *idxattr = IFLA_STATS_LINK_XSTATS;
4414
- attr = nla_nest_start(skb,
4415
- IFLA_STATS_LINK_XSTATS);
5190
+ attr = nla_nest_start_noflag(skb,
5191
+ IFLA_STATS_LINK_XSTATS);
44165192 if (!attr)
44175193 goto nla_put_failure;
44185194
....@@ -4434,8 +5210,8 @@
44345210 ops = master->rtnl_link_ops;
44355211 if (ops && ops->fill_linkxstats) {
44365212 *idxattr = IFLA_STATS_LINK_XSTATS_SLAVE;
4437
- attr = nla_nest_start(skb,
4438
- IFLA_STATS_LINK_XSTATS_SLAVE);
5213
+ attr = nla_nest_start_noflag(skb,
5214
+ IFLA_STATS_LINK_XSTATS_SLAVE);
44395215 if (!attr)
44405216 goto nla_put_failure;
44415217
....@@ -4450,7 +5226,8 @@
44505226 if (stats_attr_valid(filter_mask, IFLA_STATS_LINK_OFFLOAD_XSTATS,
44515227 *idxattr)) {
44525228 *idxattr = IFLA_STATS_LINK_OFFLOAD_XSTATS;
4453
- attr = nla_nest_start(skb, IFLA_STATS_LINK_OFFLOAD_XSTATS);
5229
+ attr = nla_nest_start_noflag(skb,
5230
+ IFLA_STATS_LINK_OFFLOAD_XSTATS);
44545231 if (!attr)
44555232 goto nla_put_failure;
44565233
....@@ -4469,7 +5246,7 @@
44695246 struct rtnl_af_ops *af_ops;
44705247
44715248 *idxattr = IFLA_STATS_AF_SPEC;
4472
- attr = nla_nest_start(skb, IFLA_STATS_AF_SPEC);
5249
+ attr = nla_nest_start_noflag(skb, IFLA_STATS_AF_SPEC);
44735250 if (!attr)
44745251 goto nla_put_failure;
44755252
....@@ -4479,7 +5256,8 @@
44795256 struct nlattr *af;
44805257 int err;
44815258
4482
- af = nla_nest_start(skb, af_ops->family);
5259
+ af = nla_nest_start_noflag(skb,
5260
+ af_ops->family);
44835261 if (!af) {
44845262 rcu_read_unlock();
44855263 goto nla_put_failure;
....@@ -4581,6 +5359,40 @@
45815359 return size;
45825360 }
45835361
5362
+static int rtnl_valid_stats_req(const struct nlmsghdr *nlh, bool strict_check,
5363
+ bool is_dump, struct netlink_ext_ack *extack)
5364
+{
5365
+ struct if_stats_msg *ifsm;
5366
+
5367
+ if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ifsm))) {
5368
+ NL_SET_ERR_MSG(extack, "Invalid header for stats dump");
5369
+ return -EINVAL;
5370
+ }
5371
+
5372
+ if (!strict_check)
5373
+ return 0;
5374
+
5375
+ ifsm = nlmsg_data(nlh);
5376
+
5377
+ /* only requests using strict checks can pass data to influence
5378
+ * the dump. The legacy exception is filter_mask.
5379
+ */
5380
+ if (ifsm->pad1 || ifsm->pad2 || (is_dump && ifsm->ifindex)) {
5381
+ NL_SET_ERR_MSG(extack, "Invalid values in header for stats dump request");
5382
+ return -EINVAL;
5383
+ }
5384
+ if (nlmsg_attrlen(nlh, sizeof(*ifsm))) {
5385
+ NL_SET_ERR_MSG(extack, "Invalid attributes after stats header");
5386
+ return -EINVAL;
5387
+ }
5388
+ if (ifsm->filter_mask >= IFLA_STATS_FILTER_BIT(IFLA_STATS_MAX + 1)) {
5389
+ NL_SET_ERR_MSG(extack, "Invalid stats requested through filter mask");
5390
+ return -EINVAL;
5391
+ }
5392
+
5393
+ return 0;
5394
+}
5395
+
45845396 static int rtnl_stats_get(struct sk_buff *skb, struct nlmsghdr *nlh,
45855397 struct netlink_ext_ack *extack)
45865398 {
....@@ -4592,8 +5404,10 @@
45925404 u32 filter_mask;
45935405 int err;
45945406
4595
- if (nlmsg_len(nlh) < sizeof(*ifsm))
4596
- return -EINVAL;
5407
+ err = rtnl_valid_stats_req(nlh, netlink_strict_get_check(skb),
5408
+ false, extack);
5409
+ if (err)
5410
+ return err;
45975411
45985412 ifsm = nlmsg_data(nlh);
45995413 if (ifsm->ifindex > 0)
....@@ -4628,6 +5442,7 @@
46285442
46295443 static int rtnl_stats_dump(struct sk_buff *skb, struct netlink_callback *cb)
46305444 {
5445
+ struct netlink_ext_ack *extack = cb->extack;
46315446 int h, s_h, err, s_idx, s_idxattr, s_prividx;
46325447 struct net *net = sock_net(skb->sk);
46335448 unsigned int flags = NLM_F_MULTI;
....@@ -4644,13 +5459,16 @@
46445459
46455460 cb->seq = net->dev_base_seq;
46465461
4647
- if (nlmsg_len(cb->nlh) < sizeof(*ifsm))
4648
- return -EINVAL;
5462
+ err = rtnl_valid_stats_req(cb->nlh, cb->strict_check, true, extack);
5463
+ if (err)
5464
+ return err;
46495465
46505466 ifsm = nlmsg_data(cb->nlh);
46515467 filter_mask = ifsm->filter_mask;
4652
- if (!filter_mask)
5468
+ if (!filter_mask) {
5469
+ NL_SET_ERR_MSG(extack, "Filter mask must be set for stats dump");
46535470 return -EINVAL;
5471
+ }
46545472
46555473 for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
46565474 idx = 0;
....@@ -4721,7 +5539,7 @@
47215539 if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) {
47225540 struct sock *rtnl;
47235541 rtnl_dumpit_func dumpit;
4724
- u16 min_dump_alloc = 0;
5542
+ u32 min_dump_alloc = 0;
47255543
47265544 link = rtnl_get_link(family, type);
47275545 if (!link || !link->dumpit) {
....@@ -4898,9 +5716,12 @@
48985716 rtnl_register(PF_UNSPEC, RTM_GETROUTE, NULL, rtnl_dump_all, 0);
48995717 rtnl_register(PF_UNSPEC, RTM_GETNETCONF, NULL, rtnl_dump_all, 0);
49005718
5719
+ rtnl_register(PF_UNSPEC, RTM_NEWLINKPROP, rtnl_newlinkprop, NULL, 0);
5720
+ rtnl_register(PF_UNSPEC, RTM_DELLINKPROP, rtnl_dellinkprop, NULL, 0);
5721
+
49015722 rtnl_register(PF_BRIDGE, RTM_NEWNEIGH, rtnl_fdb_add, NULL, 0);
49025723 rtnl_register(PF_BRIDGE, RTM_DELNEIGH, rtnl_fdb_del, NULL, 0);
4903
- rtnl_register(PF_BRIDGE, RTM_GETNEIGH, NULL, rtnl_fdb_dump, 0);
5724
+ rtnl_register(PF_BRIDGE, RTM_GETNEIGH, rtnl_fdb_get, rtnl_fdb_dump, 0);
49045725
49055726 rtnl_register(PF_BRIDGE, RTM_GETLINK, NULL, rtnl_bridge_getlink, 0);
49065727 rtnl_register(PF_BRIDGE, RTM_DELLINK, rtnl_bridge_dellink, NULL, 0);