aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/rtnetlink.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/core/rtnetlink.c')
-rw-r--r--net/core/rtnetlink.c59
1 files changed, 57 insertions, 2 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 18b5aae99bec..152744643074 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -837,8 +837,7 @@ static void copy_rtnl_link_stats(struct rtnl_link_stats *a,
837static inline int rtnl_vfinfo_size(const struct net_device *dev, 837static inline int rtnl_vfinfo_size(const struct net_device *dev,
838 u32 ext_filter_mask) 838 u32 ext_filter_mask)
839{ 839{
840 if (dev->dev.parent && dev_is_pci(dev->dev.parent) && 840 if (dev->dev.parent && (ext_filter_mask & RTEXT_FILTER_VF)) {
841 (ext_filter_mask & RTEXT_FILTER_VF)) {
842 int num_vfs = dev_num_vf(dev->dev.parent); 841 int num_vfs = dev_num_vf(dev->dev.parent);
843 size_t size = nla_total_size(0); 842 size_t size = nla_total_size(0);
844 size += num_vfs * 843 size += num_vfs *
@@ -3829,6 +3828,39 @@ static int rtnl_fill_statsinfo(struct sk_buff *skb, struct net_device *dev,
3829 *idxattr = 0; 3828 *idxattr = 0;
3830 } 3829 }
3831 3830
3831 if (stats_attr_valid(filter_mask, IFLA_STATS_AF_SPEC, *idxattr)) {
3832 struct rtnl_af_ops *af_ops;
3833
3834 *idxattr = IFLA_STATS_AF_SPEC;
3835 attr = nla_nest_start(skb, IFLA_STATS_AF_SPEC);
3836 if (!attr)
3837 goto nla_put_failure;
3838
3839 list_for_each_entry(af_ops, &rtnl_af_ops, list) {
3840 if (af_ops->fill_stats_af) {
3841 struct nlattr *af;
3842 int err;
3843
3844 af = nla_nest_start(skb, af_ops->family);
3845 if (!af)
3846 goto nla_put_failure;
3847
3848 err = af_ops->fill_stats_af(skb, dev);
3849
3850 if (err == -ENODATA)
3851 nla_nest_cancel(skb, af);
3852 else if (err < 0)
3853 goto nla_put_failure;
3854
3855 nla_nest_end(skb, af);
3856 }
3857 }
3858
3859 nla_nest_end(skb, attr);
3860
3861 *idxattr = 0;
3862 }
3863
3832 nlmsg_end(skb, nlh); 3864 nlmsg_end(skb, nlh);
3833 3865
3834 return 0; 3866 return 0;
@@ -3885,6 +3917,23 @@ static size_t if_nlmsg_stats_size(const struct net_device *dev,
3885 if (stats_attr_valid(filter_mask, IFLA_STATS_LINK_OFFLOAD_XSTATS, 0)) 3917 if (stats_attr_valid(filter_mask, IFLA_STATS_LINK_OFFLOAD_XSTATS, 0))
3886 size += rtnl_get_offload_stats_size(dev); 3918 size += rtnl_get_offload_stats_size(dev);
3887 3919
3920 if (stats_attr_valid(filter_mask, IFLA_STATS_AF_SPEC, 0)) {
3921 struct rtnl_af_ops *af_ops;
3922
3923 /* for IFLA_STATS_AF_SPEC */
3924 size += nla_total_size(0);
3925
3926 list_for_each_entry(af_ops, &rtnl_af_ops, list) {
3927 if (af_ops->get_stats_af_size) {
3928 size += nla_total_size(
3929 af_ops->get_stats_af_size(dev));
3930
3931 /* for AF_* */
3932 size += nla_total_size(0);
3933 }
3934 }
3935 }
3936
3888 return size; 3937 return size;
3889} 3938}
3890 3939
@@ -3898,6 +3947,9 @@ static int rtnl_stats_get(struct sk_buff *skb, struct nlmsghdr *nlh)
3898 u32 filter_mask; 3947 u32 filter_mask;
3899 int err; 3948 int err;
3900 3949
3950 if (nlmsg_len(nlh) < sizeof(*ifsm))
3951 return -EINVAL;
3952
3901 ifsm = nlmsg_data(nlh); 3953 ifsm = nlmsg_data(nlh);
3902 if (ifsm->ifindex > 0) 3954 if (ifsm->ifindex > 0)
3903 dev = __dev_get_by_index(net, ifsm->ifindex); 3955 dev = __dev_get_by_index(net, ifsm->ifindex);
@@ -3947,6 +3999,9 @@ static int rtnl_stats_dump(struct sk_buff *skb, struct netlink_callback *cb)
3947 3999
3948 cb->seq = net->dev_base_seq; 4000 cb->seq = net->dev_base_seq;
3949 4001
4002 if (nlmsg_len(cb->nlh) < sizeof(*ifsm))
4003 return -EINVAL;
4004
3950 ifsm = nlmsg_data(cb->nlh); 4005 ifsm = nlmsg_data(cb->nlh);
3951 filter_mask = ifsm->filter_mask; 4006 filter_mask = ifsm->filter_mask;
3952 if (!filter_mask) 4007 if (!filter_mask)