]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
libnftables: Store top_scope in struct nft_ctx
authorPhil Sutter <phil@nwl.cc>
Wed, 30 Oct 2019 20:45:39 +0000 (21:45 +0100)
committerPhil Sutter <phil@nwl.cc>
Thu, 7 Nov 2019 11:46:16 +0000 (12:46 +0100)
Allow for interactive sessions to make use of defines. Since parser is
initialized for each line, top scope defines didn't persist although
they are actually useful for stuff like:

| # nft -i
| define goodports = { 22, 23, 80, 443 }
| add rule inet t c tcp dport $goodports accept
| add rule inet t c tcp sport $goodports accept

While being at it, introduce scope_alloc() and scope_free().

Signed-off-by: Phil Sutter <phil@nwl.cc>
Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
include/nftables.h
include/parser.h
include/rule.h
src/libnftables.c
src/parser_bison.y
src/rule.c
tests/shell/testcases/nft-i/0001define_0 [new file with mode: 0755]

index 21553c6bb3a52256a8b6d5d5dd2cd537f275ce8b..90d331960ef29d25c2e05caeb49d4553f7f7fbe9 100644 (file)
@@ -104,6 +104,7 @@ struct nft_cache {
 
 struct mnl_socket;
 struct parser_state;
+struct scope;
 
 #define MAX_INCLUDE_DEPTH      16
 
@@ -119,6 +120,7 @@ struct nft_ctx {
        uint32_t                flags;
        struct parser_state     *state;
        void                    *scanner;
+       struct scope            *top_scope;
        void                    *json_root;
        FILE                    *f[MAX_INCLUDE_DEPTH];
 };
index 39a752121a6b8ec25c2d321d9f7ae9bd987b1966..949284d9466c62797bfd7d35e33bc25c92f27a65 100644 (file)
@@ -22,7 +22,6 @@ struct parser_state {
        struct list_head                *msgs;
        unsigned int                    nerrs;
 
-       struct scope                    top_scope;
        struct scope                    *scopes[SCOPE_NEST_MAX];
        unsigned int                    scope;
 
@@ -32,7 +31,8 @@ struct parser_state {
 struct mnl_socket;
 
 extern void parser_init(struct nft_ctx *nft, struct parser_state *state,
-                       struct list_head *msgs, struct list_head *cmds);
+                       struct list_head *msgs, struct list_head *cmds,
+                       struct scope *top_scope);
 extern int nft_parse(struct nft_ctx *ctx, void *, struct parser_state *state);
 
 extern void *scanner_init(struct parser_state *state);
index 48b5ba5009657f4d4ee3bb32e76133ac239f293b..0b2eba37934b1ddfcf05403b33600390323fbbd6 100644 (file)
@@ -97,8 +97,10 @@ struct scope {
        struct list_head        symbols;
 };
 
+extern struct scope *scope_alloc(void);
 extern struct scope *scope_init(struct scope *scope, const struct scope *parent);
 extern void scope_release(const struct scope *scope);
+extern void scope_free(struct scope *scope);
 
 /**
  * struct symbol
index e20372438db622e63e9cdd4697a9f1087c4e8235..cd2fcf2fd522188f428a894c6b1c320d0afec555 100644 (file)
@@ -155,6 +155,7 @@ struct nft_ctx *nft_ctx_new(uint32_t flags)
        nft_ctx_add_include_path(ctx, DEFAULT_INCLUDE_PATH);
        ctx->parser_max_errors  = 10;
        init_list_head(&ctx->cache.list);
+       ctx->top_scope = scope_alloc();
        ctx->flags = flags;
        ctx->output.output_fp = stdout;
        ctx->output.error_fp = stderr;
@@ -292,6 +293,7 @@ void nft_ctx_free(struct nft_ctx *ctx)
        iface_cache_release();
        cache_release(&ctx->cache);
        nft_ctx_clear_include_paths(ctx);
+       scope_free(ctx->top_scope);
        xfree(ctx->state);
        nft_exit(ctx);
        xfree(ctx);
@@ -368,7 +370,7 @@ static int nft_parse_bison_buffer(struct nft_ctx *nft, const char *buf,
 {
        int ret;
 
-       parser_init(nft, nft->state, msgs, cmds);
+       parser_init(nft, nft->state, msgs, cmds, nft->top_scope);
        nft->scanner = scanner_init(nft->state);
        scanner_push_buffer(nft->scanner, &indesc_cmdline, buf);
 
@@ -384,7 +386,7 @@ static int nft_parse_bison_filename(struct nft_ctx *nft, const char *filename,
 {
        int ret;
 
-       parser_init(nft, nft->state, msgs, cmds);
+       parser_init(nft, nft->state, msgs, cmds, nft->top_scope);
        nft->scanner = scanner_init(nft->state);
        if (scanner_read_file(nft, filename, &internal_location) < 0)
                return -1;
index 6f525d5b85240f023afee6bf30362796315e8c3b..3f2832564036e16b4d7bacf3db00637258156407 100644 (file)
 #include "parser_bison.h"
 
 void parser_init(struct nft_ctx *nft, struct parser_state *state,
-                struct list_head *msgs, struct list_head *cmds)
+                struct list_head *msgs, struct list_head *cmds,
+                struct scope *top_scope)
 {
        memset(state, 0, sizeof(*state));
-       init_list_head(&state->top_scope.symbols);
        state->msgs = msgs;
        state->cmds = cmds;
-       state->scopes[0] = scope_init(&state->top_scope, NULL);
+       state->scopes[0] = scope_init(top_scope, NULL);
        init_list_head(&state->indesc_list);
 }
 
index 552b3c6b303a36f0d696f6158ac0a9203b15d569..4abc13c993b8925756d229e50e920263672df1f6 100644 (file)
@@ -645,6 +645,15 @@ struct rule *rule_lookup_by_index(const struct chain *chain, uint64_t index)
        return NULL;
 }
 
+struct scope *scope_alloc(void)
+{
+       struct scope *scope = xzalloc(sizeof(struct scope));
+
+       init_list_head(&scope->symbols);
+
+       return scope;
+}
+
 struct scope *scope_init(struct scope *scope, const struct scope *parent)
 {
        scope->parent = parent;
@@ -664,6 +673,12 @@ void scope_release(const struct scope *scope)
        }
 }
 
+void scope_free(struct scope *scope)
+{
+       scope_release(scope);
+       xfree(scope);
+}
+
 void symbol_bind(struct scope *scope, const char *identifier, struct expr *expr)
 {
        struct symbol *sym;
diff --git a/tests/shell/testcases/nft-i/0001define_0 b/tests/shell/testcases/nft-i/0001define_0
new file mode 100755 (executable)
index 0000000..62e1b6d
--- /dev/null
@@ -0,0 +1,22 @@
+#!/bin/bash
+
+set -e
+
+# test if using defines in interactive nft sessions works
+
+$NFT -i >/dev/null <<EOF
+add table inet t
+add chain inet t c
+define ports = { 22, 443 }
+add rule inet t c tcp dport \$ports accept
+add rule inet t c udp dport \$ports accept
+EOF
+
+$NFT -i >/dev/null <<EOF
+define port = 22
+flush chain inet t c
+redefine port = 443
+delete chain inet t c
+undefine port
+delete table inet t
+EOF