summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJeremy Sowden <jeremy@azazel.net>2020-02-24 13:12:01 +0000
committerPablo Neira Ayuso <pablo@netfilter.org>2020-03-02 13:09:19 +0100
commit75b8778e5bf630a3fc13e5d76bc64838135f02a9 (patch)
tree6cf4ad4b3d79c9d8faab6969717244fdf822c827 /src
parent8db0a9417b04f40bffb4d026eca9708e5757e5a4 (diff)
bitwise: add support for passing mask and xor via registers.
The kernel supports passing mask and xor values for bitwise boolean operations via registers. These are mutually exclusive with the existing data attributes: e.g., setting both NFTA_EXPR_BITWISE_MASK and NFTA_EXPR_BITWISE_MREG is an error. Add support to libnftnl. Signed-off-by: Jeremy Sowden <jeremy@azazel.net> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src')
-rw-r--r--src/expr/bitwise.c60
1 files changed, 54 insertions, 6 deletions
diff --git a/src/expr/bitwise.c b/src/expr/bitwise.c
index 9ea2f66..1ad4f08 100644
--- a/src/expr/bitwise.c
+++ b/src/expr/bitwise.c
@@ -29,6 +29,8 @@ struct nftnl_expr_bitwise {
union nftnl_data_reg mask;
union nftnl_data_reg xor;
union nftnl_data_reg data;
+ enum nft_registers mreg;
+ enum nft_registers xreg;
};
static int
@@ -51,10 +53,14 @@ nftnl_expr_bitwise_set(struct nftnl_expr *e, uint16_t type,
memcpy(&bitwise->len, data, sizeof(bitwise->len));
break;
case NFTNL_EXPR_BITWISE_MASK:
+ if (e->flags & (1 << NFTNL_EXPR_BITWISE_MREG))
+ return -1;
memcpy(&bitwise->mask.val, data, data_len);
bitwise->mask.len = data_len;
break;
case NFTNL_EXPR_BITWISE_XOR:
+ if (e->flags & (1 << NFTNL_EXPR_BITWISE_XREG))
+ return -1;
memcpy(&bitwise->xor.val, data, data_len);
bitwise->xor.len = data_len;
break;
@@ -62,6 +68,16 @@ nftnl_expr_bitwise_set(struct nftnl_expr *e, uint16_t type,
memcpy(&bitwise->data.val, data, data_len);
bitwise->data.len = data_len;
break;
+ case NFTNL_EXPR_BITWISE_MREG:
+ if (e->flags & (1 << NFTNL_EXPR_BITWISE_MASK))
+ return -1;
+ memcpy(&bitwise->mreg, data, sizeof(bitwise->mreg));
+ break;
+ case NFTNL_EXPR_BITWISE_XREG:
+ if (e->flags & (1 << NFTNL_EXPR_BITWISE_XOR))
+ return -1;
+ memcpy(&bitwise->xreg, data, sizeof(bitwise->xreg));
+ break;
default:
return -1;
}
@@ -96,6 +112,12 @@ nftnl_expr_bitwise_get(const struct nftnl_expr *e, uint16_t type,
case NFTNL_EXPR_BITWISE_DATA:
*data_len = bitwise->data.len;
return &bitwise->data.val;
+ case NFTNL_EXPR_BITWISE_MREG:
+ *data_len = sizeof(bitwise->mreg);
+ return &bitwise->mreg;
+ case NFTNL_EXPR_BITWISE_XREG:
+ *data_len = sizeof(bitwise->xreg);
+ return &bitwise->xreg;
}
return NULL;
}
@@ -113,6 +135,8 @@ static int nftnl_expr_bitwise_cb(const struct nlattr *attr, void *data)
case NFTA_BITWISE_DREG:
case NFTA_BITWISE_OP:
case NFTA_BITWISE_LEN:
+ case NFTA_BITWISE_MREG:
+ case NFTA_BITWISE_XREG:
if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
abi_breakage();
break;
@@ -165,6 +189,10 @@ nftnl_expr_bitwise_build(struct nlmsghdr *nlh, const struct nftnl_expr *e)
bitwise->data.val);
mnl_attr_nest_end(nlh, nest);
}
+ if (e->flags & (1 << NFTNL_EXPR_BITWISE_MREG))
+ mnl_attr_put_u32(nlh, NFTA_BITWISE_MREG, htonl(bitwise->mreg));
+ if (e->flags & (1 << NFTNL_EXPR_BITWISE_XREG))
+ mnl_attr_put_u32(nlh, NFTA_BITWISE_XREG, htonl(bitwise->xreg));
}
static int
@@ -205,13 +233,22 @@ nftnl_expr_bitwise_parse(struct nftnl_expr *e, struct nlattr *attr)
ret = nftnl_parse_data(&bitwise->data, tb[NFTA_BITWISE_DATA], NULL);
e->flags |= (1 << NFTNL_EXPR_BITWISE_DATA);
}
+ if (tb[NFTA_BITWISE_MREG]) {
+ bitwise->mreg = ntohl(mnl_attr_get_u32(tb[NFTA_BITWISE_MREG]));
+ e->flags |= (1 << NFTNL_EXPR_BITWISE_MREG);
+ }
+ if (tb[NFTA_BITWISE_XREG]) {
+ bitwise->xreg = ntohl(mnl_attr_get_u32(tb[NFTA_BITWISE_XREG]));
+ e->flags |= (1 << NFTNL_EXPR_BITWISE_XREG);
+ }
return ret;
}
static int
nftnl_expr_bitwise_snprintf_bool(char *buf, size_t size,
- const struct nftnl_expr_bitwise *bitwise)
+ const struct nftnl_expr_bitwise *bitwise,
+ uint32_t flags)
{
int remain = size, offset = 0, ret;
@@ -219,15 +256,25 @@ nftnl_expr_bitwise_snprintf_bool(char *buf, size_t size,
bitwise->dreg, bitwise->sreg);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
- ret = nftnl_data_reg_snprintf(buf + offset, remain, &bitwise->mask,
- NFTNL_OUTPUT_DEFAULT, 0, DATA_VALUE);
+ if (flags & (1 << NFTA_BITWISE_MASK))
+ ret = nftnl_data_reg_snprintf(buf + offset, remain,
+ &bitwise->mask,
+ NFTNL_OUTPUT_DEFAULT, 0,
+ DATA_VALUE);
+ else
+ ret = snprintf(buf + offset, remain, "reg %u ", bitwise->mreg);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
ret = snprintf(buf + offset, remain, ") ^ ");
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
- ret = nftnl_data_reg_snprintf(buf + offset, remain, &bitwise->xor,
- NFTNL_OUTPUT_DEFAULT, 0, DATA_VALUE);
+ if (flags & (1 << NFTA_BITWISE_XOR))
+ ret = nftnl_data_reg_snprintf(buf + offset, remain,
+ &bitwise->xor,
+ NFTNL_OUTPUT_DEFAULT, 0,
+ DATA_VALUE);
+ else
+ ret = snprintf(buf + offset, remain, "reg %u ", bitwise->xreg);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
return offset;
@@ -260,7 +307,8 @@ static int nftnl_expr_bitwise_snprintf_default(char *buf, size_t size,
switch (bitwise->op) {
case NFT_BITWISE_BOOL:
- err = nftnl_expr_bitwise_snprintf_bool(buf, size, bitwise);
+ err = nftnl_expr_bitwise_snprintf_bool(buf, size, bitwise,
+ e->flags);
break;
case NFT_BITWISE_LSHIFT:
err = nftnl_expr_bitwise_snprintf_shift(buf, size, "<<", bitwise);