@@ -307,6 +307,9 @@ static int nf_tables_dump_tables(struct sk_buff *skb,
307
307
return skb -> len ;
308
308
}
309
309
310
+ /* Internal table flags */
311
+ #define NFT_TABLE_INACTIVE (1 << 15)
312
+
310
313
static int nf_tables_gettable (struct sock * nlsk , struct sk_buff * skb ,
311
314
const struct nlmsghdr * nlh ,
312
315
const struct nlattr * const nla [])
@@ -333,6 +336,8 @@ static int nf_tables_gettable(struct sock *nlsk, struct sk_buff *skb,
333
336
table = nf_tables_table_lookup (afi , nla [NFTA_TABLE_NAME ]);
334
337
if (IS_ERR (table ))
335
338
return PTR_ERR (table );
339
+ if (table -> flags & NFT_TABLE_INACTIVE )
340
+ return - ENOENT ;
336
341
337
342
skb2 = alloc_skb (NLMSG_GOODSIZE , GFP_KERNEL );
338
343
if (!skb2 )
@@ -395,9 +400,9 @@ static void nf_tables_table_disable(const struct nft_af_info *afi,
395
400
396
401
static int nf_tables_updtable (struct nft_ctx * ctx )
397
402
{
398
- const struct nfgenmsg * nfmsg = nlmsg_data (ctx -> nlh );
399
- int family = nfmsg -> nfgen_family , ret = 0 ;
403
+ struct nft_trans * trans ;
400
404
u32 flags ;
405
+ int ret = 0 ;
401
406
402
407
if (!ctx -> nla [NFTA_TABLE_FLAGS ])
403
408
return 0 ;
@@ -406,25 +411,48 @@ static int nf_tables_updtable(struct nft_ctx *ctx)
406
411
if (flags & ~NFT_TABLE_F_DORMANT )
407
412
return - EINVAL ;
408
413
414
+ trans = nft_trans_alloc (ctx , NFT_MSG_NEWTABLE ,
415
+ sizeof (struct nft_trans_table ));
416
+ if (trans == NULL )
417
+ return - ENOMEM ;
418
+
409
419
if ((flags & NFT_TABLE_F_DORMANT ) &&
410
420
!(ctx -> table -> flags & NFT_TABLE_F_DORMANT )) {
411
- nf_tables_table_disable (ctx -> afi , ctx -> table );
412
- ctx -> table -> flags |= NFT_TABLE_F_DORMANT ;
421
+ nft_trans_table_enable (trans ) = false;
413
422
} else if (!(flags & NFT_TABLE_F_DORMANT ) &&
414
423
ctx -> table -> flags & NFT_TABLE_F_DORMANT ) {
415
424
ret = nf_tables_table_enable (ctx -> afi , ctx -> table );
416
- if (ret >= 0 )
425
+ if (ret >= 0 ) {
417
426
ctx -> table -> flags &= ~NFT_TABLE_F_DORMANT ;
427
+ nft_trans_table_enable (trans ) = true;
428
+ }
418
429
}
419
430
if (ret < 0 )
420
431
goto err ;
421
432
422
- nf_tables_table_notify (ctx -> skb , ctx -> nlh , ctx -> table ,
423
- NFT_MSG_NEWTABLE , family );
433
+ nft_trans_table_update (trans ) = true;
434
+ list_add_tail (& trans -> list , & ctx -> net -> nft .commit_list );
435
+ return 0 ;
424
436
err :
437
+ nft_trans_destroy (trans );
425
438
return ret ;
426
439
}
427
440
441
+ static int nft_trans_table_add (struct nft_ctx * ctx , int msg_type )
442
+ {
443
+ struct nft_trans * trans ;
444
+
445
+ trans = nft_trans_alloc (ctx , msg_type , sizeof (struct nft_trans_table ));
446
+ if (trans == NULL )
447
+ return - ENOMEM ;
448
+
449
+ if (msg_type == NFT_MSG_NEWTABLE )
450
+ ctx -> table -> flags |= NFT_TABLE_INACTIVE ;
451
+
452
+ list_add_tail (& trans -> list , & ctx -> net -> nft .commit_list );
453
+ return 0 ;
454
+ }
455
+
428
456
static int nf_tables_newtable (struct sock * nlsk , struct sk_buff * skb ,
429
457
const struct nlmsghdr * nlh ,
430
458
const struct nlattr * const nla [])
@@ -437,6 +465,7 @@ static int nf_tables_newtable(struct sock *nlsk, struct sk_buff *skb,
437
465
int family = nfmsg -> nfgen_family ;
438
466
u32 flags = 0 ;
439
467
struct nft_ctx ctx ;
468
+ int err ;
440
469
441
470
afi = nf_tables_afinfo_lookup (net , family , true);
442
471
if (IS_ERR (afi ))
@@ -451,6 +480,8 @@ static int nf_tables_newtable(struct sock *nlsk, struct sk_buff *skb,
451
480
}
452
481
453
482
if (table != NULL ) {
483
+ if (table -> flags & NFT_TABLE_INACTIVE )
484
+ return - ENOENT ;
454
485
if (nlh -> nlmsg_flags & NLM_F_EXCL )
455
486
return - EEXIST ;
456
487
if (nlh -> nlmsg_flags & NLM_F_REPLACE )
@@ -480,8 +511,14 @@ static int nf_tables_newtable(struct sock *nlsk, struct sk_buff *skb,
480
511
INIT_LIST_HEAD (& table -> sets );
481
512
table -> flags = flags ;
482
513
514
+ nft_ctx_init (& ctx , skb , nlh , afi , table , NULL , nla );
515
+ err = nft_trans_table_add (& ctx , NFT_MSG_NEWTABLE );
516
+ if (err < 0 ) {
517
+ kfree (table );
518
+ module_put (afi -> owner );
519
+ return err ;
520
+ }
483
521
list_add_tail (& table -> list , & afi -> tables );
484
- nf_tables_table_notify (skb , nlh , table , NFT_MSG_NEWTABLE , family );
485
522
return 0 ;
486
523
}
487
524
@@ -493,7 +530,8 @@ static int nf_tables_deltable(struct sock *nlsk, struct sk_buff *skb,
493
530
struct nft_af_info * afi ;
494
531
struct nft_table * table ;
495
532
struct net * net = sock_net (skb -> sk );
496
- int family = nfmsg -> nfgen_family ;
533
+ int family = nfmsg -> nfgen_family , err ;
534
+ struct nft_ctx ctx ;
497
535
498
536
afi = nf_tables_afinfo_lookup (net , family , false);
499
537
if (IS_ERR (afi ))
@@ -502,17 +540,27 @@ static int nf_tables_deltable(struct sock *nlsk, struct sk_buff *skb,
502
540
table = nf_tables_table_lookup (afi , nla [NFTA_TABLE_NAME ]);
503
541
if (IS_ERR (table ))
504
542
return PTR_ERR (table );
543
+ if (table -> flags & NFT_TABLE_INACTIVE )
544
+ return - ENOENT ;
505
545
506
546
if (!list_empty (& table -> chains ) || !list_empty (& table -> sets ))
507
547
return - EBUSY ;
508
548
549
+ nft_ctx_init (& ctx , skb , nlh , afi , table , NULL , nla );
550
+ err = nft_trans_table_add (& ctx , NFT_MSG_DELTABLE );
551
+ if (err < 0 )
552
+ return err ;
553
+
509
554
list_del (& table -> list );
510
- nf_tables_table_notify (skb , nlh , table , NFT_MSG_DELTABLE , family );
511
- kfree (table );
512
- module_put (afi -> owner );
513
555
return 0 ;
514
556
}
515
557
558
+ static void nf_tables_table_destroy (struct nft_ctx * ctx )
559
+ {
560
+ kfree (ctx -> table );
561
+ module_put (ctx -> afi -> owner );
562
+ }
563
+
516
564
int nft_register_chain_type (const struct nf_chain_type * ctype )
517
565
{
518
566
int err = 0 ;
@@ -776,6 +824,8 @@ static int nf_tables_getchain(struct sock *nlsk, struct sk_buff *skb,
776
824
table = nf_tables_table_lookup (afi , nla [NFTA_CHAIN_TABLE ]);
777
825
if (IS_ERR (table ))
778
826
return PTR_ERR (table );
827
+ if (table -> flags & NFT_TABLE_INACTIVE )
828
+ return - ENOENT ;
779
829
780
830
chain = nf_tables_chain_lookup (table , nla [NFTA_CHAIN_NAME ]);
781
831
if (IS_ERR (chain ))
@@ -1120,6 +1170,8 @@ static int nf_tables_delchain(struct sock *nlsk, struct sk_buff *skb,
1120
1170
table = nf_tables_table_lookup (afi , nla [NFTA_CHAIN_TABLE ]);
1121
1171
if (IS_ERR (table ))
1122
1172
return PTR_ERR (table );
1173
+ if (table -> flags & NFT_TABLE_INACTIVE )
1174
+ return - ENOENT ;
1123
1175
1124
1176
chain = nf_tables_chain_lookup (table , nla [NFTA_CHAIN_NAME ]);
1125
1177
if (IS_ERR (chain ))
@@ -1573,6 +1625,8 @@ static int nf_tables_getrule(struct sock *nlsk, struct sk_buff *skb,
1573
1625
table = nf_tables_table_lookup (afi , nla [NFTA_RULE_TABLE ]);
1574
1626
if (IS_ERR (table ))
1575
1627
return PTR_ERR (table );
1628
+ if (table -> flags & NFT_TABLE_INACTIVE )
1629
+ return - ENOENT ;
1576
1630
1577
1631
chain = nf_tables_chain_lookup (table , nla [NFTA_RULE_CHAIN ]);
1578
1632
if (IS_ERR (chain ))
@@ -1838,6 +1892,8 @@ static int nf_tables_delrule(struct sock *nlsk, struct sk_buff *skb,
1838
1892
table = nf_tables_table_lookup (afi , nla [NFTA_RULE_TABLE ]);
1839
1893
if (IS_ERR (table ))
1840
1894
return PTR_ERR (table );
1895
+ if (table -> flags & NFT_TABLE_INACTIVE )
1896
+ return - ENOENT ;
1841
1897
1842
1898
if (nla [NFTA_RULE_CHAIN ]) {
1843
1899
chain = nf_tables_chain_lookup (table , nla [NFTA_RULE_CHAIN ]);
@@ -2004,6 +2060,8 @@ static int nft_ctx_init_from_setattr(struct nft_ctx *ctx,
2004
2060
table = nf_tables_table_lookup (afi , nla [NFTA_SET_TABLE ]);
2005
2061
if (IS_ERR (table ))
2006
2062
return PTR_ERR (table );
2063
+ if (table -> flags & NFT_TABLE_INACTIVE )
2064
+ return - ENOENT ;
2007
2065
}
2008
2066
2009
2067
nft_ctx_init (ctx , skb , nlh , afi , table , NULL , nla );
@@ -2681,7 +2739,8 @@ static const struct nla_policy nft_set_elem_list_policy[NFTA_SET_ELEM_LIST_MAX +
2681
2739
static int nft_ctx_init_from_elemattr (struct nft_ctx * ctx ,
2682
2740
const struct sk_buff * skb ,
2683
2741
const struct nlmsghdr * nlh ,
2684
- const struct nlattr * const nla [])
2742
+ const struct nlattr * const nla [],
2743
+ bool trans )
2685
2744
{
2686
2745
const struct nfgenmsg * nfmsg = nlmsg_data (nlh );
2687
2746
struct nft_af_info * afi ;
@@ -2695,6 +2754,8 @@ static int nft_ctx_init_from_elemattr(struct nft_ctx *ctx,
2695
2754
table = nf_tables_table_lookup (afi , nla [NFTA_SET_ELEM_LIST_TABLE ]);
2696
2755
if (IS_ERR (table ))
2697
2756
return PTR_ERR (table );
2757
+ if (!trans && (table -> flags & NFT_TABLE_INACTIVE ))
2758
+ return - ENOENT ;
2698
2759
2699
2760
nft_ctx_init (ctx , skb , nlh , afi , table , NULL , nla );
2700
2761
return 0 ;
@@ -2768,7 +2829,8 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
2768
2829
if (err < 0 )
2769
2830
return err ;
2770
2831
2771
- err = nft_ctx_init_from_elemattr (& ctx , cb -> skb , cb -> nlh , (void * )nla );
2832
+ err = nft_ctx_init_from_elemattr (& ctx , cb -> skb , cb -> nlh , (void * )nla ,
2833
+ false);
2772
2834
if (err < 0 )
2773
2835
return err ;
2774
2836
@@ -2833,7 +2895,7 @@ static int nf_tables_getsetelem(struct sock *nlsk, struct sk_buff *skb,
2833
2895
struct nft_ctx ctx ;
2834
2896
int err ;
2835
2897
2836
- err = nft_ctx_init_from_elemattr (& ctx , skb , nlh , nla );
2898
+ err = nft_ctx_init_from_elemattr (& ctx , skb , nlh , nla , false );
2837
2899
if (err < 0 )
2838
2900
return err ;
2839
2901
@@ -3033,7 +3095,7 @@ static int nf_tables_newsetelem(struct sock *nlsk, struct sk_buff *skb,
3033
3095
struct nft_ctx ctx ;
3034
3096
int rem , err ;
3035
3097
3036
- err = nft_ctx_init_from_elemattr (& ctx , skb , nlh , nla );
3098
+ err = nft_ctx_init_from_elemattr (& ctx , skb , nlh , nla , true );
3037
3099
if (err < 0 )
3038
3100
return err ;
3039
3101
@@ -3111,7 +3173,7 @@ static int nf_tables_delsetelem(struct sock *nlsk, struct sk_buff *skb,
3111
3173
struct nft_ctx ctx ;
3112
3174
int rem , err ;
3113
3175
3114
- err = nft_ctx_init_from_elemattr (& ctx , skb , nlh , nla );
3176
+ err = nft_ctx_init_from_elemattr (& ctx , skb , nlh , nla , false );
3115
3177
if (err < 0 )
3116
3178
return err ;
3117
3179
@@ -3131,7 +3193,7 @@ static int nf_tables_delsetelem(struct sock *nlsk, struct sk_buff *skb,
3131
3193
3132
3194
static const struct nfnl_callback nf_tables_cb [NFT_MSG_MAX ] = {
3133
3195
[NFT_MSG_NEWTABLE ] = {
3134
- .call = nf_tables_newtable ,
3196
+ .call_batch = nf_tables_newtable ,
3135
3197
.attr_count = NFTA_TABLE_MAX ,
3136
3198
.policy = nft_table_policy ,
3137
3199
},
@@ -3141,7 +3203,7 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = {
3141
3203
.policy = nft_table_policy ,
3142
3204
},
3143
3205
[NFT_MSG_DELTABLE ] = {
3144
- .call = nf_tables_deltable ,
3206
+ .call_batch = nf_tables_deltable ,
3145
3207
.attr_count = NFTA_TABLE_MAX ,
3146
3208
.policy = nft_table_policy ,
3147
3209
},
@@ -3246,6 +3308,28 @@ static int nf_tables_commit(struct sk_buff *skb)
3246
3308
3247
3309
list_for_each_entry_safe (trans , next , & net -> nft .commit_list , list ) {
3248
3310
switch (trans -> msg_type ) {
3311
+ case NFT_MSG_NEWTABLE :
3312
+ if (nft_trans_table_update (trans )) {
3313
+ if (!nft_trans_table_enable (trans )) {
3314
+ nf_tables_table_disable (trans -> ctx .afi ,
3315
+ trans -> ctx .table );
3316
+ trans -> ctx .table -> flags |= NFT_TABLE_F_DORMANT ;
3317
+ }
3318
+ } else {
3319
+ trans -> ctx .table -> flags &= ~NFT_TABLE_INACTIVE ;
3320
+ }
3321
+ nf_tables_table_notify (trans -> ctx .skb , trans -> ctx .nlh ,
3322
+ trans -> ctx .table ,
3323
+ NFT_MSG_NEWTABLE ,
3324
+ trans -> ctx .afi -> family );
3325
+ nft_trans_destroy (trans );
3326
+ break ;
3327
+ case NFT_MSG_DELTABLE :
3328
+ nf_tables_table_notify (trans -> ctx .skb , trans -> ctx .nlh ,
3329
+ trans -> ctx .table ,
3330
+ NFT_MSG_DELTABLE ,
3331
+ trans -> ctx .afi -> family );
3332
+ break ;
3249
3333
case NFT_MSG_NEWCHAIN :
3250
3334
if (nft_trans_chain_update (trans ))
3251
3335
nft_chain_commit_update (trans );
@@ -3310,6 +3394,9 @@ static int nf_tables_commit(struct sk_buff *skb)
3310
3394
/* Now we can safely release unused old rules */
3311
3395
list_for_each_entry_safe (trans , next , & net -> nft .commit_list , list ) {
3312
3396
switch (trans -> msg_type ) {
3397
+ case NFT_MSG_DELTABLE :
3398
+ nf_tables_table_destroy (& trans -> ctx );
3399
+ break ;
3313
3400
case NFT_MSG_DELCHAIN :
3314
3401
nf_tables_chain_destroy (trans -> ctx .chain );
3315
3402
break ;
@@ -3334,6 +3421,23 @@ static int nf_tables_abort(struct sk_buff *skb)
3334
3421
3335
3422
list_for_each_entry_safe (trans , next , & net -> nft .commit_list , list ) {
3336
3423
switch (trans -> msg_type ) {
3424
+ case NFT_MSG_NEWTABLE :
3425
+ if (nft_trans_table_update (trans )) {
3426
+ if (nft_trans_table_enable (trans )) {
3427
+ nf_tables_table_disable (trans -> ctx .afi ,
3428
+ trans -> ctx .table );
3429
+ trans -> ctx .table -> flags |= NFT_TABLE_F_DORMANT ;
3430
+ }
3431
+ nft_trans_destroy (trans );
3432
+ } else {
3433
+ list_del (& trans -> ctx .table -> list );
3434
+ }
3435
+ break ;
3436
+ case NFT_MSG_DELTABLE :
3437
+ list_add_tail (& trans -> ctx .table -> list ,
3438
+ & trans -> ctx .afi -> tables );
3439
+ nft_trans_destroy (trans );
3440
+ break ;
3337
3441
case NFT_MSG_NEWCHAIN :
3338
3442
if (nft_trans_chain_update (trans )) {
3339
3443
if (nft_trans_chain_stats (trans ))
@@ -3377,6 +3481,9 @@ static int nf_tables_abort(struct sk_buff *skb)
3377
3481
3378
3482
list_for_each_entry_safe (trans , next , & net -> nft .commit_list , list ) {
3379
3483
switch (trans -> msg_type ) {
3484
+ case NFT_MSG_NEWTABLE :
3485
+ nf_tables_table_destroy (& trans -> ctx );
3486
+ break ;
3380
3487
case NFT_MSG_NEWCHAIN :
3381
3488
nf_tables_chain_destroy (trans -> ctx .chain );
3382
3489
break ;
0 commit comments