summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/evaluate.c6
-rw-r--r--src/netlink_delinearize.c29
-rw-r--r--src/netlink_linearize.c24
-rw-r--r--src/parser_bison.y23
-rw-r--r--src/statement.c11
5 files changed, 85 insertions, 8 deletions
diff --git a/src/evaluate.c b/src/evaluate.c
index 28e17cb2..b17cc82f 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -1881,6 +1881,12 @@ static int stmt_evaluate_masq(struct eval_ctx *ctx, struct stmt *stmt)
if (err < 0)
return err;
+ if (stmt->masq.proto != NULL) {
+ err = nat_evaluate_transport(ctx, stmt, &stmt->masq.proto);
+ if (err < 0)
+ return err;
+ }
+
stmt->flags |= STMT_F_TERMINAL;
return 0;
}
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index fae6e33d..d431588f 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -726,16 +726,41 @@ static void netlink_parse_masq(struct netlink_parse_ctx *ctx,
const struct location *loc,
const struct nftnl_expr *nle)
{
+ enum nft_registers reg1, reg2;
+ struct expr *proto;
struct stmt *stmt;
- uint32_t flags;
+ uint32_t flags = 0;
- flags = 0;
if (nftnl_expr_is_set(nle, NFTNL_EXPR_MASQ_FLAGS))
flags = nftnl_expr_get_u32(nle, NFTNL_EXPR_MASQ_FLAGS);
stmt = masq_stmt_alloc(loc);
stmt->masq.flags = flags;
+ reg1 = netlink_parse_register(nle, NFTNL_EXPR_MASQ_REG_PROTO_MIN);
+ if (reg1) {
+ proto = netlink_get_register(ctx, loc, reg1);
+ if (proto == NULL)
+ return netlink_error(ctx, loc,
+ "MASQUERADE statement"
+ "has no proto expression");
+ expr_set_type(proto, &inet_service_type, BYTEORDER_BIG_ENDIAN);
+ stmt->masq.proto = proto;
+ }
+
+ reg2 = netlink_parse_register(nle, NFTNL_EXPR_MASQ_REG_PROTO_MAX);
+ if (reg2 && reg2 != reg1) {
+ proto = netlink_get_register(ctx, loc, reg2);
+ if (proto == NULL)
+ return netlink_error(ctx, loc,
+ "MASQUERADE statement"
+ "has no proto expression");
+ expr_set_type(proto, &inet_service_type, BYTEORDER_BIG_ENDIAN);
+ if (stmt->masq.proto != NULL)
+ proto = range_expr_alloc(loc, stmt->masq.proto, proto);
+ stmt->masq.proto = proto;
+ }
+
list_add_tail(&stmt->list, &ctx->rule->stmts);
}
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
index 7ff3b004..07f70e06 100644
--- a/src/netlink_linearize.c
+++ b/src/netlink_linearize.c
@@ -916,12 +916,36 @@ static void netlink_gen_nat_stmt(struct netlink_linearize_ctx *ctx,
static void netlink_gen_masq_stmt(struct netlink_linearize_ctx *ctx,
const struct stmt *stmt)
{
+ enum nft_registers pmin_reg, pmax_reg;
struct nftnl_expr *nle;
+ int registers = 0;
nle = alloc_nft_expr("masq");
if (stmt->masq.flags != 0)
nftnl_expr_set_u32(nle, NFTNL_EXPR_MASQ_FLAGS,
stmt->masq.flags);
+ if (stmt->masq.proto) {
+ pmin_reg = get_register(ctx, NULL);
+ registers++;
+
+ if (stmt->masq.proto->ops->type == EXPR_RANGE) {
+ pmax_reg = get_register(ctx, NULL);
+ registers++;
+
+ netlink_gen_expr(ctx, stmt->masq.proto->left, pmin_reg);
+ netlink_gen_expr(ctx, stmt->masq.proto->right, pmax_reg);
+ netlink_put_register(nle, NFTNL_EXPR_MASQ_REG_PROTO_MIN, pmin_reg);
+ netlink_put_register(nle, NFTNL_EXPR_MASQ_REG_PROTO_MAX, pmax_reg);
+ } else {
+ netlink_gen_expr(ctx, stmt->masq.proto, pmin_reg);
+ netlink_put_register(nle, NFTNL_EXPR_MASQ_REG_PROTO_MIN, pmin_reg);
+ }
+ }
+
+ while (registers > 0) {
+ release_register(ctx, NULL);
+ registers--;
+ }
nftnl_rule_add_expr(ctx->nlr, nle);
}
diff --git a/src/parser_bison.y b/src/parser_bison.y
index 05ade0fa..d41fc0ab 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -1644,17 +1644,28 @@ nat_stmt_args : stmt_expr
}
;
-masq_stmt : masq_stmt_alloc
- | masq_stmt_alloc nf_nat_flags
- {
- $$ = $1;
- $$->masq.flags = $2;
- }
+masq_stmt : masq_stmt_alloc masq_stmt_args
+ | masq_stmt_alloc
;
masq_stmt_alloc : MASQUERADE { $$ = masq_stmt_alloc(&@$); }
;
+masq_stmt_args : TO COLON stmt_expr
+ {
+ $<stmt>0->masq.proto = $3;
+ }
+ | TO COLON stmt_expr nf_nat_flags
+ {
+ $<stmt>0->masq.proto = $3;
+ $<stmt>0->masq.flags = $4;
+ }
+ | nf_nat_flags
+ {
+ $<stmt>0->masq.flags = $1;
+ }
+ ;
+
redir_stmt : redir_stmt_alloc redir_stmt_arg
| redir_stmt_alloc
;
diff --git a/src/statement.c b/src/statement.c
index ca924410..2a6f19f8 100644
--- a/src/statement.c
+++ b/src/statement.c
@@ -385,13 +385,24 @@ static void masq_stmt_print(const struct stmt *stmt)
{
printf("masquerade");
+ if (stmt->masq.proto) {
+ printf(" to :");
+ expr_print(stmt->masq.proto);
+ }
+
print_nf_nat_flags(stmt->masq.flags);
}
+static void masq_stmt_destroy(struct stmt *stmt)
+{
+ expr_free(stmt->masq.proto);
+}
+
static const struct stmt_ops masq_stmt_ops = {
.type = STMT_MASQ,
.name = "masq",
.print = masq_stmt_print,
+ .destroy = masq_stmt_destroy,
};
struct stmt *masq_stmt_alloc(const struct location *loc)