@@ -727,17 +727,18 @@ static u32 inet6_base_seq(const struct net *net)
727
727
return res ;
728
728
}
729
729
730
-
731
730
static int inet6_netconf_dump_devconf (struct sk_buff * skb ,
732
731
struct netlink_callback * cb )
733
732
{
734
733
const struct nlmsghdr * nlh = cb -> nlh ;
735
734
struct net * net = sock_net (skb -> sk );
736
- int h , s_h ;
737
- int idx , s_idx ;
735
+ struct {
736
+ unsigned long ifindex ;
737
+ unsigned int all_default ;
738
+ } * ctx = (void * )cb -> ctx ;
738
739
struct net_device * dev ;
739
740
struct inet6_dev * idev ;
740
- struct hlist_head * head ;
741
+ int err = 0 ;
741
742
742
743
if (cb -> strict_check ) {
743
744
struct netlink_ext_ack * extack = cb -> extack ;
@@ -754,64 +755,48 @@ static int inet6_netconf_dump_devconf(struct sk_buff *skb,
754
755
}
755
756
}
756
757
757
- s_h = cb -> args [0 ];
758
- s_idx = idx = cb -> args [1 ];
759
-
760
- for (h = s_h ; h < NETDEV_HASHENTRIES ; h ++ , s_idx = 0 ) {
761
- idx = 0 ;
762
- head = & net -> dev_index_head [h ];
763
- rcu_read_lock ();
764
- cb -> seq = inet6_base_seq (net );
765
- hlist_for_each_entry_rcu (dev , head , index_hlist ) {
766
- if (idx < s_idx )
767
- goto cont ;
768
- idev = __in6_dev_get (dev );
769
- if (!idev )
770
- goto cont ;
771
-
772
- if (inet6_netconf_fill_devconf (skb , dev -> ifindex ,
773
- & idev -> cnf ,
774
- NETLINK_CB (cb -> skb ).portid ,
775
- nlh -> nlmsg_seq ,
776
- RTM_NEWNETCONF ,
777
- NLM_F_MULTI ,
778
- NETCONFA_ALL ) < 0 ) {
779
- rcu_read_unlock ();
780
- goto done ;
781
- }
782
- nl_dump_check_consistent (cb , nlmsg_hdr (skb ));
783
- cont :
784
- idx ++ ;
785
- }
786
- rcu_read_unlock ();
758
+ rcu_read_lock ();
759
+ for_each_netdev_dump (net , dev , ctx -> ifindex ) {
760
+ idev = __in6_dev_get (dev );
761
+ if (!idev )
762
+ continue ;
763
+ err = inet6_netconf_fill_devconf (skb , dev -> ifindex ,
764
+ & idev -> cnf ,
765
+ NETLINK_CB (cb -> skb ).portid ,
766
+ nlh -> nlmsg_seq ,
767
+ RTM_NEWNETCONF ,
768
+ NLM_F_MULTI ,
769
+ NETCONFA_ALL );
770
+ if (err < 0 )
771
+ goto done ;
787
772
}
788
- if (h == NETDEV_HASHENTRIES ) {
789
- if (inet6_netconf_fill_devconf (skb , NETCONFA_IFINDEX_ALL ,
790
- net -> ipv6 .devconf_all ,
791
- NETLINK_CB (cb -> skb ).portid ,
792
- nlh -> nlmsg_seq ,
793
- RTM_NEWNETCONF , NLM_F_MULTI ,
794
- NETCONFA_ALL ) < 0 )
773
+ if (ctx -> all_default == 0 ) {
774
+ err = inet6_netconf_fill_devconf (skb , NETCONFA_IFINDEX_ALL ,
775
+ net -> ipv6 .devconf_all ,
776
+ NETLINK_CB (cb -> skb ).portid ,
777
+ nlh -> nlmsg_seq ,
778
+ RTM_NEWNETCONF , NLM_F_MULTI ,
779
+ NETCONFA_ALL );
780
+ if (err < 0 )
795
781
goto done ;
796
- else
797
- h ++ ;
798
- }
799
- if ( h == NETDEV_HASHENTRIES + 1 ) {
800
- if ( inet6_netconf_fill_devconf ( skb , NETCONFA_IFINDEX_DEFAULT ,
801
- net -> ipv6 . devconf_dflt ,
802
- NETLINK_CB ( cb -> skb ). portid ,
803
- nlh -> nlmsg_seq ,
804
- RTM_NEWNETCONF , NLM_F_MULTI ,
805
- NETCONFA_ALL ) < 0 )
782
+ ctx -> all_default ++ ;
783
+ }
784
+ if ( ctx -> all_default == 1 ) {
785
+ err = inet6_netconf_fill_devconf ( skb , NETCONFA_IFINDEX_DEFAULT ,
786
+ net -> ipv6 . devconf_dflt ,
787
+ NETLINK_CB ( cb -> skb ). portid ,
788
+ nlh -> nlmsg_seq ,
789
+ RTM_NEWNETCONF , NLM_F_MULTI ,
790
+ NETCONFA_ALL );
791
+ if ( err < 0 )
806
792
goto done ;
807
- else
808
- h ++ ;
793
+ ctx -> all_default ++ ;
809
794
}
810
795
done :
811
- cb -> args [ 0 ] = h ;
812
- cb -> args [ 1 ] = idx ;
813
-
814
- return skb -> len ;
796
+ if ( err < 0 && likely ( skb -> len ))
797
+ err = skb -> len ;
798
+ rcu_read_unlock ();
799
+ return err ;
815
800
}
816
801
817
802
#ifdef CONFIG_SYSCTL
@@ -7503,7 +7488,8 @@ int __init addrconf_init(void)
7503
7488
err = rtnl_register_module (THIS_MODULE , PF_INET6 , RTM_GETNETCONF ,
7504
7489
inet6_netconf_get_devconf ,
7505
7490
inet6_netconf_dump_devconf ,
7506
- RTNL_FLAG_DOIT_UNLOCKED );
7491
+ RTNL_FLAG_DOIT_UNLOCKED |
7492
+ RTNL_FLAG_DUMP_UNLOCKED );
7507
7493
if (err < 0 )
7508
7494
goto errout ;
7509
7495
err = ipv6_addr_label_rtnl_register ();
0 commit comments