src: add nat persistent and random options
PATCH 1/2 src: add nat persistent and random options
This patch adds more configuration options to the nat expression.
The syntax is as follow:
% nft add rule nat postrouting <snat|dnat> <nat_arguments> [flags]
Flags are: random, persistent, random-fully.
Example:
% nft add rule nat postrouting dnat 1.1.1.1 random,persistent
A requirement is to cache some [recent] copies of kernel headers.
--- .../linux/netfilter/nf_conntrack_tuple_common.h | 32 ++++++++++++++- include/linux/netfilter/nf_nat.h | 42 ++++++++++++++++++++ include/statement.h | 1 src/netlink_delinearize.c | 4 ++ src/netlink_linearize.c | 3 + src/parser.y | 21 ++++++++++ src/scanner.l | 3 + src/statement.c | 26 ++++++++++++ 8 files changed, 130 insertions(+), 2 deletions(-) create mode 100644 include/linux/netfilter/nf_nat.h
include/linux/netfilter/nf_conntrack_tuple_common.h +30 -2
@@ -1,13 +1,41 @@#ifndef _NF_CONNTRACK_TUPLE_COMMON_H#define _NF_CONNTRACK_TUPLE_COMMON_H -enum ip_conntrack_dir -{ +#include <linux/types.h> + +enum ip_conntrack_dir {IP_CT_DIR_ORIGINAL ,IP_CT_DIR_REPLY ,IP_CT_DIR_MAX }; +/* The protocol-specific manipulable parts of the tuple: always in +* network order +*/ +union nf_conntrack_man_proto { +/* Add other protocols here. */ +__be16 all; + +struct { +__be16 port; + } tcp; +struct { +__be16 port; + } udp; +struct { +__be16 id; + } icmp; +struct { +__be16 port; + } dccp; +struct { +__be16 port; + } sctp; +struct { +__be16 key;/* GRE key is 32bit, PPtP only uses 16bit */ + } gre; +}; +#define CTINFO2DIR (ctinfo) ((ctinfo) >= IP_CT_IS_REPLY ? IP_CT_DIR_REPLY : IP_CT_DIR_ORIGINAL)#endif /* _NF_CONNTRACK_TUPLE_COMMON_H */
include/linux/netfilter/nf_nat.h new file +42 -0
42 lines not on this page · raw message
include/statement.h +1 -0
@@ -65,6 +65,7 @@ struct nat_stmt {enum nft_nat_types type;struct expr *addr;struct expr *proto; +uint32_t flags; };extern struct stmt *nat_stmt_alloc (const struct location *loc);
src/netlink_delinearize.c +4 -0
@@ -491,6 +491,10 @@ static void netlink_parse_nat(struct netlink_parse_ctx *ctx, family =nft_rule_expr_get_u32 (nle,NFT_EXPR_NAT_FAMILY ); +if (nft_rule_expr_is_set (nle,NFT_EXPR_NAT_FLAGS )) + stmt->nat.flags =nft_rule_expr_get_u32 (nle, +NFT_EXPR_NAT_FLAGS ); + reg1 =nft_rule_expr_get_u32 (nle,NFT_EXPR_NAT_REG_ADDR_MIN );if (reg1) { addr =netlink_get_register (ctx, loc, reg1);
src/netlink_linearize.c +3 -0
@@ -631,6 +631,9 @@ static void netlink_gen_nat_stmt(struct netlink_linearize_ctx *ctx, family =nft_rule_attr_get_u32 (ctx->nlr,NFT_RULE_ATTR_FAMILY );nft_rule_expr_set_u32 (nle,NFT_EXPR_NAT_FAMILY , family); +if (stmt->nat.flags !=0 ) +nft_rule_expr_set_u32 (nle,NFT_EXPR_NAT_FLAGS , stmt->nat.flags); +if (stmt->nat.addr) { amin_reg =get_register (ctx); registers++;
src/parser.y +21 -0
@@ -19,6 +19,7 @@ #include <linux/netfilter.h> #include <linux/netfilter/nf_tables.h> #include <linux/netfilter/nf_conntrack_tuple_common.h> +#include <linux/netfilter/nf_nat.h> #include <libnftnl/common.h> #include <libnftnl/set.h>
@@ -371,6 +372,9 @@ static void location_update(struct location *loc, struct location *rhs, int n) %token SNAT "snat" %token DNAT "dnat" +%token RANDOM "random" +%token RANDOM_FULLY "random-fully" +%token PERSISTENT "persistent" %token QUEUE "queue" %token QUEUENUM "num"
@@ -435,6 +439,7 @@ static void location_update(struct location *loc, struct location *rhs, int n) %destructor { stmt_free($$); } reject_stmt %type <stmt> nat_stmt nat_stmt_alloc %destructor { stmt_free($$); } nat_stmt nat_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
@@ -1408,6 +1413,22 @@ nat_stmt_args : expr { $<stmt>0->nat.proto = $2; } + | nat_stmt_args nf_nat_flags + { + $<stmt>0->nat.flags = $2; + } + ; + +nf_nat_flags : nf_nat_flag + | nf_nat_flags COMMA nf_nat_flag + { + $$ = $1 | $3; + } + ; + +nf_nat_flag : RANDOM { $$ = NF_NAT_RANGE_PROTO_RANDOM; } + | RANDOM_FULLY { $$ = NF_NAT_RANGE_PROTO_RANDOM_FULLY; } + | PERSISTENT { $$ = NF_NAT_RANGE_PERSISTENT; } ; queue_stmt : queue_stmt_alloc
src/scanner.l +3 -0
@@ -316,6 +316,9 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "snat" { return SNAT; } "dnat" { return DNAT; } +"random" { return RANDOM; } +"random-fully" { return RANDOM_FULLY; } +"persistent" { return PERSISTENT; } "ll" { return LL_HDR; } "nh" { return NETWORK_HDR; }
src/statement.c +26 -0
@@ -20,6 +20,9 @@#include <utils.h> #include <list.h> +#include <netinet/in.h> +#include <linux/netfilter/nf_nat.h> +struct stmt *stmt_alloc (const struct location *loc,const struct stmt_ops *ops) {
@@ -240,6 +243,27 @@ struct stmt *reject_stmt_alloc(const struct location *loc)return stmt_alloc (loc, &reject_stmt_ops); } +static void print_nf_nat_flags (uint32_t flags) +{ +const char *delim =" " ; + +if (flags ==0 ) +return ; + +if (flags &NF_NAT_RANGE_PROTO_RANDOM ) { +printf ("%srandom" , delim); + delim ="," ; + } + +if (flags &NF_NAT_RANGE_PROTO_RANDOM_FULLY ) { +printf ("%srandom-fully" , delim); + delim ="," ; + } + +if (flags &NF_NAT_RANGE_PERSISTENT ) +printf ("%spersistent" , delim); +} +static void nat_stmt_print (const struct stmt *stmt) {static const char *nat_types[] = {
@@ -254,6 +278,8 @@ static void nat_stmt_print(const struct stmt *stmt)printf (":" );expr_print (stmt->nat.proto); } + +print_nf_nat_flags (stmt->nat.flags); }static void nat_stmt_destroy (struct stmt *stmt)
PATCH 2/2 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
--- include/statement.h | 9 +++++++++ src/evaluate.c | 17 +++++++++++++++++ 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, 92 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_NAT: 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 +17 -0
@@ -1171,6 +1171,21 @@ 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 && (pctx->family ==AF_INET )) +expr_set_context (&ctx->ectx, &ipaddr_type, +4 *BITS_PER_BYTE ); +else +expr_set_context (&ctx->ectx, &ip6addr_type, +16 *BITS_PER_BYTE ); + + 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 +1246,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); +}
Pablo Neira Ayuso
maintainerRe: [nft PATCH 2/2] src: add masquerade support
include/statement.h extern struct stmt *ct_stmt_alloc(const struct location *loc, · line 109
Quoted 9 lines · Arturo Borrero Gonzalez
include/statement.h +2
-0+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_NAT: masquerade statement
^
typoQuoted 27 lines
include/statement.h +2
-0* @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 +0
-0@@ -1171,6 +1171,21 @@ static int stmt_evaluate_nat(struct eval_ctx *ctx, struct stmt *stmt)return 0 ; }
src/evaluate.c static int stmt_evaluate_nat(struct eval_ctx *ctx, struct stmt *stmt) · line 1183
Quoted 10 lines
src/evaluate.c +10
-0+static int stmt_evaluate_masq (struct eval_ctx *ctx,struct stmt *stmt) +{ +struct proto_ctx *pctx = &ctx->pctx; + +if (pctx && (pctx->family ==AF_INET )) +expr_set_context (&ctx->ectx, &ipaddr_type, +4 *BITS_PER_BYTE ); +else +expr_set_context (&ctx->ectx, &ip6addr_type, +16 *BITS_PER_BYTE );
Could you use a switch to check pctx->family?
Spot an error for unsupported family, so we don't crash badly if someone tries to use this from a different context.
Quoted 4 lines
src/evaluate.c +4
-0+ stmt->flags |=STMT_F_TERMINAL ; +return 0 ; +} +
Quoted 11 lines · Arturo Borrero Gonzalez
This patch adds more configuration options to the nat expression.
The syntax is as follow:
% nft add rule nat postrouting <snat|dnat> <nat_arguments> [flags]Flags are: random, persistent, random-fully.
Example:% nft add rule nat postrouting dnat 1.1.1.1 random,persistent
A requirement is to cache some [recent] copies of kernel headers.
Applied, thanks Arturo.
Please, send me a follow-up patch to add test for the new regression testing infrastructure and document this in our wiki page.