summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/parser.h8
-rw-r--r--include/rule.h33
-rw-r--r--src/parser.y32
-rw-r--r--src/rule.c32
4 files changed, 103 insertions, 2 deletions
diff --git a/include/parser.h b/include/parser.h
index a47bd0f0..f5dd6f4b 100644
--- a/include/parser.h
+++ b/include/parser.h
@@ -2,6 +2,7 @@
#define NFTABLES_PARSER_H
#include <list.h>
+#include <rule.h> // FIXME
#define MAX_INCLUDE_DEPTH 16
#define TABSIZE 8
@@ -10,12 +11,19 @@
#define YYLTYPE_IS_TRIVIAL 0
#define YYENABLE_NLS 0
+#define SCOPE_NEST_MAX 3
+
struct parser_state {
struct input_descriptor *indesc;
struct input_descriptor indescs[MAX_INCLUDE_DEPTH];
unsigned int indesc_idx;
struct list_head *msgs;
+
+ struct scope top_scope;
+ struct scope *scopes[SCOPE_NEST_MAX];
+ unsigned int scope;
+
struct list_head cmds;
};
diff --git a/include/rule.h b/include/rule.h
index 991d1125..4e5da064 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -24,6 +24,37 @@ extern void handle_merge(struct handle *dst, const struct handle *src);
extern void handle_free(struct handle *h);
/**
+ * struct scope
+ *
+ * @parent: pointer to parent scope
+ * @symbols: symbols bound in the scope
+ */
+struct scope {
+ const struct scope *parent;
+ struct list_head symbols;
+};
+
+extern struct scope *scope_init(struct scope *scope, const struct scope *parent);
+
+/**
+ * struct symbol
+ *
+ * @list: scope symbol list node
+ * @identifier: identifier
+ * @expr: initializer
+ */
+struct symbol {
+ struct list_head list;
+ const char *identifier;
+ struct expr *expr;
+};
+
+extern void symbol_bind(struct scope *scope, const char *identifier,
+ struct expr *expr);
+extern struct symbol *symbol_lookup(const struct scope *scope,
+ const char *identifier);
+
+/**
* struct table - nftables table
*
* @list: list node
@@ -33,6 +64,7 @@ extern void handle_free(struct handle *h);
struct table {
struct list_head list;
struct handle handle;
+ struct scope scope;
struct list_head chains;
};
@@ -55,6 +87,7 @@ struct chain {
struct handle handle;
unsigned int hooknum;
unsigned int priority;
+ struct scope scope;
struct list_head rules;
};
diff --git a/src/parser.y b/src/parser.y
index b13e932e..1ca5981b 100644
--- a/src/parser.y
+++ b/src/parser.y
@@ -33,6 +33,7 @@ void parser_init(struct parser_state *state, struct list_head *msgs)
memset(state, 0, sizeof(*state));
init_list_head(&state->cmds);
state->msgs = msgs;
+ state->scopes[0] = scope_init(&state->top_scope, NULL);
}
static void yyerror(struct location *loc, void *scanner,
@@ -41,6 +42,22 @@ static void yyerror(struct location *loc, void *scanner,
erec_queue(error(loc, "%s", s), state->msgs);
}
+static struct scope *current_scope(const struct parser_state *state)
+{
+ return state->scopes[state->scope];
+}
+
+static void open_scope(struct parser_state *state, struct scope *scope)
+{
+ scope_init(scope, current_scope(state));
+ state->scopes[++state->scope] = scope;
+}
+
+static void close_scope(struct parser_state *state)
+{
+ state->scope--;
+}
+
static void location_init(void *scanner, struct parser_state *state,
struct location *loc)
{
@@ -474,6 +491,7 @@ add_cmd : TABLE table_spec
'{' table_block '}'
{
handle_merge(&$3->handle, &$2);
+ close_scope(state);
$$ = cmd_alloc(CMD_ADD, CMD_OBJ_TABLE, &$2, $5);
}
| CHAIN chain_spec
@@ -484,6 +502,7 @@ add_cmd : TABLE table_spec
'{' chain_block '}'
{
handle_merge(&$3->handle, &$2);
+ close_scope(state);
$$ = cmd_alloc(CMD_ADD, CMD_OBJ_CHAIN, &$2, $5);
}
| RULE ruleid_spec rule
@@ -530,7 +549,11 @@ flush_cmd : TABLE table_spec
}
;
-table_block_alloc : /* empty */ { $$ = table_alloc(); }
+table_block_alloc : /* empty */
+ {
+ $$ = table_alloc();
+ open_scope(state, &$$->scope);
+ }
;
table_block : /* empty */ { $$ = $<table>-1; }
@@ -547,11 +570,16 @@ table_line : CHAIN chain_identifier chain_block_alloc
'{' chain_block '}'
{
handle_merge(&$3->handle, &$2);
+ close_scope(state);
$$ = $3;
}
;
-chain_block_alloc : /* empty */ { $$ = chain_alloc(NULL); }
+chain_block_alloc : /* empty */
+ {
+ $$ = chain_alloc(NULL);
+ open_scope(state, &$$->scope);
+ }
;
chain_block : /* empty */ { $$ = $<chain>-1; }
diff --git a/src/rule.c b/src/rule.c
index e86c78aa..8efbd887 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -68,6 +68,38 @@ void rule_print(const struct rule *rule)
printf("\n");
}
+struct scope *scope_init(struct scope *scope, const struct scope *parent)
+{
+ scope->parent = parent;
+ init_list_head(&scope->symbols);
+ return scope;
+}
+
+void symbol_bind(struct scope *scope, const char *identifier, struct expr *expr)
+{
+ struct symbol *sym;
+
+ sym = xzalloc(sizeof(*sym));
+ sym->identifier = xstrdup(identifier);
+ sym->expr = expr;
+
+ list_add_tail(&sym->list, &scope->symbols);
+}
+
+struct symbol *symbol_lookup(const struct scope *scope, const char *identifier)
+{
+ struct symbol *sym;
+
+ while (scope != NULL) {
+ list_for_each_entry(sym, &scope->symbols, list) {
+ if (!strcmp(sym->identifier, identifier))
+ return sym;
+ }
+ scope = scope->parent;
+ }
+ return NULL;
+}
+
struct chain *chain_alloc(const char *name)
{
struct chain *chain;