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
158158 * @priv: element private data and extensions
159159 */
160160 struct 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;
162165 void *priv;
163166 };
164167
include/uapi/linux/netfilter/nf_tables.h+3−0
@@ -388,6 +388,9 @@ enum nft_data_attributes { · 387 unmodified lines
388388 };
389389 #define NFTA_DATA_MAX (__NFTA_DATA_MAX - 1)
390390
391+/* Maximum length of a value */
392+#define NFT_DATA_VALUE_MAXLEN 64
393+
391394 /**
392395 * enum nft_verdict_attributes - nf_tables verdict netlink attributes
393396 *
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
26082608 }
26092609
26102610 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)
26122612 return -EINVAL;
26132613
26142614 flags = 0;
@@ -2634,11 +2634,10 @@ static int nf_tables_newset(struct sock *nlsk, struct sk_buff *skb, · 19 unmodified lines
26342634 if (nla[NFTA_SET_DATA_LEN] == NULL)
26352635 return -EINVAL;
26362636 desc.dlen = ntohl(nla_get_be32(nla[NFTA_SET_DATA_LEN]));
2637− if (desc.dlen == 0 ||
2638− desc.dlen > FIELD_SIZEOF(struct nft_data, data))
2637+ if (desc.dlen == 0 || desc.dlen > NFT_DATA_VALUE_MAXLEN)
26392638 return -EINVAL;
26402639 } else
2641− desc.dlen = sizeof(struct nft_data);
2640+ desc.dlen = sizeof(struct nft_verdict);
26422641 } else if (flags & NFT_SET_MAP)
26432642 return -EINVAL;
26442643
@@ -2854,12 +2853,10 @@ void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set, · 209 unmodified lines
28542853
28552854 const struct nft_set_ext_type nft_set_ext_types[] = {
28562855 [NFT_SET_EXT_KEY] = {
2857− .len = sizeof(struct nft_data),
2858− .align = __alignof__(struct nft_data),
2856+ .align = __alignof__(u32),
28592857 },
28602858 [NFT_SET_EXT_DATA] = {
2861− .len = sizeof(struct nft_data),
2862− .align = __alignof__(struct nft_data),
2859+ .align = __alignof__(u32),
28632860 },
28642861 [NFT_SET_EXT_FLAGS] = {
28652862 .len = sizeof(u8),
@@ -3299,7 +3296,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, · 433 unmodified lines
32993296 timeout = set->timeout;
33003297 }
33013298
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,
33033300 nla[NFTA_SET_ELEM_KEY]);
33043301 if (err < 0)
33053302 goto err1;
@@ -3307,7 +3304,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, · 1 unmodified line
33073304 if (d1.type != NFT_DATA_VALUE || d1.len != set->klen)
33083305 goto err2;
33093306
3310− nft_set_ext_add(&tmpl, NFT_SET_EXT_KEY);
3307+ nft_set_ext_add_length(&tmpl, NFT_SET_EXT_KEY, d1.len);
33113308 if (timeout > 0) {
33123309 nft_set_ext_add(&tmpl, NFT_SET_EXT_EXPIRATION);
33133310 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
33423339 goto err3;
33433340 }
33443341
3345− nft_set_ext_add(&tmpl, NFT_SET_EXT_DATA);
3342+ nft_set_ext_add_length(&tmpl, NFT_SET_EXT_DATA, d2.len);
33463343 }
33473344
33483345 /* 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
33583355 }
33593356
33603357 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,
33623359 timeout, GFP_KERNEL);
33633360 if (elem.priv == NULL)
33643361 goto err3;
@@ -3393,7 +3390,7 @@ err3: · 28 unmodified lines
33933390 if (nla[NFTA_SET_ELEM_DATA] != NULL)
33943391 nft_data_uninit(&data, d2.type);
33953392 err2:
3396− nft_data_uninit(&elem.key, d1.type);
3393+ nft_data_uninit(&elem.key.val, d1.type);
33973394 err1:
33983395 return err;
33993396 }
@@ -3460,7 +3457,7 @@ static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set, · 60 unmodified lines
34603457 if (nla[NFTA_SET_ELEM_KEY] == NULL)
34613458 goto err1;
34623459
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,
34643461 nla[NFTA_SET_ELEM_KEY]);
34653462 if (err < 0)
34663463 goto err1;
@@ -3488,7 +3485,7 @@ static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set, · 21 unmodified lines
34883485 err3:
34893486 kfree(trans);
34903487 err2:
3491− nft_data_uninit(&elem.key, desc.type);
3488+ nft_data_uninit(&elem.key.val, desc.type);
34923489 err1:
34933490 return err;
34943491 }
net/netfilter/nft_hash.c+2−2
@@ -133,7 +133,7 @@ static int nft_hash_insert(const struct nft_set *set, · 132 unmodified lines
133133 struct nft_hash_cmp_arg arg = {
134134 .genmask = nft_genmask_next(read_pnet(&set->pnet)),
135135 .set = set,
136− .key = elem->key.data,
136+ .key = elem->key.val.data,
137137 };
138138
139139 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
157157 struct nft_hash_cmp_arg arg = {
158158 .genmask = nft_genmask_next(read_pnet(&set->pnet)),
159159 .set = set,
160− .key = elem->key.data,
160+ .key = elem->key.val.data,
161161 };
162162
163163 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
152152 while (parent != NULL) {
153153 rbe = rb_entry(parent, struct nft_rbtree_elem, node);
154154
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);
156157 if (d < 0)
157158 parent = parent->rb_left;
158159 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