@@ -2452,6 +2452,7 @@ static const struct nla_policy nft_set_policy[NFTA_SET_MAX + 1] = {
2452
2452
[NFTA_SET_GC_INTERVAL ] = { .type = NLA_U32 },
2453
2453
[NFTA_SET_USERDATA ] = { .type = NLA_BINARY ,
2454
2454
.len = NFT_USERDATA_MAXLEN },
2455
+ [NFTA_SET_OBJ_TYPE ] = { .type = NLA_U32 },
2455
2456
};
2456
2457
2457
2458
static const struct nla_policy nft_set_desc_policy [NFTA_SET_DESC_MAX + 1 ] = {
@@ -2609,6 +2610,9 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx,
2609
2610
if (nla_put_be32 (skb , NFTA_SET_DATA_LEN , htonl (set -> dlen )))
2610
2611
goto nla_put_failure ;
2611
2612
}
2613
+ if (set -> flags & NFT_SET_OBJECT &&
2614
+ nla_put_be32 (skb , NFTA_SET_OBJ_TYPE , htonl (set -> objtype )))
2615
+ goto nla_put_failure ;
2612
2616
2613
2617
if (set -> timeout &&
2614
2618
nla_put_be64 (skb , NFTA_SET_TIMEOUT ,
@@ -2838,7 +2842,7 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
2838
2842
unsigned int size ;
2839
2843
bool create ;
2840
2844
u64 timeout ;
2841
- u32 ktype , dtype , flags , policy , gc_int ;
2845
+ u32 ktype , dtype , flags , policy , gc_int , objtype ;
2842
2846
struct nft_set_desc desc ;
2843
2847
unsigned char * udata ;
2844
2848
u16 udlen ;
@@ -2868,11 +2872,12 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
2868
2872
flags = ntohl (nla_get_be32 (nla [NFTA_SET_FLAGS ]));
2869
2873
if (flags & ~(NFT_SET_ANONYMOUS | NFT_SET_CONSTANT |
2870
2874
NFT_SET_INTERVAL | NFT_SET_TIMEOUT |
2871
- NFT_SET_MAP | NFT_SET_EVAL ))
2875
+ NFT_SET_MAP | NFT_SET_EVAL |
2876
+ NFT_SET_OBJECT ))
2872
2877
return - EINVAL ;
2873
- /* Only one of both operations is supported */
2874
- if ((flags & (NFT_SET_MAP | NFT_SET_EVAL )) ==
2875
- (NFT_SET_MAP | NFT_SET_EVAL ))
2878
+ /* Only one of these operations is supported */
2879
+ if ((flags & (NFT_SET_MAP | NFT_SET_EVAL | NFT_SET_OBJECT )) ==
2880
+ (NFT_SET_MAP | NFT_SET_EVAL | NFT_SET_OBJECT ))
2876
2881
return - EOPNOTSUPP ;
2877
2882
}
2878
2883
@@ -2897,6 +2902,19 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
2897
2902
} else if (flags & NFT_SET_MAP )
2898
2903
return - EINVAL ;
2899
2904
2905
+ if (nla [NFTA_SET_OBJ_TYPE ] != NULL ) {
2906
+ if (!(flags & NFT_SET_OBJECT ))
2907
+ return - EINVAL ;
2908
+
2909
+ objtype = ntohl (nla_get_be32 (nla [NFTA_SET_OBJ_TYPE ]));
2910
+ if (objtype == NFT_OBJECT_UNSPEC ||
2911
+ objtype > NFT_OBJECT_MAX )
2912
+ return - EINVAL ;
2913
+ } else if (flags & NFT_SET_OBJECT )
2914
+ return - EINVAL ;
2915
+ else
2916
+ objtype = NFT_OBJECT_UNSPEC ;
2917
+
2900
2918
timeout = 0 ;
2901
2919
if (nla [NFTA_SET_TIMEOUT ] != NULL ) {
2902
2920
if (!(flags & NFT_SET_TIMEOUT ))
@@ -2984,6 +3002,7 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
2984
3002
set -> ktype = ktype ;
2985
3003
set -> klen = desc .klen ;
2986
3004
set -> dtype = dtype ;
3005
+ set -> objtype = objtype ;
2987
3006
set -> dlen = desc .dlen ;
2988
3007
set -> flags = flags ;
2989
3008
set -> size = desc .size ;
@@ -3126,6 +3145,10 @@ const struct nft_set_ext_type nft_set_ext_types[] = {
3126
3145
[NFT_SET_EXT_EXPR ] = {
3127
3146
.align = __alignof__(struct nft_expr ),
3128
3147
},
3148
+ [NFT_SET_EXT_OBJREF ] = {
3149
+ .len = sizeof (struct nft_object * ),
3150
+ .align = __alignof__(struct nft_object * ),
3151
+ },
3129
3152
[NFT_SET_EXT_FLAGS ] = {
3130
3153
.len = sizeof (u8 ),
3131
3154
.align = __alignof__(u8 ),
@@ -3214,6 +3237,11 @@ static int nf_tables_fill_setelem(struct sk_buff *skb,
3214
3237
nft_expr_dump (skb , NFTA_SET_ELEM_EXPR , nft_set_ext_expr (ext )) < 0 )
3215
3238
goto nla_put_failure ;
3216
3239
3240
+ if (nft_set_ext_exists (ext , NFT_SET_EXT_OBJREF ) &&
3241
+ nla_put_string (skb , NFTA_SET_ELEM_OBJREF ,
3242
+ (* nft_set_ext_obj (ext ))-> name ) < 0 )
3243
+ goto nla_put_failure ;
3244
+
3217
3245
if (nft_set_ext_exists (ext , NFT_SET_EXT_FLAGS ) &&
3218
3246
nla_put_be32 (skb , NFTA_SET_ELEM_FLAGS ,
3219
3247
htonl (* nft_set_ext_flags (ext ))))
@@ -3508,7 +3536,8 @@ void nft_set_elem_destroy(const struct nft_set *set, void *elem,
3508
3536
nft_data_uninit (nft_set_ext_data (ext ), set -> dtype );
3509
3537
if (destroy_expr && nft_set_ext_exists (ext , NFT_SET_EXT_EXPR ))
3510
3538
nf_tables_expr_destroy (NULL , nft_set_ext_expr (ext ));
3511
-
3539
+ if (nft_set_ext_exists (ext , NFT_SET_EXT_OBJREF ))
3540
+ (* nft_set_ext_obj (ext ))-> use -- ;
3512
3541
kfree (elem );
3513
3542
}
3514
3543
EXPORT_SYMBOL_GPL (nft_set_elem_destroy );
@@ -3533,11 +3562,13 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
3533
3562
const struct nlattr * attr , u32 nlmsg_flags )
3534
3563
{
3535
3564
struct nlattr * nla [NFTA_SET_ELEM_MAX + 1 ];
3565
+ u8 genmask = nft_genmask_next (ctx -> net );
3536
3566
struct nft_data_desc d1 , d2 ;
3537
3567
struct nft_set_ext_tmpl tmpl ;
3538
3568
struct nft_set_ext * ext , * ext2 ;
3539
3569
struct nft_set_elem elem ;
3540
3570
struct nft_set_binding * binding ;
3571
+ struct nft_object * obj = NULL ;
3541
3572
struct nft_userdata * udata ;
3542
3573
struct nft_data data ;
3543
3574
enum nft_registers dreg ;
@@ -3600,6 +3631,20 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
3600
3631
nft_set_ext_add (& tmpl , NFT_SET_EXT_TIMEOUT );
3601
3632
}
3602
3633
3634
+ if (nla [NFTA_SET_ELEM_OBJREF ] != NULL ) {
3635
+ if (!(set -> flags & NFT_SET_OBJECT )) {
3636
+ err = - EINVAL ;
3637
+ goto err2 ;
3638
+ }
3639
+ obj = nf_tables_obj_lookup (ctx -> table , nla [NFTA_SET_ELEM_OBJREF ],
3640
+ set -> objtype , genmask );
3641
+ if (IS_ERR (obj )) {
3642
+ err = PTR_ERR (obj );
3643
+ goto err2 ;
3644
+ }
3645
+ nft_set_ext_add (& tmpl , NFT_SET_EXT_OBJREF );
3646
+ }
3647
+
3603
3648
if (nla [NFTA_SET_ELEM_DATA ] != NULL ) {
3604
3649
err = nft_data_init (ctx , & data , sizeof (data ), & d2 ,
3605
3650
nla [NFTA_SET_ELEM_DATA ]);
@@ -3658,6 +3703,10 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
3658
3703
udata -> len = ulen - 1 ;
3659
3704
nla_memcpy (& udata -> data , nla [NFTA_SET_ELEM_USERDATA ], ulen );
3660
3705
}
3706
+ if (obj ) {
3707
+ * nft_set_ext_obj (ext ) = obj ;
3708
+ obj -> use ++ ;
3709
+ }
3661
3710
3662
3711
trans = nft_trans_elem_alloc (ctx , NFT_MSG_NEWSETELEM , set );
3663
3712
if (trans == NULL )
@@ -3667,10 +3716,13 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
3667
3716
err = set -> ops -> insert (ctx -> net , set , & elem , & ext2 );
3668
3717
if (err ) {
3669
3718
if (err == - EEXIST ) {
3670
- if (nft_set_ext_exists (ext , NFT_SET_EXT_DATA ) &&
3671
- nft_set_ext_exists (ext2 , NFT_SET_EXT_DATA ) &&
3672
- memcmp (nft_set_ext_data (ext ),
3673
- nft_set_ext_data (ext2 ), set -> dlen ) != 0 )
3719
+ if ((nft_set_ext_exists (ext , NFT_SET_EXT_DATA ) &&
3720
+ nft_set_ext_exists (ext2 , NFT_SET_EXT_DATA ) &&
3721
+ memcmp (nft_set_ext_data (ext ),
3722
+ nft_set_ext_data (ext2 ), set -> dlen ) != 0 ) ||
3723
+ (nft_set_ext_exists (ext , NFT_SET_EXT_OBJREF ) &&
3724
+ nft_set_ext_exists (ext2 , NFT_SET_EXT_OBJREF ) &&
3725
+ * nft_set_ext_obj (ext ) != * nft_set_ext_obj (ext2 )))
3674
3726
err = - EBUSY ;
3675
3727
else if (!(nlmsg_flags & NLM_F_EXCL ))
3676
3728
err = 0 ;
0 commit comments