From a2ed880a19d0861342b3515721804b18d698bf44 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Thu, 2 Aug 2018 17:05:17 +0200 Subject: xshared: Consolidate argv construction routines Implementations were equal in {ip,ip6,x}tables-restore.c. The one in iptables-xml.c differed slightly. For now, collect all features together. Maybe it would make sense to migrate iptables-xml.c to using add_param_to_argv() at some point and therefore extend the latter to store whether a given parameter was quoted or not. While being at it, a few improvements were done: * free_argv() now also resets 'newargc' variable, so users don't have to do that anymore. * Indenting level in add_param_to_argv() was reduced a bit. * That long error message is put into a single line to aid in grepping for it. * Explicit call to exit() after xtables_error() is removed since the latter does not return anyway. Signed-off-by: Phil Sutter Signed-off-by: Florian Westphal --- iptables/xshared.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) (limited to 'iptables/xshared.c') diff --git a/iptables/xshared.c b/iptables/xshared.c index ec5c4955..492e0087 100644 --- a/iptables/xshared.c +++ b/iptables/xshared.c @@ -379,3 +379,126 @@ inline bool xs_has_arg(int argc, char *argv[]) argv[optind][0] != '-' && argv[optind][0] != '!'; } + +/* global new argv and argc */ +char *newargv[255]; +int newargc = 0; + +/* saved newargv and newargc from save_argv() */ +char *oldargv[255]; +int oldargc = 0; + +/* arg meta data, were they quoted, frinstance */ +int newargvattr[255]; + +/* function adding one argument to newargv, updating newargc + * returns true if argument added, false otherwise */ +int add_argv(const char *what, int quoted) +{ + DEBUGP("add_argv: %s\n", what); + if (what && newargc + 1 < ARRAY_SIZE(newargv)) { + newargv[newargc] = strdup(what); + newargvattr[newargc] = quoted; + newargv[++newargc] = NULL; + return 1; + } else { + xtables_error(PARAMETER_PROBLEM, + "Parser cannot handle more arguments\n"); + } +} + +void free_argv(void) +{ + while (newargc) + free(newargv[--newargc]); + while (oldargc) + free(oldargv[--oldargc]); +} + +/* Save parsed rule for comparison with next rule to perform action aggregation + * on duplicate conditions. + */ +void save_argv(void) +{ + unsigned int i; + + while (oldargc) + free(oldargv[--oldargc]); + + oldargc = newargc; + newargc = 0; + for (i = 0; i < oldargc; i++) { + oldargv[i] = newargv[i]; + } +} + +void add_param_to_argv(char *parsestart, int line) +{ + int quote_open = 0, escaped = 0, param_len = 0; + char param_buffer[1024], *curchar; + + /* After fighting with strtok enough, here's now + * a 'real' parser. According to Rusty I'm now no + * longer a real hacker, but I can live with that */ + + for (curchar = parsestart; *curchar; curchar++) { + if (quote_open) { + if (escaped) { + param_buffer[param_len++] = *curchar; + escaped = 0; + continue; + } else if (*curchar == '\\') { + escaped = 1; + continue; + } else if (*curchar == '"') { + quote_open = 0; + *curchar = '"'; + } else { + param_buffer[param_len++] = *curchar; + continue; + } + } else { + if (*curchar == '"') { + quote_open = 1; + continue; + } + } + + switch (*curchar) { + case '"': + break; + case ' ': + case '\t': + case '\n': + if (!param_len) { + /* two spaces? */ + continue; + } + break; + default: + /* regular character, copy to buffer */ + param_buffer[param_len++] = *curchar; + + if (param_len >= sizeof(param_buffer)) + xtables_error(PARAMETER_PROBLEM, + "Parameter too long!"); + continue; + } + + param_buffer[param_len] = '\0'; + + /* check if table name specified */ + if ((param_buffer[0] == '-' && + param_buffer[1] != '-' && + strchr(param_buffer, 't')) || + (!strncmp(param_buffer, "--t", 3) && + !strncmp(param_buffer, "--table", strlen(param_buffer)))) { + xtables_error(PARAMETER_PROBLEM, + "The -t option (seen in line %u) cannot be used in %s.\n", + line, xt_params->program_name); + } + + add_argv(param_buffer, 0); + param_len = 0; + } +} -- cgit v1.2.3