.. | .. |
---|
929 | 929 | nla_total_size(sizeof(struct ifla_vf_rate)) + |
---|
930 | 930 | nla_total_size(sizeof(struct ifla_vf_link_state)) + |
---|
931 | 931 | nla_total_size(sizeof(struct ifla_vf_rss_query_en)) + |
---|
932 | | - nla_total_size(0) + /* nest IFLA_VF_STATS */ |
---|
933 | | - /* IFLA_VF_STATS_RX_PACKETS */ |
---|
934 | | - nla_total_size_64bit(sizeof(__u64)) + |
---|
935 | | - /* IFLA_VF_STATS_TX_PACKETS */ |
---|
936 | | - nla_total_size_64bit(sizeof(__u64)) + |
---|
937 | | - /* IFLA_VF_STATS_RX_BYTES */ |
---|
938 | | - nla_total_size_64bit(sizeof(__u64)) + |
---|
939 | | - /* IFLA_VF_STATS_TX_BYTES */ |
---|
940 | | - nla_total_size_64bit(sizeof(__u64)) + |
---|
941 | | - /* IFLA_VF_STATS_BROADCAST */ |
---|
942 | | - nla_total_size_64bit(sizeof(__u64)) + |
---|
943 | | - /* IFLA_VF_STATS_MULTICAST */ |
---|
944 | | - nla_total_size_64bit(sizeof(__u64)) + |
---|
945 | | - /* IFLA_VF_STATS_RX_DROPPED */ |
---|
946 | | - nla_total_size_64bit(sizeof(__u64)) + |
---|
947 | | - /* IFLA_VF_STATS_TX_DROPPED */ |
---|
948 | | - nla_total_size_64bit(sizeof(__u64)) + |
---|
949 | 932 | 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 | + } |
---|
950 | 953 | return size; |
---|
951 | 954 | } else |
---|
952 | 955 | return 0; |
---|
.. | .. |
---|
1221 | 1224 | static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb, |
---|
1222 | 1225 | struct net_device *dev, |
---|
1223 | 1226 | int vfs_num, |
---|
1224 | | - struct nlattr *vfinfo) |
---|
| 1227 | + struct nlattr *vfinfo, |
---|
| 1228 | + u32 ext_filter_mask) |
---|
1225 | 1229 | { |
---|
1226 | 1230 | struct ifla_vf_rss_query_en vf_rss_query_en; |
---|
1227 | 1231 | struct nlattr *vf, *vfstats, *vfvlanlist; |
---|
.. | .. |
---|
1327 | 1331 | goto nla_put_vf_failure; |
---|
1328 | 1332 | } |
---|
1329 | 1333 | nla_nest_end(skb, vfvlanlist); |
---|
1330 | | - memset(&vf_stats, 0, sizeof(vf_stats)); |
---|
1331 | | - if (dev->netdev_ops->ndo_get_vf_stats) |
---|
1332 | | - dev->netdev_ops->ndo_get_vf_stats(dev, vfs_num, |
---|
1333 | | - &vf_stats); |
---|
1334 | | - vfstats = nla_nest_start_noflag(skb, IFLA_VF_STATS); |
---|
1335 | | - if (!vfstats) |
---|
1336 | | - goto nla_put_vf_failure; |
---|
1337 | | - if (nla_put_u64_64bit(skb, IFLA_VF_STATS_RX_PACKETS, |
---|
1338 | | - vf_stats.rx_packets, IFLA_VF_STATS_PAD) || |
---|
1339 | | - nla_put_u64_64bit(skb, IFLA_VF_STATS_TX_PACKETS, |
---|
1340 | | - vf_stats.tx_packets, IFLA_VF_STATS_PAD) || |
---|
1341 | | - nla_put_u64_64bit(skb, IFLA_VF_STATS_RX_BYTES, |
---|
1342 | | - vf_stats.rx_bytes, IFLA_VF_STATS_PAD) || |
---|
1343 | | - nla_put_u64_64bit(skb, IFLA_VF_STATS_TX_BYTES, |
---|
1344 | | - vf_stats.tx_bytes, IFLA_VF_STATS_PAD) || |
---|
1345 | | - nla_put_u64_64bit(skb, IFLA_VF_STATS_BROADCAST, |
---|
1346 | | - vf_stats.broadcast, IFLA_VF_STATS_PAD) || |
---|
1347 | | - nla_put_u64_64bit(skb, IFLA_VF_STATS_MULTICAST, |
---|
1348 | | - vf_stats.multicast, IFLA_VF_STATS_PAD) || |
---|
1349 | | - nla_put_u64_64bit(skb, IFLA_VF_STATS_RX_DROPPED, |
---|
1350 | | - vf_stats.rx_dropped, IFLA_VF_STATS_PAD) || |
---|
1351 | | - nla_put_u64_64bit(skb, IFLA_VF_STATS_TX_DROPPED, |
---|
1352 | | - vf_stats.tx_dropped, IFLA_VF_STATS_PAD)) { |
---|
1353 | | - nla_nest_cancel(skb, vfstats); |
---|
1354 | | - 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); |
---|
1355 | 1362 | } |
---|
1356 | | - nla_nest_end(skb, vfstats); |
---|
1357 | 1363 | nla_nest_end(skb, vf); |
---|
1358 | 1364 | return 0; |
---|
1359 | 1365 | |
---|
.. | .. |
---|
1386 | 1392 | return -EMSGSIZE; |
---|
1387 | 1393 | |
---|
1388 | 1394 | for (i = 0; i < num_vfs; i++) { |
---|
1389 | | - if (rtnl_fill_vfinfo(skb, dev, i, vfinfo)) |
---|
| 1395 | + if (rtnl_fill_vfinfo(skb, dev, i, vfinfo, ext_filter_mask)) |
---|
1390 | 1396 | return -EMSGSIZE; |
---|
1391 | 1397 | } |
---|
1392 | 1398 | |
---|
.. | .. |
---|
2155 | 2161 | return err; |
---|
2156 | 2162 | } |
---|
2157 | 2163 | |
---|
2158 | | -int rtnl_nla_parse_ifla(struct nlattr **tb, const struct nlattr *head, int len, |
---|
2159 | | - 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) |
---|
2160 | 2166 | { |
---|
2161 | | - return nla_parse_deprecated(tb, IFLA_MAX, head, len, ifla_policy, |
---|
| 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, |
---|
2162 | 2182 | exterr); |
---|
2163 | 2183 | } |
---|
2164 | | -EXPORT_SYMBOL(rtnl_nla_parse_ifla); |
---|
| 2184 | +EXPORT_SYMBOL(rtnl_nla_parse_ifinfomsg); |
---|
2165 | 2185 | |
---|
2166 | 2186 | struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[]) |
---|
2167 | 2187 | { |
---|
.. | .. |
---|
3252 | 3272 | struct ifinfomsg *ifm; |
---|
3253 | 3273 | char ifname[IFNAMSIZ]; |
---|
3254 | 3274 | struct nlattr **data; |
---|
| 3275 | + bool link_specified; |
---|
3255 | 3276 | int err; |
---|
3256 | 3277 | |
---|
3257 | 3278 | #ifdef CONFIG_MODULES |
---|
.. | .. |
---|
3272 | 3293 | ifname[0] = '\0'; |
---|
3273 | 3294 | |
---|
3274 | 3295 | ifm = nlmsg_data(nlh); |
---|
3275 | | - if (ifm->ifi_index > 0) |
---|
| 3296 | + if (ifm->ifi_index > 0) { |
---|
| 3297 | + link_specified = true; |
---|
3276 | 3298 | dev = __dev_get_by_index(net, ifm->ifi_index); |
---|
3277 | | - else if (tb[IFLA_IFNAME] || tb[IFLA_ALT_IFNAME]) |
---|
| 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; |
---|
3278 | 3304 | dev = rtnl_dev_get(net, NULL, tb[IFLA_ALT_IFNAME], ifname); |
---|
3279 | | - else |
---|
| 3305 | + } else { |
---|
| 3306 | + link_specified = false; |
---|
3280 | 3307 | dev = NULL; |
---|
| 3308 | + } |
---|
3281 | 3309 | |
---|
3282 | 3310 | master_dev = NULL; |
---|
3283 | 3311 | m_ops = NULL; |
---|
.. | .. |
---|
3380 | 3408 | } |
---|
3381 | 3409 | |
---|
3382 | 3410 | if (!(nlh->nlmsg_flags & NLM_F_CREATE)) { |
---|
3383 | | - if (ifm->ifi_index == 0 && tb[IFLA_GROUP]) |
---|
| 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]) |
---|
3384 | 3417 | return rtnl_group_changelink(skb, net, |
---|
3385 | 3418 | nla_get_u32(tb[IFLA_GROUP]), |
---|
3386 | 3419 | ifm, extack, tb); |
---|
.. | .. |
---|
3883 | 3916 | ndm->ndm_ifindex = dev->ifindex; |
---|
3884 | 3917 | ndm->ndm_state = ndm_state; |
---|
3885 | 3918 | |
---|
3886 | | - if (nla_put(skb, NDA_LLADDR, ETH_ALEN, addr)) |
---|
| 3919 | + if (nla_put(skb, NDA_LLADDR, dev->addr_len, addr)) |
---|
3887 | 3920 | goto nla_put_failure; |
---|
3888 | 3921 | if (vid) |
---|
3889 | 3922 | if (nla_put(skb, NDA_VLAN, sizeof(u16), &vid)) |
---|
.. | .. |
---|
3897 | 3930 | return -EMSGSIZE; |
---|
3898 | 3931 | } |
---|
3899 | 3932 | |
---|
3900 | | -static inline size_t rtnl_fdb_nlmsg_size(void) |
---|
| 3933 | +static inline size_t rtnl_fdb_nlmsg_size(const struct net_device *dev) |
---|
3901 | 3934 | { |
---|
3902 | 3935 | return NLMSG_ALIGN(sizeof(struct ndmsg)) + |
---|
3903 | | - nla_total_size(ETH_ALEN) + /* NDA_LLADDR */ |
---|
| 3936 | + nla_total_size(dev->addr_len) + /* NDA_LLADDR */ |
---|
3904 | 3937 | nla_total_size(sizeof(u16)) + /* NDA_VLAN */ |
---|
3905 | 3938 | 0; |
---|
3906 | 3939 | } |
---|
.. | .. |
---|
3912 | 3945 | struct sk_buff *skb; |
---|
3913 | 3946 | int err = -ENOBUFS; |
---|
3914 | 3947 | |
---|
3915 | | - skb = nlmsg_new(rtnl_fdb_nlmsg_size(), GFP_ATOMIC); |
---|
| 3948 | + skb = nlmsg_new(rtnl_fdb_nlmsg_size(dev), GFP_ATOMIC); |
---|
3916 | 3949 | if (!skb) |
---|
3917 | 3950 | goto errout; |
---|
3918 | 3951 | |
---|
.. | .. |
---|
4891 | 4924 | br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC); |
---|
4892 | 4925 | if (br_spec) { |
---|
4893 | 4926 | nla_for_each_nested(attr, br_spec, rem) { |
---|
4894 | | - if (nla_type(attr) == IFLA_BRIDGE_FLAGS) { |
---|
| 4927 | + if (nla_type(attr) == IFLA_BRIDGE_FLAGS && !have_flags) { |
---|
4895 | 4928 | if (nla_len(attr) < sizeof(flags)) |
---|
4896 | 4929 | return -EINVAL; |
---|
4897 | 4930 | |
---|
4898 | 4931 | have_flags = true; |
---|
4899 | 4932 | flags = nla_get_u16(attr); |
---|
4900 | | - break; |
---|
| 4933 | + } |
---|
| 4934 | + |
---|
| 4935 | + if (nla_type(attr) == IFLA_BRIDGE_MODE) { |
---|
| 4936 | + if (nla_len(attr) < sizeof(u16)) |
---|
| 4937 | + return -EINVAL; |
---|
4901 | 4938 | } |
---|
4902 | 4939 | } |
---|
4903 | 4940 | } |
---|