diff options
Diffstat (limited to 'src/netlink_delinearize.c')
-rw-r--r-- | src/netlink_delinearize.c | 49 |
1 files changed, 44 insertions, 5 deletions
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c index 1767098d..de5d66c0 100644 --- a/src/netlink_delinearize.c +++ b/src/netlink_delinearize.c @@ -35,6 +35,9 @@ struct netlink_parse_ctx { struct expr *registers[1 + NFT_REG32_15 - NFT_REG32_00 + 1]; }; +static int netlink_parse_expr(const struct nftnl_expr *nle, + struct netlink_parse_ctx *ctx); + static void __fmtstring(3, 4) netlink_error(struct netlink_parse_ctx *ctx, const struct location *loc, const char *fmt, ...) @@ -910,8 +913,9 @@ static void netlink_parse_dynset(struct netlink_parse_ctx *ctx, const struct location *loc, const struct nftnl_expr *nle) { + const struct nftnl_expr *dnle; struct expr *expr; - struct stmt *stmt; + struct stmt *stmt, *dstmt; struct set *set; enum nft_registers sreg; const char *name; @@ -938,10 +942,28 @@ static void netlink_parse_dynset(struct netlink_parse_ctx *ctx, expr = set_elem_expr_alloc(&expr->location, expr); expr->timeout = nftnl_expr_get_u64(nle, NFTNL_EXPR_DYNSET_TIMEOUT); - stmt = set_stmt_alloc(loc); - stmt->set.set = set_ref_expr_alloc(loc, set); - stmt->set.op = nftnl_expr_get_u32(nle, NFTNL_EXPR_DYNSET_OP); - stmt->set.key = expr; + dstmt = NULL; + dnle = nftnl_expr_get(nle, NFTNL_EXPR_DYNSET_EXPR, NULL); + if (dnle != NULL) { + if (netlink_parse_expr(dnle, ctx) < 0) + return; + if (ctx->stmt == NULL) + return netlink_error(ctx, loc, + "Could not parse dynset stmt"); + dstmt = ctx->stmt; + } + + if (dstmt != NULL) { + stmt = flow_stmt_alloc(loc); + stmt->flow.set = set_ref_expr_alloc(loc, set); + stmt->flow.key = expr; + stmt->flow.stmt = dstmt; + } else { + stmt = set_stmt_alloc(loc); + stmt->set.set = set_ref_expr_alloc(loc, set); + stmt->set.op = nftnl_expr_get_u32(nle, NFTNL_EXPR_DYNSET_OP); + stmt->set.key = expr; + } ctx->stmt = stmt; } @@ -1011,6 +1033,20 @@ static int netlink_parse_rule_expr(struct nftnl_expr *nle, void *arg) return 0; } +struct stmt *netlink_parse_set_expr(const struct set *set, + const struct nftnl_expr *nle) +{ + struct netlink_parse_ctx ctx, *pctx = &ctx; + + pctx->rule = rule_alloc(&netlink_location, &set->handle); + pctx->table = table_lookup(&set->handle); + assert(pctx->table != NULL); + + if (netlink_parse_expr(nle, pctx) < 0) + return NULL; + return pctx->stmt; +} + struct rule_pp_ctx { struct proto_ctx pctx; struct payload_dep_ctx pdctx; @@ -1717,6 +1753,9 @@ static void rule_parse_postprocess(struct netlink_parse_ctx *ctx, struct rule *r stmt->payload.expr->byteorder); expr_postprocess(&rctx, &stmt->payload.val); break; + case STMT_FLOW: + expr_postprocess(&rctx, &stmt->flow.key); + break; case STMT_META: if (stmt->meta.expr != NULL) expr_postprocess(&rctx, &stmt->meta.expr); |