summaryrefslogtreecommitdiffstats
path: root/src/netlink.c
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2021-05-10 18:52:45 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2021-05-11 21:39:01 +0200
commit419d196886889e9b37f76f8c803cb08dcbc05505 (patch)
treeeed1e42837a4a55d8cf16e65914b9ae961adddcd /src/netlink.c
parent62b02808594d962f83e8b76f4da32da0673c7cfe (diff)
src: add set element catch-all support
Add a catchall expression (EXPR_SET_ELEM_CATCHALL). Use the asterisk (*) to represent the catch-all set element, e.g. table x { set y { type ipv4_addr counter elements = { 1.2.3.4 counter packets 0 bytes 0, * counter packets 0 bytes 0 } } } Special handling for segtree: zap the catch-all element from the set element list and re-add it after processing. Remove wildcard_expr deadcode in src/parser_bison.y This patch also adds several tests for the tests/py and tests/shell infrastructures. Acked-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src/netlink.c')
-rw-r--r--src/netlink.c71
1 files changed, 45 insertions, 26 deletions
diff --git a/src/netlink.c b/src/netlink.c
index e4926a80..8cdd6d81 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -104,6 +104,7 @@ static struct nftnl_set_elem *alloc_nftnl_setelem(const struct expr *set,
struct nftnl_set_elem *nlse;
struct nft_data_linearize nld;
struct nftnl_udata_buf *udbuf = NULL;
+ uint32_t flags = 0;
int num_exprs = 0;
struct stmt *stmt;
struct expr *key;
@@ -125,16 +126,21 @@ static struct nftnl_set_elem *alloc_nftnl_setelem(const struct expr *set,
key = elem->key;
- netlink_gen_data(key, &nld);
- nftnl_set_elem_set(nlse, NFTNL_SET_ELEM_KEY, &nld.value, nld.len);
-
- if (set->set_flags & NFT_SET_INTERVAL && key->field_count > 1) {
- key->flags |= EXPR_F_INTERVAL_END;
+ switch (key->etype) {
+ case EXPR_SET_ELEM_CATCHALL:
+ break;
+ default:
netlink_gen_data(key, &nld);
- key->flags &= ~EXPR_F_INTERVAL_END;
-
- nftnl_set_elem_set(nlse, NFTNL_SET_ELEM_KEY_END, &nld.value,
- nld.len);
+ nftnl_set_elem_set(nlse, NFTNL_SET_ELEM_KEY, &nld.value, nld.len);
+ if (set->set_flags & NFT_SET_INTERVAL && key->field_count > 1) {
+ key->flags |= EXPR_F_INTERVAL_END;
+ netlink_gen_data(key, &nld);
+ key->flags &= ~EXPR_F_INTERVAL_END;
+
+ nftnl_set_elem_set(nlse, NFTNL_SET_ELEM_KEY_END,
+ &nld.value, nld.len);
+ }
+ break;
}
if (elem->timeout)
@@ -209,8 +215,12 @@ static struct nftnl_set_elem *alloc_nftnl_setelem(const struct expr *set,
}
if (expr->flags & EXPR_F_INTERVAL_END)
- nftnl_set_elem_set_u32(nlse, NFTNL_SET_ELEM_FLAGS,
- NFT_SET_ELEM_INTERVAL_END);
+ flags |= NFT_SET_ELEM_INTERVAL_END;
+ if (key->etype == EXPR_SET_ELEM_CATCHALL)
+ flags |= NFT_SET_ELEM_CATCHALL;
+
+ if (flags)
+ nftnl_set_elem_set_u32(nlse, NFTNL_SET_ELEM_FLAGS, flags);
return nlse;
}
@@ -1133,25 +1143,34 @@ int netlink_delinearize_setelem(struct nftnl_set_elem *nlse,
init_list_head(&setelem_parse_ctx.stmt_list);
- nld.value =
- nftnl_set_elem_get(nlse, NFTNL_SET_ELEM_KEY, &nld.len);
+ if (nftnl_set_elem_is_set(nlse, NFTNL_SET_ELEM_KEY))
+ nld.value = nftnl_set_elem_get(nlse, NFTNL_SET_ELEM_KEY, &nld.len);
if (nftnl_set_elem_is_set(nlse, NFTNL_SET_ELEM_FLAGS))
flags = nftnl_set_elem_get_u32(nlse, NFTNL_SET_ELEM_FLAGS);
key_end:
- key = netlink_alloc_value(&netlink_location, &nld);
- datatype_set(key, set->key->dtype);
- key->byteorder = set->key->byteorder;
- if (set->key->dtype->subtypes)
- key = netlink_parse_concat_elem(set->key->dtype, key);
-
- if (!(set->flags & NFT_SET_INTERVAL) &&
- key->byteorder == BYTEORDER_HOST_ENDIAN)
- mpz_switch_byteorder(key->value, key->len / BITS_PER_BYTE);
-
- if (key->dtype->basetype != NULL &&
- key->dtype->basetype->type == TYPE_BITMASK)
- key = bitmask_expr_to_binops(key);
+ if (nftnl_set_elem_is_set(nlse, NFTNL_SET_ELEM_KEY)) {
+ key = netlink_alloc_value(&netlink_location, &nld);
+ datatype_set(key, set->key->dtype);
+ key->byteorder = set->key->byteorder;
+ if (set->key->dtype->subtypes)
+ key = netlink_parse_concat_elem(set->key->dtype, key);
+
+ if (!(set->flags & NFT_SET_INTERVAL) &&
+ key->byteorder == BYTEORDER_HOST_ENDIAN)
+ mpz_switch_byteorder(key->value, key->len / BITS_PER_BYTE);
+
+ if (key->dtype->basetype != NULL &&
+ key->dtype->basetype->type == TYPE_BITMASK)
+ key = bitmask_expr_to_binops(key);
+ } else if (flags & NFT_SET_ELEM_CATCHALL) {
+ key = set_elem_catchall_expr_alloc(&netlink_location);
+ datatype_set(key, set->key->dtype);
+ key->byteorder = set->key->byteorder;
+ key->len = set->key->len;
+ } else {
+ BUG("Unexpected set element with no key\n");
+ }
expr = set_elem_expr_alloc(&netlink_location, key);