@@ -3367,35 +3367,50 @@ static int nf_tables_dump_setelem(const struct nft_ctx *ctx,
3367
3367
return nf_tables_fill_setelem (args -> skb , set , elem );
3368
3368
}
3369
3369
3370
+ struct nft_set_dump_ctx {
3371
+ const struct nft_set * set ;
3372
+ struct nft_ctx ctx ;
3373
+ };
3374
+
3370
3375
static int nf_tables_dump_set (struct sk_buff * skb , struct netlink_callback * cb )
3371
3376
{
3377
+ struct nft_set_dump_ctx * dump_ctx = cb -> data ;
3372
3378
struct net * net = sock_net (skb -> sk );
3373
- u8 genmask = nft_genmask_cur (net );
3379
+ struct nft_af_info * afi ;
3380
+ struct nft_table * table ;
3374
3381
struct nft_set * set ;
3375
3382
struct nft_set_dump_args args ;
3376
- struct nft_ctx ctx ;
3377
- struct nlattr * nla [NFTA_SET_ELEM_LIST_MAX + 1 ];
3383
+ bool set_found = false;
3378
3384
struct nfgenmsg * nfmsg ;
3379
3385
struct nlmsghdr * nlh ;
3380
3386
struct nlattr * nest ;
3381
3387
u32 portid , seq ;
3382
- int event , err ;
3388
+ int event ;
3383
3389
3384
- err = nlmsg_parse (cb -> nlh , sizeof (struct nfgenmsg ), nla ,
3385
- NFTA_SET_ELEM_LIST_MAX , nft_set_elem_list_policy ,
3386
- NULL );
3387
- if (err < 0 )
3388
- return err ;
3390
+ rcu_read_lock ();
3391
+ list_for_each_entry_rcu (afi , & net -> nft .af_info , list ) {
3392
+ if (afi != dump_ctx -> ctx .afi )
3393
+ continue ;
3389
3394
3390
- err = nft_ctx_init_from_elemattr (& ctx , net , cb -> skb , cb -> nlh ,
3391
- (void * )nla , genmask );
3392
- if (err < 0 )
3393
- return err ;
3395
+ list_for_each_entry_rcu (table , & afi -> tables , list ) {
3396
+ if (table != dump_ctx -> ctx .table )
3397
+ continue ;
3394
3398
3395
- set = nf_tables_set_lookup (ctx .table , nla [NFTA_SET_ELEM_LIST_SET ],
3396
- genmask );
3397
- if (IS_ERR (set ))
3398
- return PTR_ERR (set );
3399
+ list_for_each_entry_rcu (set , & table -> sets , list ) {
3400
+ if (set == dump_ctx -> set ) {
3401
+ set_found = true;
3402
+ break ;
3403
+ }
3404
+ }
3405
+ break ;
3406
+ }
3407
+ break ;
3408
+ }
3409
+
3410
+ if (!set_found ) {
3411
+ rcu_read_unlock ();
3412
+ return - ENOENT ;
3413
+ }
3399
3414
3400
3415
event = nfnl_msg_type (NFNL_SUBSYS_NFTABLES , NFT_MSG_NEWSETELEM );
3401
3416
portid = NETLINK_CB (cb -> skb ).portid ;
@@ -3407,11 +3422,11 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
3407
3422
goto nla_put_failure ;
3408
3423
3409
3424
nfmsg = nlmsg_data (nlh );
3410
- nfmsg -> nfgen_family = ctx . afi -> family ;
3425
+ nfmsg -> nfgen_family = afi -> family ;
3411
3426
nfmsg -> version = NFNETLINK_V0 ;
3412
- nfmsg -> res_id = htons (ctx . net -> nft .base_seq & 0xffff );
3427
+ nfmsg -> res_id = htons (net -> nft .base_seq & 0xffff );
3413
3428
3414
- if (nla_put_string (skb , NFTA_SET_ELEM_LIST_TABLE , ctx . table -> name ))
3429
+ if (nla_put_string (skb , NFTA_SET_ELEM_LIST_TABLE , table -> name ))
3415
3430
goto nla_put_failure ;
3416
3431
if (nla_put_string (skb , NFTA_SET_ELEM_LIST_SET , set -> name ))
3417
3432
goto nla_put_failure ;
@@ -3422,12 +3437,13 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
3422
3437
3423
3438
args .cb = cb ;
3424
3439
args .skb = skb ;
3425
- args .iter .genmask = nft_genmask_cur (ctx . net );
3440
+ args .iter .genmask = nft_genmask_cur (net );
3426
3441
args .iter .skip = cb -> args [0 ];
3427
3442
args .iter .count = 0 ;
3428
3443
args .iter .err = 0 ;
3429
3444
args .iter .fn = nf_tables_dump_setelem ;
3430
- set -> ops -> walk (& ctx , set , & args .iter );
3445
+ set -> ops -> walk (& dump_ctx -> ctx , set , & args .iter );
3446
+ rcu_read_unlock ();
3431
3447
3432
3448
nla_nest_end (skb , nest );
3433
3449
nlmsg_end (skb , nlh );
@@ -3441,9 +3457,16 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
3441
3457
return skb -> len ;
3442
3458
3443
3459
nla_put_failure :
3460
+ rcu_read_unlock ();
3444
3461
return - ENOSPC ;
3445
3462
}
3446
3463
3464
+ static int nf_tables_dump_set_done (struct netlink_callback * cb )
3465
+ {
3466
+ kfree (cb -> data );
3467
+ return 0 ;
3468
+ }
3469
+
3447
3470
static int nf_tables_getsetelem (struct net * net , struct sock * nlsk ,
3448
3471
struct sk_buff * skb , const struct nlmsghdr * nlh ,
3449
3472
const struct nlattr * const nla [])
@@ -3465,7 +3488,18 @@ static int nf_tables_getsetelem(struct net *net, struct sock *nlsk,
3465
3488
if (nlh -> nlmsg_flags & NLM_F_DUMP ) {
3466
3489
struct netlink_dump_control c = {
3467
3490
.dump = nf_tables_dump_set ,
3491
+ .done = nf_tables_dump_set_done ,
3468
3492
};
3493
+ struct nft_set_dump_ctx * dump_ctx ;
3494
+
3495
+ dump_ctx = kmalloc (sizeof (* dump_ctx ), GFP_KERNEL );
3496
+ if (!dump_ctx )
3497
+ return - ENOMEM ;
3498
+
3499
+ dump_ctx -> set = set ;
3500
+ dump_ctx -> ctx = ctx ;
3501
+
3502
+ c .data = dump_ctx ;
3469
3503
return netlink_dump_start (nlsk , skb , nlh , & c );
3470
3504
}
3471
3505
return - EOPNOTSUPP ;
0 commit comments