diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2018-03-03 22:52:35 +0100 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2018-03-04 00:22:50 +0100 |
commit | 3b20f47277c0cb4ea07ad30f94496c9f383035e7 (patch) | |
tree | c5b0b1fc569dd64cd3fdcedaecfacf22b0abe6dd /src/rule.c | |
parent | 8162d2b96718041dadc52ab127db9d91a2c223cc (diff) |
src: add variable expression and use it to allow redefinitions
Add new variable expression that we can use to attach symbols in
runtime, this allows us to redefine variables via new keyword, eg.
table ip x {
chain y {
define address = { 1.1.1.1, 2.2.2.2 }
ip saddr $address
redefine address = { 3.3.3.3 }
ip saddr $address
}
}
# nft list ruleset
table ip x {
chain y {
ip saddr { 1.1.1.1, 2.2.2.2 }
ip saddr { 3.3.3.3 }
}
}
Note that redefinition just places a new symbol version before the
existing one, so symbol lookups always find the latest version. The
undefine keyword decrements the reference counter and removes the symbol
from the list, so it cannot be used anymore. Still, previous references
to this symbol via variable expression are still valid.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src/rule.c')
-rw-r--r-- | src/rule.c | 39 |
1 files changed, 33 insertions, 6 deletions
@@ -467,6 +467,7 @@ void scope_release(const struct scope *scope) struct symbol *sym, *next; list_for_each_entry_safe(sym, next, &scope->symbols, list) { + assert(sym->refcnt == 1); list_del(&sym->list); xfree(sym->identifier); expr_free(sym->expr); @@ -481,22 +482,48 @@ void symbol_bind(struct scope *scope, const char *identifier, struct expr *expr) sym = xzalloc(sizeof(*sym)); sym->identifier = xstrdup(identifier); sym->expr = expr; + sym->refcnt = 1; - list_add_tail(&sym->list, &scope->symbols); + list_add(&sym->list, &scope->symbols); } -int symbol_unbind(struct scope *scope, const char *identifier) +struct symbol *symbol_get(const struct scope *scope, const char *identifier) { struct symbol *sym; sym = symbol_lookup(scope, identifier); if (!sym) - return -1; + return NULL; + + sym->refcnt++; + return sym; +} + +static void symbol_put(struct symbol *sym) +{ + if (--sym->refcnt == 0) { + xfree(sym->identifier); + expr_free(sym->expr); + xfree(sym); + } +} + +static void symbol_remove(struct symbol *sym) +{ list_del(&sym->list); - xfree(sym->identifier); - expr_free(sym->expr); - xfree(sym); + symbol_put(sym); +} + +int symbol_unbind(const struct scope *scope, const char *identifier) +{ + struct symbol *sym, *next; + + list_for_each_entry_safe(sym, next, &scope->symbols, list) { + if (!strcmp(sym->identifier, identifier)) + symbol_remove(sym); + } + return 0; } |