* [PATCH v3] iptables: allow service names in [DS]NAT targets
@ 2013-07-31 16:48 Phil Oester
0 siblings, 0 replies; only message in thread
From: Phil Oester @ 2013-07-31 16:48 UTC (permalink / raw)
To: netfilter-devel; +Cc: pablo
[-- Attachment #1: Type: text/plain, Size: 470 bytes --]
As reported by Alexander Hoogerhuis, the [DS]NAT targets do not allow use of
service names in the --to argument. The same problem was fixed in the REDIRECT
target in commit 84d758b3 ("extensions: REDIRECT: fix --to-ports parser").
Use a similar fix here.
This closes bugzilla #514.
Phil
Signed-off-by: Phil Oester <kernel@linuxace.com>
---
v2: also handle IPv6 [DS]NAT targets
v3: update manpage to reflect when this option becomes available + limitation on range
[-- Attachment #2: patch-514 --]
[-- Type: text/plain, Size: 12452 bytes --]
diff --git a/extensions/libip6t_DNAT.c b/extensions/libip6t_DNAT.c
index eaa6bf1..f842e40 100644
--- a/extensions/libip6t_DNAT.c
+++ b/extensions/libip6t_DNAT.c
@@ -46,7 +46,7 @@ static const struct xt_option_entry DNAT_opts[] = {
static void
parse_to(const char *orig_arg, int portok, struct nf_nat_range *range)
{
- char *arg, *start, *end = NULL, *colon = NULL, *dash, *error;
+ char *arg, *start, *end = "", *colon = NULL, *dash;
const struct in6_addr *ip;
arg = strdup(orig_arg);
@@ -60,8 +60,7 @@ parse_to(const char *orig_arg, int portok, struct nf_nat_range *range)
colon = strchr(arg, ':');
if (colon && strchr(colon+1, ':'))
colon = NULL;
- }
- else {
+ } else {
start++;
end = strchr(start, ']');
if (end == NULL)
@@ -73,7 +72,7 @@ parse_to(const char *orig_arg, int portok, struct nf_nat_range *range)
}
if (colon) {
- int port;
+ unsigned int port, maxport;
if (!portok)
xtables_error(PARAMETER_PROBLEM,
@@ -81,34 +80,29 @@ parse_to(const char *orig_arg, int portok, struct nf_nat_range *range)
range->flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
- port = atoi(colon+1);
- if (port <= 0 || port > 65535)
- xtables_error(PARAMETER_PROBLEM,
- "Port `%s' not valid\n", colon+1);
-
- error = strchr(colon+1, ':');
- if (error)
- xtables_error(PARAMETER_PROBLEM,
- "Invalid port:port syntax - use dash\n");
+ if (!xtables_strtoui(colon + 1, &end, &port, 0, UINT16_MAX) &&
+ (port = xtables_service_to_port(colon + 1, NULL)) == (unsigned)-1)
+ xtables_param_act(XTF_BAD_VALUE, "DNAT", "--to", colon);
- dash = strchr(colon, '-');
- if (!dash) {
+ switch (*end) {
+ case '\0':
range->min_proto.tcp.port
= range->max_proto.tcp.port
= htons(port);
- } else {
- int maxport;
+ break;
+ case '-':
+ if (!xtables_strtoui(end + 1, NULL, &maxport, 0, UINT16_MAX) &&
+ (maxport = xtables_service_to_port(end + 1, NULL)) == (unsigned)-1)
+ xtables_param_act(XTF_BAD_VALUE, "DNAT", "--to", colon);
- maxport = atoi(dash + 1);
- if (maxport <= 0 || maxport > 65535)
- xtables_error(PARAMETER_PROBLEM,
- "Port `%s' not valid\n", dash+1);
if (maxport < port)
- /* People are stupid. */
- xtables_error(PARAMETER_PROBLEM,
- "Port range `%s' funky\n", colon+1);
+ xtables_param_act(XTF_BAD_VALUE, "DNAT", "--to", colon);
+
range->min_proto.tcp.port = htons(port);
range->max_proto.tcp.port = htons(maxport);
+ break;
+ default:
+ xtables_param_act(XTF_BAD_VALUE, "DNAT", "--to", colon);
}
/* Starts with colon or [] colon? No IP info...*/
if (colon == arg || colon == arg+2) {
diff --git a/extensions/libip6t_SNAT.c b/extensions/libip6t_SNAT.c
index 7382ad0..ea46f1a 100644
--- a/extensions/libip6t_SNAT.c
+++ b/extensions/libip6t_SNAT.c
@@ -46,7 +46,7 @@ static const struct xt_option_entry SNAT_opts[] = {
static void
parse_to(const char *orig_arg, int portok, struct nf_nat_range *range)
{
- char *arg, *start, *end = NULL, *colon = NULL, *dash, *error;
+ char *arg, *start, *end = "", *colon = NULL, *dash;
const struct in6_addr *ip;
arg = strdup(orig_arg);
@@ -60,8 +60,7 @@ parse_to(const char *orig_arg, int portok, struct nf_nat_range *range)
colon = strchr(arg, ':');
if (colon && strchr(colon+1, ':'))
colon = NULL;
- }
- else {
+ } else {
start++;
end = strchr(start, ']');
if (end == NULL)
@@ -73,7 +72,7 @@ parse_to(const char *orig_arg, int portok, struct nf_nat_range *range)
}
if (colon) {
- int port;
+ unsigned int port, maxport;
if (!portok)
xtables_error(PARAMETER_PROBLEM,
@@ -81,34 +80,29 @@ parse_to(const char *orig_arg, int portok, struct nf_nat_range *range)
range->flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
- port = atoi(colon+1);
- if (port <= 0 || port > 65535)
- xtables_error(PARAMETER_PROBLEM,
- "Port `%s' not valid\n", colon+1);
-
- error = strchr(colon+1, ':');
- if (error)
- xtables_error(PARAMETER_PROBLEM,
- "Invalid port:port syntax - use dash\n");
+ if (!xtables_strtoui(colon + 1, &end, &port, 0, UINT16_MAX) &&
+ (port = xtables_service_to_port(colon + 1, NULL)) == (unsigned)-1)
+ xtables_param_act(XTF_BAD_VALUE, "SNAT", "--to", colon);
- dash = strchr(colon, '-');
- if (!dash) {
+ switch (*end) {
+ case '\0':
range->min_proto.tcp.port
= range->max_proto.tcp.port
= htons(port);
- } else {
- int maxport;
+ break;
+ case '-':
+ if (!xtables_strtoui(end + 1, NULL, &maxport, 0, UINT16_MAX) &&
+ (maxport = xtables_service_to_port(end + 1, NULL)) == (unsigned)-1)
+ xtables_param_act(XTF_BAD_VALUE, "SNAT", "--to", colon);
- maxport = atoi(dash + 1);
- if (maxport <= 0 || maxport > 65535)
- xtables_error(PARAMETER_PROBLEM,
- "Port `%s' not valid\n", dash+1);
if (maxport < port)
- /* People are stupid. */
- xtables_error(PARAMETER_PROBLEM,
- "Port range `%s' funky\n", colon+1);
+ xtables_param_act(XTF_BAD_VALUE, "SNAT", "--to", colon);
+
range->min_proto.tcp.port = htons(port);
range->max_proto.tcp.port = htons(maxport);
+ break;
+ default:
+ xtables_param_act(XTF_BAD_VALUE, "SNAT", "--to", colon);
}
/* Starts with colon or [] colon? No IP info...*/
if (colon == arg || colon == arg+2) {
diff --git a/extensions/libipt_DNAT.c b/extensions/libipt_DNAT.c
index ff18799..e452cfc 100644
--- a/extensions/libipt_DNAT.c
+++ b/extensions/libipt_DNAT.c
@@ -67,7 +67,7 @@ static struct xt_entry_target *
parse_to(const char *orig_arg, int portok, struct ipt_natinfo *info)
{
struct nf_nat_ipv4_range range;
- char *arg, *colon, *dash, *error;
+ char *arg, *colon, *dash;
const struct in_addr *ip;
arg = strdup(orig_arg);
@@ -77,7 +77,8 @@ parse_to(const char *orig_arg, int portok, struct ipt_natinfo *info)
colon = strchr(arg, ':');
if (colon) {
- int port;
+ char *end = "";
+ unsigned int port, maxport;
if (!portok)
xtables_error(PARAMETER_PROBLEM,
@@ -85,34 +86,29 @@ parse_to(const char *orig_arg, int portok, struct ipt_natinfo *info)
range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
- port = atoi(colon+1);
- if (port <= 0 || port > 65535)
- xtables_error(PARAMETER_PROBLEM,
- "Port `%s' not valid\n", colon+1);
-
- error = strchr(colon+1, ':');
- if (error)
- xtables_error(PARAMETER_PROBLEM,
- "Invalid port:port syntax - use dash\n");
+ if (!xtables_strtoui(colon + 1, &end, &port, 0, UINT16_MAX) &&
+ (port = xtables_service_to_port(colon + 1, NULL)) == (unsigned)-1)
+ xtables_param_act(XTF_BAD_VALUE, "DNAT", "--to", arg);
- dash = strchr(colon, '-');
- if (!dash) {
+ switch (*end) {
+ case '\0':
range.min.tcp.port
= range.max.tcp.port
= htons(port);
- } else {
- int maxport;
+ break;
+ case '-':
+ if (!xtables_strtoui(end + 1, NULL, &maxport, 0, UINT16_MAX) &&
+ (maxport = xtables_service_to_port(end + 1, NULL)) == (unsigned)-1)
+ xtables_param_act(XTF_BAD_VALUE, "DNAT", "--to", arg);
- maxport = atoi(dash + 1);
- if (maxport <= 0 || maxport > 65535)
- xtables_error(PARAMETER_PROBLEM,
- "Port `%s' not valid\n", dash+1);
if (maxport < port)
- /* People are stupid. */
- xtables_error(PARAMETER_PROBLEM,
- "Port range `%s' funky\n", colon+1);
+ xtables_param_act(XTF_BAD_VALUE, "DNAT", "--to", arg);
+
range.min.tcp.port = htons(port);
range.max.tcp.port = htons(maxport);
+ break;
+ default:
+ xtables_param_act(XTF_BAD_VALUE, "DNAT", "--to", arg);
}
/* Starts with a colon? No IP info...*/
if (colon == arg) {
diff --git a/extensions/libipt_SNAT.c b/extensions/libipt_SNAT.c
index 1a24f3d..01be677 100644
--- a/extensions/libipt_SNAT.c
+++ b/extensions/libipt_SNAT.c
@@ -67,7 +67,7 @@ static struct xt_entry_target *
parse_to(const char *orig_arg, int portok, struct ipt_natinfo *info)
{
struct nf_nat_ipv4_range range;
- char *arg, *colon, *dash, *error;
+ char *arg, *colon, *dash;
const struct in_addr *ip;
arg = strdup(orig_arg);
@@ -77,7 +77,8 @@ parse_to(const char *orig_arg, int portok, struct ipt_natinfo *info)
colon = strchr(arg, ':');
if (colon) {
- int port;
+ char *end = "";
+ unsigned int port, maxport;
if (!portok)
xtables_error(PARAMETER_PROBLEM,
@@ -85,34 +86,29 @@ parse_to(const char *orig_arg, int portok, struct ipt_natinfo *info)
range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
- port = atoi(colon+1);
- if (port <= 0 || port > 65535)
- xtables_error(PARAMETER_PROBLEM,
- "Port `%s' not valid\n", colon+1);
-
- error = strchr(colon+1, ':');
- if (error)
- xtables_error(PARAMETER_PROBLEM,
- "Invalid port:port syntax - use dash\n");
+ if (!xtables_strtoui(colon + 1, &end, &port, 0, UINT16_MAX) &&
+ (port = xtables_service_to_port(colon + 1, NULL)) == (unsigned)-1)
+ xtables_param_act(XTF_BAD_VALUE, "SNAT", "--to", arg);
- dash = strchr(colon, '-');
- if (!dash) {
+ switch (*end) {
+ case '\0':
range.min.tcp.port
= range.max.tcp.port
= htons(port);
- } else {
- int maxport;
+ break;
+ case '-':
+ if (!xtables_strtoui(end + 1, NULL, &maxport, 0, UINT16_MAX) &&
+ (maxport = xtables_service_to_port(end + 1, NULL)) == (unsigned)-1)
+ xtables_param_act(XTF_BAD_VALUE, "SNAT", "--to", arg);
- maxport = atoi(dash + 1);
- if (maxport <= 0 || maxport > 65535)
- xtables_error(PARAMETER_PROBLEM,
- "Port `%s' not valid\n", dash+1);
if (maxport < port)
- /* People are stupid. */
- xtables_error(PARAMETER_PROBLEM,
- "Port range `%s' funky\n", colon+1);
+ xtables_param_act(XTF_BAD_VALUE, "SNAT", "--to", arg);
+
range.min.tcp.port = htons(port);
range.max.tcp.port = htons(maxport);
+ break;
+ default:
+ xtables_param_act(XTF_BAD_VALUE, "SNAT", "--to", arg);
}
/* Starts with a colon? No IP info...*/
if (colon == arg) {
diff --git a/extensions/libxt_DNAT.man b/extensions/libxt_DNAT.man
index 225274f..70e5d9a 100644
--- a/extensions/libxt_DNAT.man
+++ b/extensions/libxt_DNAT.man
@@ -12,12 +12,15 @@ following options:
.TP
\fB\-\-to\-destination\fP [\fIipaddr\fP[\fB\-\fP\fIipaddr\fP]][\fB:\fP\fIport\fP[\fB\-\fP\fIport\fP]]
which can specify a single new destination IP address, an inclusive
-range of IP addresses. Optionally a port range,
+range of IP addresses. Optionally a port or port range,
if the rule also specifies one of the following protocols:
\fBtcp\fP, \fBudp\fP, \fBdccp\fP or \fBsctp\fP.
-If no port range is specified, then the destination port will never be
+If no port or port range is specified, then the destination port will never be
modified. If no IP address is specified then only the destination port
will be modified.
+Versions of iptables >= 1.4.20 accept service names for the port, however
+because service names can contain dashes, you cannot specify a port range if you
+use service names.
In Kernels up to 2.6.10 you can add several \-\-to\-destination options. For
those kernels, if you specify more than one destination address, either via an
address range or multiple \-\-to\-destination options, a simple round-robin (one
diff --git a/extensions/libxt_SNAT.man b/extensions/libxt_SNAT.man
index f0620a2..368ddc7 100644
--- a/extensions/libxt_SNAT.man
+++ b/extensions/libxt_SNAT.man
@@ -12,13 +12,16 @@ following options:
.TP
\fB\-\-to\-source\fP [\fIipaddr\fP[\fB\-\fP\fIipaddr\fP]][\fB:\fP\fIport\fP[\fB\-\fP\fIport\fP]]
which can specify a single new source IP address, an inclusive range
-of IP addresses. Optionally a port range,
+of IP addresses. Optionally a port or port range,
if the rule also specifies one of the following protocols:
\fBtcp\fP, \fBudp\fP, \fBdccp\fP or \fBsctp\fP.
-If no port range is specified, then source ports below 512 will be
+If no port or port range is specified, then source ports below 512 will be
mapped to other ports below 512: those between 512 and 1023 inclusive
will be mapped to ports below 1024, and other ports will be mapped to
1024 or above. Where possible, no port alteration will occur.
+Versions of iptables >= 1.4.20 accept service names for the port, however
+because service names can contain dashes, you cannot specify a port range if you
+use service names.
In Kernels up to 2.6.10, you can add several \-\-to\-source options. For those
kernels, if you specify more than one source address, either via an address
range or multiple \-\-to\-source options, a simple round-robin (one after another
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2013-07-31 16:48 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-07-31 16:48 [PATCH v3] iptables: allow service names in [DS]NAT targets Phil Oester
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).