summaryrefslogtreecommitdiffstats
path: root/src/evaluate.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/evaluate.c')
-rw-r--r--src/evaluate.c83
1 files changed, 74 insertions, 9 deletions
diff --git a/src/evaluate.c b/src/evaluate.c
index 40e26467..b23ae89e 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -41,7 +41,9 @@
struct proto_ctx *eval_proto_ctx(struct eval_ctx *ctx)
{
- return &ctx->_pctx;
+ uint8_t idx = ctx->inner_desc ? 1 : 0;
+
+ return &ctx->_pctx[idx];
}
static int expr_evaluate(struct eval_ctx *ctx, struct expr **expr);
@@ -473,6 +475,9 @@ conflict_resolution_gen_dependency(struct eval_ctx *ctx, int protocol,
return expr_error(ctx->msgs, expr,
"dependency statement is invalid");
+ if (ctx->inner_desc)
+ left->payload.inner_desc = ctx->inner_desc;
+
*res = stmt;
return 0;
}
@@ -672,6 +677,9 @@ static int meta_iiftype_gen_dependency(struct eval_ctx *ctx,
return expr_error(ctx->msgs, payload,
"dependency statement is invalid");
+ if (ctx->inner_desc)
+ nstmt->expr->left->meta.inner_desc = ctx->inner_desc;
+
*res = nstmt;
return 0;
}
@@ -694,12 +702,16 @@ static int resolve_protocol_conflict(struct eval_ctx *ctx,
if (payload->payload.base == PROTO_BASE_LL_HDR) {
if (proto_is_dummy(desc)) {
- err = meta_iiftype_gen_dependency(ctx, payload, &nstmt);
- if (err < 0)
- return err;
-
- desc = payload->payload.desc;
- rule_stmt_insert_at(ctx->rule, nstmt, ctx->stmt);
+ if (ctx->inner_desc) {
+ proto_ctx_update(pctx, PROTO_BASE_LL_HDR, &payload->location, &proto_eth);
+ } else {
+ err = meta_iiftype_gen_dependency(ctx, payload, &nstmt);
+ if (err < 0)
+ return err;
+
+ desc = payload->payload.desc;
+ rule_stmt_insert_at(ctx->rule, nstmt, ctx->stmt);
+ }
} else {
unsigned int i;
@@ -866,6 +878,48 @@ static int expr_evaluate_payload(struct eval_ctx *ctx, struct expr **exprp)
return 0;
}
+static int expr_evaluate_inner(struct eval_ctx *ctx, struct expr **exprp)
+{
+ struct proto_ctx *pctx = eval_proto_ctx(ctx);
+ const struct proto_desc *desc;
+ struct expr *expr = *exprp;
+ int ret;
+
+ desc = pctx->protocol[expr->payload.inner_desc->base - 1].desc;
+ if (!desc) {
+ return expr_error(ctx->msgs, expr,
+ "no transport protocol specified");
+ }
+
+ if (proto_find_num(desc, expr->payload.inner_desc) < 0) {
+ return expr_error(ctx->msgs, expr,
+ "unexpected transport protocol %s",
+ desc->name);
+ }
+
+ proto_ctx_update(pctx, PROTO_BASE_INNER_HDR, &expr->location,
+ expr->payload.inner_desc);
+
+ if (expr->payload.base != PROTO_BASE_INNER_HDR)
+ ctx->inner_desc = expr->payload.inner_desc;
+
+ ret = expr_evaluate_payload(ctx, exprp);
+
+ return ret;
+}
+
+static int expr_evaluate_payload_inner(struct eval_ctx *ctx, struct expr **exprp)
+{
+ int ret;
+
+ if ((*exprp)->payload.inner_desc)
+ ret = expr_evaluate_inner(ctx, exprp);
+ else
+ ret = expr_evaluate_payload(ctx, exprp);
+
+ return ret;
+}
+
/*
* RT expression: validate protocol dependencies.
*/
@@ -1423,6 +1477,8 @@ static int expr_evaluate_concat(struct eval_ctx *ctx, struct expr **expr)
key = list_next_entry(key, list);
}
+
+ ctx->inner_desc = NULL;
}
(*expr)->flags |= flags;
@@ -2498,7 +2554,7 @@ static int expr_evaluate(struct eval_ctx *ctx, struct expr **expr)
case EXPR_FIB:
return expr_evaluate_fib(ctx, expr);
case EXPR_PAYLOAD:
- return expr_evaluate_payload(ctx, expr);
+ return expr_evaluate_payload_inner(ctx, expr);
case EXPR_RT:
return expr_evaluate_rt(ctx, expr);
case EXPR_CT:
@@ -2706,6 +2762,11 @@ static int stmt_evaluate_payload(struct eval_ctx *ctx, struct stmt *stmt)
mpz_t bitmask, ff;
bool need_csum;
+ if (stmt->payload.expr->payload.inner_desc) {
+ return expr_error(ctx->msgs, stmt->payload.expr,
+ "payload statement for this expression is not supported");
+ }
+
if (__expr_evaluate_payload(ctx, stmt->payload.expr) < 0)
return -1;
@@ -4565,7 +4626,9 @@ static int rule_evaluate(struct eval_ctx *ctx, struct rule *rule,
struct stmt *stmt, *tstmt = NULL;
struct error_record *erec;
- proto_ctx_init(&ctx->_pctx, rule->handle.family, ctx->nft->debug_mask);
+ proto_ctx_init(&ctx->_pctx[0], rule->handle.family, ctx->nft->debug_mask);
+ /* use NFPROTO_BRIDGE to set up proto_eth as base protocol. */
+ proto_ctx_init(&ctx->_pctx[1], NFPROTO_BRIDGE, ctx->nft->debug_mask);
memset(&ctx->ectx, 0, sizeof(ctx->ectx));
ctx->rule = rule;
@@ -4580,6 +4643,8 @@ static int rule_evaluate(struct eval_ctx *ctx, struct rule *rule,
return -1;
if (stmt->flags & STMT_F_TERMINAL)
tstmt = stmt;
+
+ ctx->inner_desc = NULL;
}
erec = rule_postprocess(rule);