src: add masquerade support
PATCH v2 1/1 src: add masquerade support
This patch adds masquerade support for nft.
The syntax is:
% nft add rule nat postrouting masquerade [flags]
Currently, flags are:
random, random-fully, persistent
Example:
% nft add rule nat postrouting masquerade random,persistent
---
v2: fixed typo in header. Use switch in the evaluation stage and report error
if family is neither ip nor ip6. Requested by Pablo.
include/statement.h | 9 +++++++++ src/evaluate.c | 28 ++++++++++++++++++++++++++++ src/netlink_delinearize.c | 16 ++++++++++++++++ src/netlink_linearize.c | 15 +++++++++++++++ src/parser.y | 18 ++++++++++++++++-- src/scanner.l | 1 + src/statement.c | 18 ++++++++++++++++++ 7 files changed, 103 insertions(+), 2 deletions(-)
include/statement.h +9 -0
@@ -70,6 +70,12 @@ struct nat_stmt {extern struct stmt *nat_stmt_alloc (const struct location *loc); +struct masq_stmt { +uint32_t flags; +}; + +extern struct stmt *masq_stmt_alloc (const struct location *loc); +struct queue_stmt {struct expr *queue;uint16_t flags;
@@ -100,6 +106,7 @@ extern struct stmt *ct_stmt_alloc(const struct location *loc,* @STMT_LOG: log statement * @STMT_REJECT: REJECT statement * @STMT_NAT: NAT statement +* @STMT_MASQ: masquerade statement * @STMT_QUEUE: QUEUE statement * @STMT_CT: conntrack statement */
@@ -113,6 +120,7 @@ enum stmt_types {STMT_LOG ,STMT_REJECT ,STMT_NAT , +STMT_MASQ ,STMT_QUEUE , STMT_CT, };
@@ -160,6 +168,7 @@ struct stmt {struct limit_stmt limit;struct reject_stmt reject;struct nat_stmt nat; +struct masq_stmt masq;struct queue_stmt queue;struct ct_stmt ct; };
src/evaluate.c +28 -0
@@ -1171,6 +1171,32 @@ static int stmt_evaluate_nat(struct eval_ctx *ctx, struct stmt *stmt)return 0 ; } +static int stmt_evaluate_masq (struct eval_ctx *ctx,struct stmt *stmt) +{ +struct proto_ctx *pctx = &ctx->pctx; + +if (!pctx) + goto out; + +switch (pctx->family) { +case AF_INET : +expr_set_context (&ctx->ectx, &ipaddr_type, +4 *BITS_PER_BYTE ); +break ; +case AF_INET6 : +expr_set_context (&ctx->ectx, &ip6addr_type, +16 *BITS_PER_BYTE ); +break ; +default : +return stmt_error (ctx, stmt, +"masquerade family must be ip or ipv6" ); + } + +out: + stmt->flags |=STMT_F_TERMINAL ; +return 0 ; +} +static int stmt_evaluate_ct (struct eval_ctx *ctx,struct stmt *stmt) { expr_set_context(&ctx->ectx, stmt->ct.tmpl->dtype,
@@ -1231,6 +1257,8 @@ static int stmt_evaluate(struct eval_ctx *ctx, struct stmt *stmt)return stmt_evaluate_reject (ctx, stmt);case STMT_NAT :return stmt_evaluate_nat (ctx, stmt); +case STMT_MASQ : +return stmt_evaluate_masq (ctx, stmt);case STMT_QUEUE :return stmt_evaluate_queue (ctx, stmt);case STMT_CT :
src/netlink_delinearize.c +16 -0
@@ -558,6 +558,21 @@ static void netlink_parse_nat(struct netlink_parse_ctx *ctx,list_add_tail (&stmt->list, &ctx->rule->stmts); } +static void netlink_parse_masq (struct netlink_parse_ctx *ctx, +const struct location *loc, +const struct nft_rule_expr *nle) +{ +struct stmt *stmt; + + stmt =masq_stmt_alloc (loc); + +if (nft_rule_expr_is_set (nle,NFT_EXPR_MASQ_FLAGS )) + stmt->masq.flags =nft_rule_expr_get_u32 (nle, +NFT_EXPR_MASQ_FLAGS ); + +list_add_tail (&stmt->list, &ctx->rule->stmts); +} +static void netlink_parse_queue (struct netlink_parse_ctx *ctx,const struct location *loc,const struct nft_rule_expr *nle)
@@ -604,6 +619,7 @@ static const struct { { .name = "limit", .parse = netlink_parse_limit }, { .name = "reject", .parse = netlink_parse_reject }, { .name = "nat", .parse = netlink_parse_nat }, + { .name = "masq", .parse = netlink_parse_masq }, { .name = "queue", .parse = netlink_parse_queue }, };
src/netlink_linearize.c +15 -0
@@ -685,6 +685,19 @@ static void netlink_gen_nat_stmt(struct netlink_linearize_ctx *ctx,nft_rule_add_expr (ctx->nlr, nle); } +static void netlink_gen_masq_stmt (struct netlink_linearize_ctx *ctx, +const struct stmt *stmt) +{ +struct nft_rule_expr *nle; + + nle =alloc_nft_expr ("masq" ); +if (stmt->masq.flags !=0 ) +nft_rule_expr_set_u32 (nle,NFT_EXPR_MASQ_FLAGS , + stmt->masq.flags); + +nft_rule_add_expr (ctx->nlr, nle); +} +static void netlink_gen_queue_stmt (struct netlink_linearize_ctx *ctx,const struct stmt *stmt) {
@@ -749,6 +762,8 @@ static void netlink_gen_stmt(struct netlink_linearize_ctx *ctx,return netlink_gen_reject_stmt (ctx, stmt);case STMT_NAT :return netlink_gen_nat_stmt (ctx, stmt); +case STMT_MASQ : +return netlink_gen_masq_stmt (ctx, stmt);case STMT_QUEUE :return netlink_gen_queue_stmt (ctx, stmt);case STMT_CT :
src/parser.y +16 -2
@@ -372,6 +372,7 @@ static void location_update(struct location *loc, struct location *rhs, int n) %token SNAT "snat" %token DNAT "dnat" +%token MASQUERADE "masquerade" %token RANDOM "random" %token RANDOM_FULLY "random-fully" %token PERSISTENT "persistent"
@@ -437,9 +438,10 @@ static void location_update(struct location *loc, struct location *rhs, int n) %type <val> time_unit %type <stmt> reject_stmt %destructor { stmt_free($$); } reject_stmt -%type <stmt> nat_stmt nat_stmt_alloc -%destructor { stmt_free($$); } nat_stmt nat_stmt_alloc +%type <stmt> nat_stmt nat_stmt_alloc masq_stmt masq_stmt_alloc +%destructor { stmt_free($$); } nat_stmt nat_stmt_alloc masq_stmt masq_stmt_alloc %type <val> nf_nat_flags nf_nat_flag + %type <stmt> queue_stmt queue_stmt_alloc %destructor { stmt_free($$); } queue_stmt queue_stmt_alloc %type <val> queue_stmt_flags queue_stmt_flag
@@ -1239,6 +1241,7 @@ stmt : verdict_stmt | nat_stmt | queue_stmt | ct_stmt + | masq_stmt ; verdict_stmt : verdict_expr
@@ -1419,6 +1422,17 @@ nat_stmt_args : expr } ; +masq_stmt : masq_stmt_alloc + | masq_stmt_alloc nf_nat_flags + { + $$ = $1; + $$->masq.flags = $2; + } + ; + +masq_stmt_alloc : MASQUERADE { $$ = masq_stmt_alloc(&@$); } + ; + nf_nat_flags : nf_nat_flag | nf_nat_flags COMMA nf_nat_flag {
src/scanner.l +1 -0
@@ -316,6 +316,7 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "snat" { return SNAT; } "dnat" { return DNAT; } +"masquerade" { return MASQUERADE; } "random" { return RANDOM; } "random-fully" { return RANDOM_FULLY; } "persistent" { return PERSISTENT; }
src/statement.c +18 -0
@@ -299,3 +299,21 @@ struct stmt *nat_stmt_alloc(const struct location *loc) {return stmt_alloc (loc, &nat_stmt_ops); } + +static void masq_stmt_print (const struct stmt *stmt) +{ +printf ("masquerade" ); + +print_nf_nat_flags (stmt->masq.flags); +} + +static const struct stmt_ops masq_stmt_ops = { + .type =STMT_MASQ , + .name ="masq" , + .print = masq_stmt_print, +}; + +struct stmt *masq_stmt_alloc (const struct location *loc) +{ +return stmt_alloc (loc, &masq_stmt_ops); +}
Quoted 11 lines · Arturo Borrero Gonzalez
This patch adds masquerade support for nft.
The syntax is:
% nft add rule nat postrouting masquerade [flags]
Currently, flags are:
random, random-fully, persistentExample:
% nft add rule nat postrouting masquerade random,persistent
Applied, thanks Arturo.
BTW, I mangled the error message for bridge to this:
# nft add rule bridge test test masquerade
<cmdline>:1:27-36: Error: ip and ip6 support only
add rule bridge test test masquerade
^^^^^^^^^^Please, send me a patch to unit test this and update wiki.nftables.org. Thanks.