netconf: add the handler to dump entries
It's useful to be able to get the initial state of all entries. The patch adds the support for IPv4 and IPv6. Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Родитель
753f993911
Коммит
7a6742003f
|
@ -1791,6 +1791,74 @@ errout:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int inet_netconf_dump_devconf(struct sk_buff *skb,
|
||||||
|
struct netlink_callback *cb)
|
||||||
|
{
|
||||||
|
struct net *net = sock_net(skb->sk);
|
||||||
|
int h, s_h;
|
||||||
|
int idx, s_idx;
|
||||||
|
struct net_device *dev;
|
||||||
|
struct in_device *in_dev;
|
||||||
|
struct hlist_head *head;
|
||||||
|
|
||||||
|
s_h = cb->args[0];
|
||||||
|
s_idx = idx = cb->args[1];
|
||||||
|
|
||||||
|
for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
|
||||||
|
idx = 0;
|
||||||
|
head = &net->dev_index_head[h];
|
||||||
|
rcu_read_lock();
|
||||||
|
hlist_for_each_entry_rcu(dev, head, index_hlist) {
|
||||||
|
if (idx < s_idx)
|
||||||
|
goto cont;
|
||||||
|
in_dev = __in_dev_get_rcu(dev);
|
||||||
|
if (!in_dev)
|
||||||
|
goto cont;
|
||||||
|
|
||||||
|
if (inet_netconf_fill_devconf(skb, dev->ifindex,
|
||||||
|
&in_dev->cnf,
|
||||||
|
NETLINK_CB(cb->skb).portid,
|
||||||
|
cb->nlh->nlmsg_seq,
|
||||||
|
RTM_NEWNETCONF,
|
||||||
|
NLM_F_MULTI,
|
||||||
|
-1) <= 0) {
|
||||||
|
rcu_read_unlock();
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
cont:
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
rcu_read_unlock();
|
||||||
|
}
|
||||||
|
if (h == NETDEV_HASHENTRIES) {
|
||||||
|
if (inet_netconf_fill_devconf(skb, NETCONFA_IFINDEX_ALL,
|
||||||
|
net->ipv4.devconf_all,
|
||||||
|
NETLINK_CB(cb->skb).portid,
|
||||||
|
cb->nlh->nlmsg_seq,
|
||||||
|
RTM_NEWNETCONF, NLM_F_MULTI,
|
||||||
|
-1) <= 0)
|
||||||
|
goto done;
|
||||||
|
else
|
||||||
|
h++;
|
||||||
|
}
|
||||||
|
if (h == NETDEV_HASHENTRIES + 1) {
|
||||||
|
if (inet_netconf_fill_devconf(skb, NETCONFA_IFINDEX_DEFAULT,
|
||||||
|
net->ipv4.devconf_dflt,
|
||||||
|
NETLINK_CB(cb->skb).portid,
|
||||||
|
cb->nlh->nlmsg_seq,
|
||||||
|
RTM_NEWNETCONF, NLM_F_MULTI,
|
||||||
|
-1) <= 0)
|
||||||
|
goto done;
|
||||||
|
else
|
||||||
|
h++;
|
||||||
|
}
|
||||||
|
done:
|
||||||
|
cb->args[0] = h;
|
||||||
|
cb->args[1] = idx;
|
||||||
|
|
||||||
|
return skb->len;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_SYSCTL
|
#ifdef CONFIG_SYSCTL
|
||||||
|
|
||||||
static void devinet_copy_dflt_conf(struct net *net, int i)
|
static void devinet_copy_dflt_conf(struct net *net, int i)
|
||||||
|
@ -2195,6 +2263,6 @@ void __init devinet_init(void)
|
||||||
rtnl_register(PF_INET, RTM_DELADDR, inet_rtm_deladdr, NULL, NULL);
|
rtnl_register(PF_INET, RTM_DELADDR, inet_rtm_deladdr, NULL, NULL);
|
||||||
rtnl_register(PF_INET, RTM_GETADDR, NULL, inet_dump_ifaddr, NULL);
|
rtnl_register(PF_INET, RTM_GETADDR, NULL, inet_dump_ifaddr, NULL);
|
||||||
rtnl_register(PF_INET, RTM_GETNETCONF, inet_netconf_get_devconf,
|
rtnl_register(PF_INET, RTM_GETNETCONF, inet_netconf_get_devconf,
|
||||||
NULL, NULL);
|
inet_netconf_dump_devconf, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -605,6 +605,74 @@ errout:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int inet6_netconf_dump_devconf(struct sk_buff *skb,
|
||||||
|
struct netlink_callback *cb)
|
||||||
|
{
|
||||||
|
struct net *net = sock_net(skb->sk);
|
||||||
|
int h, s_h;
|
||||||
|
int idx, s_idx;
|
||||||
|
struct net_device *dev;
|
||||||
|
struct inet6_dev *idev;
|
||||||
|
struct hlist_head *head;
|
||||||
|
|
||||||
|
s_h = cb->args[0];
|
||||||
|
s_idx = idx = cb->args[1];
|
||||||
|
|
||||||
|
for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
|
||||||
|
idx = 0;
|
||||||
|
head = &net->dev_index_head[h];
|
||||||
|
rcu_read_lock();
|
||||||
|
hlist_for_each_entry_rcu(dev, head, index_hlist) {
|
||||||
|
if (idx < s_idx)
|
||||||
|
goto cont;
|
||||||
|
idev = __in6_dev_get(dev);
|
||||||
|
if (!idev)
|
||||||
|
goto cont;
|
||||||
|
|
||||||
|
if (inet6_netconf_fill_devconf(skb, dev->ifindex,
|
||||||
|
&idev->cnf,
|
||||||
|
NETLINK_CB(cb->skb).portid,
|
||||||
|
cb->nlh->nlmsg_seq,
|
||||||
|
RTM_NEWNETCONF,
|
||||||
|
NLM_F_MULTI,
|
||||||
|
-1) <= 0) {
|
||||||
|
rcu_read_unlock();
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
cont:
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
rcu_read_unlock();
|
||||||
|
}
|
||||||
|
if (h == NETDEV_HASHENTRIES) {
|
||||||
|
if (inet6_netconf_fill_devconf(skb, NETCONFA_IFINDEX_ALL,
|
||||||
|
net->ipv6.devconf_all,
|
||||||
|
NETLINK_CB(cb->skb).portid,
|
||||||
|
cb->nlh->nlmsg_seq,
|
||||||
|
RTM_NEWNETCONF, NLM_F_MULTI,
|
||||||
|
-1) <= 0)
|
||||||
|
goto done;
|
||||||
|
else
|
||||||
|
h++;
|
||||||
|
}
|
||||||
|
if (h == NETDEV_HASHENTRIES + 1) {
|
||||||
|
if (inet6_netconf_fill_devconf(skb, NETCONFA_IFINDEX_DEFAULT,
|
||||||
|
net->ipv6.devconf_dflt,
|
||||||
|
NETLINK_CB(cb->skb).portid,
|
||||||
|
cb->nlh->nlmsg_seq,
|
||||||
|
RTM_NEWNETCONF, NLM_F_MULTI,
|
||||||
|
-1) <= 0)
|
||||||
|
goto done;
|
||||||
|
else
|
||||||
|
h++;
|
||||||
|
}
|
||||||
|
done:
|
||||||
|
cb->args[0] = h;
|
||||||
|
cb->args[1] = idx;
|
||||||
|
|
||||||
|
return skb->len;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_SYSCTL
|
#ifdef CONFIG_SYSCTL
|
||||||
static void dev_forward_change(struct inet6_dev *idev)
|
static void dev_forward_change(struct inet6_dev *idev)
|
||||||
{
|
{
|
||||||
|
@ -4940,7 +5008,7 @@ int __init addrconf_init(void)
|
||||||
__rtnl_register(PF_INET6, RTM_GETANYCAST, NULL,
|
__rtnl_register(PF_INET6, RTM_GETANYCAST, NULL,
|
||||||
inet6_dump_ifacaddr, NULL);
|
inet6_dump_ifacaddr, NULL);
|
||||||
__rtnl_register(PF_INET6, RTM_GETNETCONF, inet6_netconf_get_devconf,
|
__rtnl_register(PF_INET6, RTM_GETNETCONF, inet6_netconf_get_devconf,
|
||||||
NULL, NULL);
|
inet6_netconf_dump_devconf, NULL);
|
||||||
|
|
||||||
ipv6_addr_label_rtnl_register();
|
ipv6_addr_label_rtnl_register();
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче