summaryrefslogtreecommitdiffstats
path: root/src/netlink.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/netlink.c')
-rw-r--r--src/netlink.c71
1 files changed, 52 insertions, 19 deletions
diff --git a/src/netlink.c b/src/netlink.c
index e4128963..7b7ef39e 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -138,6 +138,9 @@ static struct nftnl_set_elem *alloc_nftnl_setelem(const struct expr *set,
if (elem->expiration)
nftnl_set_elem_set_u64(nlse, NFTNL_SET_ELEM_EXPIRATION,
elem->expiration);
+ if (elem->stmt)
+ nftnl_set_elem_set(nlse, NFTNL_SET_ELEM_EXPR,
+ netlink_gen_stmt_stateful(elem->stmt), 0);
if (elem->comment || expr->elem_flags) {
udbuf = nftnl_udata_buf_alloc(NFT_USERDATA_MAXLEN);
if (!udbuf)
@@ -169,6 +172,9 @@ static struct nftnl_set_elem *alloc_nftnl_setelem(const struct expr *set,
nftnl_set_elem_set(nlse, NFTNL_SET_ELEM_CHAIN,
nld.chain, strlen(nld.chain));
break;
+ case EXPR_CONCAT:
+ assert(nld.len > 0);
+ /* fallthrough */
case EXPR_VALUE:
nftnl_set_elem_set(nlse, NFTNL_SET_ELEM_DATA,
nld.value, nld.len);
@@ -432,15 +438,17 @@ struct chain *netlink_delinearize_chain(struct netlink_ctx *ctx,
xstrdup(nftnl_chain_get_str(nlc, NFTNL_CHAIN_TABLE));
chain->handle.handle.id =
nftnl_chain_get_u64(nlc, NFTNL_CHAIN_HANDLE);
+ if (nftnl_chain_is_set(nlc, NFTNL_CHAIN_FLAGS))
+ chain->flags = nftnl_chain_get_u32(nlc, NFTNL_CHAIN_FLAGS);
if (nftnl_chain_is_set(nlc, NFTNL_CHAIN_HOOKNUM) &&
nftnl_chain_is_set(nlc, NFTNL_CHAIN_PRIO) &&
nftnl_chain_is_set(nlc, NFTNL_CHAIN_TYPE) &&
nftnl_chain_is_set(nlc, NFTNL_CHAIN_POLICY)) {
- chain->hooknum =
+ chain->hook.num =
nftnl_chain_get_u32(nlc, NFTNL_CHAIN_HOOKNUM);
- chain->hookstr =
- hooknum2str(chain->handle.family, chain->hooknum);
+ chain->hook.name =
+ hooknum2str(chain->handle.family, chain->hook.num);
priority = nftnl_chain_get_s32(nlc, NFTNL_CHAIN_PRIO);
chain->priority.expr =
constant_expr_alloc(&netlink_location,
@@ -758,6 +766,13 @@ struct set *netlink_delinearize_set(struct netlink_ctx *ctx,
set->handle.set.name = xstrdup(nftnl_set_get_str(nls, NFTNL_SET_NAME));
set->automerge = automerge;
+ if (nftnl_set_is_set(nls, NFTNL_SET_EXPR)) {
+ const struct nftnl_expr *nle;
+
+ nle = nftnl_set_get(nls, NFTNL_SET_EXPR);
+ set->stmt = netlink_parse_set_expr(set, &ctx->nft->cache, nle);
+ }
+
if (datatype) {
dtype = set_datatype_alloc(datatype, databyteorder);
klen = nftnl_set_get_u32(nls, NFTNL_SET_DATA_LEN) * BITS_PER_BYTE;
@@ -1005,6 +1020,10 @@ key_end:
NFT_REG_VERDICT : NFT_REG_1);
datatype_set(data, set->data->dtype);
data->byteorder = set->data->byteorder;
+
+ if (set->data->dtype->subtypes)
+ data = netlink_parse_concat_elem(set->data->dtype, data);
+
if (data->byteorder == BYTEORDER_HOST_ENDIAN)
mpz_switch_byteorder(data->value, data->len / BITS_PER_BYTE);
@@ -1321,8 +1340,10 @@ netlink_delinearize_flowtable(struct netlink_ctx *ctx,
sizeof(int) *
BITS_PER_BYTE,
&priority);
- flowtable->hooknum =
+ flowtable->hook.num =
nftnl_flowtable_get_u32(nlo, NFTNL_FLOWTABLE_HOOKNUM);
+ flowtable->flags =
+ nftnl_flowtable_get_u32(nlo, NFTNL_FLOWTABLE_FLAGS);
return flowtable;
}
@@ -1428,38 +1449,50 @@ static void trace_print_policy(const struct nftnl_trace *nlt,
expr_free(expr);
}
-static void trace_print_rule(const struct nftnl_trace *nlt,
- struct output_ctx *octx, struct nft_cache *cache)
+static struct rule *trace_lookup_rule(const struct nftnl_trace *nlt,
+ uint64_t rule_handle,
+ struct nft_cache *cache)
{
- const struct table *table;
- uint64_t rule_handle;
struct chain *chain;
- struct rule *rule;
+ struct table *table;
struct handle h;
h.family = nftnl_trace_get_u32(nlt, NFTNL_TRACE_FAMILY);
- h.table.name = nftnl_trace_get_str(nlt, NFTNL_TRACE_TABLE);
- h.chain.name = nftnl_trace_get_str(nlt, NFTNL_TRACE_CHAIN);
+ h.table.name = nftnl_trace_get_str(nlt, NFTNL_TRACE_TABLE);
+ h.chain.name = nftnl_trace_get_str(nlt, NFTNL_TRACE_CHAIN);
if (!h.table.name)
- return;
+ return NULL;
table = table_lookup(&h, cache);
if (!table)
- return;
+ return NULL;
chain = chain_lookup(table, &h);
if (!chain)
- return;
+ return NULL;
+
+ return rule_lookup(chain, rule_handle);
+}
+
+static void trace_print_rule(const struct nftnl_trace *nlt,
+ struct output_ctx *octx, struct nft_cache *cache)
+{
+ uint64_t rule_handle;
+ struct rule *rule;
rule_handle = nftnl_trace_get_u64(nlt, NFTNL_TRACE_RULE_HANDLE);
- rule = rule_lookup(chain, rule_handle);
- if (!rule)
- return;
+ rule = trace_lookup_rule(nlt, rule_handle, cache);
trace_print_hdr(nlt, octx);
- nft_print(octx, "rule ");
- rule_print(rule, octx);
+
+ if (rule) {
+ nft_print(octx, "rule ");
+ rule_print(rule, octx);
+ } else {
+ nft_print(octx, "unknown rule handle %" PRIu64, rule_handle);
+ }
+
nft_print(octx, " (");
trace_print_verdict(nlt, octx);
nft_print(octx, ")\n");