@@ -640,21 +640,65 @@ static int tcf_node_dump(struct tcf_proto *tp, unsigned long n,
640
640
RTM_NEWTFILTER );
641
641
}
642
642
643
+ static void tcf_chain_dump (struct tcf_chain * chain , struct sk_buff * skb ,
644
+ struct netlink_callback * cb ,
645
+ long index_start , long * p_index )
646
+ {
647
+ struct net * net = sock_net (skb -> sk );
648
+ struct tcmsg * tcm = nlmsg_data (cb -> nlh );
649
+ struct tcf_dump_args arg ;
650
+ struct tcf_proto * tp ;
651
+
652
+ for (tp = rtnl_dereference (chain -> filter_chain );
653
+ tp ; tp = rtnl_dereference (tp -> next ), (* p_index )++ ) {
654
+ if (* p_index < index_start )
655
+ continue ;
656
+ if (TC_H_MAJ (tcm -> tcm_info ) &&
657
+ TC_H_MAJ (tcm -> tcm_info ) != tp -> prio )
658
+ continue ;
659
+ if (TC_H_MIN (tcm -> tcm_info ) &&
660
+ TC_H_MIN (tcm -> tcm_info ) != tp -> protocol )
661
+ continue ;
662
+ if (* p_index > index_start )
663
+ memset (& cb -> args [1 ], 0 ,
664
+ sizeof (cb -> args ) - sizeof (cb -> args [0 ]));
665
+ if (cb -> args [1 ] == 0 ) {
666
+ if (tcf_fill_node (net , skb , tp , 0 ,
667
+ NETLINK_CB (cb -> skb ).portid ,
668
+ cb -> nlh -> nlmsg_seq , NLM_F_MULTI ,
669
+ RTM_NEWTFILTER ) <= 0 )
670
+ break ;
671
+
672
+ cb -> args [1 ] = 1 ;
673
+ }
674
+ if (!tp -> ops -> walk )
675
+ continue ;
676
+ arg .w .fn = tcf_node_dump ;
677
+ arg .skb = skb ;
678
+ arg .cb = cb ;
679
+ arg .w .stop = 0 ;
680
+ arg .w .skip = cb -> args [1 ] - 1 ;
681
+ arg .w .count = 0 ;
682
+ tp -> ops -> walk (tp , & arg .w );
683
+ cb -> args [1 ] = arg .w .count + 1 ;
684
+ if (arg .w .stop )
685
+ break ;
686
+ }
687
+ }
688
+
643
689
/* called with RTNL */
644
690
static int tc_dump_tfilter (struct sk_buff * skb , struct netlink_callback * cb )
645
691
{
646
692
struct net * net = sock_net (skb -> sk );
647
- int t ;
648
- int s_t ;
649
693
struct net_device * dev ;
650
694
struct Qdisc * q ;
651
695
struct tcf_block * block ;
652
- struct tcf_proto * tp ;
653
696
struct tcf_chain * chain ;
654
697
struct tcmsg * tcm = nlmsg_data (cb -> nlh );
655
698
unsigned long cl = 0 ;
656
699
const struct Qdisc_class_ops * cops ;
657
- struct tcf_dump_args arg ;
700
+ long index_start ;
701
+ long index ;
658
702
659
703
if (nlmsg_len (cb -> nlh ) < sizeof (* tcm ))
660
704
return skb -> len ;
@@ -683,45 +727,10 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)
683
727
goto errout ;
684
728
chain = block -> chain ;
685
729
686
- s_t = cb -> args [0 ];
687
-
688
- for (tp = rtnl_dereference (chain -> filter_chain ), t = 0 ;
689
- tp ; tp = rtnl_dereference (tp -> next ), t ++ ) {
690
- if (t < s_t )
691
- continue ;
692
- if (TC_H_MAJ (tcm -> tcm_info ) &&
693
- TC_H_MAJ (tcm -> tcm_info ) != tp -> prio )
694
- continue ;
695
- if (TC_H_MIN (tcm -> tcm_info ) &&
696
- TC_H_MIN (tcm -> tcm_info ) != tp -> protocol )
697
- continue ;
698
- if (t > s_t )
699
- memset (& cb -> args [1 ], 0 ,
700
- sizeof (cb -> args )- sizeof (cb -> args [0 ]));
701
- if (cb -> args [1 ] == 0 ) {
702
- if (tcf_fill_node (net , skb , tp , 0 ,
703
- NETLINK_CB (cb -> skb ).portid ,
704
- cb -> nlh -> nlmsg_seq , NLM_F_MULTI ,
705
- RTM_NEWTFILTER ) <= 0 )
706
- break ;
707
-
708
- cb -> args [1 ] = 1 ;
709
- }
710
- if (tp -> ops -> walk == NULL )
711
- continue ;
712
- arg .w .fn = tcf_node_dump ;
713
- arg .skb = skb ;
714
- arg .cb = cb ;
715
- arg .w .stop = 0 ;
716
- arg .w .skip = cb -> args [1 ] - 1 ;
717
- arg .w .count = 0 ;
718
- tp -> ops -> walk (tp , & arg .w );
719
- cb -> args [1 ] = arg .w .count + 1 ;
720
- if (arg .w .stop )
721
- break ;
722
- }
723
-
724
- cb -> args [0 ] = t ;
730
+ index_start = cb -> args [0 ];
731
+ index = 0 ;
732
+ tcf_chain_dump (chain , skb , cb , index_start , & index );
733
+ cb -> args [0 ] = index ;
725
734
726
735
errout :
727
736
if (cl )
0 commit comments