@@ -2452,6 +2452,7 @@ static const struct nla_policy nft_set_policy[NFTA_SET_MAX + 1] = {
24522452 [NFTA_SET_GC_INTERVAL ] = { .type = NLA_U32 },
24532453 [NFTA_SET_USERDATA ] = { .type = NLA_BINARY ,
24542454 .len = NFT_USERDATA_MAXLEN },
2455+ [NFTA_SET_OBJ_TYPE ] = { .type = NLA_U32 },
24552456};
24562457
24572458static 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,
26092610 if (nla_put_be32 (skb , NFTA_SET_DATA_LEN , htonl (set -> dlen )))
26102611 goto nla_put_failure ;
26112612 }
2613+ if (set -> flags & NFT_SET_OBJECT &&
2614+ nla_put_be32 (skb , NFTA_SET_OBJ_TYPE , htonl (set -> objtype )))
2615+ goto nla_put_failure ;
26122616
26132617 if (set -> timeout &&
26142618 nla_put_be64 (skb , NFTA_SET_TIMEOUT ,
@@ -2838,7 +2842,7 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
28382842 unsigned int size ;
28392843 bool create ;
28402844 u64 timeout ;
2841- u32 ktype , dtype , flags , policy , gc_int ;
2845+ u32 ktype , dtype , flags , policy , gc_int , objtype ;
28422846 struct nft_set_desc desc ;
28432847 unsigned char * udata ;
28442848 u16 udlen ;
@@ -2868,11 +2872,12 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
28682872 flags = ntohl (nla_get_be32 (nla [NFTA_SET_FLAGS ]));
28692873 if (flags & ~(NFT_SET_ANONYMOUS | NFT_SET_CONSTANT |
28702874 NFT_SET_INTERVAL | NFT_SET_TIMEOUT |
2871- NFT_SET_MAP | NFT_SET_EVAL ))
2875+ NFT_SET_MAP | NFT_SET_EVAL |
2876+ NFT_SET_OBJECT ))
28722877 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 ))
28762881 return - EOPNOTSUPP ;
28772882 }
28782883
@@ -2897,6 +2902,19 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
28972902 } else if (flags & NFT_SET_MAP )
28982903 return - EINVAL ;
28992904
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+
29002918 timeout = 0 ;
29012919 if (nla [NFTA_SET_TIMEOUT ] != NULL ) {
29022920 if (!(flags & NFT_SET_TIMEOUT ))
@@ -2984,6 +3002,7 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
29843002 set -> ktype = ktype ;
29853003 set -> klen = desc .klen ;
29863004 set -> dtype = dtype ;
3005+ set -> objtype = objtype ;
29873006 set -> dlen = desc .dlen ;
29883007 set -> flags = flags ;
29893008 set -> size = desc .size ;
@@ -3126,6 +3145,10 @@ const struct nft_set_ext_type nft_set_ext_types[] = {
31263145 [NFT_SET_EXT_EXPR ] = {
31273146 .align = __alignof__(struct nft_expr ),
31283147 },
3148+ [NFT_SET_EXT_OBJREF ] = {
3149+ .len = sizeof (struct nft_object * ),
3150+ .align = __alignof__(struct nft_object * ),
3151+ },
31293152 [NFT_SET_EXT_FLAGS ] = {
31303153 .len = sizeof (u8 ),
31313154 .align = __alignof__(u8 ),
@@ -3214,6 +3237,11 @@ static int nf_tables_fill_setelem(struct sk_buff *skb,
32143237 nft_expr_dump (skb , NFTA_SET_ELEM_EXPR , nft_set_ext_expr (ext )) < 0 )
32153238 goto nla_put_failure ;
32163239
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+
32173245 if (nft_set_ext_exists (ext , NFT_SET_EXT_FLAGS ) &&
32183246 nla_put_be32 (skb , NFTA_SET_ELEM_FLAGS ,
32193247 htonl (* nft_set_ext_flags (ext ))))
@@ -3508,7 +3536,8 @@ void nft_set_elem_destroy(const struct nft_set *set, void *elem,
35083536 nft_data_uninit (nft_set_ext_data (ext ), set -> dtype );
35093537 if (destroy_expr && nft_set_ext_exists (ext , NFT_SET_EXT_EXPR ))
35103538 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 -- ;
35123541 kfree (elem );
35133542}
35143543EXPORT_SYMBOL_GPL (nft_set_elem_destroy );
@@ -3533,11 +3562,13 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
35333562 const struct nlattr * attr , u32 nlmsg_flags )
35343563{
35353564 struct nlattr * nla [NFTA_SET_ELEM_MAX + 1 ];
3565+ u8 genmask = nft_genmask_next (ctx -> net );
35363566 struct nft_data_desc d1 , d2 ;
35373567 struct nft_set_ext_tmpl tmpl ;
35383568 struct nft_set_ext * ext , * ext2 ;
35393569 struct nft_set_elem elem ;
35403570 struct nft_set_binding * binding ;
3571+ struct nft_object * obj = NULL ;
35413572 struct nft_userdata * udata ;
35423573 struct nft_data data ;
35433574 enum nft_registers dreg ;
@@ -3600,6 +3631,20 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
36003631 nft_set_ext_add (& tmpl , NFT_SET_EXT_TIMEOUT );
36013632 }
36023633
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+
36033648 if (nla [NFTA_SET_ELEM_DATA ] != NULL ) {
36043649 err = nft_data_init (ctx , & data , sizeof (data ), & d2 ,
36053650 nla [NFTA_SET_ELEM_DATA ]);
@@ -3658,6 +3703,10 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
36583703 udata -> len = ulen - 1 ;
36593704 nla_memcpy (& udata -> data , nla [NFTA_SET_ELEM_USERDATA ], ulen );
36603705 }
3706+ if (obj ) {
3707+ * nft_set_ext_obj (ext ) = obj ;
3708+ obj -> use ++ ;
3709+ }
36613710
36623711 trans = nft_trans_elem_alloc (ctx , NFT_MSG_NEWSETELEM , set );
36633712 if (trans == NULL )
@@ -3667,10 +3716,13 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
36673716 err = set -> ops -> insert (ctx -> net , set , & elem , & ext2 );
36683717 if (err ) {
36693718 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 )))
36743726 err = - EBUSY ;
36753727 else if (!(nlmsg_flags & NLM_F_EXCL ))
36763728 err = 0 ;
0 commit comments