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.c80
1 files changed, 59 insertions, 21 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 65aebd450027..f965dce6f20f 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -60,7 +60,6 @@ struct rtnl_link {
60}; 60};
61 61
62static DEFINE_MUTEX(rtnl_mutex); 62static DEFINE_MUTEX(rtnl_mutex);
63static u16 min_ifinfo_dump_size;
64 63
65void rtnl_lock(void) 64void rtnl_lock(void)
66{ 65{
@@ -724,10 +723,11 @@ static void copy_rtnl_link_stats64(void *v, const struct rtnl_link_stats64 *b)
724} 723}
725 724
726/* All VF info */ 725/* All VF info */
727static inline int rtnl_vfinfo_size(const struct net_device *dev) 726static inline int rtnl_vfinfo_size(const struct net_device *dev,
727 u32 ext_filter_mask)
728{ 728{
729 if (dev->dev.parent && dev_is_pci(dev->dev.parent)) { 729 if (dev->dev.parent && dev_is_pci(dev->dev.parent) &&
730 730 (ext_filter_mask & RTEXT_FILTER_VF)) {
731 int num_vfs = dev_num_vf(dev->dev.parent); 731 int num_vfs = dev_num_vf(dev->dev.parent);
732 size_t size = nla_total_size(sizeof(struct nlattr)); 732 size_t size = nla_total_size(sizeof(struct nlattr));
733 size += nla_total_size(num_vfs * sizeof(struct nlattr)); 733 size += nla_total_size(num_vfs * sizeof(struct nlattr));
@@ -766,7 +766,8 @@ static size_t rtnl_port_size(const struct net_device *dev)
766 return port_self_size; 766 return port_self_size;
767} 767}
768 768
769static noinline size_t if_nlmsg_size(const struct net_device *dev) 769static noinline size_t if_nlmsg_size(const struct net_device *dev,
770 u32 ext_filter_mask)
770{ 771{
771 return NLMSG_ALIGN(sizeof(struct ifinfomsg)) 772 return NLMSG_ALIGN(sizeof(struct ifinfomsg))
772 + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */ 773 + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */
@@ -784,8 +785,9 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev)
784 + nla_total_size(4) /* IFLA_MASTER */ 785 + nla_total_size(4) /* IFLA_MASTER */
785 + nla_total_size(1) /* IFLA_OPERSTATE */ 786 + nla_total_size(1) /* IFLA_OPERSTATE */
786 + nla_total_size(1) /* IFLA_LINKMODE */ 787 + nla_total_size(1) /* IFLA_LINKMODE */
787 + nla_total_size(4) /* IFLA_NUM_VF */ 788 + nla_total_size(ext_filter_mask
788 + rtnl_vfinfo_size(dev) /* IFLA_VFINFO_LIST */ 789 & RTEXT_FILTER_VF ? 4 : 0) /* IFLA_NUM_VF */
790 + rtnl_vfinfo_size(dev, ext_filter_mask) /* IFLA_VFINFO_LIST */
789 + rtnl_port_size(dev) /* IFLA_VF_PORTS + IFLA_PORT_SELF */ 791 + rtnl_port_size(dev) /* IFLA_VF_PORTS + IFLA_PORT_SELF */
790 + rtnl_link_get_size(dev) /* IFLA_LINKINFO */ 792 + rtnl_link_get_size(dev) /* IFLA_LINKINFO */
791 + rtnl_link_get_af_size(dev); /* IFLA_AF_SPEC */ 793 + rtnl_link_get_af_size(dev); /* IFLA_AF_SPEC */
@@ -868,7 +870,7 @@ static int rtnl_port_fill(struct sk_buff *skb, struct net_device *dev)
868 870
869static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, 871static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
870 int type, u32 pid, u32 seq, u32 change, 872 int type, u32 pid, u32 seq, u32 change,
871 unsigned int flags) 873 unsigned int flags, u32 ext_filter_mask)
872{ 874{
873 struct ifinfomsg *ifm; 875 struct ifinfomsg *ifm;
874 struct nlmsghdr *nlh; 876 struct nlmsghdr *nlh;
@@ -941,10 +943,11 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
941 goto nla_put_failure; 943 goto nla_put_failure;
942 copy_rtnl_link_stats64(nla_data(attr), stats); 944 copy_rtnl_link_stats64(nla_data(attr), stats);
943 945
944 if (dev->dev.parent) 946 if (dev->dev.parent && (ext_filter_mask & RTEXT_FILTER_VF))
945 NLA_PUT_U32(skb, IFLA_NUM_VF, dev_num_vf(dev->dev.parent)); 947 NLA_PUT_U32(skb, IFLA_NUM_VF, dev_num_vf(dev->dev.parent));
946 948
947 if (dev->netdev_ops->ndo_get_vf_config && dev->dev.parent) { 949 if (dev->netdev_ops->ndo_get_vf_config && dev->dev.parent
950 && (ext_filter_mask & RTEXT_FILTER_VF)) {
948 int i; 951 int i;
949 952
950 struct nlattr *vfinfo, *vf; 953 struct nlattr *vfinfo, *vf;
@@ -1048,6 +1051,8 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
1048 struct net_device *dev; 1051 struct net_device *dev;
1049 struct hlist_head *head; 1052 struct hlist_head *head;
1050 struct hlist_node *node; 1053 struct hlist_node *node;
1054 struct nlattr *tb[IFLA_MAX+1];
1055 u32 ext_filter_mask = 0;
1051 1056
1052 s_h = cb->args[0]; 1057 s_h = cb->args[0];
1053 s_idx = cb->args[1]; 1058 s_idx = cb->args[1];
@@ -1055,6 +1060,13 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
1055 rcu_read_lock(); 1060 rcu_read_lock();
1056 cb->seq = net->dev_base_seq; 1061 cb->seq = net->dev_base_seq;
1057 1062
1063 if (nlmsg_parse(cb->nlh, sizeof(struct rtgenmsg), tb, IFLA_MAX,
1064 ifla_policy) >= 0) {
1065
1066 if (tb[IFLA_EXT_MASK])
1067 ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]);
1068 }
1069
1058 for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) { 1070 for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
1059 idx = 0; 1071 idx = 0;
1060 head = &net->dev_index_head[h]; 1072 head = &net->dev_index_head[h];
@@ -1064,7 +1076,8 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
1064 if (rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK, 1076 if (rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK,
1065 NETLINK_CB(cb->skb).pid, 1077 NETLINK_CB(cb->skb).pid,
1066 cb->nlh->nlmsg_seq, 0, 1078 cb->nlh->nlmsg_seq, 0,
1067 NLM_F_MULTI) <= 0) 1079 NLM_F_MULTI,
1080 ext_filter_mask) <= 0)
1068 goto out; 1081 goto out;
1069 1082
1070 nl_dump_check_consistent(cb, nlmsg_hdr(skb)); 1083 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
@@ -1100,6 +1113,7 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = {
1100 [IFLA_VF_PORTS] = { .type = NLA_NESTED }, 1113 [IFLA_VF_PORTS] = { .type = NLA_NESTED },
1101 [IFLA_PORT_SELF] = { .type = NLA_NESTED }, 1114 [IFLA_PORT_SELF] = { .type = NLA_NESTED },
1102 [IFLA_AF_SPEC] = { .type = NLA_NESTED }, 1115 [IFLA_AF_SPEC] = { .type = NLA_NESTED },
1116 [IFLA_EXT_MASK] = { .type = NLA_U32 },
1103}; 1117};
1104EXPORT_SYMBOL(ifla_policy); 1118EXPORT_SYMBOL(ifla_policy);
1105 1119
@@ -1509,8 +1523,6 @@ errout:
1509 1523
1510 if (send_addr_notify) 1524 if (send_addr_notify)
1511 call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); 1525 call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
1512 min_ifinfo_dump_size = max_t(u16, if_nlmsg_size(dev),
1513 min_ifinfo_dump_size);
1514 1526
1515 return err; 1527 return err;
1516} 1528}
@@ -1842,6 +1854,7 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
1842 struct net_device *dev = NULL; 1854 struct net_device *dev = NULL;
1843 struct sk_buff *nskb; 1855 struct sk_buff *nskb;
1844 int err; 1856 int err;
1857 u32 ext_filter_mask = 0;
1845 1858
1846 err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy); 1859 err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy);
1847 if (err < 0) 1860 if (err < 0)
@@ -1850,6 +1863,9 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
1850 if (tb[IFLA_IFNAME]) 1863 if (tb[IFLA_IFNAME])
1851 nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ); 1864 nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ);
1852 1865
1866 if (tb[IFLA_EXT_MASK])
1867 ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]);
1868
1853 ifm = nlmsg_data(nlh); 1869 ifm = nlmsg_data(nlh);
1854 if (ifm->ifi_index > 0) 1870 if (ifm->ifi_index > 0)
1855 dev = __dev_get_by_index(net, ifm->ifi_index); 1871 dev = __dev_get_by_index(net, ifm->ifi_index);
@@ -1861,12 +1877,12 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
1861 if (dev == NULL) 1877 if (dev == NULL)
1862 return -ENODEV; 1878 return -ENODEV;
1863 1879
1864 nskb = nlmsg_new(if_nlmsg_size(dev), GFP_KERNEL); 1880 nskb = nlmsg_new(if_nlmsg_size(dev, ext_filter_mask), GFP_KERNEL);
1865 if (nskb == NULL) 1881 if (nskb == NULL)
1866 return -ENOBUFS; 1882 return -ENOBUFS;
1867 1883
1868 err = rtnl_fill_ifinfo(nskb, dev, RTM_NEWLINK, NETLINK_CB(skb).pid, 1884 err = rtnl_fill_ifinfo(nskb, dev, RTM_NEWLINK, NETLINK_CB(skb).pid,
1869 nlh->nlmsg_seq, 0, 0); 1885 nlh->nlmsg_seq, 0, 0, ext_filter_mask);
1870 if (err < 0) { 1886 if (err < 0) {
1871 /* -EMSGSIZE implies BUG in if_nlmsg_size */ 1887 /* -EMSGSIZE implies BUG in if_nlmsg_size */
1872 WARN_ON(err == -EMSGSIZE); 1888 WARN_ON(err == -EMSGSIZE);
@@ -1877,8 +1893,32 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
1877 return err; 1893 return err;
1878} 1894}
1879 1895
1880static u16 rtnl_calcit(struct sk_buff *skb) 1896static u16 rtnl_calcit(struct sk_buff *skb, struct nlmsghdr *nlh)
1881{ 1897{
1898 struct net *net = sock_net(skb->sk);
1899 struct net_device *dev;
1900 struct nlattr *tb[IFLA_MAX+1];
1901 u32 ext_filter_mask = 0;
1902 u16 min_ifinfo_dump_size = 0;
1903
1904 if (nlmsg_parse(nlh, sizeof(struct rtgenmsg), tb, IFLA_MAX,
1905 ifla_policy) >= 0) {
1906 if (tb[IFLA_EXT_MASK])
1907 ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]);
1908 }
1909
1910 if (!ext_filter_mask)
1911 return NLMSG_GOODSIZE;
1912 /*
1913 * traverse the list of net devices and compute the minimum
1914 * buffer size based upon the filter mask.
1915 */
1916 list_for_each_entry(dev, &net->dev_base_head, dev_list) {
1917 min_ifinfo_dump_size = max_t(u16, min_ifinfo_dump_size,
1918 if_nlmsg_size(dev,
1919 ext_filter_mask));
1920 }
1921
1882 return min_ifinfo_dump_size; 1922 return min_ifinfo_dump_size;
1883} 1923}
1884 1924
@@ -1913,13 +1953,11 @@ void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change)
1913 int err = -ENOBUFS; 1953 int err = -ENOBUFS;
1914 size_t if_info_size; 1954 size_t if_info_size;
1915 1955
1916 skb = nlmsg_new((if_info_size = if_nlmsg_size(dev)), GFP_KERNEL); 1956 skb = nlmsg_new((if_info_size = if_nlmsg_size(dev, 0)), GFP_KERNEL);
1917 if (skb == NULL) 1957 if (skb == NULL)
1918 goto errout; 1958 goto errout;
1919 1959
1920 min_ifinfo_dump_size = max_t(u16, if_info_size, min_ifinfo_dump_size); 1960 err = rtnl_fill_ifinfo(skb, dev, type, 0, 0, change, 0, 0);
1921
1922 err = rtnl_fill_ifinfo(skb, dev, type, 0, 0, change, 0);
1923 if (err < 0) { 1961 if (err < 0) {
1924 /* -EMSGSIZE implies BUG in if_nlmsg_size() */ 1962 /* -EMSGSIZE implies BUG in if_nlmsg_size() */
1925 WARN_ON(err == -EMSGSIZE); 1963 WARN_ON(err == -EMSGSIZE);
@@ -1977,7 +2015,7 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
1977 return -EOPNOTSUPP; 2015 return -EOPNOTSUPP;
1978 calcit = rtnl_get_calcit(family, type); 2016 calcit = rtnl_get_calcit(family, type);
1979 if (calcit) 2017 if (calcit)
1980 min_dump_alloc = calcit(skb); 2018 min_dump_alloc = calcit(skb, nlh);
1981 2019
1982 __rtnl_unlock(); 2020 __rtnl_unlock();
1983 rtnl = net->rtnl; 2021 rtnl = net->rtnl;