netfilter: nft_hash: Add hash offset value
Subsystems (2)
PATCH 1/1 netfilter: nft_hash: Add hash offset value
Add support to pass through an offset to the hash value. With this feature, the sysadmin is able to generate a hash with a given offset value.
Example:
meta mark set jhash ip saddr mod 2 seed 0xabcd sum 100
This option generates marks according to the source address from 100 to 101.
--- include/uapi/linux/netfilter/nf_tables.h | 2 ++ net/netfilter/nft_hash.c | 13 +++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-)
include/uapi/linux/netfilter/nf_tables.h +2 -0
@@ -764,6 +764,7 @@ enum nft_meta_keys {* @NFTA_HASH_LEN: source data length (NLA_U32) * @NFTA_HASH_MODULUS: modulus value (NLA_U32) * @NFTA_HASH_SEED: seed value (NLA_U32) +* @NFTA_HASH_SUM: Hash offset value (NLA_U32) */ enum nft_hash_attributes {NFTA_HASH_UNSPEC ,
@@ -772,6 +773,7 @@ enum nft_hash_attributes {NFTA_HASH_LEN ,NFTA_HASH_MODULUS ,NFTA_HASH_SEED , +NFTA_HASH_SUM , __NFTA_HASH_MAX, };#define NFTA_HASH_MAX (__NFTA_HASH_MAX - 1)
net/netfilter/nft_hash.c +11 -2
@@ -23,6 +23,7 @@ struct nft_hash {u8 len;u32 modulus;u32 seed; +u32 sum; }; static void nft_hash_eval(const struct nft_expr *expr,
@@ -35,7 +36,7 @@ static void nft_hash_eval(const struct nft_expr *expr, h =reciprocal_scale (jhash (data, priv->len, priv->seed), priv->modulus); - regs->data[priv->dreg] = h; + regs->data[priv->dreg] = priv->sum + h; }const struct nla_policy nft_hash_policy[NFTA_HASH_MAX +1 ] = {
@@ -44,6 +45,7 @@ const struct nla_policy nft_hash_policy[NFTA_HASH_MAX + 1] = { [NFTA_HASH_LEN] = { .type = NLA_U32 }, [NFTA_HASH_MODULUS] = { .type = NLA_U32 }, [NFTA_HASH_SEED] = { .type = NLA_U32 }, + [NFTA_HASH_SUM] = { .type = NLA_U32 }, }; static int nft_hash_init(const struct nft_ctx *ctx,
@@ -60,6 +62,11 @@ static int nft_hash_init(const struct nft_ctx *ctx, !tb[NFTA_HASH_MODULUS])return -EINVAL ; +if (tb[NFTA_HASH_SUM ]) + priv->sum =ntohl (nla_get_be32 (tb[NFTA_HASH_SUM ])); +else + priv->sum =0 ; + priv->sreg =nft_parse_register (tb[NFTA_HASH_SREG ]);if (priv->sreg <0 )return -ERANGE ;
@@ -99,7 +106,9 @@ static int nft_hash_dump(struct sk_buff *skb, goto nla_put_failure;if (nft_dump_register (skb,NFTA_HASH_SEED , priv->seed)) goto nla_put_failure; - +if (priv->sum !=0 ) +if (nft_dump_register (skb,NFTA_HASH_SUM , priv->sum)) + goto nla_put_failure;return 0 ; nla_put_failure:
Signature · 1 line
2.8.1
Pablo Neira Ayuso
maintainerQuoted 67 lines · Laura Garcia Liebana
Add support to pass through an offset to the hash value. With this feature, the sysadmin is able to generate a hash with a given offset value.
Example:
meta mark set jhash ip saddr mod 2 seed 0xabcd sum 100This option generates marks according to the source address from 100 to 101.
Signed-off-by Laura Garcia Liebana <[email protected]>--- include/uapi/linux/netfilter/nf_tables.h | 2 ++ net/netfilter/nft_hash.c | 13 +++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-)include/uapi/linux/netfilter/nf_tables.h +2
-0@@ -764,6 +764,7 @@ enum nft_meta_keys {* @NFTA_HASH_LEN: source data length (NLA_U32) * @NFTA_HASH_MODULUS: modulus value (NLA_U32) * @NFTA_HASH_SEED: seed value (NLA_U32) +* @NFTA_HASH_SUM: Hash offset value (NLA_U32) */ enum nft_hash_attributes {NFTA_HASH_UNSPEC ,@@ -772,6 +773,7 @@ enum nft_hash_attributes {NFTA_HASH_LEN ,NFTA_HASH_MODULUS ,NFTA_HASH_SEED , +NFTA_HASH_SUM , __NFTA_HASH_MAX, };#define NFTA_HASH_MAX (__NFTA_HASH_MAX - 1)net/netfilter/nft_hash.c +3
-1@@ -23,6 +23,7 @@ struct nft_hash {u8 len;u32 modulus;u32 seed; +u32 sum; }; static void nft_hash_eval(const struct nft_expr *expr,@@ -35,7 +36,7 @@ static void nft_hash_eval(const struct nft_expr *expr, h =reciprocal_scale (jhash (data, priv->len, priv->seed), priv->modulus); - regs->data[priv->dreg] = h; + regs->data[priv->dreg] = priv->sum + h; }const struct nla_policy nft_hash_policy[NFTA_HASH_MAX +1 ] = {@@ -44,6 +45,7 @@ const struct nla_policy nft_hash_policy[NFTA_HASH_MAX + 1] = { [NFTA_HASH_LEN] = { .type = NLA_U32 }, [NFTA_HASH_MODULUS] = { .type = NLA_U32 }, [NFTA_HASH_SEED] = { .type = NLA_U32 }, + [NFTA_HASH_SUM] = { .type = NLA_U32 }, }; static int nft_hash_init(const struct nft_ctx *ctx,
net/netfilter/nft_hash.c static int nft_hash_init(const struct nft_ctx *ctx, · line 68
Quoted 7 lines
net/netfilter/nft_hash.c +4
-0@@ -60,6 +62,11 @@ static int nft_hash_init(const struct nft_ctx *ctx, !tb[NFTA_HASH_MODULUS])return -EINVAL ; +if (tb[NFTA_HASH_SUM ]) + priv->sum =ntohl (nla_get_be32 (tb[NFTA_HASH_SUM ])); +else + priv->sum =0 ;
There is a corner case that we should reject from the kernel, I think this is:
if (priv->sum + priv->modulus - 1 < priv->sum)
return -EOVERFLOW;We'll handle this from userspace anyway too, but I think it's easy to reject this crazy this.
Quoted 79 lines · Pablo Neira Ayuso
Quoted 67 lines · Laura Garcia Liebana
Add support to pass through an offset to the hash value. With this feature, the sysadmin is able to generate a hash with a given offset value.
Example:
meta mark set jhash ip saddr mod 2 seed 0xabcd sum 100This option generates marks according to the source address from 100 to 101.
Signed-off-by Laura Garcia Liebana <[email protected]>--- include/uapi/linux/netfilter/nf_tables.h | 2 ++ net/netfilter/nft_hash.c | 13 +++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-)include/uapi/linux/netfilter/nf_tables.h +2
-0@@ -764,6 +764,7 @@ enum nft_meta_keys {* @NFTA_HASH_LEN: source data length (NLA_U32) * @NFTA_HASH_MODULUS: modulus value (NLA_U32) * @NFTA_HASH_SEED: seed value (NLA_U32) +* @NFTA_HASH_SUM: Hash offset value (NLA_U32) */ enum nft_hash_attributes {NFTA_HASH_UNSPEC ,@@ -772,6 +773,7 @@ enum nft_hash_attributes {NFTA_HASH_LEN ,NFTA_HASH_MODULUS ,NFTA_HASH_SEED , +NFTA_HASH_SUM , __NFTA_HASH_MAX, };#define NFTA_HASH_MAX (__NFTA_HASH_MAX - 1)net/netfilter/nft_hash.c +3
-1@@ -23,6 +23,7 @@ struct nft_hash {u8 len;u32 modulus;u32 seed; +u32 sum; }; static void nft_hash_eval(const struct nft_expr *expr,@@ -35,7 +36,7 @@ static void nft_hash_eval(const struct nft_expr *expr, h =reciprocal_scale (jhash (data, priv->len, priv->seed), priv->modulus); - regs->data[priv->dreg] = h; + regs->data[priv->dreg] = priv->sum + h; }const struct nla_policy nft_hash_policy[NFTA_HASH_MAX +1 ] = {@@ -44,6 +45,7 @@ const struct nla_policy nft_hash_policy[NFTA_HASH_MAX + 1] = { [NFTA_HASH_LEN] = { .type = NLA_U32 }, [NFTA_HASH_MODULUS] = { .type = NLA_U32 }, [NFTA_HASH_SEED] = { .type = NLA_U32 }, + [NFTA_HASH_SUM] = { .type = NLA_U32 }, }; static int nft_hash_init(const struct nft_ctx *ctx,net/netfilter/nft_hash.c static int nft_hash_init(const struct nft_ctx *ctx, · line 68
Quoted 7 lines
net/netfilter/nft_hash.c +4
-0@@ -60,6 +62,11 @@ static int nft_hash_init(const struct nft_ctx *ctx, !tb[NFTA_HASH_MODULUS])return -EINVAL ; +if (tb[NFTA_HASH_SUM ]) + priv->sum =ntohl (nla_get_be32 (tb[NFTA_HASH_SUM ])); +else + priv->sum =0 ;There is a corner case that we should reject from the kernel, I think this is:
Quoted 5 lines
if (priv->sum + priv->modulus - 1 < priv->sum) return -EOVERFLOW;We'll handle this from userspace anyway too, but I think it's easy to reject this crazy this.
Such case shouldn't happen cause the modulus must be > 1. The init() provides:
priv->modulus = ntohl(nla_get_be32(tb[NFTA_HASH_MODULUS]));
if (priv->modulus <= 1)
return -ERANGE;Pablo Neira Ayuso
maintainerQuoted 86 lines · Laura Garcia
Quoted 79 lines · Pablo Neira Ayuso
Quoted 67 lines · Laura Garcia Liebana
Add support to pass through an offset to the hash value. With this feature, the sysadmin is able to generate a hash with a given offset value.
Example:
meta mark set jhash ip saddr mod 2 seed 0xabcd sum 100This option generates marks according to the source address from 100 to 101.
Signed-off-by Laura Garcia Liebana <[email protected]>--- include/uapi/linux/netfilter/nf_tables.h | 2 ++ net/netfilter/nft_hash.c | 13 +++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-)include/uapi/linux/netfilter/nf_tables.h +2
-0@@ -764,6 +764,7 @@ enum nft_meta_keys {* @NFTA_HASH_LEN: source data length (NLA_U32) * @NFTA_HASH_MODULUS: modulus value (NLA_U32) * @NFTA_HASH_SEED: seed value (NLA_U32) +* @NFTA_HASH_SUM: Hash offset value (NLA_U32) */ enum nft_hash_attributes {NFTA_HASH_UNSPEC ,@@ -772,6 +773,7 @@ enum nft_hash_attributes {NFTA_HASH_LEN ,NFTA_HASH_MODULUS ,NFTA_HASH_SEED , +NFTA_HASH_SUM , __NFTA_HASH_MAX, };#define NFTA_HASH_MAX (__NFTA_HASH_MAX - 1)net/netfilter/nft_hash.c +3
-1@@ -23,6 +23,7 @@ struct nft_hash {u8 len;u32 modulus;u32 seed; +u32 sum; }; static void nft_hash_eval(const struct nft_expr *expr,@@ -35,7 +36,7 @@ static void nft_hash_eval(const struct nft_expr *expr, h =reciprocal_scale (jhash (data, priv->len, priv->seed), priv->modulus); - regs->data[priv->dreg] = h; + regs->data[priv->dreg] = priv->sum + h; }const struct nla_policy nft_hash_policy[NFTA_HASH_MAX +1 ] = {@@ -44,6 +45,7 @@ const struct nla_policy nft_hash_policy[NFTA_HASH_MAX + 1] = { [NFTA_HASH_LEN] = { .type = NLA_U32 }, [NFTA_HASH_MODULUS] = { .type = NLA_U32 }, [NFTA_HASH_SEED] = { .type = NLA_U32 }, + [NFTA_HASH_SUM] = { .type = NLA_U32 }, }; static int nft_hash_init(const struct nft_ctx *ctx,net/netfilter/nft_hash.c static int nft_hash_init(const struct nft_ctx *ctx, · line 68
Quoted 7 lines
net/netfilter/nft_hash.c +4
-0@@ -60,6 +62,11 @@ static int nft_hash_init(const struct nft_ctx *ctx, !tb[NFTA_HASH_MODULUS])return -EINVAL ; +if (tb[NFTA_HASH_SUM ]) + priv->sum =ntohl (nla_get_be32 (tb[NFTA_HASH_SUM ])); +else + priv->sum =0 ;There is a corner case that we should reject from the kernel, I think this is:
Quoted 5 lines
if (priv->sum + priv->modulus - 1 < priv->sum) return -EOVERFLOW;We'll handle this from userspace anyway too, but I think it's easy to reject this crazy this.
Quoted 6 lines
Such case shouldn't happen cause the modulus must be > 1. The
init()provides:priv->modulus = ntohl(nla_get_be32(tb[NFTA_HASH_MODULUS])); if (priv->modulus <= 1) return -ERANGE;
I don't see how this is preventing an overflow of hash(x) + sum.