diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2016-08-26 18:00:00 +0200 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2016-08-29 20:30:29 +0200 |
commit | 345236211715ffb7cc28f6ff0b26acb90181e738 (patch) | |
tree | aebfc9aeece1dda1bb1ffab52aa93a9b1114f928 /src/hash.c | |
parent | 13eeed6ea6f0a5d1353ee5ad14c4322695b4f59b (diff) |
src: add hash expression
This is special expression that transforms an input expression into a
32-bit unsigned integer. This expression takes a modulus parameter to
scale the result and the random seed so the hash result becomes harder
to predict.
You can use it to set the packet mark, eg.
# nft add rule x y meta mark set jhash ip saddr . ip daddr mod 2 seed 0xdeadbeef
You can combine this with maps too, eg.
# nft add rule x y dnat to jhash ip saddr mod 2 seed 0xdeadbeef map { \
0 : 192.168.20.100, \
1 : 192.168.30.100 \
}
Currently, this expression implements the jenkins hash implementation
available in the Linux kernel:
http://lxr.free-electrons.com/source/include/linux/jhash.h
But it should be possible to extend it to support any other hash
function type.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src/hash.c')
-rw-r--r-- | src/hash.c | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/src/hash.c b/src/hash.c new file mode 100644 index 00000000..125b3202 --- /dev/null +++ b/src/hash.c @@ -0,0 +1,60 @@ +/* + * Hash expression definitions. + * + * Copyright (c) 2016 Pablo Neira Ayuso <pablo@netfilter.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <nftables.h> +#include <expression.h> +#include <datatype.h> +#include <gmputil.h> +#include <hash.h> +#include <utils.h> + +static void hash_expr_print(const struct expr *expr) +{ + printf("jhash "); + expr_print(expr->hash.expr); + printf(" mod %u", expr->hash.mod); + if (expr->hash.seed) + printf(" seed 0x%x", expr->hash.seed); +} + +static bool hash_expr_cmp(const struct expr *e1, const struct expr *e2) +{ + return expr_cmp(e1->hash.expr, e2->hash.expr) && + e1->hash.mod == e2->hash.mod && + e1->hash.seed == e2->hash.seed; +} + +static void hash_expr_clone(struct expr *new, const struct expr *expr) +{ + new->hash.expr = expr_clone(expr->hash.expr); + new->hash.mod = expr->hash.mod; + new->hash.seed = expr->hash.seed; +} + +static const struct expr_ops hash_expr_ops = { + .type = EXPR_HASH, + .name = "hash", + .print = hash_expr_print, + .cmp = hash_expr_cmp, + .clone = hash_expr_clone, +}; + +struct expr *hash_expr_alloc(const struct location *loc, uint32_t mod, + uint32_t seed) +{ + struct expr *expr; + + expr = expr_alloc(loc, &hash_expr_ops, &integer_type, + BYTEORDER_HOST_ENDIAN, 4 * BITS_PER_BYTE); + expr->hash.mod = mod; + expr->hash.seed = seed; + + return expr; +} |