]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
evaluate: add two new helpers
authorFlorian Westphal <fw@strlen.de>
Mon, 24 Feb 2020 00:03:22 +0000 (01:03 +0100)
committerPablo Neira Ayuso <pablo@netfilter.org>
Mon, 24 Feb 2020 09:58:04 +0000 (10:58 +0100)
In order to support 'dnat to ip saddr map @foo', where @foo returns
both an address and a inet_service, we will need to peek into the map
and process the concatenations sub-expressions.

Add two helpers for this, will be used in followup patches.

Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
src/evaluate.c

index 7a70eff95998b93b1fbe864dd0a75e46b53075cc..ce1e65f48995a4e8f486dad05bf941f85a1dc330 100644 (file)
@@ -2102,14 +2102,10 @@ static int stmt_prefix_conversion(struct eval_ctx *ctx, struct expr **expr,
        return 0;
 }
 
-static int stmt_evaluate_arg(struct eval_ctx *ctx, struct stmt *stmt,
-                            const struct datatype *dtype, unsigned int len,
-                            enum byteorder byteorder, struct expr **expr)
+static int __stmt_evaluate_arg(struct eval_ctx *ctx, struct stmt *stmt,
+                              const struct datatype *dtype, unsigned int len,
+                              enum byteorder byteorder, struct expr **expr)
 {
-       __expr_set_context(&ctx->ectx, dtype, byteorder, len, 0);
-       if (expr_evaluate(ctx, expr) < 0)
-               return -1;
-
        if ((*expr)->etype == EXPR_PAYLOAD &&
            (*expr)->dtype->type == TYPE_INTEGER &&
            ((*expr)->dtype->type != datatype_basetype(dtype)->type ||
@@ -2147,6 +2143,17 @@ static int stmt_evaluate_arg(struct eval_ctx *ctx, struct stmt *stmt,
        return 0;
 }
 
+static int stmt_evaluate_arg(struct eval_ctx *ctx, struct stmt *stmt,
+                            const struct datatype *dtype, unsigned int len,
+                            enum byteorder byteorder, struct expr **expr)
+{
+       __expr_set_context(&ctx->ectx, dtype, byteorder, len, 0);
+       if (expr_evaluate(ctx, expr) < 0)
+               return -1;
+
+       return __stmt_evaluate_arg(ctx, stmt, dtype, len, byteorder, expr);
+}
+
 static int stmt_evaluate_verdict(struct eval_ctx *ctx, struct stmt *stmt)
 {
        if (stmt_evaluate_arg(ctx, stmt, &verdict_type, 0, 0, &stmt->expr) < 0)
@@ -2762,22 +2769,28 @@ static int nat_evaluate_family(struct eval_ctx *ctx, struct stmt *stmt)
        }
 }
 
+static const struct datatype *get_addr_dtype(uint8_t family)
+{
+       switch (family) {
+       case NFPROTO_IPV4:
+               return &ipaddr_type;
+       case NFPROTO_IPV6:
+               return &ip6addr_type;
+       }
+
+       return &invalid_type;
+}
+
 static int evaluate_addr(struct eval_ctx *ctx, struct stmt *stmt,
                             struct expr **expr)
 {
        struct proto_ctx *pctx = &ctx->pctx;
        const struct datatype *dtype;
-       unsigned int len;
 
-       if (pctx->family == NFPROTO_IPV4) {
-               dtype = &ipaddr_type;
-               len   = 4 * BITS_PER_BYTE;
-       } else {
-               dtype = &ip6addr_type;
-               len   = 16 * BITS_PER_BYTE;
-       }
+       dtype = get_addr_dtype(pctx->family);
 
-       return stmt_evaluate_arg(ctx, stmt, dtype, len, BYTEORDER_BIG_ENDIAN,
+       return stmt_evaluate_arg(ctx, stmt, dtype, dtype->size,
+                                BYTEORDER_BIG_ENDIAN,
                                 expr);
 }
 
@@ -2819,25 +2832,15 @@ static int stmt_evaluate_addr(struct eval_ctx *ctx, struct stmt *stmt,
                              struct expr **addr)
 {
        const struct datatype *dtype;
-       unsigned int len;
        int err;
 
        if (ctx->pctx.family == NFPROTO_INET) {
-               switch (family) {
-               case NFPROTO_IPV4:
-                       dtype = &ipaddr_type;
-                       len   = 4 * BITS_PER_BYTE;
-                       break;
-               case NFPROTO_IPV6:
-                       dtype = &ip6addr_type;
-                       len   = 16 * BITS_PER_BYTE;
-                       break;
-               default:
+               dtype = get_addr_dtype(family);
+               if (dtype->size == 0)
                        return stmt_error(ctx, stmt,
                                          "ip or ip6 must be specified with address for inet tables.");
-               }
 
-               err = stmt_evaluate_arg(ctx, stmt, dtype, len,
+               err = stmt_evaluate_arg(ctx, stmt, dtype, dtype->size,
                                        BYTEORDER_BIG_ENDIAN, addr);
        } else {
                err = evaluate_addr(ctx, stmt, addr);