From 77ef4d83c8d030b183ff763605b2c3026545fc9c Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 8 Jan 2014 13:02:15 +0000 Subject: expr: add protocol context update callback Add a callback function to the expression ops to update the protocol context for relational protocol expressions (EXPR_F_PROTOCOL). Also set the EXPR_F_PROTOCOL flag for IIFTYPE meta expressions to make sure the callback is invoked when necessary. Signed-off-by: Patrick McHardy --- src/evaluate.c | 18 +++++++---------- src/meta.c | 13 +++++++++++- src/netlink_delinearize.c | 4 ++-- src/payload.c | 50 ++++++++++++++++++++++++----------------------- 4 files changed, 47 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/evaluate.c b/src/evaluate.c index 112fc944..3fe9da4f 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -919,18 +919,14 @@ static int expr_evaluate_relational(struct eval_ctx *ctx, struct expr **expr) * Update protocol context for payload and meta iiftype * equality expressions. */ - switch (left->ops->type) { - case EXPR_PAYLOAD: - payload_expr_pctx_update(&ctx->pctx, rel); - break; - case EXPR_META: - meta_expr_pctx_update(&ctx->pctx, rel); - break; - case EXPR_CONCAT: + if (left->flags & EXPR_F_PROTOCOL && + left->ops->pctx_update) + left->ops->pctx_update(&ctx->pctx, rel); + + if (left->ops->type == EXPR_CONCAT) return 0; - default: - break; - } + + /* fall through */ case OP_NEQ: case OP_FLAGCMP: if (!datatype_equal(left->dtype, right->dtype)) diff --git a/src/meta.c b/src/meta.c index 343f9a3d..9173c306 100644 --- a/src/meta.c +++ b/src/meta.c @@ -349,7 +349,8 @@ static void meta_expr_clone(struct expr *new, const struct expr *expr) * * Update LL protocol context based on IIFTYPE meta match in non-LL hooks. */ -void meta_expr_pctx_update(struct proto_ctx *ctx, const struct expr *expr) +static void meta_expr_pctx_update(struct proto_ctx *ctx, + const struct expr *expr) { const struct hook_proto_desc *h = &hook_proto_desc[ctx->family]; const struct expr *left = expr->left, *right = expr->right; @@ -375,6 +376,7 @@ static const struct expr_ops meta_expr_ops = { .name = "meta", .print = meta_expr_print, .clone = meta_expr_clone, + .pctx_update = meta_expr_pctx_update, }; struct expr *meta_expr_alloc(const struct location *loc, enum nft_meta_keys key) @@ -385,6 +387,15 @@ struct expr *meta_expr_alloc(const struct location *loc, enum nft_meta_keys key) expr = expr_alloc(loc, &meta_expr_ops, tmpl->dtype, tmpl->byteorder, tmpl->len); expr->meta.key = key; + + switch (key) { + case NFT_META_IIFTYPE: + expr->flags |= EXPR_F_PROTOCOL; + break; + default: + break; + } + return expr; } diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c index 982377f8..c02f133d 100644 --- a/src/netlink_delinearize.c +++ b/src/netlink_delinearize.c @@ -612,7 +612,7 @@ static void payload_match_postprocess(struct rule_pp_ctx *ctx, nexpr = relational_expr_alloc(&expr->location, expr->op, left, tmp); - payload_expr_pctx_update(&ctx->pctx, nexpr); + left->ops->pctx_update(&ctx->pctx, nexpr); nstmt = expr_stmt_alloc(&stmt->location, nexpr); list_add_tail(&nstmt->list, &stmt->list); @@ -644,7 +644,7 @@ static void meta_match_postprocess(struct proto_ctx *ctx, { switch (expr->op) { case OP_EQ: - meta_expr_pctx_update(ctx, expr); + expr->left->ops->pctx_update(ctx, expr); break; default: break; diff --git a/src/payload.c b/src/payload.c index 7721b755..426adc31 100644 --- a/src/payload.c +++ b/src/payload.c @@ -48,11 +48,37 @@ static void payload_expr_clone(struct expr *new, const struct expr *expr) new->payload.offset = expr->payload.offset; } +/** + * payload_expr_pctx_update - update protocol context based on payload match + * + * @ctx: protocol context + * @expr: relational payload expression + * + * Update protocol context for relational payload expressions. + */ +static void payload_expr_pctx_update(struct proto_ctx *ctx, + const struct expr *expr) +{ + const struct expr *left = expr->left, *right = expr->right; + const struct proto_desc *base, *desc; + + if (!(left->flags & EXPR_F_PROTOCOL)) + return; + + assert(expr->op == OP_EQ); + base = ctx->protocol[left->payload.base].desc; + desc = proto_find_upper(base, mpz_get_uint32(right->value)); + + ctx->protocol[left->payload.base + 1].location = expr->location; + ctx->protocol[left->payload.base + 1].desc = desc; +} + static const struct expr_ops payload_expr_ops = { .type = EXPR_PAYLOAD, .name = "payload", .print = payload_expr_print, .clone = payload_expr_clone, + .pctx_update = payload_expr_pctx_update, }; struct expr *payload_expr_alloc(const struct location *loc, @@ -94,30 +120,6 @@ void payload_init_raw(struct expr *expr, enum proto_bases base, expr->len = len; } -/** - * payload_expr_pctx_update - update protocol context based on payload match - * - * @ctx: protocol context - * @expr: relational payload expression - * - * Update protocol context for relational payload expressions. - */ -void payload_expr_pctx_update(struct proto_ctx *ctx, const struct expr *expr) -{ - const struct expr *left = expr->left, *right = expr->right; - const struct proto_desc *base, *desc; - - if (!(left->flags & EXPR_F_PROTOCOL)) - return; - - assert(expr->op == OP_EQ); - base = ctx->protocol[left->payload.base].desc; - desc = proto_find_upper(base, mpz_get_uint32(right->value)); - - ctx->protocol[left->payload.base + 1].location = expr->location; - ctx->protocol[left->payload.base + 1].desc = desc; -} - /** * payload_gen_dependency - generate match expression on payload dependency * -- cgit v1.2.3