summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2021-07-20 12:17:33 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2021-07-20 17:47:55 +0200
commit9edaa6a51eab49a378dd358e0b4254d0398c629f (patch)
treecb44b02953b6672d4239ec6f97c3d59de5d6cb10 /src
parent640dc0c8a3daef65cd93868939b5a2877615f2d5 (diff)
src: add --define key=value
This patch adds a new option to define variables from the command line. # cat test.nft table netdev x { chain y { type filter hook ingress devices = $dev priority 0; counter accept } } # nft --define dev="{ eth0, eth1 }" -f test.nft You can only combine it with -f/--filename. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src')
-rw-r--r--src/libnftables.c95
-rw-r--r--src/main.c22
2 files changed, 116 insertions, 1 deletions
diff --git a/src/libnftables.c b/src/libnftables.c
index e3b6ff0a..de6dc7cd 100644
--- a/src/libnftables.c
+++ b/src/libnftables.c
@@ -119,6 +119,43 @@ static void nft_exit(struct nft_ctx *ctx)
mark_table_exit(ctx);
}
+EXPORT_SYMBOL(nft_ctx_add_var);
+int nft_ctx_add_var(struct nft_ctx *ctx, const char *var)
+{
+ char *separator = strchr(var, '=');
+ int pcount = ctx->num_vars;
+ struct nft_vars *tmp;
+ const char *value;
+
+ if (!separator)
+ return -1;
+
+ tmp = realloc(ctx->vars, (pcount + 1) * sizeof(struct nft_vars));
+ if (!tmp)
+ return -1;
+
+ *separator = '\0';
+ value = separator + 1;
+
+ ctx->vars = tmp;
+ ctx->vars[pcount].key = xstrdup(var);
+ ctx->vars[pcount].value = xstrdup(value);
+ ctx->num_vars++;
+
+ return 0;
+}
+
+static void nft_ctx_clear_vars(struct nft_ctx *ctx)
+{
+ unsigned int i;
+
+ for (i = 0; i < ctx->num_vars; i++) {
+ xfree(ctx->vars[i].key);
+ xfree(ctx->vars[i].value);
+ }
+ xfree(ctx->vars);
+}
+
EXPORT_SYMBOL(nft_ctx_add_include_path);
int nft_ctx_add_include_path(struct nft_ctx *ctx, const char *path)
{
@@ -178,6 +215,7 @@ struct nft_ctx *nft_ctx_new(uint32_t flags)
ctx->flags = flags;
ctx->output.output_fp = stdout;
ctx->output.error_fp = stderr;
+ init_list_head(&ctx->vars_ctx.indesc_list);
if (flags == NFT_CTX_DEFAULT)
nft_ctx_netlink_init(ctx);
@@ -311,6 +349,7 @@ void nft_ctx_free(struct nft_ctx *ctx)
exit_cookie(&ctx->output.error_cookie);
iface_cache_release();
nft_cache_release(&ctx->cache);
+ nft_ctx_clear_vars(ctx);
nft_ctx_clear_include_paths(ctx);
scope_free(ctx->top_scope);
xfree(ctx->state);
@@ -507,6 +546,47 @@ err:
return rc;
}
+static int load_cmdline_vars(struct nft_ctx *ctx, struct list_head *msgs)
+{
+ unsigned int bufsize, ret, i, offset = 0;
+ LIST_HEAD(cmds);
+ char *buf;
+ int rc;
+
+ if (ctx->num_vars == 0)
+ return 0;
+
+ bufsize = 1024;
+ buf = xzalloc(bufsize + 1);
+ for (i = 0; i < ctx->num_vars; i++) {
+retry:
+ ret = snprintf(buf + offset, bufsize - offset,
+ "define %s=%s; ",
+ ctx->vars[i].key, ctx->vars[i].value);
+ if (ret >= bufsize - offset) {
+ bufsize *= 2;
+ buf = xrealloc(buf, bufsize + 1);
+ goto retry;
+ }
+ offset += ret;
+ }
+ snprintf(buf + offset, bufsize - offset, "\n");
+
+ rc = nft_parse_bison_buffer(ctx, buf, msgs, &cmds);
+
+ assert(list_empty(&cmds));
+ /* Stash the buffer that contains the variable definitions and zap the
+ * list of input descriptors before releasing the scanner state,
+ * otherwise error reporting path walks over released objects.
+ */
+ ctx->vars_ctx.buf = buf;
+ list_splice_init(&ctx->state->indesc_list, &ctx->vars_ctx.indesc_list);
+ scanner_destroy(ctx);
+ ctx->scanner = NULL;
+
+ return rc;
+}
+
EXPORT_SYMBOL(nft_run_cmd_from_filename);
int nft_run_cmd_from_filename(struct nft_ctx *nft, const char *filename)
{
@@ -515,6 +595,10 @@ int nft_run_cmd_from_filename(struct nft_ctx *nft, const char *filename)
LIST_HEAD(msgs);
LIST_HEAD(cmds);
+ rc = load_cmdline_vars(nft, &msgs);
+ if (rc < 0)
+ goto err;
+
if (!strcmp(filename, "-"))
filename = "/dev/stdin";
@@ -548,6 +632,17 @@ err:
scanner_destroy(nft);
nft->scanner = NULL;
}
+ if (!list_empty(&nft->vars_ctx.indesc_list)) {
+ struct input_descriptor *indesc, *next;
+
+ list_for_each_entry_safe(indesc, next, &nft->vars_ctx.indesc_list, list) {
+ if (indesc->name)
+ xfree(indesc->name);
+
+ xfree(indesc);
+ }
+ }
+ xfree(nft->vars_ctx.buf);
if (!rc &&
nft_output_json(&nft->output) &&
diff --git a/src/main.c b/src/main.c
index 8c470644..21096fc7 100644
--- a/src/main.c
+++ b/src/main.c
@@ -32,6 +32,7 @@ enum opt_indices {
/* Ruleset input handling */
IDX_FILE,
#define IDX_RULESET_INPUT_START IDX_FILE
+ IDX_DEFINE,
IDX_INTERACTIVE,
IDX_INCLUDEPATH,
IDX_CHECK,
@@ -63,6 +64,7 @@ enum opt_vals {
OPT_VERSION_LONG = 'V',
OPT_CHECK = 'c',
OPT_FILE = 'f',
+ OPT_DEFINE = 'D',
OPT_INTERACTIVE = 'i',
OPT_INCLUDEPATH = 'I',
OPT_JSON = 'j',
@@ -100,6 +102,8 @@ static const struct nft_opt nft_options[] = {
"Show extended version information"),
[IDX_FILE] = NFT_OPT("file", OPT_FILE, "<filename>",
"Read input from <filename>"),
+ [IDX_DEFINE] = NFT_OPT("define", OPT_DEFINE, "<name=value>",
+ "Define variable, e.g. --define foo=1.2.3.4"),
[IDX_INTERACTIVE] = NFT_OPT("interactive", OPT_INTERACTIVE, NULL,
"Read input from interactive CLI"),
[IDX_INCLUDEPATH] = NFT_OPT("includepath", OPT_INCLUDEPATH, "<directory>",
@@ -332,8 +336,10 @@ static bool nft_options_check(int argc, char * const argv[])
} else if (argv[i][1] == 'd' ||
argv[i][1] == 'I' ||
argv[i][1] == 'f' ||
+ argv[i][1] == 'D' ||
!strcmp(argv[i], "--debug") ||
!strcmp(argv[i], "--includepath") ||
+ !strcmp(argv[i], "--define") ||
!strcmp(argv[i], "--file")) {
skip = true;
continue;
@@ -349,10 +355,10 @@ static bool nft_options_check(int argc, char * const argv[])
int main(int argc, char * const *argv)
{
const struct option *options = get_options();
+ bool interactive = false, define = false;
const char *optstring = get_optstring();
char *buf = NULL, *filename = NULL;
unsigned int output_flags = 0;
- bool interactive = false;
unsigned int debug_mask;
unsigned int len;
int i, val, rc;
@@ -378,6 +384,15 @@ int main(int argc, char * const *argv)
case OPT_VERSION_LONG:
show_version();
exit(EXIT_SUCCESS);
+ case OPT_DEFINE:
+ if (nft_ctx_add_var(nft, optarg)) {
+ fprintf(stderr,
+ "Failed to define variable '%s'\n",
+ optarg);
+ exit(EXIT_FAILURE);
+ }
+ define = true;
+ break;
case OPT_CHECK:
nft_ctx_set_dry_run(nft, true);
break;
@@ -470,6 +485,11 @@ int main(int argc, char * const *argv)
}
}
+ if (!filename && define) {
+ fprintf(stderr, "Error: -D/--define can only be used with -f/--filename\n");
+ exit(EXIT_FAILURE);
+ }
+
nft_ctx_output_set_flags(nft, output_flags);
if (optind != argc) {