aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2015-04-05 08:43:38 -0400
committerPablo Neira Ayuso <pablo@netfilter.org>2015-04-08 10:58:27 -0400
commit68e942e88add0ac8576fc8397e86495edf3dcea7 (patch)
treea068c331abf3b14574ecc9bab024a879bcb21bcb /net
parent22fe54d5fefcfa98c58cc2f4607dd26d9648b3f5 (diff)
netfilter: nf_tables: support optional userdata for set elements
Add an userdata set extension and allow the user to attach arbitrary data to set elements. This is intended to hold TLV encoded data like comments or DNS annotations that have no meaning to the kernel. Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net')
-rw-r--r--net/netfilter/nf_tables_api.c34
1 files changed, 34 insertions, 0 deletions
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 598e53eb64b3..0b96fa0d64b2 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -2872,6 +2872,10 @@ const struct nft_set_ext_type nft_set_ext_types[] = {
2872 .len = sizeof(unsigned long), 2872 .len = sizeof(unsigned long),
2873 .align = __alignof__(unsigned long), 2873 .align = __alignof__(unsigned long),
2874 }, 2874 },
2875 [NFT_SET_EXT_USERDATA] = {
2876 .len = sizeof(struct nft_userdata),
2877 .align = __alignof__(struct nft_userdata),
2878 },
2875}; 2879};
2876EXPORT_SYMBOL_GPL(nft_set_ext_types); 2880EXPORT_SYMBOL_GPL(nft_set_ext_types);
2877 2881
@@ -2884,6 +2888,8 @@ static const struct nla_policy nft_set_elem_policy[NFTA_SET_ELEM_MAX + 1] = {
2884 [NFTA_SET_ELEM_DATA] = { .type = NLA_NESTED }, 2888 [NFTA_SET_ELEM_DATA] = { .type = NLA_NESTED },
2885 [NFTA_SET_ELEM_FLAGS] = { .type = NLA_U32 }, 2889 [NFTA_SET_ELEM_FLAGS] = { .type = NLA_U32 },
2886 [NFTA_SET_ELEM_TIMEOUT] = { .type = NLA_U64 }, 2890 [NFTA_SET_ELEM_TIMEOUT] = { .type = NLA_U64 },
2891 [NFTA_SET_ELEM_USERDATA] = { .type = NLA_BINARY,
2892 .len = NFT_USERDATA_MAXLEN },
2887}; 2893};
2888 2894
2889static const struct nla_policy nft_set_elem_list_policy[NFTA_SET_ELEM_LIST_MAX + 1] = { 2895static const struct nla_policy nft_set_elem_list_policy[NFTA_SET_ELEM_LIST_MAX + 1] = {
@@ -2964,6 +2970,15 @@ static int nf_tables_fill_setelem(struct sk_buff *skb,
2964 goto nla_put_failure; 2970 goto nla_put_failure;
2965 } 2971 }
2966 2972
2973 if (nft_set_ext_exists(ext, NFT_SET_EXT_USERDATA)) {
2974 struct nft_userdata *udata;
2975
2976 udata = nft_set_ext_userdata(ext);
2977 if (nla_put(skb, NFTA_SET_ELEM_USERDATA,
2978 udata->len + 1, udata->data))
2979 goto nla_put_failure;
2980 }
2981
2967 nla_nest_end(skb, nest); 2982 nla_nest_end(skb, nest);
2968 return 0; 2983 return 0;
2969 2984
@@ -3232,11 +3247,13 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
3232 struct nft_set_ext *ext; 3247 struct nft_set_ext *ext;
3233 struct nft_set_elem elem; 3248 struct nft_set_elem elem;
3234 struct nft_set_binding *binding; 3249 struct nft_set_binding *binding;
3250 struct nft_userdata *udata;
3235 struct nft_data data; 3251 struct nft_data data;
3236 enum nft_registers dreg; 3252 enum nft_registers dreg;
3237 struct nft_trans *trans; 3253 struct nft_trans *trans;
3238 u64 timeout; 3254 u64 timeout;
3239 u32 flags; 3255 u32 flags;
3256 u8 ulen;
3240 int err; 3257 int err;
3241 3258
3242 err = nla_parse_nested(nla, NFTA_SET_ELEM_MAX, attr, 3259 err = nla_parse_nested(nla, NFTA_SET_ELEM_MAX, attr,
@@ -3325,6 +3342,18 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
3325 nft_set_ext_add(&tmpl, NFT_SET_EXT_DATA); 3342 nft_set_ext_add(&tmpl, NFT_SET_EXT_DATA);
3326 } 3343 }
3327 3344
3345 /* The full maximum length of userdata can exceed the maximum
3346 * offset value (U8_MAX) for following extensions, therefor it
3347 * must be the last extension added.
3348 */
3349 ulen = 0;
3350 if (nla[NFTA_SET_ELEM_USERDATA] != NULL) {
3351 ulen = nla_len(nla[NFTA_SET_ELEM_USERDATA]);
3352 if (ulen > 0)
3353 nft_set_ext_add_length(&tmpl, NFT_SET_EXT_USERDATA,
3354 ulen);
3355 }
3356
3328 err = -ENOMEM; 3357 err = -ENOMEM;
3329 elem.priv = nft_set_elem_init(set, &tmpl, &elem.key, &data, 3358 elem.priv = nft_set_elem_init(set, &tmpl, &elem.key, &data,
3330 timeout, GFP_KERNEL); 3359 timeout, GFP_KERNEL);
@@ -3334,6 +3363,11 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
3334 ext = nft_set_elem_ext(set, elem.priv); 3363 ext = nft_set_elem_ext(set, elem.priv);
3335 if (flags) 3364 if (flags)
3336 *nft_set_ext_flags(ext) = flags; 3365 *nft_set_ext_flags(ext) = flags;
3366 if (ulen > 0) {
3367 udata = nft_set_ext_userdata(ext);
3368 udata->len = ulen - 1;
3369 nla_memcpy(&udata->data, nla[NFTA_SET_ELEM_USERDATA], ulen);
3370 }
3337 3371
3338 trans = nft_trans_elem_alloc(ctx, NFT_MSG_NEWSETELEM, set); 3372 trans = nft_trans_elem_alloc(ctx, NFT_MSG_NEWSETELEM, set);
3339 if (trans == NULL) 3373 if (trans == NULL)