@@ -727,17 +727,18 @@ static u32 inet6_base_seq(const struct net *net)
727727 return res ;
728728}
729729
730-
731730static int inet6_netconf_dump_devconf (struct sk_buff * skb ,
732731 struct netlink_callback * cb )
733732{
734733 const struct nlmsghdr * nlh = cb -> nlh ;
735734 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 ;
738739 struct net_device * dev ;
739740 struct inet6_dev * idev ;
740- struct hlist_head * head ;
741+ int err = 0 ;
741742
742743 if (cb -> strict_check ) {
743744 struct netlink_ext_ack * extack = cb -> extack ;
@@ -754,64 +755,48 @@ static int inet6_netconf_dump_devconf(struct sk_buff *skb,
754755 }
755756 }
756757
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 ;
787772 }
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 )
795781 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 )
806792 goto done ;
807- else
808- h ++ ;
793+ ctx -> all_default ++ ;
809794 }
810795done :
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 ;
815800}
816801
817802#ifdef CONFIG_SYSCTL
@@ -7503,7 +7488,8 @@ int __init addrconf_init(void)
75037488 err = rtnl_register_module (THIS_MODULE , PF_INET6 , RTM_GETNETCONF ,
75047489 inet6_netconf_get_devconf ,
75057490 inet6_netconf_dump_devconf ,
7506- RTNL_FLAG_DOIT_UNLOCKED );
7491+ RTNL_FLAG_DOIT_UNLOCKED |
7492+ RTNL_FLAG_DUMP_UNLOCKED );
75077493 if (err < 0 )
75087494 goto errout ;
75097495 err = ipv6_addr_label_rtnl_register ();
0 commit comments