[iptables PATCH 9/9] extensions: DNAT: Support service names in all spots

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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




[Index of Archives]     [Netfitler Users]     [Berkeley Packet Filter]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux