diff options
Diffstat (limited to 'libxtables/xtables.c')
-rw-r--r-- | libxtables/xtables.c | 116 |
1 files changed, 87 insertions, 29 deletions
diff --git a/libxtables/xtables.c b/libxtables/xtables.c index 0638f927..f2fcc5c2 100644 --- a/libxtables/xtables.c +++ b/libxtables/xtables.c @@ -64,7 +64,6 @@ #endif #include <getopt.h> #include "iptables/internal.h" -#include "xshared.h" #define NPROTO 255 @@ -112,10 +111,8 @@ void basic_exit_err(enum xtables_exittype status, const char *msg, ...) void xtables_free_opts(int unused) { - if (xt_params->opts != xt_params->orig_opts) { - free(xt_params->opts); - xt_params->opts = NULL; - } + free(xt_params->opts); + xt_params->opts = NULL; } struct option *xtables_merge_options(struct option *orig_opts, @@ -482,14 +479,9 @@ static char *get_modprobe(void) char *ret; int count; - procfile = open(PROC_SYS_MODPROBE, O_RDONLY); + procfile = open(PROC_SYS_MODPROBE, O_RDONLY | O_CLOEXEC); if (procfile < 0) return NULL; - if (fcntl(procfile, F_SETFD, FD_CLOEXEC) == -1) { - fprintf(stderr, "Could not set close on exec: %s\n", - strerror(errno)); - exit(1); - } ret = malloc(PATH_MAX); if (ret) { @@ -586,23 +578,23 @@ int xtables_load_ko(const char *modprobe, bool quiet) } /** - * xtables_strtou{i,l} - string to number conversion + * xtables_strtoul_base - string to number conversion * @s: input string * @end: like strtoul's "end" pointer * @value: pointer for result * @min: minimum accepted value * @max: maximum accepted value + * @base: assumed base of value * * If @end is NULL, we assume the caller wants a "strict strtoul", and hence * "15a" is rejected. * In either case, the value obtained is compared for min-max compliance. - * Base is always 0, i.e. autodetect depending on @s. * * Returns true/false whether number was accepted. On failure, *value has * undefined contents. */ -bool xtables_strtoul(const char *s, char **end, uintmax_t *value, - uintmax_t min, uintmax_t max) +bool xtables_strtoul_base(const char *s, char **end, uintmax_t *value, + uintmax_t min, uintmax_t max, unsigned int base) { uintmax_t v; const char *p; @@ -614,7 +606,7 @@ bool xtables_strtoul(const char *s, char **end, uintmax_t *value, ; if (*p == '-') return false; - v = strtoumax(s, &my_end, 0); + v = strtoumax(s, &my_end, base); if (my_end == s) return false; if (end != NULL) @@ -631,6 +623,12 @@ bool xtables_strtoul(const char *s, char **end, uintmax_t *value, return false; } +bool xtables_strtoul(const char *s, char **end, uintmax_t *value, + uintmax_t min, uintmax_t max) +{ + return xtables_strtoul_base(s, end, value, min, max, 0); +} + bool xtables_strtoui(const char *s, char **end, unsigned int *value, unsigned int min, unsigned int max) { @@ -777,6 +775,7 @@ xtables_find_match(const char *name, enum xtables_tryload tryload, struct xtables_match *ptr; const char *icmp6 = "icmp6"; bool found = false; + bool seen = false; if (strlen(name) >= XT_EXTENSION_MAXNAMELEN) xtables_error(PARAMETER_PROBLEM, @@ -795,6 +794,7 @@ xtables_find_match(const char *name, enum xtables_tryload tryload, if (extension_cmp(name, (*dptr)->name, (*dptr)->family)) { ptr = *dptr; *dptr = (*dptr)->next; + seen = true; if (!found && xtables_fully_register_pending_match(ptr, prev)) { found = true; @@ -808,6 +808,11 @@ xtables_find_match(const char *name, enum xtables_tryload tryload, dptr = &((*dptr)->next); } + if (seen && !found) + fprintf(stderr, + "Warning: Extension %s is not supported, missing kernel module?\n", + name); + for (ptr = xtables_matches; ptr; ptr = ptr->next) { if (extension_cmp(name, ptr->name, ptr->family)) { struct xtables_match *clone; @@ -900,6 +905,7 @@ xtables_find_target(const char *name, enum xtables_tryload tryload) struct xtables_target **dptr; struct xtables_target *ptr; bool found = false; + bool seen = false; /* Standard target? */ if (strcmp(name, "") == 0 @@ -918,6 +924,7 @@ xtables_find_target(const char *name, enum xtables_tryload tryload) if (extension_cmp(name, (*dptr)->name, (*dptr)->family)) { ptr = *dptr; *dptr = (*dptr)->next; + seen = true; if (!found && xtables_fully_register_pending_target(ptr, prev)) { found = true; @@ -931,6 +938,11 @@ xtables_find_target(const char *name, enum xtables_tryload tryload) dptr = &((*dptr)->next); } + if (seen && !found) + fprintf(stderr, + "Warning: Extension %s is not supported, missing kernel module?\n", + name); + for (ptr = xtables_targets; ptr; ptr = ptr->next) { if (extension_cmp(name, ptr->name, ptr->family)) { struct xtables_target *clone; @@ -1010,7 +1022,7 @@ int xtables_compatible_revision(const char *name, uint8_t revision, int opt) socklen_t s = sizeof(rev); int max_rev, sockfd; - sockfd = socket(afinfo->family, SOCK_RAW, IPPROTO_RAW); + sockfd = socket(afinfo->family, SOCK_RAW | SOCK_CLOEXEC, IPPROTO_RAW); if (sockfd < 0) { if (errno == EPERM) { /* revision 0 is always supported. */ @@ -1026,12 +1038,6 @@ int xtables_compatible_revision(const char *name, uint8_t revision, int opt) exit(1); } - if (fcntl(sockfd, F_SETFD, FD_CLOEXEC) == -1) { - fprintf(stderr, "Could not set close on exec: %s\n", - strerror(errno)); - exit(1); - } - xtables_load_ko(xtables_modprobe_program, true); strncpy(rev.name, name, XT_EXTENSION_MAXNAMELEN - 1); @@ -1412,6 +1418,10 @@ void xtables_rule_matches_free(struct xtables_rule_match **matches) free(matchp->match->m); matchp->match->m = NULL; } + if (matchp->match->udata_size) { + free(matchp->match->udata); + matchp->match->udata = NULL; + } if (matchp->match == matchp->match->next) { free(matchp->match); matchp->match = NULL; @@ -2193,6 +2203,8 @@ const struct xtables_pprot xtables_chain_protos[] = { {"mobility-header", IPPROTO_MH}, {"ipv6-mh", IPPROTO_MH}, {"mh", IPPROTO_MH}, + {"dccp", IPPROTO_DCCP}, + {"ipcomp", IPPROTO_COMP}, {"all", 0}, {NULL}, }; @@ -2477,16 +2489,39 @@ void xt_xlate_free(struct xt_xlate *xl) free(xl); } +static bool isbrace(char c) +{ + switch (c) { + case '(': + case ')': + case '{': + case '}': + case '[': + case ']': + return true; + } + return false; +} + static void __xt_xlate_add(struct xt_xlate *xl, enum xt_xlate_type type, - const char *fmt, va_list ap) + bool space, const char *fmt, va_list ap) { struct xt_xlate_buf *buf = &xl->buf[type]; + char tmpbuf[1024] = ""; int len; - len = vsnprintf(buf->data + buf->off, buf->rem, fmt, ap); - if (len < 0 || len >= buf->rem) + len = vsnprintf(tmpbuf, 1024, fmt, ap); + if (len < 0 || len >= buf->rem - 1) xtables_error(RESOURCE_PROBLEM, "OOM"); + if (space && buf->off && + !isspace(buf->data[buf->off - 1]) && + (isalnum(tmpbuf[0]) || isbrace(tmpbuf[0]))) { + buf->data[buf->off] = ' '; + buf->off++; + buf->rem--; + } + sprintf(buf->data + buf->off, "%s", tmpbuf); buf->rem -= len; buf->off += len; } @@ -2496,7 +2531,16 @@ void xt_xlate_rule_add(struct xt_xlate *xl, const char *fmt, ...) va_list ap; va_start(ap, fmt); - __xt_xlate_add(xl, XT_XLATE_RULE, fmt, ap); + __xt_xlate_add(xl, XT_XLATE_RULE, true, fmt, ap); + va_end(ap); +} + +void xt_xlate_rule_add_nospc(struct xt_xlate *xl, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + __xt_xlate_add(xl, XT_XLATE_RULE, false, fmt, ap); va_end(ap); } @@ -2505,7 +2549,16 @@ void xt_xlate_set_add(struct xt_xlate *xl, const char *fmt, ...) va_list ap; va_start(ap, fmt); - __xt_xlate_add(xl, XT_XLATE_SET, fmt, ap); + __xt_xlate_add(xl, XT_XLATE_SET, true, fmt, ap); + va_end(ap); +} + +void xt_xlate_set_add_nospc(struct xt_xlate *xl, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + __xt_xlate_add(xl, XT_XLATE_SET, false, fmt, ap); va_end(ap); } @@ -2532,7 +2585,12 @@ uint8_t xt_xlate_get_family(struct xt_xlate *xl) const char *xt_xlate_get(struct xt_xlate *xl) { - return xl->buf[XT_XLATE_RULE].data; + struct xt_xlate_buf *buf = &xl->buf[XT_XLATE_RULE]; + + while (buf->off && isspace(buf->data[buf->off - 1])) + buf->data[--buf->off] = '\0'; + + return buf->data; } const char *xt_xlate_set_get(struct xt_xlate *xl) |