src: add tee statement support
PATCH 1/1 src: add tee statement support
The syntax is:
tee gw <addr> [oifname <str>]
Only valid in IPv4/IPv6 families. No inet/bridge/arp support by now. No limits regarding chain hooks.
--- include/statement.h | 9 +++++++++ src/evaluate.c | 30 +++++++++++++++++++++++++++--- src/netlink_delinearize.c | 32 ++++++++++++++++++++++++++++++++ src/netlink_linearize.c | 17 +++++++++++++++++ src/parser_bison.y | 25 +++++++++++++++++++++++++ src/scanner.l | 3 +++ src/statement.c | 27 +++++++++++++++++++++++++++ 7 files changed, 140 insertions(+), 3 deletions(-)
include/statement.h +9 -0
@@ -103,6 +103,12 @@ struct ct_stmt {extern struct stmt *ct_stmt_alloc (const struct location *loc,enum nft_ct_keys key,struct expr *expr); +struct tee_stmt { +struct expr *gw; +const char *oifname; +}; + +struct stmt *tee_stmt_alloc (const struct location *loc);/** * enum stmt_types - statement types
@@ -120,6 +126,7 @@ extern struct stmt *ct_stmt_alloc(const struct location *loc,* @STMT_REDIR: redirect statement * @STMT_QUEUE: QUEUE statement * @STMT_CT: conntrack statement +* @STMT_TEE: tee statement */ enum stmt_types {STMT_INVALID ,
@@ -135,6 +142,7 @@ enum stmt_types {STMT_REDIR ,STMT_QUEUE ,STMT_CT , + STMT_TEE, };/**
@@ -184,6 +192,7 @@ struct stmt {struct redir_stmt redir;struct queue_stmt queue;struct ct_stmt ct; +struct tee_stmt tee; }; };
src/evaluate.c +27 -3
@@ -1535,8 +1535,8 @@ static int nat_evaluate_family(struct eval_ctx *ctx, struct stmt *stmt) } } -static int nat_evaluate_addr (struct eval_ctx *ctx,struct stmt *stmt, -struct expr **expr) +static int evaluate_addr (struct eval_ctx *ctx,struct stmt *stmt, +struct expr **expr) {struct proto_ctx *pctx = &ctx->pctx;const struct datatype *dtype;
@@ -1577,7 +1577,7 @@ static int stmt_evaluate_nat(struct eval_ctx *ctx, struct stmt *stmt)return err;if (stmt->nat.addr !=NULL ) { - err =nat_evaluate_addr (ctx, stmt, &stmt->nat.addr); + err =evaluate_addr (ctx, stmt, &stmt->nat.addr);if (err <0 )return err; }
@@ -1646,6 +1646,28 @@ static int stmt_evaluate_log(struct eval_ctx *ctx, struct stmt *stmt)return 0 ; } +static int stmt_evaluate_tee (struct eval_ctx *ctx,struct stmt *stmt) +{ +int err; + +switch (ctx->pctx.family) { +case NFPROTO_IPV4 : +case NFPROTO_IPV6 : +break ; +default : +return stmt_error (ctx, stmt,"tee only supported in ip,ip6" ); + } + +if (stmt->tee.gw ==NULL ) +return stmt_error (ctx, stmt,"tee requires gw parameter" ); + + err =evaluate_addr (ctx, stmt, &stmt->tee.gw); +if (err <0 ) +return err; + +return 0 ; +} +int stmt_evaluate (struct eval_ctx *ctx,struct stmt *stmt) {#ifdef DEBUG
@@ -1680,6 +1702,8 @@ int stmt_evaluate(struct eval_ctx *ctx, struct stmt *stmt)return stmt_evaluate_redir (ctx, stmt);case STMT_QUEUE :return stmt_evaluate_queue (ctx, stmt); +case STMT_TEE : +return stmt_evaluate_tee (ctx, stmt);default :BUG ("unknown statement type %s\n" , stmt->ops->name); }
src/netlink_delinearize.c +32 -0
@@ -694,6 +694,20 @@ static void netlink_parse_queue(struct netlink_parse_ctx *ctx,list_add_tail (&stmt->list, &ctx->rule->stmts); } +static void netlink_parse_tee (struct netlink_parse_ctx *ctx, +const struct location *loc, +const struct nft_rule_expr *nle) +{ +struct nft_data_delinearize nld; +struct stmt *stmt; + + stmt =tee_stmt_alloc (loc); + nld.value =nft_rule_expr_get (nle,NFT_EXPR_TEE_GW , &nld.len); + stmt->tee.gw =netlink_alloc_value (loc, &nld); + stmt->tee.oifname =nft_rule_expr_get_str (nle,NFT_EXPR_TEE_OIF ); +list_add_tail (&stmt->list, &ctx->rule->stmts); +} + static const struct { const char *name; void (*parse)(struct netlink_parse_ctx *ctx,
@@ -717,6 +731,7 @@ static const struct { { .name = "masq", .parse = netlink_parse_masq }, { .name = "redir", .parse = netlink_parse_redir }, { .name = "queue", .parse = netlink_parse_queue }, + { .name = "tee", .parse = netlink_parse_tee }, };static int netlink_parse_expr (struct nft_rule_expr *nle,void *arg)
@@ -1102,6 +1117,20 @@ static void stmt_reject_postprocess(struct rule_pp_ctx rctx, struct stmt *stmt) } } +static void stmt_tee_postprocess (struct rule_pp_ctx rctx,struct stmt *stmt) +{ +switch (rctx.pctx.family) { +case NFPROTO_IPV4 : + stmt->tee.gw->dtype = &ipaddr_type; +break ; +case NFPROTO_IPV6 : + stmt->tee.gw->dtype = &ip6addr_type; +break ; +default : +break ; + } +} +static void rule_parse_postprocess (struct netlink_parse_ctx *ctx,struct rule *rule) {struct rule_pp_ctx rctx;
@@ -1137,6 +1166,9 @@ static void rule_parse_postprocess(struct netlink_parse_ctx *ctx, struct rule *rcase STMT_REJECT :stmt_reject_postprocess (rctx, stmt);break ; +case STMT_TEE : +stmt_tee_postprocess (rctx, stmt); +break ;default :break ; }
src/netlink_linearize.c +17 -0
@@ -798,6 +798,21 @@ static void netlink_gen_ct_stmt(struct netlink_linearize_ctx *ctx,nft_rule_add_expr (ctx->nlr, nle); } +static void netlink_gen_tee_stmt (struct netlink_linearize_ctx *ctx, +const struct stmt *stmt) +{ +struct nft_rule_expr *nle; +struct nft_data_linearize nld; +const char *oifname = stmt->tee.oifname; + + nle =alloc_nft_expr ("tee" ); +netlink_gen_data (stmt->tee.gw, &nld); +nft_rule_expr_set (nle,NFT_EXPR_TEE_GW , nld.value, nld.len); +if (oifname !=NULL ) +nft_rule_expr_set_str (nle,NFT_EXPR_TEE_OIF , oifname); +nft_rule_add_expr (ctx->nlr, nle); +} +static void netlink_gen_stmt (struct netlink_linearize_ctx *ctx,const struct stmt *stmt) {
@@ -826,6 +841,8 @@ static void netlink_gen_stmt(struct netlink_linearize_ctx *ctx,return netlink_gen_queue_stmt (ctx, stmt);case STMT_CT :return netlink_gen_ct_stmt (ctx, stmt); +case STMT_TEE : +return netlink_gen_tee_stmt (ctx, stmt);default :BUG ("unknown statement type %s\n" , stmt->ops->name); }
src/parser_bison.y +25 -0
@@ -390,6 +390,9 @@ static void location_update(struct location *loc, struct location *rhs, int n) %token POSITION "position" %token COMMENT "comment" +%token TEE "tee" +%token GW "gw" + %token XML "xml" %token JSON "json"
@@ -452,6 +455,8 @@ static void location_update(struct location *loc, struct location *rhs, int n) %type <stmt> queue_stmt queue_stmt_alloc %destructor { stmt_free($$); } queue_stmt queue_stmt_alloc %type <val> queue_stmt_flags queue_stmt_flag +%type <stmt> tee_stmt tee_stmt_alloc +%destructor { stmt_free($$); } tee_stmt tee_stmt_alloc %type <expr> symbol_expr verdict_expr integer_expr %destructor { expr_free($$); } symbol_expr verdict_expr integer_expr
@@ -1207,6 +1212,7 @@ stmt : verdict_stmt | ct_stmt | masq_stmt | redir_stmt + | tee_stmt ; verdict_stmt : verdict_expr
@@ -1526,6 +1532,25 @@ match_stmt : relational_expr } ; +tee_stmt : tee_stmt_alloc tee_stmt_opt + ; + +tee_stmt_alloc : TEE + { + $$ = tee_stmt_alloc(&@$); + } + ; + +tee_stmt_opt : GW expr + { + $<stmt>0->tee.gw = $2; + } + | OIFNAME STRING + { + $<stmt>0->tee.oifname = strdup($2); + } + ; + symbol_expr : string { $$ = symbol_expr_alloc(&@$, SYMBOL_VALUE,
src/scanner.l +3 -0
@@ -449,6 +449,9 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "proto-dst" { return PROTO_DST; } "label" { return LABEL; } +"tee" { return TEE; } +"gw" { return GW; } + "xml" { return XML; } "json" { return JSON; }
src/statement.c +27 -0
@@ -377,3 +377,30 @@ struct stmt *redir_stmt_alloc(const struct location *loc) {return stmt_alloc (loc, &redir_stmt_ops); } + +static void tee_stmt_print (const struct stmt *stmt) +{ +printf ("tee gw " ); +expr_print (stmt->tee.gw); +if (stmt->tee.oifname !=NULL ) +printf (" oifname %s" , stmt->tee.oifname); +} + +static void tee_stmt_destroy (struct stmt *stmt) +{ +expr_free (stmt->tee.gw); +if (stmt->tee.oifname !=NULL ) +xfree (stmt->tee.oifname); +} + +static const struct stmt_ops tee_stmt_ops = { + .type =STMT_TEE , + .name ="tee" , + .print = tee_stmt_print, + .destroy = tee_stmt_destroy, +}; + +struct stmt *tee_stmt_alloc (const struct location *loc) +{ +return stmt_alloc (loc, &tee_stmt_ops); +}
Quoted 3 lines · Arturo Borrero Gonzalez
The syntax is:
tee gw <addr> [oifname <str>]
[...]
Quoted 10 lines
src/parser_bison.y +9
-0+tee_stmt : tee_stmt_alloc tee_stmt_opt + ; + +tee_stmt_alloc : TEE + { + $$ = tee_stmt_alloc(&@$); + } + ; +
src/parser_bison.y match_stmt : relational_expr · line 1553
Quoted 10 lines
src/parser_bison.y +10
-0+tee_stmt_opt : GW expr + { + $<stmt>0->tee.gw = $2; + } + | OIFNAME STRING + { + $<stmt>0->tee.oifname = strdup($2); + } + ; +
This grammar is not completely right.
However, using something like this:
tee_stmt : TEE tee_stmt_opts
{
$$ = tee_stmt_alloc(&@$);
}
;tee_stmt_opts : tee_stmt_opts tee_stmt_opt
| tee_stmt_opt
;tee_stmt_opt : GW expr
{
$<stmt>0->tee.gw = $2;
}
| OIFNAME string
{
$<stmt>0->tee.oifname = strdup($2);
}
;lead to shift/reduce conflicts, because expr can be `OIFNAME string'.
Any idea?
Signature · 5 lines
Arturo Borrero González -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Pablo Neira Ayuso
maintainerQuoted 51 lines · Arturo Borrero Gonzalez
Quoted 3 lines · Arturo Borrero Gonzalez
The syntax is:
tee gw <addr> [oifname <str>][...]
Quoted 10 lines
src/parser_bison.y +9
-0+tee_stmt : tee_stmt_alloc tee_stmt_opt + ; + +tee_stmt_alloc : TEE + { + $$ = tee_stmt_alloc(&@$); + } + ; +src/parser_bison.y match_stmt : relational_expr · line 1553
Quoted 10 lines
src/parser_bison.y +10
-0+tee_stmt_opt : GW expr + { + $<stmt>0->tee.gw = $2; + } + | OIFNAME STRING + { + $<stmt>0->tee.oifname = strdup($2); + } + ; +This grammar is not completely right.
However, using something like this:
tee_stmt: TEEtee_stmt_opts{ $$ = tee_stmt_alloc(&@$); } ;tee_stmt_opts : tee_stmt_opts tee_stmt_opt | tee_stmt_opt ;
tee_stmt_opt: GW expr{ $<stmt>0->tee.gw = $2; } | OIFNAME string { $<stmt>0->tee.oifname = strdup($2); } ;
Quoted 3 lines
lead to shift/reduce conflicts, because expr can be `OIFNAME string'.
Any idea?
You use STRING instead for GW and make sure from the evaluation step that this is a valid address?
Quoted 52 lines · Pablo Neira Ayuso
Quoted 51 lines · Arturo Borrero Gonzalez
Quoted 3 lines · Arturo Borrero Gonzalez
The syntax is:
tee gw <addr> [oifname <str>][...]
Quoted 10 lines
src/parser_bison.y +9
-0+tee_stmt : tee_stmt_alloc tee_stmt_opt + ; + +tee_stmt_alloc : TEE + { + $$ = tee_stmt_alloc(&@$); + } + ; +src/parser_bison.y match_stmt : relational_expr · line 1553
Quoted 10 lines
src/parser_bison.y +10
-0+tee_stmt_opt : GW expr + { + $<stmt>0->tee.gw = $2; + } + | OIFNAME STRING + { + $<stmt>0->tee.oifname = strdup($2); + } + ; +This grammar is not completely right.
However, using something like this:
tee_stmt: TEEtee_stmt_opts{ $$ = tee_stmt_alloc(&@$); } ;tee_stmt_opts : tee_stmt_opts tee_stmt_opt | tee_stmt_opt ;
tee_stmt_opt: GW expr{ $<stmt>0->tee.gw = $2; } | OIFNAME string { $<stmt>0->tee.oifname = strdup($2); } ;
Quoted 6 lines
Quoted 3 lines
lead to shift/reduce conflicts, because expr can be `OIFNAME string'.
Any idea?
You use STRING instead for GW and make sure from the evaluation step that this is a valid address?
Nop :-( still conflict.
Signature · 5 lines
Arturo Borrero González -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 52 lines · Pablo Neira Ayuso
Quoted 51 lines · Arturo Borrero Gonzalez
Quoted 3 lines · Arturo Borrero Gonzalez
The syntax is:
tee gw <addr> [oifname <str>][...]
Quoted 10 lines
src/parser_bison.y +9
-0+tee_stmt : tee_stmt_alloc tee_stmt_opt + ; + +tee_stmt_alloc : TEE + { + $$ = tee_stmt_alloc(&@$); + } + ; +src/parser_bison.y match_stmt : relational_expr · line 1553
Quoted 10 lines
src/parser_bison.y +10
-0+tee_stmt_opt : GW expr + { + $<stmt>0->tee.gw = $2; + } + | OIFNAME STRING + { + $<stmt>0->tee.oifname = strdup($2); + } + ; +This grammar is not completely right.
However, using something like this:
tee_stmt: TEEtee_stmt_opts{ $$ = tee_stmt_alloc(&@$); } ;tee_stmt_opts : tee_stmt_opts tee_stmt_opt | tee_stmt_opt ;
tee_stmt_opt: GW expr{ $<stmt>0->tee.gw = $2; } | OIFNAME string { $<stmt>0->tee.oifname = strdup($2); } ;
Quoted 6 lines
Quoted 3 lines
lead to shift/reduce conflicts, because expr can be `OIFNAME string'.
Any idea?
You use STRING instead for GW and make sure from the evaluation step that this is a valid address?
Never use string please, it breaks symbol resolution. symbol_expr would be a better choice.