From fbf19ddf396b3526718a64e24ace316c64d3ed1f Mon Sep 17 00:00:00 2001 From: Jeremy Sowden Date: Wed, 15 Jan 2020 20:05:48 +0000 Subject: netfilter: nf_tables: white-space fixes. Indentation fixes for the parameters of a few nft functions. Signed-off-by: Jeremy Sowden Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nft_bitwise.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net/netfilter/nft_bitwise.c') diff --git a/net/netfilter/nft_bitwise.c b/net/netfilter/nft_bitwise.c index 10e9d50e4e19..e8ca1ec105f8 100644 --- a/net/netfilter/nft_bitwise.c +++ b/net/netfilter/nft_bitwise.c @@ -130,8 +130,8 @@ nla_put_failure: static struct nft_data zero; static int nft_bitwise_offload(struct nft_offload_ctx *ctx, - struct nft_flow_rule *flow, - const struct nft_expr *expr) + struct nft_flow_rule *flow, + const struct nft_expr *expr) { const struct nft_bitwise *priv = nft_expr_priv(expr); struct nft_offload_reg *reg = &ctx->regs[priv->dreg]; -- cgit v1.2.3 From 265ec7b0e8c35ea70e694da43aa8896e2614def9 Mon Sep 17 00:00:00 2001 From: Jeremy Sowden Date: Wed, 15 Jan 2020 20:05:49 +0000 Subject: netfilter: bitwise: remove NULL comparisons from attribute checks. In later patches, we will be adding more checks. In order to be consistent and prevent complaints from checkpatch.pl, replace the existing comparisons with NULL with logical NOT operators. Signed-off-by: Jeremy Sowden Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nft_bitwise.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'net/netfilter/nft_bitwise.c') diff --git a/net/netfilter/nft_bitwise.c b/net/netfilter/nft_bitwise.c index e8ca1ec105f8..85605fb1e360 100644 --- a/net/netfilter/nft_bitwise.c +++ b/net/netfilter/nft_bitwise.c @@ -52,11 +52,11 @@ static int nft_bitwise_init(const struct nft_ctx *ctx, u32 len; int err; - if (tb[NFTA_BITWISE_SREG] == NULL || - tb[NFTA_BITWISE_DREG] == NULL || - tb[NFTA_BITWISE_LEN] == NULL || - tb[NFTA_BITWISE_MASK] == NULL || - tb[NFTA_BITWISE_XOR] == NULL) + if (!tb[NFTA_BITWISE_SREG] || + !tb[NFTA_BITWISE_DREG] || + !tb[NFTA_BITWISE_LEN] || + !tb[NFTA_BITWISE_MASK] || + !tb[NFTA_BITWISE_XOR]) return -EINVAL; err = nft_parse_u32_check(tb[NFTA_BITWISE_LEN], U8_MAX, &len); -- cgit v1.2.3 From 577c734a81e2f59aa4490071ebe074fc05d5540b Mon Sep 17 00:00:00 2001 From: Jeremy Sowden Date: Wed, 15 Jan 2020 20:05:50 +0000 Subject: netfilter: bitwise: replace gotos with returns. When dumping a bitwise expression, if any of the puts fails, we use goto to jump to a label. However, no clean-up is required and the only statement at the label is a return. Drop the goto's and return immediately instead. Signed-off-by: Jeremy Sowden Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nft_bitwise.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'net/netfilter/nft_bitwise.c') diff --git a/net/netfilter/nft_bitwise.c b/net/netfilter/nft_bitwise.c index 85605fb1e360..c15e9beb5243 100644 --- a/net/netfilter/nft_bitwise.c +++ b/net/netfilter/nft_bitwise.c @@ -107,24 +107,21 @@ static int nft_bitwise_dump(struct sk_buff *skb, const struct nft_expr *expr) const struct nft_bitwise *priv = nft_expr_priv(expr); if (nft_dump_register(skb, NFTA_BITWISE_SREG, priv->sreg)) - goto nla_put_failure; + return -1; if (nft_dump_register(skb, NFTA_BITWISE_DREG, priv->dreg)) - goto nla_put_failure; + return -1; if (nla_put_be32(skb, NFTA_BITWISE_LEN, htonl(priv->len))) - goto nla_put_failure; + return -1; if (nft_data_dump(skb, NFTA_BITWISE_MASK, &priv->mask, NFT_DATA_VALUE, priv->len) < 0) - goto nla_put_failure; + return -1; if (nft_data_dump(skb, NFTA_BITWISE_XOR, &priv->xor, NFT_DATA_VALUE, priv->len) < 0) - goto nla_put_failure; + return -1; return 0; - -nla_put_failure: - return -1; } static struct nft_data zero; -- cgit v1.2.3 From 9d1f979986c2e29632b6a8f7a8ef8b3c7d24a48c Mon Sep 17 00:00:00 2001 From: Jeremy Sowden Date: Wed, 15 Jan 2020 20:05:51 +0000 Subject: netfilter: bitwise: add NFTA_BITWISE_OP netlink attribute. Add a new bitwise netlink attribute, NFTA_BITWISE_OP, which is set to a value of a new enum, nft_bitwise_ops. It describes the type of operation an expression contains. Currently, it only has one value: NFT_BITWISE_BOOL. More values will be added later to implement shifts. Signed-off-by: Jeremy Sowden Signed-off-by: Pablo Neira Ayuso --- include/uapi/linux/netfilter/nf_tables.h | 12 ++++++++++++ net/netfilter/nft_bitwise.c | 16 ++++++++++++++++ 2 files changed, 28 insertions(+) (limited to 'net/netfilter/nft_bitwise.c') diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h index dd4611767933..0cddf357281f 100644 --- a/include/uapi/linux/netfilter/nf_tables.h +++ b/include/uapi/linux/netfilter/nf_tables.h @@ -484,6 +484,16 @@ enum nft_immediate_attributes { }; #define NFTA_IMMEDIATE_MAX (__NFTA_IMMEDIATE_MAX - 1) +/** + * enum nft_bitwise_ops - nf_tables bitwise operations + * + * @NFT_BITWISE_BOOL: mask-and-xor operation used to implement NOT, AND, OR and + * XOR boolean operations + */ +enum nft_bitwise_ops { + NFT_BITWISE_BOOL, +}; + /** * enum nft_bitwise_attributes - nf_tables bitwise expression netlink attributes * @@ -492,6 +502,7 @@ enum nft_immediate_attributes { * @NFTA_BITWISE_LEN: length of operands (NLA_U32) * @NFTA_BITWISE_MASK: mask value (NLA_NESTED: nft_data_attributes) * @NFTA_BITWISE_XOR: xor value (NLA_NESTED: nft_data_attributes) + * @NFTA_BITWISE_OP: type of operation (NLA_U32: nft_bitwise_ops) * * The bitwise expression performs the following operation: * @@ -512,6 +523,7 @@ enum nft_bitwise_attributes { NFTA_BITWISE_LEN, NFTA_BITWISE_MASK, NFTA_BITWISE_XOR, + NFTA_BITWISE_OP, __NFTA_BITWISE_MAX }; #define NFTA_BITWISE_MAX (__NFTA_BITWISE_MAX - 1) diff --git a/net/netfilter/nft_bitwise.c b/net/netfilter/nft_bitwise.c index c15e9beb5243..6948df7b0587 100644 --- a/net/netfilter/nft_bitwise.c +++ b/net/netfilter/nft_bitwise.c @@ -18,6 +18,7 @@ struct nft_bitwise { enum nft_registers sreg:8; enum nft_registers dreg:8; + enum nft_bitwise_ops op:8; u8 len; struct nft_data mask; struct nft_data xor; @@ -41,6 +42,7 @@ static const struct nla_policy nft_bitwise_policy[NFTA_BITWISE_MAX + 1] = { [NFTA_BITWISE_LEN] = { .type = NLA_U32 }, [NFTA_BITWISE_MASK] = { .type = NLA_NESTED }, [NFTA_BITWISE_XOR] = { .type = NLA_NESTED }, + [NFTA_BITWISE_OP] = { .type = NLA_U32 }, }; static int nft_bitwise_init(const struct nft_ctx *ctx, @@ -76,6 +78,18 @@ static int nft_bitwise_init(const struct nft_ctx *ctx, if (err < 0) return err; + if (tb[NFTA_BITWISE_OP]) { + priv->op = ntohl(nla_get_be32(tb[NFTA_BITWISE_OP])); + switch (priv->op) { + case NFT_BITWISE_BOOL: + break; + default: + return -EOPNOTSUPP; + } + } else { + priv->op = NFT_BITWISE_BOOL; + } + err = nft_data_init(NULL, &priv->mask, sizeof(priv->mask), &d1, tb[NFTA_BITWISE_MASK]); if (err < 0) @@ -112,6 +126,8 @@ static int nft_bitwise_dump(struct sk_buff *skb, const struct nft_expr *expr) return -1; if (nla_put_be32(skb, NFTA_BITWISE_LEN, htonl(priv->len))) return -1; + if (nla_put_be32(skb, NFTA_BITWISE_OP, htonl(priv->op))) + return -1; if (nft_data_dump(skb, NFTA_BITWISE_MASK, &priv->mask, NFT_DATA_VALUE, priv->len) < 0) -- cgit v1.2.3 From 3f8d9eb032ec76c35344a2453c4c4a0a29805e3f Mon Sep 17 00:00:00 2001 From: Jeremy Sowden Date: Wed, 15 Jan 2020 20:05:52 +0000 Subject: netfilter: bitwise: add helper for initializing boolean operations. Split the code specific to initializing bitwise boolean operations out into a separate function. A similar function will be added later for shift operations. Signed-off-by: Jeremy Sowden Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nft_bitwise.c | 66 ++++++++++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 25 deletions(-) (limited to 'net/netfilter/nft_bitwise.c') diff --git a/net/netfilter/nft_bitwise.c b/net/netfilter/nft_bitwise.c index 6948df7b0587..d0cc5f753e52 100644 --- a/net/netfilter/nft_bitwise.c +++ b/net/netfilter/nft_bitwise.c @@ -45,20 +45,53 @@ static const struct nla_policy nft_bitwise_policy[NFTA_BITWISE_MAX + 1] = { [NFTA_BITWISE_OP] = { .type = NLA_U32 }, }; +static int nft_bitwise_init_bool(struct nft_bitwise *priv, + const struct nlattr *const tb[]) +{ + struct nft_data_desc d1, d2; + int err; + + if (!tb[NFTA_BITWISE_MASK] || + !tb[NFTA_BITWISE_XOR]) + return -EINVAL; + + err = nft_data_init(NULL, &priv->mask, sizeof(priv->mask), &d1, + tb[NFTA_BITWISE_MASK]); + if (err < 0) + return err; + if (d1.type != NFT_DATA_VALUE || d1.len != priv->len) { + err = -EINVAL; + goto err1; + } + + err = nft_data_init(NULL, &priv->xor, sizeof(priv->xor), &d2, + tb[NFTA_BITWISE_XOR]); + if (err < 0) + goto err1; + if (d2.type != NFT_DATA_VALUE || d2.len != priv->len) { + err = -EINVAL; + goto err2; + } + + return 0; +err2: + nft_data_release(&priv->xor, d2.type); +err1: + nft_data_release(&priv->mask, d1.type); + return err; +} + static int nft_bitwise_init(const struct nft_ctx *ctx, const struct nft_expr *expr, const struct nlattr * const tb[]) { struct nft_bitwise *priv = nft_expr_priv(expr); - struct nft_data_desc d1, d2; u32 len; int err; if (!tb[NFTA_BITWISE_SREG] || !tb[NFTA_BITWISE_DREG] || - !tb[NFTA_BITWISE_LEN] || - !tb[NFTA_BITWISE_MASK] || - !tb[NFTA_BITWISE_XOR]) + !tb[NFTA_BITWISE_LEN]) return -EINVAL; err = nft_parse_u32_check(tb[NFTA_BITWISE_LEN], U8_MAX, &len); @@ -90,29 +123,12 @@ static int nft_bitwise_init(const struct nft_ctx *ctx, priv->op = NFT_BITWISE_BOOL; } - err = nft_data_init(NULL, &priv->mask, sizeof(priv->mask), &d1, - tb[NFTA_BITWISE_MASK]); - if (err < 0) - return err; - if (d1.type != NFT_DATA_VALUE || d1.len != priv->len) { - err = -EINVAL; - goto err1; - } - - err = nft_data_init(NULL, &priv->xor, sizeof(priv->xor), &d2, - tb[NFTA_BITWISE_XOR]); - if (err < 0) - goto err1; - if (d2.type != NFT_DATA_VALUE || d2.len != priv->len) { - err = -EINVAL; - goto err2; + switch(priv->op) { + case NFT_BITWISE_BOOL: + err = nft_bitwise_init_bool(priv, tb); + break; } - return 0; -err2: - nft_data_release(&priv->xor, d2.type); -err1: - nft_data_release(&priv->mask, d1.type); return err; } -- cgit v1.2.3 From 71d6ded3ac496f9a6563752917921b7db0f38a34 Mon Sep 17 00:00:00 2001 From: Jeremy Sowden Date: Wed, 15 Jan 2020 20:05:53 +0000 Subject: netfilter: bitwise: add helper for evaluating boolean operations. Split the code specific to evaluating bitwise boolean operations out into a separate function. Similar functions will be added later for shift operations. Signed-off-by: Jeremy Sowden Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nft_bitwise.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'net/netfilter/nft_bitwise.c') diff --git a/net/netfilter/nft_bitwise.c b/net/netfilter/nft_bitwise.c index d0cc5f753e52..88a91c63f213 100644 --- a/net/netfilter/nft_bitwise.c +++ b/net/netfilter/nft_bitwise.c @@ -24,16 +24,27 @@ struct nft_bitwise { struct nft_data xor; }; +static void nft_bitwise_eval_bool(u32 *dst, const u32 *src, + const struct nft_bitwise *priv) +{ + unsigned int i; + + for (i = 0; i < DIV_ROUND_UP(priv->len, 4); i++) + dst[i] = (src[i] & priv->mask.data[i]) ^ priv->xor.data[i]; +} + void nft_bitwise_eval(const struct nft_expr *expr, struct nft_regs *regs, const struct nft_pktinfo *pkt) { const struct nft_bitwise *priv = nft_expr_priv(expr); const u32 *src = ®s->data[priv->sreg]; u32 *dst = ®s->data[priv->dreg]; - unsigned int i; - for (i = 0; i < DIV_ROUND_UP(priv->len, 4); i++) - dst[i] = (src[i] & priv->mask.data[i]) ^ priv->xor.data[i]; + switch (priv->op) { + case NFT_BITWISE_BOOL: + nft_bitwise_eval_bool(dst, src, priv); + break; + } } static const struct nla_policy nft_bitwise_policy[NFTA_BITWISE_MAX + 1] = { -- cgit v1.2.3 From 4d57ca2be146bdb272b57892ec59cd273f9ef3fc Mon Sep 17 00:00:00 2001 From: Jeremy Sowden Date: Wed, 15 Jan 2020 20:05:54 +0000 Subject: netfilter: bitwise: add helper for dumping boolean operations. Split the code specific to dumping bitwise boolean operations out into a separate function. A similar function will be added later for shift operations. Signed-off-by: Jeremy Sowden Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nft_bitwise.c | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) (limited to 'net/netfilter/nft_bitwise.c') diff --git a/net/netfilter/nft_bitwise.c b/net/netfilter/nft_bitwise.c index 88a91c63f213..41265134cf0b 100644 --- a/net/netfilter/nft_bitwise.c +++ b/net/netfilter/nft_bitwise.c @@ -143,9 +143,24 @@ static int nft_bitwise_init(const struct nft_ctx *ctx, return err; } +static int nft_bitwise_dump_bool(struct sk_buff *skb, + const struct nft_bitwise *priv) +{ + if (nft_data_dump(skb, NFTA_BITWISE_MASK, &priv->mask, + NFT_DATA_VALUE, priv->len) < 0) + return -1; + + if (nft_data_dump(skb, NFTA_BITWISE_XOR, &priv->xor, + NFT_DATA_VALUE, priv->len) < 0) + return -1; + + return 0; +} + static int nft_bitwise_dump(struct sk_buff *skb, const struct nft_expr *expr) { const struct nft_bitwise *priv = nft_expr_priv(expr); + int err = 0; if (nft_dump_register(skb, NFTA_BITWISE_SREG, priv->sreg)) return -1; @@ -156,15 +171,13 @@ static int nft_bitwise_dump(struct sk_buff *skb, const struct nft_expr *expr) if (nla_put_be32(skb, NFTA_BITWISE_OP, htonl(priv->op))) return -1; - if (nft_data_dump(skb, NFTA_BITWISE_MASK, &priv->mask, - NFT_DATA_VALUE, priv->len) < 0) - return -1; - - if (nft_data_dump(skb, NFTA_BITWISE_XOR, &priv->xor, - NFT_DATA_VALUE, priv->len) < 0) - return -1; + switch (priv->op) { + case NFT_BITWISE_BOOL: + err = nft_bitwise_dump_bool(skb, priv); + break; + } - return 0; + return err; } static struct nft_data zero; -- cgit v1.2.3 From ed991d43634b11e759a800850ba9656b5b467a56 Mon Sep 17 00:00:00 2001 From: Jeremy Sowden Date: Wed, 15 Jan 2020 20:05:55 +0000 Subject: netfilter: bitwise: only offload boolean operations. Only boolean operations supports offloading, so check the type of the operation and return an error for other types. Signed-off-by: Jeremy Sowden Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nft_bitwise.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'net/netfilter/nft_bitwise.c') diff --git a/net/netfilter/nft_bitwise.c b/net/netfilter/nft_bitwise.c index 41265134cf0b..b4619d9989ea 100644 --- a/net/netfilter/nft_bitwise.c +++ b/net/netfilter/nft_bitwise.c @@ -189,6 +189,9 @@ static int nft_bitwise_offload(struct nft_offload_ctx *ctx, const struct nft_bitwise *priv = nft_expr_priv(expr); struct nft_offload_reg *reg = &ctx->regs[priv->dreg]; + if (priv->op != NFT_BITWISE_BOOL) + return -EOPNOTSUPP; + if (memcmp(&priv->xor, &zero, sizeof(priv->xor)) || priv->sreg != priv->dreg || priv->len != reg->len) return -EOPNOTSUPP; -- cgit v1.2.3 From 779f725e142cd987a69296c0eb7d416ee3ba57dd Mon Sep 17 00:00:00 2001 From: Jeremy Sowden Date: Wed, 15 Jan 2020 20:05:56 +0000 Subject: netfilter: bitwise: add NFTA_BITWISE_DATA attribute. Add a new bitwise netlink attribute that will be used by shift operations to store the size of the shift. It is not used by boolean operations. Signed-off-by: Jeremy Sowden Signed-off-by: Pablo Neira Ayuso --- include/uapi/linux/netfilter/nf_tables.h | 3 +++ net/netfilter/nft_bitwise.c | 5 +++++ 2 files changed, 8 insertions(+) (limited to 'net/netfilter/nft_bitwise.c') diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h index 0cddf357281f..8bef0620bc4f 100644 --- a/include/uapi/linux/netfilter/nf_tables.h +++ b/include/uapi/linux/netfilter/nf_tables.h @@ -503,6 +503,8 @@ enum nft_bitwise_ops { * @NFTA_BITWISE_MASK: mask value (NLA_NESTED: nft_data_attributes) * @NFTA_BITWISE_XOR: xor value (NLA_NESTED: nft_data_attributes) * @NFTA_BITWISE_OP: type of operation (NLA_U32: nft_bitwise_ops) + * @NFTA_BITWISE_DATA: argument for non-boolean operations + * (NLA_NESTED: nft_data_attributes) * * The bitwise expression performs the following operation: * @@ -524,6 +526,7 @@ enum nft_bitwise_attributes { NFTA_BITWISE_MASK, NFTA_BITWISE_XOR, NFTA_BITWISE_OP, + NFTA_BITWISE_DATA, __NFTA_BITWISE_MAX }; #define NFTA_BITWISE_MAX (__NFTA_BITWISE_MAX - 1) diff --git a/net/netfilter/nft_bitwise.c b/net/netfilter/nft_bitwise.c index b4619d9989ea..744008a527fb 100644 --- a/net/netfilter/nft_bitwise.c +++ b/net/netfilter/nft_bitwise.c @@ -22,6 +22,7 @@ struct nft_bitwise { u8 len; struct nft_data mask; struct nft_data xor; + struct nft_data data; }; static void nft_bitwise_eval_bool(u32 *dst, const u32 *src, @@ -54,6 +55,7 @@ static const struct nla_policy nft_bitwise_policy[NFTA_BITWISE_MAX + 1] = { [NFTA_BITWISE_MASK] = { .type = NLA_NESTED }, [NFTA_BITWISE_XOR] = { .type = NLA_NESTED }, [NFTA_BITWISE_OP] = { .type = NLA_U32 }, + [NFTA_BITWISE_DATA] = { .type = NLA_NESTED }, }; static int nft_bitwise_init_bool(struct nft_bitwise *priv, @@ -62,6 +64,9 @@ static int nft_bitwise_init_bool(struct nft_bitwise *priv, struct nft_data_desc d1, d2; int err; + if (tb[NFTA_BITWISE_DATA]) + return -EINVAL; + if (!tb[NFTA_BITWISE_MASK] || !tb[NFTA_BITWISE_XOR]) return -EINVAL; -- cgit v1.2.3 From 567d746b55bc66d3800c9ae91d50f0c5deb2fd93 Mon Sep 17 00:00:00 2001 From: Jeremy Sowden Date: Wed, 15 Jan 2020 20:05:57 +0000 Subject: netfilter: bitwise: add support for shifts. Hitherto nft_bitwise has only supported boolean operations: NOT, AND, OR and XOR. Extend it to do shifts as well. Signed-off-by: Jeremy Sowden Signed-off-by: Pablo Neira Ayuso --- include/uapi/linux/netfilter/nf_tables.h | 9 +++- net/netfilter/nft_bitwise.c | 77 ++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 2 deletions(-) (limited to 'net/netfilter/nft_bitwise.c') diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h index 8bef0620bc4f..261864736b26 100644 --- a/include/uapi/linux/netfilter/nf_tables.h +++ b/include/uapi/linux/netfilter/nf_tables.h @@ -489,9 +489,13 @@ enum nft_immediate_attributes { * * @NFT_BITWISE_BOOL: mask-and-xor operation used to implement NOT, AND, OR and * XOR boolean operations + * @NFT_BITWISE_LSHIFT: left-shift operation + * @NFT_BITWISE_RSHIFT: right-shift operation */ enum nft_bitwise_ops { NFT_BITWISE_BOOL, + NFT_BITWISE_LSHIFT, + NFT_BITWISE_RSHIFT, }; /** @@ -506,11 +510,12 @@ enum nft_bitwise_ops { * @NFTA_BITWISE_DATA: argument for non-boolean operations * (NLA_NESTED: nft_data_attributes) * - * The bitwise expression performs the following operation: + * The bitwise expression supports boolean and shift operations. It implements + * the boolean operations by performing the following operation: * * dreg = (sreg & mask) ^ xor * - * which allow to express all bitwise operations: + * with these mask and xor values: * * mask xor * NOT: 1 1 diff --git a/net/netfilter/nft_bitwise.c b/net/netfilter/nft_bitwise.c index 744008a527fb..0ed2281f03be 100644 --- a/net/netfilter/nft_bitwise.c +++ b/net/netfilter/nft_bitwise.c @@ -34,6 +34,32 @@ static void nft_bitwise_eval_bool(u32 *dst, const u32 *src, dst[i] = (src[i] & priv->mask.data[i]) ^ priv->xor.data[i]; } +static void nft_bitwise_eval_lshift(u32 *dst, const u32 *src, + const struct nft_bitwise *priv) +{ + u32 shift = priv->data.data[0]; + unsigned int i; + u32 carry = 0; + + for (i = DIV_ROUND_UP(priv->len, sizeof(u32)); i > 0; i--) { + dst[i - 1] = (src[i - 1] << shift) | carry; + carry = src[i - 1] >> (BITS_PER_TYPE(u32) - shift); + } +} + +static void nft_bitwise_eval_rshift(u32 *dst, const u32 *src, + const struct nft_bitwise *priv) +{ + u32 shift = priv->data.data[0]; + unsigned int i; + u32 carry = 0; + + for (i = 0; i < DIV_ROUND_UP(priv->len, sizeof(u32)); i++) { + dst[i] = carry | (src[i] >> shift); + carry = src[i] << (BITS_PER_TYPE(u32) - shift); + } +} + void nft_bitwise_eval(const struct nft_expr *expr, struct nft_regs *regs, const struct nft_pktinfo *pkt) { @@ -45,6 +71,12 @@ void nft_bitwise_eval(const struct nft_expr *expr, case NFT_BITWISE_BOOL: nft_bitwise_eval_bool(dst, src, priv); break; + case NFT_BITWISE_LSHIFT: + nft_bitwise_eval_lshift(dst, src, priv); + break; + case NFT_BITWISE_RSHIFT: + nft_bitwise_eval_rshift(dst, src, priv); + break; } } @@ -97,6 +129,32 @@ err1: return err; } +static int nft_bitwise_init_shift(struct nft_bitwise *priv, + const struct nlattr *const tb[]) +{ + struct nft_data_desc d; + int err; + + if (tb[NFTA_BITWISE_MASK] || + tb[NFTA_BITWISE_XOR]) + return -EINVAL; + + if (!tb[NFTA_BITWISE_DATA]) + return -EINVAL; + + err = nft_data_init(NULL, &priv->data, sizeof(priv->data), &d, + tb[NFTA_BITWISE_DATA]); + if (err < 0) + return err; + if (d.type != NFT_DATA_VALUE || d.len != sizeof(u32) || + priv->data.data[0] >= BITS_PER_TYPE(u32)) { + nft_data_release(&priv->data, d.type); + return -EINVAL; + } + + return 0; +} + static int nft_bitwise_init(const struct nft_ctx *ctx, const struct nft_expr *expr, const struct nlattr * const tb[]) @@ -131,6 +189,8 @@ static int nft_bitwise_init(const struct nft_ctx *ctx, priv->op = ntohl(nla_get_be32(tb[NFTA_BITWISE_OP])); switch (priv->op) { case NFT_BITWISE_BOOL: + case NFT_BITWISE_LSHIFT: + case NFT_BITWISE_RSHIFT: break; default: return -EOPNOTSUPP; @@ -143,6 +203,10 @@ static int nft_bitwise_init(const struct nft_ctx *ctx, case NFT_BITWISE_BOOL: err = nft_bitwise_init_bool(priv, tb); break; + case NFT_BITWISE_LSHIFT: + case NFT_BITWISE_RSHIFT: + err = nft_bitwise_init_shift(priv, tb); + break; } return err; @@ -162,6 +226,15 @@ static int nft_bitwise_dump_bool(struct sk_buff *skb, return 0; } +static int nft_bitwise_dump_shift(struct sk_buff *skb, + const struct nft_bitwise *priv) +{ + if (nft_data_dump(skb, NFTA_BITWISE_DATA, &priv->data, + NFT_DATA_VALUE, sizeof(u32)) < 0) + return -1; + return 0; +} + static int nft_bitwise_dump(struct sk_buff *skb, const struct nft_expr *expr) { const struct nft_bitwise *priv = nft_expr_priv(expr); @@ -180,6 +253,10 @@ static int nft_bitwise_dump(struct sk_buff *skb, const struct nft_expr *expr) case NFT_BITWISE_BOOL: err = nft_bitwise_dump_bool(skb, priv); break; + case NFT_BITWISE_LSHIFT: + case NFT_BITWISE_RSHIFT: + err = nft_bitwise_dump_shift(skb, priv); + break; } return err; -- cgit v1.2.3