|
@@ -1121,56 +1121,7 @@ nla_put_failure:
|
|
|
return -EMSGSIZE;
|
|
|
}
|
|
|
|
|
|
-static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
|
|
|
-{
|
|
|
- struct net *net = sock_net(skb->sk);
|
|
|
- int h, s_h;
|
|
|
- int idx = 0, s_idx;
|
|
|
- struct net_device *dev;
|
|
|
- struct hlist_head *head;
|
|
|
- struct nlattr *tb[IFLA_MAX+1];
|
|
|
- u32 ext_filter_mask = 0;
|
|
|
-
|
|
|
- s_h = cb->args[0];
|
|
|
- s_idx = cb->args[1];
|
|
|
-
|
|
|
- rcu_read_lock();
|
|
|
- cb->seq = net->dev_base_seq;
|
|
|
-
|
|
|
- if (nlmsg_parse(cb->nlh, sizeof(struct ifinfomsg), tb, IFLA_MAX,
|
|
|
- ifla_policy) >= 0) {
|
|
|
-
|
|
|
- if (tb[IFLA_EXT_MASK])
|
|
|
- ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]);
|
|
|
- }
|
|
|
-
|
|
|
- for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
|
|
|
- idx = 0;
|
|
|
- head = &net->dev_index_head[h];
|
|
|
- hlist_for_each_entry_rcu(dev, head, index_hlist) {
|
|
|
- if (idx < s_idx)
|
|
|
- goto cont;
|
|
|
- if (rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK,
|
|
|
- NETLINK_CB(cb->skb).portid,
|
|
|
- cb->nlh->nlmsg_seq, 0,
|
|
|
- NLM_F_MULTI,
|
|
|
- ext_filter_mask) <= 0)
|
|
|
- goto out;
|
|
|
-
|
|
|
- nl_dump_check_consistent(cb, nlmsg_hdr(skb));
|
|
|
-cont:
|
|
|
- idx++;
|
|
|
- }
|
|
|
- }
|
|
|
-out:
|
|
|
- rcu_read_unlock();
|
|
|
- cb->args[1] = idx;
|
|
|
- cb->args[0] = h;
|
|
|
-
|
|
|
- return skb->len;
|
|
|
-}
|
|
|
-
|
|
|
-const struct nla_policy ifla_policy[IFLA_MAX+1] = {
|
|
|
+static const struct nla_policy ifla_policy[IFLA_MAX+1] = {
|
|
|
[IFLA_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ-1 },
|
|
|
[IFLA_ADDRESS] = { .type = NLA_BINARY, .len = MAX_ADDR_LEN },
|
|
|
[IFLA_BROADCAST] = { .type = NLA_BINARY, .len = MAX_ADDR_LEN },
|
|
@@ -1197,7 +1148,6 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = {
|
|
|
[IFLA_NUM_RX_QUEUES] = { .type = NLA_U32 },
|
|
|
[IFLA_PHYS_PORT_ID] = { .type = NLA_BINARY, .len = MAX_PHYS_PORT_ID_LEN },
|
|
|
};
|
|
|
-EXPORT_SYMBOL(ifla_policy);
|
|
|
|
|
|
static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
|
|
|
[IFLA_INFO_KIND] = { .type = NLA_STRING },
|
|
@@ -1235,6 +1185,61 @@ static const struct nla_policy ifla_port_policy[IFLA_PORT_MAX+1] = {
|
|
|
[IFLA_PORT_RESPONSE] = { .type = NLA_U16, },
|
|
|
};
|
|
|
|
|
|
+static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
|
|
|
+{
|
|
|
+ struct net *net = sock_net(skb->sk);
|
|
|
+ int h, s_h;
|
|
|
+ int idx = 0, s_idx;
|
|
|
+ struct net_device *dev;
|
|
|
+ struct hlist_head *head;
|
|
|
+ struct nlattr *tb[IFLA_MAX+1];
|
|
|
+ u32 ext_filter_mask = 0;
|
|
|
+
|
|
|
+ s_h = cb->args[0];
|
|
|
+ s_idx = cb->args[1];
|
|
|
+
|
|
|
+ rcu_read_lock();
|
|
|
+ cb->seq = net->dev_base_seq;
|
|
|
+
|
|
|
+ if (nlmsg_parse(cb->nlh, sizeof(struct ifinfomsg), tb, IFLA_MAX,
|
|
|
+ ifla_policy) >= 0) {
|
|
|
+
|
|
|
+ if (tb[IFLA_EXT_MASK])
|
|
|
+ ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]);
|
|
|
+ }
|
|
|
+
|
|
|
+ for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
|
|
|
+ idx = 0;
|
|
|
+ head = &net->dev_index_head[h];
|
|
|
+ hlist_for_each_entry_rcu(dev, head, index_hlist) {
|
|
|
+ if (idx < s_idx)
|
|
|
+ goto cont;
|
|
|
+ if (rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK,
|
|
|
+ NETLINK_CB(cb->skb).portid,
|
|
|
+ cb->nlh->nlmsg_seq, 0,
|
|
|
+ NLM_F_MULTI,
|
|
|
+ ext_filter_mask) <= 0)
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ nl_dump_check_consistent(cb, nlmsg_hdr(skb));
|
|
|
+cont:
|
|
|
+ idx++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+out:
|
|
|
+ rcu_read_unlock();
|
|
|
+ cb->args[1] = idx;
|
|
|
+ cb->args[0] = h;
|
|
|
+
|
|
|
+ return skb->len;
|
|
|
+}
|
|
|
+
|
|
|
+int rtnl_nla_parse_ifla(struct nlattr **tb, const struct nlattr *head, int len)
|
|
|
+{
|
|
|
+ return nla_parse(tb, IFLA_MAX, head, len, ifla_policy);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(rtnl_nla_parse_ifla);
|
|
|
+
|
|
|
struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[])
|
|
|
{
|
|
|
struct net *net;
|