On Wed, Aug 10, 2016 at 11:43:36AM +0200, Laura Garcia Liebana wrote: > diff --git a/net/netfilter/nft_hash.c b/net/netfilter/nft_hash.c > new file mode 100644 > index 0000000..d0069eb > --- /dev/null > +++ b/net/netfilter/nft_hash.c > @@ -0,0 +1,141 @@ > +/* > + * Copyright (c) 2016 Laura Garcia <nevola@xxxxxxxxx> > + * > + * 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 <linux/kernel.h> > +#include <linux/init.h> > +#include <linux/module.h> > +#include <linux/netlink.h> > +#include <linux/netfilter.h> > +#include <linux/netfilter/nf_tables.h> > +#include <net/netfilter/nf_tables.h> > +#include <net/netfilter/nf_tables_core.h> > +#include <linux/jhash.h> > + > +struct nft_hash { > + enum nft_registers sreg:8; > + enum nft_registers dreg:8; > + u8 len; > + u32 modulus; > + u32 seed; > +}; > + > +static void nft_hash_eval(const struct nft_expr *expr, > + struct nft_regs *regs, > + const struct nft_pktinfo *pkt) > +{ > + struct nft_hash *priv = nft_expr_priv(expr); > + const void *data = ®s->data[priv->sreg]; > + u32 h; > + > + h = reciprocal_scale(jhash(data, priv->len, priv->seed), priv->modulus); > + > + regs->data[priv->dreg] = h; > +} > + > +const struct nla_policy nft_hash_policy[NFTA_HASH_MAX + 1] = { > + [NFTA_HASH_SREG] = { .type = NLA_U32 }, > + [NFTA_HASH_DREG] = { .type = NLA_U32 }, > + [NFTA_HASH_LEN] = { .type = NLA_U32 }, > + [NFTA_HASH_MODULUS] = { .type = NLA_U32 }, > + [NFTA_HASH_SEED] = { .type = NLA_U32 }, > +}; > + > +static int nft_hash_init(const struct nft_ctx *ctx, > + const struct nft_expr *expr, > + const struct nlattr * const tb[]) > +{ > + struct nft_hash *priv = nft_expr_priv(expr); > + u32 len; > + u32 seed = 0; > + > + if (!tb[NFTA_HASH_SREG] || > + !tb[NFTA_HASH_DREG] || > + !tb[NFTA_HASH_LEN] || > + !tb[NFTA_HASH_MODULUS]) > + return -EINVAL; > + > + priv->sreg = nft_parse_register(tb[NFTA_HASH_SREG]); > + priv->dreg = nft_parse_register(tb[NFTA_HASH_DREG]); > + > + len = ntohl(nla_get_be32(tb[NFTA_HASH_LEN])); > + if (len == 0 || len > U8_MAX) > + return -EINVAL; Use return -ERANGE here so we get in sync with lib/nlattr.c policy validation, that returns this error for values out of range. > + > + priv->len = len; > + > + priv->modulus = ntohl(nla_get_be32(tb[NFTA_HASH_MODULUS])); > + if (priv->modulus <= 1) > + return -EINVAL; Use return -ERANGE instead. > + > + if (tb[NFTA_HASH_LEN]) typo here, this should be NFTA_HASH_SEED. > + seed = ntohl(nla_get_be32(tb[NFTA_HASH_SEED])); I don't see any benefit from making this optional, worst case userspace can pass zero to us, right? > + > + priv->seed = seed; > + > + return nft_validate_register_store(ctx, priv->sreg, NULL, This should be a validate_register_load instead. > + NFT_DATA_VALUE, len) && > + nft_validate_register_store(ctx, priv->dreg, NULL, ^ Comestic: If you do this, you have to get this aligned with the line above tabs and then spaces, ie. return nft_validate_register_store(ctx, priv->sreg, NULL, NFT_DATA_VALUE, len) && nft_validate_register_store(ctx, priv->dreg, NULL, Anyway, the code above needs a respin. > + NFT_DATA_VALUE, sizeof(u32)); > +} Thanks. -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html