From 878cc0e4e863e6b2c9fa71f791d35245b3ddbdb2 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Fri, 20 Mar 2009 08:34:59 +0100 Subject: Add support for user-defined symbolic constants User-defined constants can be used like this: define allowed_hosts = { 192.168.0.0/24, 10.0.0.20-10.0.0.30 } define udp_services = domain define tcp_services = { ssh, domain } ip saddr $allowed_hosts udp dport $udp_services counter accept ip saddr $allowed_hosts tcp dport $tcp_services counter accept Recursive definitions are possible, but currently not fully handled. Anything requiring transformations (sets using ranges) can not be used more than once currently since the expressions need to be COW'ed previously. Signed-off-by: Patrick McHardy --- src/evaluate.c | 37 +++++++++++++++++++++++++++++++++---- src/expression.c | 2 +- src/parser.y | 27 ++++++++++++++++++++------- src/scanner.l | 3 +++ 4 files changed, 57 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/evaluate.c b/src/evaluate.c index 0deff9ad..706ec2e5 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -102,13 +102,25 @@ static int byteorder_conversion(struct eval_ctx *ctx, struct expr **expr, static int expr_evaluate_symbol(struct eval_ctx *ctx, struct expr **expr) { struct error_record *erec; + struct symbol *sym; struct expr *new; (*expr)->sym_type = ctx->ectx.dtype; - erec = symbol_parse(*expr, &new); - if (erec != NULL) { - erec_queue(erec, ctx->msgs); - return -1; + + if ((*expr)->scope != NULL) { + sym = symbol_lookup((*expr)->scope, (*expr)->identifier); + if (sym == NULL) + return expr_error(ctx, *expr, + "undefined identifier '%s'", + (*expr)->identifier); + // FIXME: need to copy (on write) + new = expr_get(sym->expr); + } else { + erec = symbol_parse(*expr, &new); + if (erec != NULL) { + erec_queue(erec, ctx->msgs); + return -1; + } } expr_free(*expr); @@ -702,6 +714,23 @@ static int expr_evaluate_relational(struct eval_ctx *ctx, struct expr **expr) "constant value", expr_op_symbols[rel->op]); + if (rel->op == OP_IMPLICIT) { + switch (right->ops->type) { + case EXPR_RANGE: + rel->op = OP_RANGE; + break; + case EXPR_SET: + rel->op = OP_LOOKUP; + break; + case EXPR_LIST: + rel->op = OP_FLAGCMP; + break; + default: + rel->op = OP_EQ; + break; + } + } + switch (rel->op) { case OP_LOOKUP: /* Data for range lookups needs to be in big endian order */ diff --git a/src/expression.c b/src/expression.c index 66a8793f..4b3e1e04 100644 --- a/src/expression.c +++ b/src/expression.c @@ -162,7 +162,7 @@ struct expr *verdict_expr_alloc(const struct location *loc, static void symbol_expr_print(const struct expr *expr) { - printf("%s", expr->identifier); + printf("%s%s", expr->scope != NULL ? "$" : "", expr->identifier); } static void symbol_expr_destroy(struct expr *expr) diff --git a/src/parser.y b/src/parser.y index 1ca5981b..d9da115a 100644 --- a/src/parser.y +++ b/src/parser.y @@ -151,6 +151,7 @@ static void location_update(struct location *loc, struct location *rhs, int n) %token SET "set" %token INCLUDE "include" +%token DEFINE "define" %token HOOK "hook" %token HOOKNUM "hooknum" @@ -379,8 +380,8 @@ static void location_update(struct location *loc, struct location *rhs, int n) %type set_expr set_list_expr set_list_member_expr %destructor { expr_free($$); } set_expr set_list_expr set_list_member_expr -%type expr -%destructor { expr_free($$); } expr +%type expr initializer_expr +%destructor { expr_free($$); } expr initializer_expr %type match_expr %destructor { expr_free($$); } match_expr @@ -461,6 +462,11 @@ common_block : INCLUDE QUOTED_STRING stmt_seperator } xfree($2); } + | DEFINE identifier '=' initializer_expr stmt_seperator + { + symbol_bind(current_scope(state), $2, $4); + xfree($2); + } ; line : common_block { $$ = NULL; } @@ -809,6 +815,12 @@ symbol_expr : string $$ = symbol_expr_alloc(&@$, $1); xfree($1); } + | '$' identifier + { + $$ = symbol_expr_alloc(&@$, $2); + $$->scope = current_scope(state); + xfree($2); + } ; integer_expr : NUM @@ -985,17 +997,18 @@ expr : concat_expr | multiton_expr ; +initializer_expr : expr + | set_expr + | list_expr + ; + match_expr : relational_expr | membership_expr ; relational_expr : expr /* implicit */ expr { - enum ops op; - - /* RHS determines operation */ - op = ($2->ops->type == EXPR_RANGE) ? OP_RANGE : OP_EQ; - $$ = relational_expr_alloc(&@$, op, $1, $2); + $$ = relational_expr_alloc(&@$, OP_IMPLICIT, $1, $2); } | expr /* implicit */ list_expr { diff --git a/src/scanner.l b/src/scanner.l index 3b22bb9e..7fc01f77 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -207,6 +207,8 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "-" { return DASH; } "*" { return ASTERISK; } "@" { return AT; } +"$" { return '$'; } +"=" { return '='; } "=>" { return ARROW; } "map" { return MAP; } "vmap" { return VMAP; } @@ -219,6 +221,7 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "NF_INET_POST_ROUTING" { yylval->val = NF_INET_POST_ROUTING; return HOOKNUM; } "include" { return INCLUDE; } +"define" { return DEFINE; } "describe" { return DESCRIBE; } -- cgit v1.2.3