@@ -862,8 +862,6 @@ ctnetlink_conntrack_event(unsigned int events, const struct nf_ct_event *item)
862862
863863static int ctnetlink_done (struct netlink_callback * cb )
864864{
865- if (cb -> args [1 ])
866- nf_ct_put ((struct nf_conn * )cb -> args [1 ]);
867865 kfree (cb -> data );
868866 return 0 ;
869867}
@@ -1178,19 +1176,26 @@ static int ctnetlink_filter_match(struct nf_conn *ct, void *data)
11781176 return 0 ;
11791177}
11801178
1179+ static unsigned long ctnetlink_get_id (const struct nf_conn * ct )
1180+ {
1181+ unsigned long id = nf_ct_get_id (ct );
1182+
1183+ return id ? id : 1 ;
1184+ }
1185+
11811186static int
11821187ctnetlink_dump_table (struct sk_buff * skb , struct netlink_callback * cb )
11831188{
11841189 unsigned int flags = cb -> data ? NLM_F_DUMP_FILTERED : 0 ;
11851190 struct net * net = sock_net (skb -> sk );
1186- struct nf_conn * ct , * last ;
1191+ unsigned long last_id = cb -> args [ 1 ] ;
11871192 struct nf_conntrack_tuple_hash * h ;
11881193 struct hlist_nulls_node * n ;
11891194 struct nf_conn * nf_ct_evict [8 ];
1195+ struct nf_conn * ct ;
11901196 int res , i ;
11911197 spinlock_t * lockp ;
11921198
1193- last = (struct nf_conn * )cb -> args [1 ];
11941199 i = 0 ;
11951200
11961201 local_bh_disable ();
@@ -1227,7 +1232,7 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
12271232 continue ;
12281233
12291234 if (cb -> args [1 ]) {
1230- if (ct != last )
1235+ if (ctnetlink_get_id ( ct ) != last_id )
12311236 continue ;
12321237 cb -> args [1 ] = 0 ;
12331238 }
@@ -1240,8 +1245,7 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
12401245 NFNL_MSG_TYPE (cb -> nlh -> nlmsg_type ),
12411246 ct , true, flags );
12421247 if (res < 0 ) {
1243- nf_conntrack_get (& ct -> ct_general );
1244- cb -> args [1 ] = (unsigned long )ct ;
1248+ cb -> args [1 ] = ctnetlink_get_id (ct );
12451249 spin_unlock (lockp );
12461250 goto out ;
12471251 }
@@ -1254,12 +1258,10 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
12541258 }
12551259out :
12561260 local_bh_enable ();
1257- if (last ) {
1261+ if (last_id ) {
12581262 /* nf ct hash resize happened, now clear the leftover. */
1259- if (( struct nf_conn * ) cb -> args [1 ] == last )
1263+ if (cb -> args [1 ] == last_id )
12601264 cb -> args [1 ] = 0 ;
1261-
1262- nf_ct_put (last );
12631265 }
12641266
12651267 while (i ) {
@@ -3153,23 +3155,27 @@ ctnetlink_expect_event(unsigned int events, const struct nf_exp_event *item)
31533155 return 0 ;
31543156}
31553157#endif
3156- static int ctnetlink_exp_done (struct netlink_callback * cb )
3158+
3159+ static unsigned long ctnetlink_exp_id (const struct nf_conntrack_expect * exp )
31573160{
3158- if (cb -> args [1 ])
3159- nf_ct_expect_put ((struct nf_conntrack_expect * )cb -> args [1 ]);
3160- return 0 ;
3161+ unsigned long id = (unsigned long )exp ;
3162+
3163+ id += nf_ct_get_id (exp -> master );
3164+ id += exp -> class ;
3165+
3166+ return id ? id : 1 ;
31613167}
31623168
31633169static int
31643170ctnetlink_exp_dump_table (struct sk_buff * skb , struct netlink_callback * cb )
31653171{
31663172 struct net * net = sock_net (skb -> sk );
3167- struct nf_conntrack_expect * exp , * last ;
31683173 struct nfgenmsg * nfmsg = nlmsg_data (cb -> nlh );
31693174 u_int8_t l3proto = nfmsg -> nfgen_family ;
3175+ unsigned long last_id = cb -> args [1 ];
3176+ struct nf_conntrack_expect * exp ;
31703177
31713178 rcu_read_lock ();
3172- last = (struct nf_conntrack_expect * )cb -> args [1 ];
31733179 for (; cb -> args [0 ] < nf_ct_expect_hsize ; cb -> args [0 ]++ ) {
31743180restart :
31753181 hlist_for_each_entry_rcu (exp , & nf_ct_expect_hash [cb -> args [0 ]],
@@ -3181,7 +3187,7 @@ ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
31813187 continue ;
31823188
31833189 if (cb -> args [1 ]) {
3184- if (exp != last )
3190+ if (ctnetlink_exp_id ( exp ) != last_id )
31853191 continue ;
31863192 cb -> args [1 ] = 0 ;
31873193 }
@@ -3190,9 +3196,7 @@ ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
31903196 cb -> nlh -> nlmsg_seq ,
31913197 IPCTNL_MSG_EXP_NEW ,
31923198 exp ) < 0 ) {
3193- if (!refcount_inc_not_zero (& exp -> use ))
3194- continue ;
3195- cb -> args [1 ] = (unsigned long )exp ;
3199+ cb -> args [1 ] = ctnetlink_exp_id (exp );
31963200 goto out ;
31973201 }
31983202 }
@@ -3203,42 +3207,38 @@ ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
32033207 }
32043208out :
32053209 rcu_read_unlock ();
3206- if (last )
3207- nf_ct_expect_put (last );
3208-
32093210 return skb -> len ;
32103211}
32113212
32123213static int
32133214ctnetlink_exp_ct_dump_table (struct sk_buff * skb , struct netlink_callback * cb )
32143215{
3215- struct nf_conntrack_expect * exp , * last ;
32163216 struct nfgenmsg * nfmsg = nlmsg_data (cb -> nlh );
32173217 struct nf_conn * ct = cb -> data ;
32183218 struct nf_conn_help * help = nfct_help (ct );
32193219 u_int8_t l3proto = nfmsg -> nfgen_family ;
3220+ unsigned long last_id = cb -> args [1 ];
3221+ struct nf_conntrack_expect * exp ;
32203222
32213223 if (cb -> args [0 ])
32223224 return 0 ;
32233225
32243226 rcu_read_lock ();
3225- last = ( struct nf_conntrack_expect * ) cb -> args [ 1 ];
3227+
32263228restart :
32273229 hlist_for_each_entry_rcu (exp , & help -> expectations , lnode ) {
32283230 if (l3proto && exp -> tuple .src .l3num != l3proto )
32293231 continue ;
32303232 if (cb -> args [1 ]) {
3231- if (exp != last )
3233+ if (ctnetlink_exp_id ( exp ) != last_id )
32323234 continue ;
32333235 cb -> args [1 ] = 0 ;
32343236 }
32353237 if (ctnetlink_exp_fill_info (skb , NETLINK_CB (cb -> skb ).portid ,
32363238 cb -> nlh -> nlmsg_seq ,
32373239 IPCTNL_MSG_EXP_NEW ,
32383240 exp ) < 0 ) {
3239- if (!refcount_inc_not_zero (& exp -> use ))
3240- continue ;
3241- cb -> args [1 ] = (unsigned long )exp ;
3241+ cb -> args [1 ] = ctnetlink_exp_id (exp );
32423242 goto out ;
32433243 }
32443244 }
@@ -3249,9 +3249,6 @@ ctnetlink_exp_ct_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
32493249 cb -> args [0 ] = 1 ;
32503250out :
32513251 rcu_read_unlock ();
3252- if (last )
3253- nf_ct_expect_put (last );
3254-
32553252 return skb -> len ;
32563253}
32573254
@@ -3270,7 +3267,6 @@ static int ctnetlink_dump_exp_ct(struct net *net, struct sock *ctnl,
32703267 struct nf_conntrack_zone zone ;
32713268 struct netlink_dump_control c = {
32723269 .dump = ctnetlink_exp_ct_dump_table ,
3273- .done = ctnetlink_exp_done ,
32743270 };
32753271
32763272 err = ctnetlink_parse_tuple (cda , & tuple , CTA_EXPECT_MASTER ,
@@ -3320,7 +3316,6 @@ static int ctnetlink_get_expect(struct sk_buff *skb,
33203316 else {
33213317 struct netlink_dump_control c = {
33223318 .dump = ctnetlink_exp_dump_table ,
3323- .done = ctnetlink_exp_done ,
33243319 };
33253320 return netlink_dump_start (info -> sk , skb , info -> nlh , & c );
33263321 }
0 commit comments