@@ -4215,6 +4215,9 @@ const struct nft_set_ext_type nft_set_ext_types[] = {
42154215 .len = sizeof (struct nft_userdata ),
42164216 .align = __alignof__(struct nft_userdata ),
42174217 },
4218+ [NFT_SET_EXT_KEY_END ] = {
4219+ .align = __alignof__(u32 ),
4220+ },
42184221};
42194222EXPORT_SYMBOL_GPL (nft_set_ext_types );
42204223
@@ -4233,6 +4236,7 @@ static const struct nla_policy nft_set_elem_policy[NFTA_SET_ELEM_MAX + 1] = {
42334236 [NFTA_SET_ELEM_EXPR ] = { .type = NLA_NESTED },
42344237 [NFTA_SET_ELEM_OBJREF ] = { .type = NLA_STRING ,
42354238 .len = NFT_OBJ_MAXNAMELEN - 1 },
4239+ [NFTA_SET_ELEM_KEY_END ] = { .type = NLA_NESTED },
42364240};
42374241
42384242static const struct nla_policy nft_set_elem_list_policy [NFTA_SET_ELEM_LIST_MAX + 1 ] = {
@@ -4282,6 +4286,11 @@ static int nf_tables_fill_setelem(struct sk_buff *skb,
42824286 NFT_DATA_VALUE , set -> klen ) < 0 )
42834287 goto nla_put_failure ;
42844288
4289+ if (nft_set_ext_exists (ext , NFT_SET_EXT_KEY_END ) &&
4290+ nft_data_dump (skb , NFTA_SET_ELEM_KEY_END , nft_set_ext_key_end (ext ),
4291+ NFT_DATA_VALUE , set -> klen ) < 0 )
4292+ goto nla_put_failure ;
4293+
42854294 if (nft_set_ext_exists (ext , NFT_SET_EXT_DATA ) &&
42864295 nft_data_dump (skb , NFTA_SET_ELEM_DATA , nft_set_ext_data (ext ),
42874296 set -> dtype == NFT_DATA_VERDICT ? NFT_DATA_VERDICT : NFT_DATA_VALUE ,
@@ -4569,6 +4578,13 @@ static int nft_get_set_elem(struct nft_ctx *ctx, struct nft_set *set,
45694578 if (err < 0 )
45704579 return err ;
45714580
4581+ if (nla [NFTA_SET_ELEM_KEY_END ]) {
4582+ err = nft_setelem_parse_key (ctx , set , & elem .key_end .val ,
4583+ nla [NFTA_SET_ELEM_KEY_END ]);
4584+ if (err < 0 )
4585+ return err ;
4586+ }
4587+
45724588 priv = set -> ops -> get (ctx -> net , set , & elem , flags );
45734589 if (IS_ERR (priv ))
45744590 return PTR_ERR (priv );
@@ -4694,8 +4710,8 @@ static struct nft_trans *nft_trans_elem_alloc(struct nft_ctx *ctx,
46944710
46954711void * nft_set_elem_init (const struct nft_set * set ,
46964712 const struct nft_set_ext_tmpl * tmpl ,
4697- const u32 * key , const u32 * data ,
4698- u64 timeout , u64 expiration , gfp_t gfp )
4713+ const u32 * key , const u32 * key_end ,
4714+ const u32 * data , u64 timeout , u64 expiration , gfp_t gfp )
46994715{
47004716 struct nft_set_ext * ext ;
47014717 void * elem ;
@@ -4708,6 +4724,8 @@ void *nft_set_elem_init(const struct nft_set *set,
47084724 nft_set_ext_init (ext , tmpl );
47094725
47104726 memcpy (nft_set_ext_key (ext ), key , set -> klen );
4727+ if (nft_set_ext_exists (ext , NFT_SET_EXT_KEY_END ))
4728+ memcpy (nft_set_ext_key_end (ext ), key_end , set -> klen );
47114729 if (nft_set_ext_exists (ext , NFT_SET_EXT_DATA ))
47124730 memcpy (nft_set_ext_data (ext ), data , set -> dlen );
47134731 if (nft_set_ext_exists (ext , NFT_SET_EXT_EXPIRATION )) {
@@ -4842,9 +4860,19 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
48424860 err = nft_setelem_parse_key (ctx , set , & elem .key .val ,
48434861 nla [NFTA_SET_ELEM_KEY ]);
48444862 if (err < 0 )
4845- goto err1 ;
4863+ return err ;
48464864
48474865 nft_set_ext_add_length (& tmpl , NFT_SET_EXT_KEY , set -> klen );
4866+
4867+ if (nla [NFTA_SET_ELEM_KEY_END ]) {
4868+ err = nft_setelem_parse_key (ctx , set , & elem .key_end .val ,
4869+ nla [NFTA_SET_ELEM_KEY_END ]);
4870+ if (err < 0 )
4871+ goto err_parse_key ;
4872+
4873+ nft_set_ext_add_length (& tmpl , NFT_SET_EXT_KEY_END , set -> klen );
4874+ }
4875+
48484876 if (timeout > 0 ) {
48494877 nft_set_ext_add (& tmpl , NFT_SET_EXT_EXPIRATION );
48504878 if (timeout != set -> timeout )
@@ -4854,14 +4882,14 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
48544882 if (nla [NFTA_SET_ELEM_OBJREF ] != NULL ) {
48554883 if (!(set -> flags & NFT_SET_OBJECT )) {
48564884 err = - EINVAL ;
4857- goto err2 ;
4885+ goto err_parse_key_end ;
48584886 }
48594887 obj = nft_obj_lookup (ctx -> net , ctx -> table ,
48604888 nla [NFTA_SET_ELEM_OBJREF ],
48614889 set -> objtype , genmask );
48624890 if (IS_ERR (obj )) {
48634891 err = PTR_ERR (obj );
4864- goto err2 ;
4892+ goto err_parse_key_end ;
48654893 }
48664894 nft_set_ext_add (& tmpl , NFT_SET_EXT_OBJREF );
48674895 }
@@ -4870,11 +4898,11 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
48704898 err = nft_data_init (ctx , & data , sizeof (data ), & desc ,
48714899 nla [NFTA_SET_ELEM_DATA ]);
48724900 if (err < 0 )
4873- goto err2 ;
4901+ goto err_parse_key_end ;
48744902
48754903 err = - EINVAL ;
48764904 if (set -> dtype != NFT_DATA_VERDICT && desc .len != set -> dlen )
4877- goto err3 ;
4905+ goto err_parse_data ;
48784906
48794907 dreg = nft_type_to_reg (set -> dtype );
48804908 list_for_each_entry (binding , & set -> bindings , list ) {
@@ -4892,7 +4920,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
48924920 & data ,
48934921 desc .type , desc .len );
48944922 if (err < 0 )
4895- goto err3 ;
4923+ goto err_parse_data ;
48964924
48974925 if (desc .type == NFT_DATA_VERDICT &&
48984926 (data .verdict .code == NFT_GOTO ||
@@ -4917,10 +4945,11 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
49174945 }
49184946
49194947 err = - ENOMEM ;
4920- elem .priv = nft_set_elem_init (set , & tmpl , elem .key .val .data , data .data ,
4948+ elem .priv = nft_set_elem_init (set , & tmpl , elem .key .val .data ,
4949+ elem .key_end .val .data , data .data ,
49214950 timeout , expiration , GFP_KERNEL );
49224951 if (elem .priv == NULL )
4923- goto err3 ;
4952+ goto err_parse_data ;
49244953
49254954 ext = nft_set_elem_ext (set , elem .priv );
49264955 if (flags )
@@ -4937,7 +4966,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
49374966
49384967 trans = nft_trans_elem_alloc (ctx , NFT_MSG_NEWSETELEM , set );
49394968 if (trans == NULL )
4940- goto err4 ;
4969+ goto err_trans ;
49414970
49424971 ext -> genmask = nft_genmask_cur (ctx -> net ) | NFT_SET_ELEM_BUSY_MASK ;
49434972 err = set -> ops -> insert (ctx -> net , set , & elem , & ext2 );
@@ -4948,7 +4977,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
49484977 nft_set_ext_exists (ext , NFT_SET_EXT_OBJREF ) ^
49494978 nft_set_ext_exists (ext2 , NFT_SET_EXT_OBJREF )) {
49504979 err = - EBUSY ;
4951- goto err5 ;
4980+ goto err_element_clash ;
49524981 }
49534982 if ((nft_set_ext_exists (ext , NFT_SET_EXT_DATA ) &&
49544983 nft_set_ext_exists (ext2 , NFT_SET_EXT_DATA ) &&
@@ -4961,33 +4990,35 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
49614990 else if (!(nlmsg_flags & NLM_F_EXCL ))
49624991 err = 0 ;
49634992 }
4964- goto err5 ;
4993+ goto err_element_clash ;
49654994 }
49664995
49674996 if (set -> size &&
49684997 !atomic_add_unless (& set -> nelems , 1 , set -> size + set -> ndeact )) {
49694998 err = - ENFILE ;
4970- goto err6 ;
4999+ goto err_set_full ;
49715000 }
49725001
49735002 nft_trans_elem (trans ) = elem ;
49745003 list_add_tail (& trans -> list , & ctx -> net -> nft .commit_list );
49755004 return 0 ;
49765005
4977- err6 :
5006+ err_set_full :
49785007 set -> ops -> remove (ctx -> net , set , & elem );
4979- err5 :
5008+ err_element_clash :
49805009 kfree (trans );
4981- err4 :
5010+ err_trans :
49825011 if (obj )
49835012 obj -> use -- ;
49845013 kfree (elem .priv );
4985- err3 :
5014+ err_parse_data :
49865015 if (nla [NFTA_SET_ELEM_DATA ] != NULL )
49875016 nft_data_release (& data , desc .type );
4988- err2 :
5017+ err_parse_key_end :
5018+ nft_data_release (& elem .key_end .val , NFT_DATA_VALUE );
5019+ err_parse_key :
49895020 nft_data_release (& elem .key .val , NFT_DATA_VALUE );
4990- err1 :
5021+
49915022 return err ;
49925023}
49935024
@@ -5112,9 +5143,19 @@ static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set,
51125143
51135144 nft_set_ext_add_length (& tmpl , NFT_SET_EXT_KEY , set -> klen );
51145145
5146+ if (nla [NFTA_SET_ELEM_KEY_END ]) {
5147+ err = nft_setelem_parse_key (ctx , set , & elem .key_end .val ,
5148+ nla [NFTA_SET_ELEM_KEY_END ]);
5149+ if (err < 0 )
5150+ return err ;
5151+
5152+ nft_set_ext_add_length (& tmpl , NFT_SET_EXT_KEY_END , set -> klen );
5153+ }
5154+
51155155 err = - ENOMEM ;
5116- elem .priv = nft_set_elem_init (set , & tmpl , elem .key .val .data , NULL , 0 ,
5117- 0 , GFP_KERNEL );
5156+ elem .priv = nft_set_elem_init (set , & tmpl , elem .key .val .data ,
5157+ elem .key_end .val .data , NULL , 0 , 0 ,
5158+ GFP_KERNEL );
51185159 if (elem .priv == NULL )
51195160 goto fail_elem ;
51205161
0 commit comments