aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorNicolas Dichtel <nicolas.dichtel@6wind.com>2013-03-05 18:42:06 -0500
committerDavid S. Miller <davem@davemloft.net>2013-03-06 15:40:53 -0500
commit7a6742003f3c8650c4d3f9edcae1cf8a5cdda276 (patch)
tree26b37b324a5efe81c42af647ed701107e3c05077 /net
parent753f993911b32e479b4fab5d228dc07c11d1e7e7 (diff)
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>
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/devinet.c70
-rw-r--r--net/ipv6/addrconf.c70
2 files changed, 138 insertions, 2 deletions
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index f678507bc829..af57bbae05b9 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1791,6 +1791,74 @@ errout:
1791 return err; 1791 return err;
1792} 1792}
1793 1793
1794static int inet_netconf_dump_devconf(struct sk_buff *skb,
1795 struct netlink_callback *cb)
1796{
1797 struct net *net = sock_net(skb->sk);
1798 int h, s_h;
1799 int idx, s_idx;
1800 struct net_device *dev;
1801 struct in_device *in_dev;
1802 struct hlist_head *head;
1803
1804 s_h = cb->args[0];
1805 s_idx = idx = cb->args[1];
1806
1807 for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
1808 idx = 0;
1809 head = &net->dev_index_head[h];
1810 rcu_read_lock();
1811 hlist_for_each_entry_rcu(dev, head, index_hlist) {
1812 if (idx < s_idx)
1813 goto cont;
1814 in_dev = __in_dev_get_rcu(dev);
1815 if (!in_dev)
1816 goto cont;
1817
1818 if (inet_netconf_fill_devconf(skb, dev->ifindex,
1819 &in_dev->cnf,
1820 NETLINK_CB(cb->skb).portid,
1821 cb->nlh->nlmsg_seq,
1822 RTM_NEWNETCONF,
1823 NLM_F_MULTI,
1824 -1) <= 0) {
1825 rcu_read_unlock();
1826 goto done;
1827 }
1828cont:
1829 idx++;
1830 }
1831 rcu_read_unlock();
1832 }
1833 if (h == NETDEV_HASHENTRIES) {
1834 if (inet_netconf_fill_devconf(skb, NETCONFA_IFINDEX_ALL,
1835 net->ipv4.devconf_all,
1836 NETLINK_CB(cb->skb).portid,
1837 cb->nlh->nlmsg_seq,
1838 RTM_NEWNETCONF, NLM_F_MULTI,
1839 -1) <= 0)
1840 goto done;
1841 else
1842 h++;
1843 }
1844 if (h == NETDEV_HASHENTRIES + 1) {
1845 if (inet_netconf_fill_devconf(skb, NETCONFA_IFINDEX_DEFAULT,
1846 net->ipv4.devconf_dflt,
1847 NETLINK_CB(cb->skb).portid,
1848 cb->nlh->nlmsg_seq,
1849 RTM_NEWNETCONF, NLM_F_MULTI,
1850 -1) <= 0)
1851 goto done;
1852 else
1853 h++;
1854 }
1855done:
1856 cb->args[0] = h;
1857 cb->args[1] = idx;
1858
1859 return skb->len;
1860}
1861
1794#ifdef CONFIG_SYSCTL 1862#ifdef CONFIG_SYSCTL
1795 1863
1796static void devinet_copy_dflt_conf(struct net *net, int i) 1864static void devinet_copy_dflt_conf(struct net *net, int i)
@@ -2195,6 +2263,6 @@ void __init devinet_init(void)
2195 rtnl_register(PF_INET, RTM_DELADDR, inet_rtm_deladdr, NULL, NULL); 2263 rtnl_register(PF_INET, RTM_DELADDR, inet_rtm_deladdr, NULL, NULL);
2196 rtnl_register(PF_INET, RTM_GETADDR, NULL, inet_dump_ifaddr, NULL); 2264 rtnl_register(PF_INET, RTM_GETADDR, NULL, inet_dump_ifaddr, NULL);
2197 rtnl_register(PF_INET, RTM_GETNETCONF, inet_netconf_get_devconf, 2265 rtnl_register(PF_INET, RTM_GETNETCONF, inet_netconf_get_devconf,
2198 NULL, NULL); 2266 inet_netconf_dump_devconf, NULL);
2199} 2267}
2200 2268
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index f2c7e615f902..fa36a677490f 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -605,6 +605,74 @@ errout:
605 return err; 605 return err;
606} 606}
607 607
608static int inet6_netconf_dump_devconf(struct sk_buff *skb,
609 struct netlink_callback *cb)
610{
611 struct net *net = sock_net(skb->sk);
612 int h, s_h;
613 int idx, s_idx;
614 struct net_device *dev;
615 struct inet6_dev *idev;
616 struct hlist_head *head;
617
618 s_h = cb->args[0];
619 s_idx = idx = cb->args[1];
620
621 for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
622 idx = 0;
623 head = &net->dev_index_head[h];
624 rcu_read_lock();
625 hlist_for_each_entry_rcu(dev, head, index_hlist) {
626 if (idx < s_idx)
627 goto cont;
628 idev = __in6_dev_get(dev);
629 if (!idev)
630 goto cont;
631
632 if (inet6_netconf_fill_devconf(skb, dev->ifindex,
633 &idev->cnf,
634 NETLINK_CB(cb->skb).portid,
635 cb->nlh->nlmsg_seq,
636 RTM_NEWNETCONF,
637 NLM_F_MULTI,
638 -1) <= 0) {
639 rcu_read_unlock();
640 goto done;
641 }
642cont:
643 idx++;
644 }
645 rcu_read_unlock();
646 }
647 if (h == NETDEV_HASHENTRIES) {
648 if (inet6_netconf_fill_devconf(skb, NETCONFA_IFINDEX_ALL,
649 net->ipv6.devconf_all,
650 NETLINK_CB(cb->skb).portid,
651 cb->nlh->nlmsg_seq,
652 RTM_NEWNETCONF, NLM_F_MULTI,
653 -1) <= 0)
654 goto done;
655 else
656 h++;
657 }
658 if (h == NETDEV_HASHENTRIES + 1) {
659 if (inet6_netconf_fill_devconf(skb, NETCONFA_IFINDEX_DEFAULT,
660 net->ipv6.devconf_dflt,
661 NETLINK_CB(cb->skb).portid,
662 cb->nlh->nlmsg_seq,
663 RTM_NEWNETCONF, NLM_F_MULTI,
664 -1) <= 0)
665 goto done;
666 else
667 h++;
668 }
669done:
670 cb->args[0] = h;
671 cb->args[1] = idx;
672
673 return skb->len;
674}
675
608#ifdef CONFIG_SYSCTL 676#ifdef CONFIG_SYSCTL
609static void dev_forward_change(struct inet6_dev *idev) 677static void dev_forward_change(struct inet6_dev *idev)
610{ 678{
@@ -4940,7 +5008,7 @@ int __init addrconf_init(void)
4940 __rtnl_register(PF_INET6, RTM_GETANYCAST, NULL, 5008 __rtnl_register(PF_INET6, RTM_GETANYCAST, NULL,
4941 inet6_dump_ifacaddr, NULL); 5009 inet6_dump_ifacaddr, NULL);
4942 __rtnl_register(PF_INET6, RTM_GETNETCONF, inet6_netconf_get_devconf, 5010 __rtnl_register(PF_INET6, RTM_GETNETCONF, inet6_netconf_get_devconf,
4943 NULL, NULL); 5011 inet6_netconf_dump_devconf, NULL);
4944 5012
4945 ipv6_addr_label_rtnl_register(); 5013 ipv6_addr_label_rtnl_register();
4946 5014