summaryrefslogtreecommitdiffstats
path: root/src/libnftables.c
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2022-01-02 21:39:42 +0100
committerPablo Neira Ayuso <pablo@netfilter.org>2022-01-15 18:11:22 +0100
commit5c2b2b0a2ba7c1403c6af3e59dd3f51d04a64645 (patch)
treebd49b55be7618b302307e808fc7c23e2acb59760 /src/libnftables.c
parent8ad4056e9182a03cf160b045532f0569d6b79c22 (diff)
src: error reporting with -f and read from stdin
Reading from stdin requires to store the ruleset in a buffer so error reporting works accordingly, eg. # cat ruleset.nft | nft -f - /dev/stdin:3:13-13: Error: unknown identifier 'x' ip saddr $x ^ The error reporting infrastructure performs a fseek() on the file descriptor which does not work in this case since the data from the descriptor has been already consumed. This patch adds a new stdin input descriptor to perform this special handling which consists on re-routing this request through the buffer functions. Fixes: 935f82e7dd49 ("Support 'nft -f -' to read from stdin") Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src/libnftables.c')
-rw-r--r--src/libnftables.c48
1 files changed, 44 insertions, 4 deletions
diff --git a/src/libnftables.c b/src/libnftables.c
index 7b9d7efa..e76f32ef 100644
--- a/src/libnftables.c
+++ b/src/libnftables.c
@@ -424,13 +424,14 @@ static const struct input_descriptor indesc_cmdline = {
};
static int nft_parse_bison_buffer(struct nft_ctx *nft, const char *buf,
- struct list_head *msgs, struct list_head *cmds)
+ struct list_head *msgs, struct list_head *cmds,
+ const struct input_descriptor *indesc)
{
int ret;
parser_init(nft, nft->state, msgs, cmds, nft->top_scope);
nft->scanner = scanner_init(nft->state);
- scanner_push_buffer(nft->scanner, &indesc_cmdline, buf);
+ scanner_push_buffer(nft->scanner, indesc, buf);
ret = nft_parse(nft, nft->scanner, nft->state);
if (ret != 0 || nft->state->nerrs > 0)
@@ -439,11 +440,42 @@ static int nft_parse_bison_buffer(struct nft_ctx *nft, const char *buf,
return 0;
}
+static char *stdin_to_buffer(void)
+{
+ unsigned int bufsiz = 16384, consumed = 0;
+ int numbytes;
+ char *buf;
+
+ buf = xmalloc(bufsiz);
+
+ numbytes = read(STDIN_FILENO, buf, bufsiz);
+ while (numbytes > 0) {
+ consumed += numbytes;
+ if (consumed == bufsiz) {
+ bufsiz *= 2;
+ buf = realloc(buf, bufsiz);
+ }
+ numbytes = read(STDIN_FILENO, buf + consumed, bufsiz - consumed);
+ }
+ buf[consumed] = '\0';
+
+ return buf;
+}
+
+static const struct input_descriptor indesc_stdin = {
+ .type = INDESC_STDIN,
+ .name = "/dev/stdin",
+};
+
static int nft_parse_bison_filename(struct nft_ctx *nft, const char *filename,
struct list_head *msgs, struct list_head *cmds)
{
int ret;
+ if (nft->stdin_buf)
+ return nft_parse_bison_buffer(nft, nft->stdin_buf, msgs, cmds,
+ &indesc_stdin);
+
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)
@@ -510,7 +542,8 @@ int nft_run_cmd_from_buffer(struct nft_ctx *nft, const char *buf)
if (nft_output_json(&nft->output))
rc = nft_parse_json_buffer(nft, nlbuf, &msgs, &cmds);
if (rc == -EINVAL)
- rc = nft_parse_bison_buffer(nft, nlbuf, &msgs, &cmds);
+ rc = nft_parse_bison_buffer(nft, nlbuf, &msgs, &cmds,
+ &indesc_cmdline);
parser_rc = rc;
@@ -578,7 +611,7 @@ retry:
}
snprintf(buf + offset, bufsize - offset, "\n");
- rc = nft_parse_bison_buffer(ctx, buf, msgs, &cmds);
+ rc = nft_parse_bison_buffer(ctx, buf, msgs, &cmds, &indesc_cmdline);
assert(list_empty(&cmds));
/* Stash the buffer that contains the variable definitions and zap the
@@ -608,6 +641,10 @@ int nft_run_cmd_from_filename(struct nft_ctx *nft, const char *filename)
if (!strcmp(filename, "-"))
filename = "/dev/stdin";
+ if (!strcmp(filename, "/dev/stdin") &&
+ !nft_output_json(&nft->output))
+ nft->stdin_buf = stdin_to_buffer();
+
rc = -EINVAL;
if (nft_output_json(&nft->output))
rc = nft_parse_json_filename(nft, filename, &msgs, &cmds);
@@ -656,5 +693,8 @@ err:
json_print_echo(nft);
if (rc)
nft_cache_release(&nft->cache);
+
+ xfree(nft->stdin_buf);
+
return rc;
}