History

netfilter: nf_tables: variable sized set element keys / data

This patch changes sets to support variable sized set element keys / data up to 64 bytes each by using variable sized set extensions. This allows to use concatenations with bigger data items suchs as IPv6 addresses. As a side effect, small keys/data now don't require the full 16 bytes of struct nft_data anymore but just the space they need.

Patrick McHardy committed 11 years ago

Commit 7d740261 parent d0a11fc5 files · +23 −19Browse files

Unified · Split

5 files
  1. include/net/netfilter/nf_tables.h +4 −1
  2. include/uapi/linux/netfilter/nf_tables.h +3 −0
  3. net/netfilter/nf_tables_api.c +12 −15
  4. net/netfilter/nft_hash.c +2 −2
  5. net/netfilter/nft_rbtree.c +2 −1
include/net/netfilter/nf_tables.h+4−1
@@ -158,7 +158,10 @@ struct nft_userdata { · 157 unmodified lines
158 * @priv: element private data and extensions158 * @priv: element private data and extensions
159 */159 */
160struct nft_set_elem {160struct nft_set_elem {
161 struct nft_data key;161 union {
162 u32 buf[NFT_DATA_VALUE_MAXLEN / sizeof(u32)];
163 struct nft_data val;
164 } key;
162 void *priv;165 void *priv;
163};166};
164 167
include/uapi/linux/netfilter/nf_tables.h+3−0
@@ -388,6 +388,9 @@ enum nft_data_attributes { · 387 unmodified lines
388};388};
389#define NFTA_DATA_MAX (__NFTA_DATA_MAX - 1)389#define NFTA_DATA_MAX (__NFTA_DATA_MAX - 1)
390 390
391/* Maximum length of a value */
392#define NFT_DATA_VALUE_MAXLEN 64
393
391/**394/**
392 * enum nft_verdict_attributes - nf_tables verdict netlink attributes395 * enum nft_verdict_attributes - nf_tables verdict netlink attributes
393 *396 *
net/netfilter/nf_tables_api.c+12−15
@@ -2608,7 +2608,7 @@ static int nf_tables_newset(struct sock *nlsk, struct sk_buff *skb, · 2607 unmodified lines
2608 }2608 }
2609 2609
2610 desc.klen = ntohl(nla_get_be32(nla[NFTA_SET_KEY_LEN]));2610 desc.klen = ntohl(nla_get_be32(nla[NFTA_SET_KEY_LEN]));
2611 if (desc.klen == 0 || desc.klen > FIELD_SIZEOF(struct nft_data, data))2611 if (desc.klen == 0 || desc.klen > NFT_DATA_VALUE_MAXLEN)
2612 return -EINVAL;2612 return -EINVAL;
2613 2613
2614 flags = 0;2614 flags = 0;
@@ -2634,11 +2634,10 @@ static int nf_tables_newset(struct sock *nlsk, struct sk_buff *skb, · 19 unmodified lines
2634 if (nla[NFTA_SET_DATA_LEN] == NULL)2634 if (nla[NFTA_SET_DATA_LEN] == NULL)
2635 return -EINVAL;2635 return -EINVAL;
2636 desc.dlen = ntohl(nla_get_be32(nla[NFTA_SET_DATA_LEN]));2636 desc.dlen = ntohl(nla_get_be32(nla[NFTA_SET_DATA_LEN]));
2637 if (desc.dlen == 0 ||2637 if (desc.dlen == 0 || desc.dlen > NFT_DATA_VALUE_MAXLEN)
2638 desc.dlen > FIELD_SIZEOF(struct nft_data, data))
2639 return -EINVAL;2638 return -EINVAL;
2640 } else2639 } else
2641 desc.dlen = sizeof(struct nft_data);2640 desc.dlen = sizeof(struct nft_verdict);
2642 } else if (flags & NFT_SET_MAP)2641 } else if (flags & NFT_SET_MAP)
2643 return -EINVAL;2642 return -EINVAL;
2644 2643
@@ -2854,12 +2853,10 @@ void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set, · 209 unmodified lines
2854 2853
2855const struct nft_set_ext_type nft_set_ext_types[] = {2854const struct nft_set_ext_type nft_set_ext_types[] = {
2856 [NFT_SET_EXT_KEY] = {2855 [NFT_SET_EXT_KEY] = {
2857 .len = sizeof(struct nft_data),2856 .align = __alignof__(u32),
2858 .align = __alignof__(struct nft_data),
2859 },2857 },
2860 [NFT_SET_EXT_DATA] = {2858 [NFT_SET_EXT_DATA] = {
2861 .len = sizeof(struct nft_data),2859 .align = __alignof__(u32),
2862 .align = __alignof__(struct nft_data),
2863 },2860 },
2864 [NFT_SET_EXT_FLAGS] = {2861 [NFT_SET_EXT_FLAGS] = {
2865 .len = sizeof(u8),2862 .len = sizeof(u8),
@@ -3299,7 +3296,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, · 433 unmodified lines
3299 timeout = set->timeout;3296 timeout = set->timeout;
3300 }3297 }
3301 3298
3302 err = nft_data_init(ctx, &elem.key, sizeof(elem.key), &d1,3299 err = nft_data_init(ctx, &elem.key.val, sizeof(elem.key), &d1,
3303 nla[NFTA_SET_ELEM_KEY]);3300 nla[NFTA_SET_ELEM_KEY]);
3304 if (err < 0)3301 if (err < 0)
3305 goto err1;3302 goto err1;
@@ -3307,7 +3304,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, · 1 unmodified line
3307 if (d1.type != NFT_DATA_VALUE || d1.len != set->klen)3304 if (d1.type != NFT_DATA_VALUE || d1.len != set->klen)
3308 goto err2;3305 goto err2;
3309 3306
3310 nft_set_ext_add(&tmpl, NFT_SET_EXT_KEY);3307 nft_set_ext_add_length(&tmpl, NFT_SET_EXT_KEY, d1.len);
3311 if (timeout > 0) {3308 if (timeout > 0) {
3312 nft_set_ext_add(&tmpl, NFT_SET_EXT_EXPIRATION);3309 nft_set_ext_add(&tmpl, NFT_SET_EXT_EXPIRATION);
3313 if (timeout != set->timeout)3310 if (timeout != set->timeout)
@@ -3342,7 +3339,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, · 28 unmodified lines
3342 goto err3;3339 goto err3;
3343 }3340 }
3344 3341
3345 nft_set_ext_add(&tmpl, NFT_SET_EXT_DATA);3342 nft_set_ext_add_length(&tmpl, NFT_SET_EXT_DATA, d2.len);
3346 }3343 }
3347 3344
3348 /* The full maximum length of userdata can exceed the maximum3345 /* The full maximum length of userdata can exceed the maximum
@@ -3358,7 +3355,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, · 9 unmodified lines
3358 }3355 }
3359 3356
3360 err = -ENOMEM;3357 err = -ENOMEM;
3361 elem.priv = nft_set_elem_init(set, &tmpl, elem.key.data, data.data,3358 elem.priv = nft_set_elem_init(set, &tmpl, elem.key.val.data, data.data,
3362 timeout, GFP_KERNEL);3359 timeout, GFP_KERNEL);
3363 if (elem.priv == NULL)3360 if (elem.priv == NULL)
3364 goto err3;3361 goto err3;
@@ -3393,7 +3390,7 @@ err3: · 28 unmodified lines
3393 if (nla[NFTA_SET_ELEM_DATA] != NULL)3390 if (nla[NFTA_SET_ELEM_DATA] != NULL)
3394 nft_data_uninit(&data, d2.type);3391 nft_data_uninit(&data, d2.type);
3395err2:3392err2:
3396 nft_data_uninit(&elem.key, d1.type);3393 nft_data_uninit(&elem.key.val, d1.type);
3397err1:3394err1:
3398 return err;3395 return err;
3399}3396}
@@ -3460,7 +3457,7 @@ static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set, · 60 unmodified lines
3460 if (nla[NFTA_SET_ELEM_KEY] == NULL)3457 if (nla[NFTA_SET_ELEM_KEY] == NULL)
3461 goto err1;3458 goto err1;
3462 3459
3463 err = nft_data_init(ctx, &elem.key, sizeof(elem.key), &desc,3460 err = nft_data_init(ctx, &elem.key.val, sizeof(elem.key), &desc,
3464 nla[NFTA_SET_ELEM_KEY]);3461 nla[NFTA_SET_ELEM_KEY]);
3465 if (err < 0)3462 if (err < 0)
3466 goto err1;3463 goto err1;
@@ -3488,7 +3485,7 @@ static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set, · 21 unmodified lines
3488err3:3485err3:
3489 kfree(trans);3486 kfree(trans);
3490err2:3487err2:
3491 nft_data_uninit(&elem.key, desc.type);3488 nft_data_uninit(&elem.key.val, desc.type);
3492err1:3489err1:
3493 return err;3490 return err;
3494}3491}
net/netfilter/nft_hash.c+2−2
@@ -133,7 +133,7 @@ static int nft_hash_insert(const struct nft_set *set, · 132 unmodified lines
133 struct nft_hash_cmp_arg arg = {133 struct nft_hash_cmp_arg arg = {
134 .genmask = nft_genmask_next(read_pnet(&set->pnet)),134 .genmask = nft_genmask_next(read_pnet(&set->pnet)),
135 .set = set,135 .set = set,
136 .key = elem->key.data,136 .key = elem->key.val.data,
137 };137 };
138 138
139 return rhashtable_lookup_insert_key(&priv->ht, &arg, &he->node,139 return rhashtable_lookup_insert_key(&priv->ht, &arg, &he->node,
@@ -157,7 +157,7 @@ static void *nft_hash_deactivate(const struct nft_set *set, · 17 unmodified lines
157 struct nft_hash_cmp_arg arg = {157 struct nft_hash_cmp_arg arg = {
158 .genmask = nft_genmask_next(read_pnet(&set->pnet)),158 .genmask = nft_genmask_next(read_pnet(&set->pnet)),
159 .set = set,159 .set = set,
160 .key = elem->key.data,160 .key = elem->key.val.data,
161 };161 };
162 162
163 rcu_read_lock();163 rcu_read_lock();
net/netfilter/nft_rbtree.c+2−1
@@ -152,7 +152,8 @@ static void *nft_rbtree_deactivate(const struct nft_set *set, · 151 unmodified lines
152 while (parent != NULL) {152 while (parent != NULL) {
153 rbe = rb_entry(parent, struct nft_rbtree_elem, node);153 rbe = rb_entry(parent, struct nft_rbtree_elem, node);
154 154
155 d = memcmp(nft_set_ext_key(&rbe->ext), &elem->key, set->klen);155 d = memcmp(nft_set_ext_key(&rbe->ext), &elem->key.val,
156 set->klen);
156 if (d < 0)157 if (d < 0)
157 parent = parent->rb_left;158 parent = parent->rb_left;
158 else if (d > 0)159 else if (d > 0)

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t