@@ -1934,6 +1934,7 @@ static const struct nla_policy nft_set_policy[NFTA_SET_MAX + 1] = {
1934
1934
[NFTA_SET_DATA_LEN ] = { .type = NLA_U32 },
1935
1935
[NFTA_SET_POLICY ] = { .type = NLA_U32 },
1936
1936
[NFTA_SET_DESC ] = { .type = NLA_NESTED },
1937
+ [NFTA_SET_ID ] = { .type = NLA_U32 },
1937
1938
};
1938
1939
1939
1940
static const struct nla_policy nft_set_desc_policy [NFTA_SET_DESC_MAX + 1 ] = {
@@ -1984,6 +1985,20 @@ struct nft_set *nf_tables_set_lookup(const struct nft_table *table,
1984
1985
return ERR_PTR (- ENOENT );
1985
1986
}
1986
1987
1988
+ struct nft_set * nf_tables_set_lookup_byid (const struct net * net ,
1989
+ const struct nlattr * nla )
1990
+ {
1991
+ struct nft_trans * trans ;
1992
+ u32 id = ntohl (nla_get_be32 (nla ));
1993
+
1994
+ list_for_each_entry (trans , & net -> nft .commit_list , list ) {
1995
+ if (trans -> msg_type == NFT_MSG_NEWSET &&
1996
+ id == nft_trans_set_id (trans ))
1997
+ return nft_trans_set (trans );
1998
+ }
1999
+ return ERR_PTR (- ENOENT );
2000
+ }
2001
+
1987
2002
static int nf_tables_set_alloc_name (struct nft_ctx * ctx , struct nft_set * set ,
1988
2003
const char * name )
1989
2004
{
@@ -2259,6 +2274,8 @@ static int nf_tables_dump_sets(struct sk_buff *skb, struct netlink_callback *cb)
2259
2274
return ret ;
2260
2275
}
2261
2276
2277
+ #define NFT_SET_INACTIVE (1 << 15) /* Internal set flag */
2278
+
2262
2279
static int nf_tables_getset (struct sock * nlsk , struct sk_buff * skb ,
2263
2280
const struct nlmsghdr * nlh ,
2264
2281
const struct nlattr * const nla [])
@@ -2288,6 +2305,8 @@ static int nf_tables_getset(struct sock *nlsk, struct sk_buff *skb,
2288
2305
set = nf_tables_set_lookup (ctx .table , nla [NFTA_SET_NAME ]);
2289
2306
if (IS_ERR (set ))
2290
2307
return PTR_ERR (set );
2308
+ if (set -> flags & NFT_SET_INACTIVE )
2309
+ return - ENOENT ;
2291
2310
2292
2311
skb2 = alloc_skb (NLMSG_GOODSIZE , GFP_KERNEL );
2293
2312
if (skb2 == NULL )
@@ -2321,6 +2340,26 @@ static int nf_tables_set_desc_parse(const struct nft_ctx *ctx,
2321
2340
return 0 ;
2322
2341
}
2323
2342
2343
+ static int nft_trans_set_add (struct nft_ctx * ctx , int msg_type ,
2344
+ struct nft_set * set )
2345
+ {
2346
+ struct nft_trans * trans ;
2347
+
2348
+ trans = nft_trans_alloc (ctx , msg_type , sizeof (struct nft_trans_set ));
2349
+ if (trans == NULL )
2350
+ return - ENOMEM ;
2351
+
2352
+ if (msg_type == NFT_MSG_NEWSET && ctx -> nla [NFTA_SET_ID ] != NULL ) {
2353
+ nft_trans_set_id (trans ) =
2354
+ ntohl (nla_get_be32 (ctx -> nla [NFTA_SET_ID ]));
2355
+ set -> flags |= NFT_SET_INACTIVE ;
2356
+ }
2357
+ nft_trans_set (trans ) = set ;
2358
+ list_add_tail (& trans -> list , & ctx -> net -> nft .commit_list );
2359
+
2360
+ return 0 ;
2361
+ }
2362
+
2324
2363
static int nf_tables_newset (struct sock * nlsk , struct sk_buff * skb ,
2325
2364
const struct nlmsghdr * nlh ,
2326
2365
const struct nlattr * const nla [])
@@ -2341,7 +2380,8 @@ static int nf_tables_newset(struct sock *nlsk, struct sk_buff *skb,
2341
2380
2342
2381
if (nla [NFTA_SET_TABLE ] == NULL ||
2343
2382
nla [NFTA_SET_NAME ] == NULL ||
2344
- nla [NFTA_SET_KEY_LEN ] == NULL )
2383
+ nla [NFTA_SET_KEY_LEN ] == NULL ||
2384
+ nla [NFTA_SET_ID ] == NULL )
2345
2385
return - EINVAL ;
2346
2386
2347
2387
memset (& desc , 0 , sizeof (desc ));
@@ -2458,8 +2498,11 @@ static int nf_tables_newset(struct sock *nlsk, struct sk_buff *skb,
2458
2498
if (err < 0 )
2459
2499
goto err2 ;
2460
2500
2501
+ err = nft_trans_set_add (& ctx , NFT_MSG_NEWSET , set );
2502
+ if (err < 0 )
2503
+ goto err2 ;
2504
+
2461
2505
list_add_tail (& set -> list , & table -> sets );
2462
- nf_tables_set_notify (& ctx , set , NFT_MSG_NEWSET );
2463
2506
return 0 ;
2464
2507
2465
2508
err2 :
@@ -2469,16 +2512,20 @@ static int nf_tables_newset(struct sock *nlsk, struct sk_buff *skb,
2469
2512
return err ;
2470
2513
}
2471
2514
2472
- static void nf_tables_set_destroy ( const struct nft_ctx * ctx , struct nft_set * set )
2515
+ static void nft_set_destroy ( struct nft_set * set )
2473
2516
{
2474
- list_del (& set -> list );
2475
- nf_tables_set_notify (ctx , set , NFT_MSG_DELSET );
2476
-
2477
2517
set -> ops -> destroy (set );
2478
2518
module_put (set -> ops -> owner );
2479
2519
kfree (set );
2480
2520
}
2481
2521
2522
+ static void nf_tables_set_destroy (const struct nft_ctx * ctx , struct nft_set * set )
2523
+ {
2524
+ list_del (& set -> list );
2525
+ nf_tables_set_notify (ctx , set , NFT_MSG_DELSET );
2526
+ nft_set_destroy (set );
2527
+ }
2528
+
2482
2529
static int nf_tables_delset (struct sock * nlsk , struct sk_buff * skb ,
2483
2530
const struct nlmsghdr * nlh ,
2484
2531
const struct nlattr * const nla [])
@@ -2500,10 +2547,16 @@ static int nf_tables_delset(struct sock *nlsk, struct sk_buff *skb,
2500
2547
set = nf_tables_set_lookup (ctx .table , nla [NFTA_SET_NAME ]);
2501
2548
if (IS_ERR (set ))
2502
2549
return PTR_ERR (set );
2550
+ if (set -> flags & NFT_SET_INACTIVE )
2551
+ return - ENOENT ;
2503
2552
if (!list_empty (& set -> bindings ))
2504
2553
return - EBUSY ;
2505
2554
2506
- nf_tables_set_destroy (& ctx , set );
2555
+ err = nft_trans_set_add (& ctx , NFT_MSG_DELSET , set );
2556
+ if (err < 0 )
2557
+ return err ;
2558
+
2559
+ list_del (& set -> list );
2507
2560
return 0 ;
2508
2561
}
2509
2562
@@ -2563,7 +2616,8 @@ void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set,
2563
2616
{
2564
2617
list_del (& binding -> list );
2565
2618
2566
- if (list_empty (& set -> bindings ) && set -> flags & NFT_SET_ANONYMOUS )
2619
+ if (list_empty (& set -> bindings ) && set -> flags & NFT_SET_ANONYMOUS &&
2620
+ !(set -> flags & NFT_SET_INACTIVE ))
2567
2621
nf_tables_set_destroy (ctx , set );
2568
2622
}
2569
2623
@@ -2581,6 +2635,7 @@ static const struct nla_policy nft_set_elem_list_policy[NFTA_SET_ELEM_LIST_MAX +
2581
2635
[NFTA_SET_ELEM_LIST_TABLE ] = { .type = NLA_STRING },
2582
2636
[NFTA_SET_ELEM_LIST_SET ] = { .type = NLA_STRING },
2583
2637
[NFTA_SET_ELEM_LIST_ELEMENTS ] = { .type = NLA_NESTED },
2638
+ [NFTA_SET_ELEM_LIST_SET_ID ] = { .type = NLA_U32 },
2584
2639
};
2585
2640
2586
2641
static int nft_ctx_init_from_elemattr (struct nft_ctx * ctx ,
@@ -2680,6 +2735,8 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
2680
2735
set = nf_tables_set_lookup (ctx .table , nla [NFTA_SET_ELEM_LIST_SET ]);
2681
2736
if (IS_ERR (set ))
2682
2737
return PTR_ERR (set );
2738
+ if (set -> flags & NFT_SET_INACTIVE )
2739
+ return - ENOENT ;
2683
2740
2684
2741
event = NFT_MSG_NEWSETELEM ;
2685
2742
event |= NFNL_SUBSYS_NFTABLES << 8 ;
@@ -2743,6 +2800,8 @@ static int nf_tables_getsetelem(struct sock *nlsk, struct sk_buff *skb,
2743
2800
set = nf_tables_set_lookup (ctx .table , nla [NFTA_SET_ELEM_LIST_SET ]);
2744
2801
if (IS_ERR (set ))
2745
2802
return PTR_ERR (set );
2803
+ if (set -> flags & NFT_SET_INACTIVE )
2804
+ return - ENOENT ;
2746
2805
2747
2806
if (nlh -> nlmsg_flags & NLM_F_DUMP ) {
2748
2807
struct netlink_dump_control c = {
@@ -2928,6 +2987,7 @@ static int nf_tables_newsetelem(struct sock *nlsk, struct sk_buff *skb,
2928
2987
const struct nlmsghdr * nlh ,
2929
2988
const struct nlattr * const nla [])
2930
2989
{
2990
+ struct net * net = sock_net (skb -> sk );
2931
2991
const struct nlattr * attr ;
2932
2992
struct nft_set * set ;
2933
2993
struct nft_ctx ctx ;
@@ -2938,8 +2998,15 @@ static int nf_tables_newsetelem(struct sock *nlsk, struct sk_buff *skb,
2938
2998
return err ;
2939
2999
2940
3000
set = nf_tables_set_lookup (ctx .table , nla [NFTA_SET_ELEM_LIST_SET ]);
2941
- if (IS_ERR (set ))
2942
- return PTR_ERR (set );
3001
+ if (IS_ERR (set )) {
3002
+ if (nla [NFTA_SET_ELEM_LIST_SET_ID ]) {
3003
+ set = nf_tables_set_lookup_byid (net ,
3004
+ nla [NFTA_SET_ELEM_LIST_SET_ID ]);
3005
+ }
3006
+ if (IS_ERR (set ))
3007
+ return PTR_ERR (set );
3008
+ }
3009
+
2943
3010
if (!list_empty (& set -> bindings ) && set -> flags & NFT_SET_CONSTANT )
2944
3011
return - EBUSY ;
2945
3012
@@ -3069,7 +3136,7 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = {
3069
3136
.policy = nft_rule_policy ,
3070
3137
},
3071
3138
[NFT_MSG_NEWSET ] = {
3072
- .call = nf_tables_newset ,
3139
+ .call_batch = nf_tables_newset ,
3073
3140
.attr_count = NFTA_SET_MAX ,
3074
3141
.policy = nft_set_policy ,
3075
3142
},
@@ -3079,12 +3146,12 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = {
3079
3146
.policy = nft_set_policy ,
3080
3147
},
3081
3148
[NFT_MSG_DELSET ] = {
3082
- .call = nf_tables_delset ,
3149
+ .call_batch = nf_tables_delset ,
3083
3150
.attr_count = NFTA_SET_MAX ,
3084
3151
.policy = nft_set_policy ,
3085
3152
},
3086
3153
[NFT_MSG_NEWSETELEM ] = {
3087
- .call = nf_tables_newsetelem ,
3154
+ .call_batch = nf_tables_newsetelem ,
3088
3155
.attr_count = NFTA_SET_ELEM_LIST_MAX ,
3089
3156
.policy = nft_set_elem_list_policy ,
3090
3157
},
@@ -3094,7 +3161,7 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = {
3094
3161
.policy = nft_set_elem_list_policy ,
3095
3162
},
3096
3163
[NFT_MSG_DELSETELEM ] = {
3097
- .call = nf_tables_delsetelem ,
3164
+ .call_batch = nf_tables_delsetelem ,
3098
3165
.attr_count = NFTA_SET_ELEM_LIST_MAX ,
3099
3166
.policy = nft_set_elem_list_policy ,
3100
3167
},
@@ -3136,6 +3203,16 @@ static int nf_tables_commit(struct sk_buff *skb)
3136
3203
nft_trans_rule (trans ), NFT_MSG_DELRULE , 0 ,
3137
3204
trans -> ctx .afi -> family );
3138
3205
break ;
3206
+ case NFT_MSG_NEWSET :
3207
+ nft_trans_set (trans )-> flags &= ~NFT_SET_INACTIVE ;
3208
+ nf_tables_set_notify (& trans -> ctx , nft_trans_set (trans ),
3209
+ NFT_MSG_NEWSET );
3210
+ nft_trans_destroy (trans );
3211
+ break ;
3212
+ case NFT_MSG_DELSET :
3213
+ nf_tables_set_notify (& trans -> ctx , nft_trans_set (trans ),
3214
+ NFT_MSG_DELSET );
3215
+ break ;
3139
3216
}
3140
3217
}
3141
3218
@@ -3148,9 +3225,12 @@ static int nf_tables_commit(struct sk_buff *skb)
3148
3225
case NFT_MSG_DELRULE :
3149
3226
nf_tables_rule_destroy (& trans -> ctx ,
3150
3227
nft_trans_rule (trans ));
3151
- nft_trans_destroy (trans );
3228
+ break ;
3229
+ case NFT_MSG_DELSET :
3230
+ nft_set_destroy (nft_trans_set (trans ));
3152
3231
break ;
3153
3232
}
3233
+ nft_trans_destroy (trans );
3154
3234
}
3155
3235
3156
3236
return 0 ;
@@ -3170,6 +3250,14 @@ static int nf_tables_abort(struct sk_buff *skb)
3170
3250
nft_rule_clear (trans -> ctx .net , nft_trans_rule (trans ));
3171
3251
nft_trans_destroy (trans );
3172
3252
break ;
3253
+ case NFT_MSG_NEWSET :
3254
+ list_del (& nft_trans_set (trans )-> list );
3255
+ break ;
3256
+ case NFT_MSG_DELSET :
3257
+ list_add_tail (& nft_trans_set (trans )-> list ,
3258
+ & trans -> ctx .table -> sets );
3259
+ nft_trans_destroy (trans );
3260
+ break ;
3173
3261
}
3174
3262
}
3175
3263
@@ -3181,9 +3269,12 @@ static int nf_tables_abort(struct sk_buff *skb)
3181
3269
case NFT_MSG_NEWRULE :
3182
3270
nf_tables_rule_destroy (& trans -> ctx ,
3183
3271
nft_trans_rule (trans ));
3184
- nft_trans_destroy (trans );
3272
+ break ;
3273
+ case NFT_MSG_NEWSET :
3274
+ nft_set_destroy (nft_trans_set (trans ));
3185
3275
break ;
3186
3276
}
3277
+ nft_trans_destroy (trans );
3187
3278
}
3188
3279
3189
3280
return 0 ;
0 commit comments