diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2022-03-28 17:53:39 +0200 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2022-03-29 10:33:40 +0200 |
commit | 64bb3f43bb96bb43a478f695f5aea5f4ab50fd4b (patch) | |
tree | 3da0c0f453a9842bbd74adca383637773f0efca6 /src/payload.c | |
parent | ff0f30e35db56da4282a477df0f334ce636915ba (diff) |
src: allow to use typeof of raw expressions in set declaration
Use the dynamic datatype to allocate an instance of TYPE_INTEGER and set
length and byteorder. Add missing information to the set userdata area
for raw payload expressions which allows to rebuild the set typeof from
the listing path.
A few examples:
- With anonymous sets:
nft add rule x y ip saddr . @ih,32,32 { 1.1.1.1 . 0x14, 2.2.2.2 . 0x1e }
- With named sets:
table x {
set y {
typeof ip saddr . @ih,32,32
elements = { 1.1.1.1 . 0x14 }
}
}
Incremental updates are also supported, eg.
nft add element x y { 3.3.3.3 . 0x28 }
expr_evaluate_concat() is used to evaluate both set key definitions
and set key values, using two different function might help to simplify
this code in the future.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src/payload.c')
-rw-r--r-- | src/payload.c | 55 |
1 files changed, 50 insertions, 5 deletions
diff --git a/src/payload.c b/src/payload.c index f433c384..fd6f7011 100644 --- a/src/payload.c +++ b/src/payload.c @@ -124,11 +124,17 @@ static void payload_expr_pctx_update(struct proto_ctx *ctx, #define NFTNL_UDATA_SET_KEY_PAYLOAD_DESC 0 #define NFTNL_UDATA_SET_KEY_PAYLOAD_TYPE 1 -#define NFTNL_UDATA_SET_KEY_PAYLOAD_MAX 2 +#define NFTNL_UDATA_SET_KEY_PAYLOAD_BASE 2 +#define NFTNL_UDATA_SET_KEY_PAYLOAD_OFFSET 3 +#define NFTNL_UDATA_SET_KEY_PAYLOAD_LEN 4 +#define NFTNL_UDATA_SET_KEY_PAYLOAD_MAX 5 static unsigned int expr_payload_type(const struct proto_desc *desc, const struct proto_hdr_template *tmpl) { + if (desc->id == PROTO_DESC_UNKNOWN) + return 0; + return (unsigned int)(tmpl - &desc->templates[0]); } @@ -142,6 +148,15 @@ static int payload_expr_build_udata(struct nftnl_udata_buf *udbuf, nftnl_udata_put_u32(udbuf, NFTNL_UDATA_SET_KEY_PAYLOAD_DESC, desc->id); nftnl_udata_put_u32(udbuf, NFTNL_UDATA_SET_KEY_PAYLOAD_TYPE, type); + if (desc->id == 0) { + nftnl_udata_put_u32(udbuf, NFTNL_UDATA_SET_KEY_PAYLOAD_BASE, + expr->payload.base); + nftnl_udata_put_u32(udbuf, NFTNL_UDATA_SET_KEY_PAYLOAD_OFFSET, + expr->payload.offset); + nftnl_udata_put_u32(udbuf, NFTNL_UDATA_SET_KEY_PAYLOAD_LEN, + expr->len); + } + return 0; } @@ -159,6 +174,9 @@ static int payload_parse_udata(const struct nftnl_udata *attr, void *data) switch (type) { case NFTNL_UDATA_SET_KEY_PAYLOAD_DESC: case NFTNL_UDATA_SET_KEY_PAYLOAD_TYPE: + case NFTNL_UDATA_SET_KEY_PAYLOAD_BASE: + case NFTNL_UDATA_SET_KEY_PAYLOAD_OFFSET: + case NFTNL_UDATA_SET_KEY_PAYLOAD_LEN: if (len != sizeof(uint32_t)) return -1; break; @@ -173,8 +191,10 @@ static int payload_parse_udata(const struct nftnl_udata *attr, void *data) static struct expr *payload_expr_parse_udata(const struct nftnl_udata *attr) { const struct nftnl_udata *ud[NFTNL_UDATA_SET_KEY_PAYLOAD_MAX + 1] = {}; + unsigned int type, base, offset, len; const struct proto_desc *desc; - unsigned int type; + bool is_raw = false; + struct expr *expr; int err; err = nftnl_udata_parse(nftnl_udata_get(attr), nftnl_udata_len(attr), @@ -187,12 +207,37 @@ static struct expr *payload_expr_parse_udata(const struct nftnl_udata *attr) return NULL; desc = find_proto_desc(ud[NFTNL_UDATA_SET_KEY_PAYLOAD_DESC]); - if (!desc) - return NULL; + if (!desc) { + if (!ud[NFTNL_UDATA_SET_KEY_PAYLOAD_BASE] || + !ud[NFTNL_UDATA_SET_KEY_PAYLOAD_OFFSET] || + !ud[NFTNL_UDATA_SET_KEY_PAYLOAD_LEN]) + return NULL; + + base = nftnl_udata_get_u32(ud[NFTNL_UDATA_SET_KEY_PAYLOAD_BASE]); + offset = nftnl_udata_get_u32(ud[NFTNL_UDATA_SET_KEY_PAYLOAD_OFFSET]); + len = nftnl_udata_get_u32(ud[NFTNL_UDATA_SET_KEY_PAYLOAD_LEN]); + is_raw = true; + } type = nftnl_udata_get_u32(ud[NFTNL_UDATA_SET_KEY_PAYLOAD_TYPE]); - return payload_expr_alloc(&internal_location, desc, type); + expr = payload_expr_alloc(&internal_location, desc, type); + + if (is_raw) { + struct datatype *dtype; + + expr->payload.base = base; + expr->payload.offset = offset; + expr->payload.is_raw = true; + expr->len = len; + dtype = dtype_clone(&xinteger_type); + dtype->size = len; + dtype->byteorder = BYTEORDER_BIG_ENDIAN; + dtype->refcnt = 1; + expr->dtype = dtype; + } + + return expr; } const struct expr_ops payload_expr_ops = { |