@@ -1676,7 +1676,7 @@ static int put_cacheinfo(struct sk_buff *skb, unsigned long cstamp,
1676
1676
return nla_put (skb , IFA_CACHEINFO , sizeof (ci ), & ci );
1677
1677
}
1678
1678
1679
- static int inet_fill_ifaddr (struct sk_buff * skb , struct in_ifaddr * ifa ,
1679
+ static int inet_fill_ifaddr (struct sk_buff * skb , const struct in_ifaddr * ifa ,
1680
1680
struct inet_fill_args * args )
1681
1681
{
1682
1682
struct ifaddrmsg * ifm ;
@@ -1805,15 +1805,15 @@ static int inet_valid_dump_ifaddr_req(const struct nlmsghdr *nlh,
1805
1805
}
1806
1806
1807
1807
static int in_dev_dump_addr (struct in_device * in_dev , struct sk_buff * skb ,
1808
- struct netlink_callback * cb , int s_ip_idx ,
1808
+ struct netlink_callback * cb , int * s_ip_idx ,
1809
1809
struct inet_fill_args * fillargs )
1810
1810
{
1811
1811
struct in_ifaddr * ifa ;
1812
1812
int ip_idx = 0 ;
1813
1813
int err ;
1814
1814
1815
- in_dev_for_each_ifa_rtnl (ifa , in_dev ) {
1816
- if (ip_idx < s_ip_idx ) {
1815
+ in_dev_for_each_ifa_rcu (ifa , in_dev ) {
1816
+ if (ip_idx < * s_ip_idx ) {
1817
1817
ip_idx ++ ;
1818
1818
continue ;
1819
1819
}
@@ -1825,9 +1825,9 @@ static int in_dev_dump_addr(struct in_device *in_dev, struct sk_buff *skb,
1825
1825
ip_idx ++ ;
1826
1826
}
1827
1827
err = 0 ;
1828
-
1828
+ ip_idx = 0 ;
1829
1829
done :
1830
- cb -> args [ 2 ] = ip_idx ;
1830
+ * s_ip_idx = ip_idx ;
1831
1831
1832
1832
return err ;
1833
1833
}
@@ -1859,75 +1859,53 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
1859
1859
};
1860
1860
struct net * net = sock_net (skb -> sk );
1861
1861
struct net * tgt_net = net ;
1862
- int h , s_h ;
1863
- int idx , s_idx ;
1864
- int s_ip_idx ;
1865
- struct net_device * dev ;
1862
+ struct {
1863
+ unsigned long ifindex ;
1864
+ int ip_idx ;
1865
+ } * ctx = ( void * ) cb -> ctx ;
1866
1866
struct in_device * in_dev ;
1867
- struct hlist_head * head ;
1867
+ struct net_device * dev ;
1868
1868
int err = 0 ;
1869
1869
1870
- s_h = cb -> args [0 ];
1871
- s_idx = idx = cb -> args [1 ];
1872
- s_ip_idx = cb -> args [2 ];
1873
-
1870
+ rcu_read_lock ();
1874
1871
if (cb -> strict_check ) {
1875
1872
err = inet_valid_dump_ifaddr_req (nlh , & fillargs , & tgt_net ,
1876
1873
skb -> sk , cb );
1877
1874
if (err < 0 )
1878
- goto put_tgt_net ;
1875
+ goto done ;
1879
1876
1880
- err = 0 ;
1881
1877
if (fillargs .ifindex ) {
1882
- dev = __dev_get_by_index (tgt_net , fillargs .ifindex );
1883
- if (!dev ) {
1884
- err = - ENODEV ;
1885
- goto put_tgt_net ;
1886
- }
1887
-
1888
- in_dev = __in_dev_get_rtnl (dev );
1889
- if (in_dev ) {
1890
- err = in_dev_dump_addr (in_dev , skb , cb , s_ip_idx ,
1891
- & fillargs );
1892
- }
1893
- goto put_tgt_net ;
1894
- }
1895
- }
1896
-
1897
- for (h = s_h ; h < NETDEV_HASHENTRIES ; h ++ , s_idx = 0 ) {
1898
- idx = 0 ;
1899
- head = & tgt_net -> dev_index_head [h ];
1900
- rcu_read_lock ();
1901
- cb -> seq = inet_base_seq (tgt_net );
1902
- hlist_for_each_entry_rcu (dev , head , index_hlist ) {
1903
- if (idx < s_idx )
1904
- goto cont ;
1905
- if (h > s_h || idx > s_idx )
1906
- s_ip_idx = 0 ;
1878
+ err = - ENODEV ;
1879
+ dev = dev_get_by_index_rcu (tgt_net , fillargs .ifindex );
1880
+ if (!dev )
1881
+ goto done ;
1907
1882
in_dev = __in_dev_get_rcu (dev );
1908
1883
if (!in_dev )
1909
- goto cont ;
1910
-
1911
- err = in_dev_dump_addr (in_dev , skb , cb , s_ip_idx ,
1912
- & fillargs );
1913
- if (err < 0 ) {
1914
- rcu_read_unlock ();
1915
1884
goto done ;
1916
- }
1917
- cont :
1918
- idx ++ ;
1885
+ err = in_dev_dump_addr ( in_dev , skb , cb , & ctx -> ip_idx ,
1886
+ & fillargs );
1887
+ goto done ;
1919
1888
}
1920
- rcu_read_unlock ();
1921
1889
}
1922
1890
1891
+ cb -> seq = inet_base_seq (tgt_net );
1892
+
1893
+ for_each_netdev_dump (net , dev , ctx -> ifindex ) {
1894
+ in_dev = __in_dev_get_rcu (dev );
1895
+ if (!in_dev )
1896
+ continue ;
1897
+ err = in_dev_dump_addr (in_dev , skb , cb , & ctx -> ip_idx ,
1898
+ & fillargs );
1899
+ if (err < 0 )
1900
+ goto done ;
1901
+ }
1923
1902
done :
1924
- cb -> args [0 ] = h ;
1925
- cb -> args [1 ] = idx ;
1926
- put_tgt_net :
1903
+ if (err < 0 && likely (skb -> len ))
1904
+ err = skb -> len ;
1927
1905
if (fillargs .netnsid >= 0 )
1928
1906
put_net (tgt_net );
1929
-
1930
- return skb -> len ? : err ;
1907
+ rcu_read_unlock ();
1908
+ return err ;
1931
1909
}
1932
1910
1933
1911
static void rtmsg_ifa (int event , struct in_ifaddr * ifa , struct nlmsghdr * nlh ,
@@ -2818,7 +2796,8 @@ void __init devinet_init(void)
2818
2796
2819
2797
rtnl_register (PF_INET , RTM_NEWADDR , inet_rtm_newaddr , NULL , 0 );
2820
2798
rtnl_register (PF_INET , RTM_DELADDR , inet_rtm_deladdr , NULL , 0 );
2821
- rtnl_register (PF_INET , RTM_GETADDR , NULL , inet_dump_ifaddr , 0 );
2799
+ rtnl_register (PF_INET , RTM_GETADDR , NULL , inet_dump_ifaddr ,
2800
+ RTNL_FLAG_DUMP_UNLOCKED );
2822
2801
rtnl_register (PF_INET , RTM_GETNETCONF , inet_netconf_get_devconf ,
2823
2802
inet_netconf_dump_devconf ,
2824
2803
RTNL_FLAG_DOIT_UNLOCKED | RTNL_FLAG_DUMP_UNLOCKED );
0 commit comments