summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2009-03-20 08:34:59 +0100
committerPatrick McHardy <kaber@trash.net>2009-03-20 08:34:59 +0100
commit878cc0e4e863e6b2c9fa71f791d35245b3ddbdb2 (patch)
treebd29fb4134cc513820af99f196671264b4c367dc
parent5c40780440c0e8661fc7cfcec72dab48b934631d (diff)
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 <kaber@trash.net>
-rw-r--r--include/expression.h2
-rw-r--r--src/evaluate.c37
-rw-r--r--src/expression.c2
-rw-r--r--src/parser.y27
-rw-r--r--src/scanner.l3
5 files changed, 59 insertions, 12 deletions
diff --git a/include/expression.h b/include/expression.h
index e9d21cfc..d4222060 100644
--- a/include/expression.h
+++ b/include/expression.h
@@ -55,6 +55,7 @@ enum expr_types {
enum ops {
OP_INVALID,
+ OP_IMPLICIT,
/* Unary operations */
OP_HTON,
OP_NTOH,
@@ -172,6 +173,7 @@ struct expr {
struct {
/* EXPR_SYMBOL */
const struct datatype *sym_type;
+ const struct scope *scope;
const char *identifier;
};
struct {
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 <val> HOOKNUM "hooknum"
@@ -379,8 +380,8 @@ static void location_update(struct location *loc, struct location *rhs, int n)
%type <expr> set_expr set_list_expr set_list_member_expr
%destructor { expr_free($$); } set_expr set_list_expr set_list_member_expr
-%type <expr> expr
-%destructor { expr_free($$); } expr
+%type <expr> expr initializer_expr
+%destructor { expr_free($$); } expr initializer_expr
%type <expr> 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; }