aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/devinet.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/devinet.c')
-rw-r--r--net/ipv4/devinet.c83
1 files changed, 78 insertions, 5 deletions
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index c6287cd978c2..dfc39d4d48b7 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -536,7 +536,7 @@ struct in_ifaddr *inet_ifa_byprefix(struct in_device *in_dev, __be32 prefix,
536 return NULL; 536 return NULL;
537} 537}
538 538
539static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) 539static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh)
540{ 540{
541 struct net *net = sock_net(skb->sk); 541 struct net *net = sock_net(skb->sk);
542 struct nlattr *tb[IFA_MAX+1]; 542 struct nlattr *tb[IFA_MAX+1];
@@ -801,7 +801,7 @@ static struct in_ifaddr *find_matching_ifa(struct in_ifaddr *ifa)
801 return NULL; 801 return NULL;
802} 802}
803 803
804static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) 804static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh)
805{ 805{
806 struct net *net = sock_net(skb->sk); 806 struct net *net = sock_net(skb->sk);
807 struct in_ifaddr *ifa; 807 struct in_ifaddr *ifa;
@@ -1529,6 +1529,8 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
1529 idx = 0; 1529 idx = 0;
1530 head = &net->dev_index_head[h]; 1530 head = &net->dev_index_head[h];
1531 rcu_read_lock(); 1531 rcu_read_lock();
1532 cb->seq = atomic_read(&net->ipv4.dev_addr_genid) ^
1533 net->dev_base_seq;
1532 hlist_for_each_entry_rcu(dev, head, index_hlist) { 1534 hlist_for_each_entry_rcu(dev, head, index_hlist) {
1533 if (idx < s_idx) 1535 if (idx < s_idx)
1534 goto cont; 1536 goto cont;
@@ -1549,6 +1551,7 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
1549 rcu_read_unlock(); 1551 rcu_read_unlock();
1550 goto done; 1552 goto done;
1551 } 1553 }
1554 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
1552 } 1555 }
1553cont: 1556cont:
1554 idx++; 1557 idx++;
@@ -1760,8 +1763,7 @@ static const struct nla_policy devconf_ipv4_policy[NETCONFA_MAX+1] = {
1760}; 1763};
1761 1764
1762static int inet_netconf_get_devconf(struct sk_buff *in_skb, 1765static int inet_netconf_get_devconf(struct sk_buff *in_skb,
1763 struct nlmsghdr *nlh, 1766 struct nlmsghdr *nlh)
1764 void *arg)
1765{ 1767{
1766 struct net *net = sock_net(in_skb->sk); 1768 struct net *net = sock_net(in_skb->sk);
1767 struct nlattr *tb[NETCONFA_MAX+1]; 1769 struct nlattr *tb[NETCONFA_MAX+1];
@@ -1821,6 +1823,77 @@ errout:
1821 return err; 1823 return err;
1822} 1824}
1823 1825
1826static int inet_netconf_dump_devconf(struct sk_buff *skb,
1827 struct netlink_callback *cb)
1828{
1829 struct net *net = sock_net(skb->sk);
1830 int h, s_h;
1831 int idx, s_idx;
1832 struct net_device *dev;
1833 struct in_device *in_dev;
1834 struct hlist_head *head;
1835
1836 s_h = cb->args[0];
1837 s_idx = idx = cb->args[1];
1838
1839 for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
1840 idx = 0;
1841 head = &net->dev_index_head[h];
1842 rcu_read_lock();
1843 cb->seq = atomic_read(&net->ipv4.dev_addr_genid) ^
1844 net->dev_base_seq;
1845 hlist_for_each_entry_rcu(dev, head, index_hlist) {
1846 if (idx < s_idx)
1847 goto cont;
1848 in_dev = __in_dev_get_rcu(dev);
1849 if (!in_dev)
1850 goto cont;
1851
1852 if (inet_netconf_fill_devconf(skb, dev->ifindex,
1853 &in_dev->cnf,
1854 NETLINK_CB(cb->skb).portid,
1855 cb->nlh->nlmsg_seq,
1856 RTM_NEWNETCONF,
1857 NLM_F_MULTI,
1858 -1) <= 0) {
1859 rcu_read_unlock();
1860 goto done;
1861 }
1862 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
1863cont:
1864 idx++;
1865 }
1866 rcu_read_unlock();
1867 }
1868 if (h == NETDEV_HASHENTRIES) {
1869 if (inet_netconf_fill_devconf(skb, NETCONFA_IFINDEX_ALL,
1870 net->ipv4.devconf_all,
1871 NETLINK_CB(cb->skb).portid,
1872 cb->nlh->nlmsg_seq,
1873 RTM_NEWNETCONF, NLM_F_MULTI,
1874 -1) <= 0)
1875 goto done;
1876 else
1877 h++;
1878 }
1879 if (h == NETDEV_HASHENTRIES + 1) {
1880 if (inet_netconf_fill_devconf(skb, NETCONFA_IFINDEX_DEFAULT,
1881 net->ipv4.devconf_dflt,
1882 NETLINK_CB(cb->skb).portid,
1883 cb->nlh->nlmsg_seq,
1884 RTM_NEWNETCONF, NLM_F_MULTI,
1885 -1) <= 0)
1886 goto done;
1887 else
1888 h++;
1889 }
1890done:
1891 cb->args[0] = h;
1892 cb->args[1] = idx;
1893
1894 return skb->len;
1895}
1896
1824#ifdef CONFIG_SYSCTL 1897#ifdef CONFIG_SYSCTL
1825 1898
1826static void devinet_copy_dflt_conf(struct net *net, int i) 1899static void devinet_copy_dflt_conf(struct net *net, int i)
@@ -2225,6 +2298,6 @@ void __init devinet_init(void)
2225 rtnl_register(PF_INET, RTM_DELADDR, inet_rtm_deladdr, NULL, NULL); 2298 rtnl_register(PF_INET, RTM_DELADDR, inet_rtm_deladdr, NULL, NULL);
2226 rtnl_register(PF_INET, RTM_GETADDR, NULL, inet_dump_ifaddr, NULL); 2299 rtnl_register(PF_INET, RTM_GETADDR, NULL, inet_dump_ifaddr, NULL);
2227 rtnl_register(PF_INET, RTM_GETNETCONF, inet_netconf_get_devconf, 2300 rtnl_register(PF_INET, RTM_GETNETCONF, inet_netconf_get_devconf,
2228 NULL, NULL); 2301 inet_netconf_dump_devconf, NULL);
2229} 2302}
2230 2303