diff options
author | Patrick McHardy <kaber@trash.net> | 2015-03-25 09:07:49 -0400 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2015-03-25 12:18:34 -0400 |
commit | 3ac4c07a24007f0f45d2082b745508768a8e21cf (patch) | |
tree | 1c37bb8fbea34f181a1f1cf85ee355fa7486dff2 | |
parent | bfd6e327e118d2fe443047829047862b49012457 (diff) |
netfilter: nf_tables: add set extensions
Add simple set extension infrastructure for maintaining variable sized
and optional per element data.
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r-- | include/net/netfilter/nf_tables.h | 105 | ||||
-rw-r--r-- | net/netfilter/nf_tables_api.c | 16 |
2 files changed, 121 insertions, 0 deletions
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h index ace67a549b30..038f8a67ca1f 100644 --- a/include/net/netfilter/nf_tables.h +++ b/include/net/netfilter/nf_tables.h | |||
@@ -311,6 +311,111 @@ int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set, | |||
311 | void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set, | 311 | void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set, |
312 | struct nft_set_binding *binding); | 312 | struct nft_set_binding *binding); |
313 | 313 | ||
314 | /** | ||
315 | * enum nft_set_extensions - set extension type IDs | ||
316 | * | ||
317 | * @NFT_SET_EXT_KEY: element key | ||
318 | * @NFT_SET_EXT_DATA: mapping data | ||
319 | * @NFT_SET_EXT_FLAGS: element flags | ||
320 | * @NFT_SET_EXT_NUM: number of extension types | ||
321 | */ | ||
322 | enum nft_set_extensions { | ||
323 | NFT_SET_EXT_KEY, | ||
324 | NFT_SET_EXT_DATA, | ||
325 | NFT_SET_EXT_FLAGS, | ||
326 | NFT_SET_EXT_NUM | ||
327 | }; | ||
328 | |||
329 | /** | ||
330 | * struct nft_set_ext_type - set extension type | ||
331 | * | ||
332 | * @len: fixed part length of the extension | ||
333 | * @align: alignment requirements of the extension | ||
334 | */ | ||
335 | struct nft_set_ext_type { | ||
336 | u8 len; | ||
337 | u8 align; | ||
338 | }; | ||
339 | |||
340 | extern const struct nft_set_ext_type nft_set_ext_types[]; | ||
341 | |||
342 | /** | ||
343 | * struct nft_set_ext_tmpl - set extension template | ||
344 | * | ||
345 | * @len: length of extension area | ||
346 | * @offset: offsets of individual extension types | ||
347 | */ | ||
348 | struct nft_set_ext_tmpl { | ||
349 | u16 len; | ||
350 | u8 offset[NFT_SET_EXT_NUM]; | ||
351 | }; | ||
352 | |||
353 | /** | ||
354 | * struct nft_set_ext - set extensions | ||
355 | * | ||
356 | * @offset: offsets of individual extension types | ||
357 | * @data: beginning of extension data | ||
358 | */ | ||
359 | struct nft_set_ext { | ||
360 | u8 offset[NFT_SET_EXT_NUM]; | ||
361 | char data[0]; | ||
362 | }; | ||
363 | |||
364 | static inline void nft_set_ext_prepare(struct nft_set_ext_tmpl *tmpl) | ||
365 | { | ||
366 | memset(tmpl, 0, sizeof(*tmpl)); | ||
367 | tmpl->len = sizeof(struct nft_set_ext); | ||
368 | } | ||
369 | |||
370 | static inline void nft_set_ext_add_length(struct nft_set_ext_tmpl *tmpl, u8 id, | ||
371 | unsigned int len) | ||
372 | { | ||
373 | tmpl->len = ALIGN(tmpl->len, nft_set_ext_types[id].align); | ||
374 | BUG_ON(tmpl->len > U8_MAX); | ||
375 | tmpl->offset[id] = tmpl->len; | ||
376 | tmpl->len += nft_set_ext_types[id].len + len; | ||
377 | } | ||
378 | |||
379 | static inline void nft_set_ext_add(struct nft_set_ext_tmpl *tmpl, u8 id) | ||
380 | { | ||
381 | nft_set_ext_add_length(tmpl, id, 0); | ||
382 | } | ||
383 | |||
384 | static inline void nft_set_ext_init(struct nft_set_ext *ext, | ||
385 | const struct nft_set_ext_tmpl *tmpl) | ||
386 | { | ||
387 | memcpy(ext->offset, tmpl->offset, sizeof(ext->offset)); | ||
388 | } | ||
389 | |||
390 | static inline bool __nft_set_ext_exists(const struct nft_set_ext *ext, u8 id) | ||
391 | { | ||
392 | return !!ext->offset[id]; | ||
393 | } | ||
394 | |||
395 | static inline bool nft_set_ext_exists(const struct nft_set_ext *ext, u8 id) | ||
396 | { | ||
397 | return ext && __nft_set_ext_exists(ext, id); | ||
398 | } | ||
399 | |||
400 | static inline void *nft_set_ext(const struct nft_set_ext *ext, u8 id) | ||
401 | { | ||
402 | return (void *)ext + ext->offset[id]; | ||
403 | } | ||
404 | |||
405 | static inline struct nft_data *nft_set_ext_key(const struct nft_set_ext *ext) | ||
406 | { | ||
407 | return nft_set_ext(ext, NFT_SET_EXT_KEY); | ||
408 | } | ||
409 | |||
410 | static inline struct nft_data *nft_set_ext_data(const struct nft_set_ext *ext) | ||
411 | { | ||
412 | return nft_set_ext(ext, NFT_SET_EXT_DATA); | ||
413 | } | ||
414 | |||
415 | static inline u8 *nft_set_ext_flags(const struct nft_set_ext *ext) | ||
416 | { | ||
417 | return nft_set_ext(ext, NFT_SET_EXT_FLAGS); | ||
418 | } | ||
314 | 419 | ||
315 | /** | 420 | /** |
316 | * struct nft_expr_type - nf_tables expression type | 421 | * struct nft_expr_type - nf_tables expression type |
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 0b969b66cb77..972c47f6e823 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c | |||
@@ -2827,6 +2827,22 @@ void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set, | |||
2827 | nf_tables_set_destroy(ctx, set); | 2827 | nf_tables_set_destroy(ctx, set); |
2828 | } | 2828 | } |
2829 | 2829 | ||
2830 | const struct nft_set_ext_type nft_set_ext_types[] = { | ||
2831 | [NFT_SET_EXT_KEY] = { | ||
2832 | .len = sizeof(struct nft_data), | ||
2833 | .align = __alignof__(struct nft_data), | ||
2834 | }, | ||
2835 | [NFT_SET_EXT_DATA] = { | ||
2836 | .len = sizeof(struct nft_data), | ||
2837 | .align = __alignof__(struct nft_data), | ||
2838 | }, | ||
2839 | [NFT_SET_EXT_FLAGS] = { | ||
2840 | .len = sizeof(u8), | ||
2841 | .align = __alignof__(u8), | ||
2842 | }, | ||
2843 | }; | ||
2844 | EXPORT_SYMBOL_GPL(nft_set_ext_types); | ||
2845 | |||
2830 | /* | 2846 | /* |
2831 | * Set elements | 2847 | * Set elements |
2832 | */ | 2848 | */ |