@@ -4215,6 +4215,9 @@ const struct nft_set_ext_type nft_set_ext_types[] = {
4215
4215
.len = sizeof (struct nft_userdata ),
4216
4216
.align = __alignof__(struct nft_userdata ),
4217
4217
},
4218
+ [NFT_SET_EXT_KEY_END ] = {
4219
+ .align = __alignof__(u32 ),
4220
+ },
4218
4221
};
4219
4222
EXPORT_SYMBOL_GPL (nft_set_ext_types );
4220
4223
@@ -4233,6 +4236,7 @@ static const struct nla_policy nft_set_elem_policy[NFTA_SET_ELEM_MAX + 1] = {
4233
4236
[NFTA_SET_ELEM_EXPR ] = { .type = NLA_NESTED },
4234
4237
[NFTA_SET_ELEM_OBJREF ] = { .type = NLA_STRING ,
4235
4238
.len = NFT_OBJ_MAXNAMELEN - 1 },
4239
+ [NFTA_SET_ELEM_KEY_END ] = { .type = NLA_NESTED },
4236
4240
};
4237
4241
4238
4242
static 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,
4282
4286
NFT_DATA_VALUE , set -> klen ) < 0 )
4283
4287
goto nla_put_failure ;
4284
4288
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
+
4285
4294
if (nft_set_ext_exists (ext , NFT_SET_EXT_DATA ) &&
4286
4295
nft_data_dump (skb , NFTA_SET_ELEM_DATA , nft_set_ext_data (ext ),
4287
4296
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,
4569
4578
if (err < 0 )
4570
4579
return err ;
4571
4580
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
+
4572
4588
priv = set -> ops -> get (ctx -> net , set , & elem , flags );
4573
4589
if (IS_ERR (priv ))
4574
4590
return PTR_ERR (priv );
@@ -4694,8 +4710,8 @@ static struct nft_trans *nft_trans_elem_alloc(struct nft_ctx *ctx,
4694
4710
4695
4711
void * nft_set_elem_init (const struct nft_set * set ,
4696
4712
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 )
4699
4715
{
4700
4716
struct nft_set_ext * ext ;
4701
4717
void * elem ;
@@ -4708,6 +4724,8 @@ void *nft_set_elem_init(const struct nft_set *set,
4708
4724
nft_set_ext_init (ext , tmpl );
4709
4725
4710
4726
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 );
4711
4729
if (nft_set_ext_exists (ext , NFT_SET_EXT_DATA ))
4712
4730
memcpy (nft_set_ext_data (ext ), data , set -> dlen );
4713
4731
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,
4842
4860
err = nft_setelem_parse_key (ctx , set , & elem .key .val ,
4843
4861
nla [NFTA_SET_ELEM_KEY ]);
4844
4862
if (err < 0 )
4845
- goto err1 ;
4863
+ return err ;
4846
4864
4847
4865
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
+
4848
4876
if (timeout > 0 ) {
4849
4877
nft_set_ext_add (& tmpl , NFT_SET_EXT_EXPIRATION );
4850
4878
if (timeout != set -> timeout )
@@ -4854,14 +4882,14 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
4854
4882
if (nla [NFTA_SET_ELEM_OBJREF ] != NULL ) {
4855
4883
if (!(set -> flags & NFT_SET_OBJECT )) {
4856
4884
err = - EINVAL ;
4857
- goto err2 ;
4885
+ goto err_parse_key_end ;
4858
4886
}
4859
4887
obj = nft_obj_lookup (ctx -> net , ctx -> table ,
4860
4888
nla [NFTA_SET_ELEM_OBJREF ],
4861
4889
set -> objtype , genmask );
4862
4890
if (IS_ERR (obj )) {
4863
4891
err = PTR_ERR (obj );
4864
- goto err2 ;
4892
+ goto err_parse_key_end ;
4865
4893
}
4866
4894
nft_set_ext_add (& tmpl , NFT_SET_EXT_OBJREF );
4867
4895
}
@@ -4870,11 +4898,11 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
4870
4898
err = nft_data_init (ctx , & data , sizeof (data ), & desc ,
4871
4899
nla [NFTA_SET_ELEM_DATA ]);
4872
4900
if (err < 0 )
4873
- goto err2 ;
4901
+ goto err_parse_key_end ;
4874
4902
4875
4903
err = - EINVAL ;
4876
4904
if (set -> dtype != NFT_DATA_VERDICT && desc .len != set -> dlen )
4877
- goto err3 ;
4905
+ goto err_parse_data ;
4878
4906
4879
4907
dreg = nft_type_to_reg (set -> dtype );
4880
4908
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,
4892
4920
& data ,
4893
4921
desc .type , desc .len );
4894
4922
if (err < 0 )
4895
- goto err3 ;
4923
+ goto err_parse_data ;
4896
4924
4897
4925
if (desc .type == NFT_DATA_VERDICT &&
4898
4926
(data .verdict .code == NFT_GOTO ||
@@ -4917,10 +4945,11 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
4917
4945
}
4918
4946
4919
4947
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 ,
4921
4950
timeout , expiration , GFP_KERNEL );
4922
4951
if (elem .priv == NULL )
4923
- goto err3 ;
4952
+ goto err_parse_data ;
4924
4953
4925
4954
ext = nft_set_elem_ext (set , elem .priv );
4926
4955
if (flags )
@@ -4937,7 +4966,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
4937
4966
4938
4967
trans = nft_trans_elem_alloc (ctx , NFT_MSG_NEWSETELEM , set );
4939
4968
if (trans == NULL )
4940
- goto err4 ;
4969
+ goto err_trans ;
4941
4970
4942
4971
ext -> genmask = nft_genmask_cur (ctx -> net ) | NFT_SET_ELEM_BUSY_MASK ;
4943
4972
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,
4948
4977
nft_set_ext_exists (ext , NFT_SET_EXT_OBJREF ) ^
4949
4978
nft_set_ext_exists (ext2 , NFT_SET_EXT_OBJREF )) {
4950
4979
err = - EBUSY ;
4951
- goto err5 ;
4980
+ goto err_element_clash ;
4952
4981
}
4953
4982
if ((nft_set_ext_exists (ext , NFT_SET_EXT_DATA ) &&
4954
4983
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,
4961
4990
else if (!(nlmsg_flags & NLM_F_EXCL ))
4962
4991
err = 0 ;
4963
4992
}
4964
- goto err5 ;
4993
+ goto err_element_clash ;
4965
4994
}
4966
4995
4967
4996
if (set -> size &&
4968
4997
!atomic_add_unless (& set -> nelems , 1 , set -> size + set -> ndeact )) {
4969
4998
err = - ENFILE ;
4970
- goto err6 ;
4999
+ goto err_set_full ;
4971
5000
}
4972
5001
4973
5002
nft_trans_elem (trans ) = elem ;
4974
5003
list_add_tail (& trans -> list , & ctx -> net -> nft .commit_list );
4975
5004
return 0 ;
4976
5005
4977
- err6 :
5006
+ err_set_full :
4978
5007
set -> ops -> remove (ctx -> net , set , & elem );
4979
- err5 :
5008
+ err_element_clash :
4980
5009
kfree (trans );
4981
- err4 :
5010
+ err_trans :
4982
5011
if (obj )
4983
5012
obj -> use -- ;
4984
5013
kfree (elem .priv );
4985
- err3 :
5014
+ err_parse_data :
4986
5015
if (nla [NFTA_SET_ELEM_DATA ] != NULL )
4987
5016
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 :
4989
5020
nft_data_release (& elem .key .val , NFT_DATA_VALUE );
4990
- err1 :
5021
+
4991
5022
return err ;
4992
5023
}
4993
5024
@@ -5112,9 +5143,19 @@ static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set,
5112
5143
5113
5144
nft_set_ext_add_length (& tmpl , NFT_SET_EXT_KEY , set -> klen );
5114
5145
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
+
5115
5155
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 );
5118
5159
if (elem .priv == NULL )
5119
5160
goto fail_elem ;
5120
5161
0 commit comments