When parsing (parts of) a port spec, if it doesn't start with a digit, try to find the largest substring getservbyname() accepts. Signed-off-by: Phil Sutter <phil@xxxxxx> --- extensions/libipt_DNAT.t | 4 +++ extensions/libxt_DNAT.c | 70 +++++++++++++++++++++++++++---------- extensions/libxt_REDIRECT.t | 2 ++ 3 files changed, 58 insertions(+), 18 deletions(-) diff --git a/extensions/libipt_DNAT.t b/extensions/libipt_DNAT.t index eb187bc91053b..c744dff3ec902 100644 --- a/extensions/libipt_DNAT.t +++ b/extensions/libipt_DNAT.t @@ -15,4 +15,8 @@ -p tcp -j DNAT --to-destination 1.1.1.1:1000-2000/65536;;FAIL -p tcp -j DNAT --to-destination 1.1.1.1:ssh;-p tcp -j DNAT --to-destination 1.1.1.1:22;OK -p tcp -j DNAT --to-destination 1.1.1.1:ftp-data;-p tcp -j DNAT --to-destination 1.1.1.1:20;OK +-p tcp -j DNAT --to-destination 1.1.1.1:ftp-data-ssh;-p tcp -j DNAT --to-destination 1.1.1.1:20-22;OK +-p tcp -j DNAT --to-destination 1.1.1.1:echo-ftp-data;-p tcp -j DNAT --to-destination 1.1.1.1:7-20;OK +-p tcp -j DNAT --to-destination 1.1.1.1:ftp-data-ssh/echo;-p tcp -j DNAT --to-destination 1.1.1.1:20-22/7;OK +-p tcp -j DNAT --to-destination 1.1.1.1:echo-ftp-data/ssh;-p tcp -j DNAT --to-destination 1.1.1.1:7-20/22;OK -j DNAT;;FAIL diff --git a/extensions/libxt_DNAT.c b/extensions/libxt_DNAT.c index 754e244e0dbe6..70d2823568c7d 100644 --- a/extensions/libxt_DNAT.c +++ b/extensions/libxt_DNAT.c @@ -77,6 +77,49 @@ static const struct xt_option_entry REDIRECT_opts[] = { XTOPT_TABLEEND, }; +static char *strrchrs(const char *s, const char *chrs) +{ + int i; + + for (i = strlen(s) - 1; i >= 0; i--) { + if (strchr(chrs, s[i])) + return (char *)s + i; + } + return NULL; +} + +static bool parse_port(const char *orig_s, char **end, unsigned int *value, + unsigned int min, unsigned int max) +{ + char *s, *pos; + int port; + + if (xtables_strtoui(orig_s, end, value, min, max)) + return true; + + s = xtables_strdup(orig_s); + port = xtables_service_to_port(s, NULL); + if (port >= min && port <= max) + goto found; + + pos = strrchrs(s, "-:/"); + while (pos) { + *pos = '\0'; + port = xtables_service_to_port(s, NULL); + if (port >= min && port <= max) + goto found; + + pos = strrchrs(s, "-:/"); + } + free(s); + return false; +found: + *end = (char *)orig_s + strlen(s); + *value = port; + free(s); + return true; +} + /* Parses ports */ static void parse_ports(const char *arg, bool portok, struct nf_nat_range2 *range) @@ -90,12 +133,9 @@ parse_ports(const char *arg, bool portok, struct nf_nat_range2 *range) range->flags |= NF_NAT_RANGE_PROTO_SPECIFIED; - if (!xtables_strtoui(arg, &end, &port, 1, UINT16_MAX)) { - port = xtables_service_to_port(arg, NULL); - if (port == (unsigned)-1) - xtables_error(PARAMETER_PROBLEM, - "Port `%s' not valid", arg); - } + if (!parse_port(arg, &end, &port, 1, UINT16_MAX)) + xtables_error(PARAMETER_PROBLEM, + "Port `%s' not valid", arg); switch (*end) { case '\0': @@ -114,12 +154,9 @@ parse_ports(const char *arg, bool portok, struct nf_nat_range2 *range) "Garbage after port value: `%s'", end); } - if (!xtables_strtoui(arg, &end, &maxport, 1, UINT16_MAX)) { - maxport = xtables_service_to_port(arg, NULL); - if (maxport == (unsigned)-1) - xtables_error(PARAMETER_PROBLEM, - "Port `%s' not valid", arg); - } + if (!parse_port(arg, &end, &maxport, 1, UINT16_MAX)) + xtables_error(PARAMETER_PROBLEM, + "Port `%s' not valid", arg); if (maxport < port) /* People are stupid. */ xtables_error(PARAMETER_PROBLEM, @@ -139,12 +176,9 @@ parse_ports(const char *arg, bool portok, struct nf_nat_range2 *range) "Garbage after port range: `%s'", end); } - if (!xtables_strtoui(arg, &end, &baseport, 1, UINT16_MAX)) { - baseport = xtables_service_to_port(arg, NULL); - if (baseport == (unsigned)-1) - xtables_error(PARAMETER_PROBLEM, - "Port `%s' not valid", arg); - } + if (!parse_port(arg, &end, &baseport, 1, UINT16_MAX)) + xtables_error(PARAMETER_PROBLEM, + "Port `%s' not valid", arg); range->flags |= NF_NAT_RANGE_PROTO_OFFSET; range->base_proto.tcp.port = htons(baseport); diff --git a/extensions/libxt_REDIRECT.t b/extensions/libxt_REDIRECT.t index 3f0b8a6000445..a50ef257ec956 100644 --- a/extensions/libxt_REDIRECT.t +++ b/extensions/libxt_REDIRECT.t @@ -6,4 +6,6 @@ -p tcp -j REDIRECT --to-ports 42-1234/567;;FAIL -p tcp -j REDIRECT --to-ports ssh;-p tcp -j REDIRECT --to-ports 22;OK -p tcp -j REDIRECT --to-ports ftp-data;-p tcp -j REDIRECT --to-ports 20;OK +-p tcp -j REDIRECT --to-ports ftp-data-ssh;-p tcp -j REDIRECT --to-ports 20-22;OK +-p tcp -j REDIRECT --to-ports echo-ftp-data;-p tcp -j REDIRECT --to-ports 7-20;OK -j REDIRECT --to-ports 42;;FAIL -- 2.34.1