summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/evaluate.c48
-rw-r--r--tests/py/ip6/dnat.t2
-rw-r--r--tests/py/ip6/dnat.t.json27
-rw-r--r--tests/py/ip6/dnat.t.payload.ip612
4 files changed, 89 insertions, 0 deletions
diff --git a/src/evaluate.c b/src/evaluate.c
index 69b853f5..429b1150 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -1933,6 +1933,52 @@ static int stmt_evaluate_expr(struct eval_ctx *ctx, struct stmt *stmt)
return expr_evaluate(ctx, &stmt->expr);
}
+static int stmt_prefix_conversion(struct eval_ctx *ctx, struct expr **expr,
+ enum byteorder byteorder)
+{
+ struct expr *mask, *and, *or, *prefix, *base, *range;
+ int ret;
+
+ prefix = *expr;
+ base = prefix->prefix;
+
+ if (base->etype != EXPR_VALUE)
+ return expr_error(ctx->msgs, prefix,
+ "you cannot specify a prefix here, "
+ "unknown type %s", base->dtype->name);
+
+ if (!expr_is_constant(base))
+ return expr_error(ctx->msgs, prefix,
+ "Prefix expression is undefined for "
+ "non-constant expressions");
+
+ if (expr_basetype(base)->type != TYPE_INTEGER)
+ return expr_error(ctx->msgs, prefix,
+ "Prefix expression expected integer value");
+
+ mask = constant_expr_alloc(&prefix->location, expr_basetype(base),
+ BYTEORDER_HOST_ENDIAN, base->len, NULL);
+
+ mpz_prefixmask(mask->value, base->len, prefix->prefix_len);
+ and = binop_expr_alloc(&prefix->location, OP_AND, expr_get(base), mask);
+
+ mask = constant_expr_alloc(&prefix->location, expr_basetype(base),
+ BYTEORDER_HOST_ENDIAN, base->len, NULL);
+ mpz_bitmask(mask->value, prefix->len - prefix->prefix_len);
+ or = binop_expr_alloc(&prefix->location, OP_OR, expr_get(base), mask);
+
+ range = range_expr_alloc(&prefix->location, and, or);
+ ret = expr_evaluate(ctx, &range);
+ if (ret < 0) {
+ expr_free(range);
+ return ret;
+ }
+
+ expr_free(*expr);
+ *expr = range;
+ 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)
@@ -1969,6 +2015,8 @@ static int stmt_evaluate_arg(struct eval_ctx *ctx, struct stmt *stmt,
"unknown value to use");
case EXPR_RT:
return byteorder_conversion(ctx, expr, byteorder);
+ case EXPR_PREFIX:
+ return stmt_prefix_conversion(ctx, expr, byteorder);
default:
break;
}
diff --git a/tests/py/ip6/dnat.t b/tests/py/ip6/dnat.t
index 78d6d0ad..db5fde58 100644
--- a/tests/py/ip6/dnat.t
+++ b/tests/py/ip6/dnat.t
@@ -5,3 +5,5 @@
tcp dport 80-90 dnat to [2001:838:35f:1::]-[2001:838:35f:2::]:80-100;ok
tcp dport 80-90 dnat to [2001:838:35f:1::]-[2001:838:35f:2::]:100;ok;tcp dport 80-90 dnat to [2001:838:35f:1::]-[2001:838:35f:2::]:100
tcp dport 80-90 dnat to [2001:838:35f:1::]:80;ok
+dnat to [2001:838:35f:1::]/64;ok;dnat to 2001:838:35f:1::-2001:838:35f:1:ffff:ffff:ffff:ffff
+dnat to 2001:838:35f:1::-2001:838:35f:1:ffff:ffff:ffff:ffff;ok
diff --git a/tests/py/ip6/dnat.t.json b/tests/py/ip6/dnat.t.json
index a5c01fd2..3419b60f 100644
--- a/tests/py/ip6/dnat.t.json
+++ b/tests/py/ip6/dnat.t.json
@@ -76,3 +76,30 @@
}
]
+# dnat to [2001:838:35f:1::]/64
+[
+ {
+ "dnat": {
+ "addr": {
+ "range": [
+ "2001:838:35f:1::",
+ "2001:838:35f:1:ffff:ffff:ffff:ffff"
+ ]
+ }
+ }
+ }
+]
+
+# dnat to 2001:838:35f:1::-2001:838:35f:1:ffff:ffff:ffff:ffff
+[
+ {
+ "dnat": {
+ "addr": {
+ "range": [
+ "2001:838:35f:1::",
+ "2001:838:35f:1:ffff:ffff:ffff:ffff"
+ ]
+ }
+ }
+ }
+]
diff --git a/tests/py/ip6/dnat.t.payload.ip6 b/tests/py/ip6/dnat.t.payload.ip6
index 4d3fafe2..985159e2 100644
--- a/tests/py/ip6/dnat.t.payload.ip6
+++ b/tests/py/ip6/dnat.t.payload.ip6
@@ -33,3 +33,15 @@ ip6 test-ip6 prerouting
[ immediate reg 1 0x38080120 0x01005f03 0x00000000 0x00000000 ]
[ immediate reg 2 0x00005000 ]
[ nat dnat ip6 addr_min reg 1 addr_max reg 0 proto_min reg 2 proto_max reg 0 ]
+
+# dnat to [2001:838:35f:1::]/64
+ip6 test-ip6 prerouting
+ [ immediate reg 1 0x38080120 0x01005f03 0x00000000 0x00000000 ]
+ [ immediate reg 2 0x38080120 0x01005f03 0xffffffff 0xffffffff ]
+ [ nat dnat ip6 addr_min reg 1 addr_max reg 2 ]
+
+# dnat to 2001:838:35f:1::-2001:838:35f:1:ffff:ffff:ffff:ffff
+ip6 test-ip6 prerouting
+ [ immediate reg 1 0x38080120 0x01005f03 0x00000000 0x00000000 ]
+ [ immediate reg 2 0x38080120 0x01005f03 0xffffffff 0xffffffff ]
+ [ nat dnat ip6 addr_min reg 1 addr_max reg 2 ]