diff options
author | Jan Engelhardt <jengelh@medozas.de> | 2011-04-17 13:33:50 +0200 |
---|---|---|
committer | Jan Engelhardt <jengelh@medozas.de> | 2011-05-01 14:43:22 +0200 |
commit | f30231a02e145020fb47524f9a0daeb498a4f7d0 (patch) | |
tree | fbd6c2e808519fc72f7e3ad6860c41080066a749 | |
parent | ee1fbbe536c6dd3a252886815314cf910d672ca6 (diff) |
libxtables: XTTYPE_PORTRC support
Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
-rw-r--r-- | include/xtables.h.in | 6 | ||||
-rw-r--r-- | xtoptions.c | 59 |
2 files changed, 64 insertions, 1 deletions
diff --git a/include/xtables.h.in b/include/xtables.h.in index b06ab613..0cd9f9f8 100644 --- a/include/xtables.h.in +++ b/include/xtables.h.in @@ -56,6 +56,8 @@ struct in_addr; * %XTTYPE_ONEHOST: one host or address (union nf_inet_addr) * %XTTYPE_PORT: 16-bit port name or number * %XTTYPE_PORT_NE: 16-bit port name or number, stored as network-endian + * %XTTYPE_PORTRC: colon-separated port range (names acceptable) + * %XTTYPE_PORTRC_NE: same as %XTTYPE_PORTRC, stored in network-endian */ enum xt_option_type { XTTYPE_NONE, @@ -74,6 +76,8 @@ enum xt_option_type { XTTYPE_ONEHOST, XTTYPE_PORT, XTTYPE_PORT_NE, + XTTYPE_PORTRC, + XTTYPE_PORTRC_NE, }; /** @@ -129,7 +133,7 @@ struct xt_option_call { uint8_t nvals; union { uint8_t u8, u8_range[2], syslog_level; - uint16_t u16, u16_range[2], port; + uint16_t u16, u16_range[2], port, port_range[2]; uint32_t u32, u32_range[2]; uint64_t u64, u64_range[2]; union nf_inet_addr inetaddr; diff --git a/xtoptions.c b/xtoptions.c index 69e43e95..5b1df889 100644 --- a/xtoptions.c +++ b/xtoptions.c @@ -483,6 +483,61 @@ static void xtopt_parse_port(struct xt_option_call *cb) *(uint16_t *)XTOPT_MKPTR(cb) = cb->val.port; } +static void xtopt_parse_mport(struct xt_option_call *cb) +{ + static const size_t esize = sizeof(uint16_t); + const struct xt_option_entry *entry = cb->entry; + char *lo_arg, *wp_arg, *arg; + unsigned int maxiter; + int value; + + wp_arg = lo_arg = strdup(cb->arg); + if (lo_arg == NULL) + xt_params->exit_err(RESOURCE_PROBLEM, "strdup"); + + maxiter = entry->size / esize; + if (maxiter == 0) + maxiter = 2; /* ARRAY_SIZE(cb->val.port_range) */ + if (entry->size % esize != 0) + xt_params->exit_err(OTHER_PROBLEM, "%s: memory block does " + "not have proper size\n", __func__); + + cb->val.port_range[0] = 0; + cb->val.port_range[1] = UINT16_MAX; + cb->nvals = 0; + + while ((arg = strsep(&wp_arg, ":")) != NULL) { + if (cb->nvals == maxiter) + xt_params->exit_err(PARAMETER_PROBLEM, "%s: Too many " + "components for option \"--%s\" (max: %u)\n", + cb->ext_name, entry->name, maxiter); + if (*arg == '\0') { + ++cb->nvals; + continue; + } + + value = xtables_getportbyname(arg); + if (value < 0) + xt_params->exit_err(PARAMETER_PROBLEM, + "Port \"%s\" does not resolve to " + "anything.\n", arg); + if (entry->type == XTTYPE_PORTRC_NE) + value = htons(value); + if (cb->nvals < ARRAY_SIZE(cb->val.port_range)) + cb->val.port_range[cb->nvals] = value; + ++cb->nvals; + } + + if (cb->nvals == 1) { + cb->val.port_range[1] = cb->val.port_range[0]; + ++cb->nvals; + } + if (entry->flags & XTOPT_PUT) + memcpy(XTOPT_MKPTR(cb), cb->val.port_range, sizeof(uint16_t) * + (cb->nvals <= maxiter ? cb->nvals : maxiter)); + free(lo_arg); +} + static void (*const xtopt_subparse[])(struct xt_option_call *) = { [XTTYPE_UINT8] = xtopt_parse_int, [XTTYPE_UINT16] = xtopt_parse_int, @@ -499,6 +554,8 @@ static void (*const xtopt_subparse[])(struct xt_option_call *) = { [XTTYPE_ONEHOST] = xtopt_parse_onehost, [XTTYPE_PORT] = xtopt_parse_port, [XTTYPE_PORT_NE] = xtopt_parse_port, + [XTTYPE_PORTRC] = xtopt_parse_mport, + [XTTYPE_PORTRC_NE] = xtopt_parse_mport, }; static const size_t xtopt_psize[] = { @@ -515,6 +572,8 @@ static const size_t xtopt_psize[] = { [XTTYPE_ONEHOST] = sizeof(union nf_inet_addr), [XTTYPE_PORT] = sizeof(uint16_t), [XTTYPE_PORT_NE] = sizeof(uint16_t), + [XTTYPE_PORTRC] = sizeof(uint16_t[2]), + [XTTYPE_PORTRC_NE] = sizeof(uint16_t[2]), }; /** |