Let users set the port range to be used for forward mode NAT:
...
<forward mode='nat'>
<nat>
<port start='1024' end='65535'/>
</nat>
</forward>
...
Signed-off-by: Natanael Copa <ncopa(a)alpinelinux.org>
---
docs/formatnetwork.html.in | 15 ++++++++++++--
src/conf/network_conf.c | 50 +++++++++++++++++++++++++++++++++++++++++----
src/conf/network_conf.h | 3 ++-
src/network/bridge_driver.c | 16 +++++++++++++++
src/util/viriptables.c | 39 +++++++++++++++++++++++++++--------
src/util/viriptables.h | 4 ++++
6 files changed, 111 insertions(+), 16 deletions(-)
diff --git a/docs/formatnetwork.html.in b/docs/formatnetwork.html.in
index 608fce1..381de41 100644
--- a/docs/formatnetwork.html.in
+++ b/docs/formatnetwork.html.in
@@ -138,7 +138,8 @@
0.4.2</span>
<p><span class="since">Since 1.0.3</span> it is
possible to
- specify the public IPv4 address to be used for the NAT by using
+ specify the public IPv4 address(es) and ports to be used for
+ the NAT. A single public address can be specified with the
the <code><nat></code> subelement and attribute
<code>address</code>:
<pre>
@@ -160,7 +161,17 @@
</forward>
...
</pre>
-
+ The port range to be used for the
<code><nat></code> can
+ be set via the subelement <code><port></code>:
+ <pre>
+...
+ <forward mode='nat'>
+ <nat>
+ <port start='500' end='1000'/>
+ </nat>
+ </forward>
+...
+ </pre>
</p>
</dd>
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index fb57b70..1d1dfd3 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -1332,7 +1332,8 @@ virNetworkForwardNatDefParseXML(const char *networkName,
{
int ret = -1;
xmlNodePtr *natAddrNodes = NULL;
- int nNatAddrs;
+ xmlNodePtr *natPortNodes = NULL;
+ int nNatAddrs, nNatPorts;
char *addr_start = NULL;
char *addr_end = NULL;
xmlNodePtr save = ctxt->node;
@@ -1392,6 +1393,36 @@ virNetworkForwardNatDefParseXML(const char *networkName,
goto cleanup;
}
+ /* ports for SNAT and MASQUERADE */
+ nNatPorts = virXPathNodeSet("./port", ctxt, &natPortNodes);
+ if (nNatPorts < 0) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("invalid <port> element found in <forward> of
"
+ "network %s"), networkName);
+ goto cleanup;
+ } else if (nNatPorts > 1) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("Only one <port> element is allowed in <nat> in
"
+ "<forward> in network %s"), networkName);
+ goto cleanup;
+ } else if (nNatPorts == 1) {
+ if (virXPathUInt("string(./port[1]/@start)", ctxt,
&def->port_start) < 0
+ || def->port_start > 65535) {
+
+ virReportError(VIR_ERR_XML_DETAIL,
+ _("Missing or invalid 'start' attribute in
<port> "
+ "in <nat> in <forward> in network
%s"),
+ networkName);
+ goto cleanup;
+ }
+ if (virXPathUInt("string(./port[1]/@end)", ctxt, &def->port_end)
< 0
+ || def->port_end > 65535 || def->port_end < def->port_start) {
+ virReportError(VIR_ERR_XML_DETAIL,
+ _("Missing or invalid 'end' attribute in
<port> in "
+ "<nat> in <forward> in network %s"),
networkName);
+ goto cleanup;
+ }
+ }
ret = 0;
cleanup:
@@ -2181,6 +2212,7 @@ virNatDefFormat(virBufferPtr buf,
char *addr_start = NULL;
char *addr_end = NULL;
int ret = -1;
+ int longdef;
if (VIR_SOCKET_ADDR_VALID(&fwd->addr_start)) {
addr_start = virSocketAddrFormat(&fwd->addr_start);
@@ -2194,14 +2226,15 @@ virNatDefFormat(virBufferPtr buf,
goto cleanup;
}
- if (!addr_end && !addr_start)
+ longdef = addr_end || fwd->port_start || fwd->port_end;
+ if (!longdef && !addr_start)
return 0;
virBufferAddLit(buf, "<nat");
if (addr_start && !addr_end)
virBufferAsprintf(buf, " address='%s'", addr_start);
- if (!addr_end) {
+ if (!longdef) {
virBufferAsprintf(buf, "/>\n");
ret = 0;
goto cleanup;
@@ -2214,6 +2247,13 @@ virNatDefFormat(virBufferPtr buf,
virBufferAsprintf(buf, "<address start='%s'
end='%s'/>\n",
addr_start, addr_end);
+ if (fwd->port_start || fwd->port_end) {
+ virBufferAsprintf(buf, "<port start='%d'",
fwd->port_start);
+ if (fwd->port_end)
+ virBufferAsprintf(buf, " end='%d'", fwd->port_end);
+ virBufferAsprintf(buf, "/>\n");
+ }
+
virBufferAdjustIndent(buf, -2);
virBufferAsprintf(buf, "</nat>\n");
ret = 0;
@@ -2270,7 +2310,9 @@ virNetworkDefFormatInternal(virBufferPtr buf,
}
shortforward = !(def->forward.nifs || def->forward.npfs
|| VIR_SOCKET_ADDR_VALID(&def->forward.addr_start)
- || VIR_SOCKET_ADDR_VALID(&def->forward.addr_end));
+ || VIR_SOCKET_ADDR_VALID(&def->forward.addr_end)
+ || def->forward.port_start
+ || def->forward.port_end);
virBufferAsprintf(buf, "%s>\n", shortforward ? "/" :
"");
virBufferAdjustIndent(buf, 2);
diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h
index 1a598e3..7df2426 100644
--- a/src/conf/network_conf.h
+++ b/src/conf/network_conf.h
@@ -175,8 +175,9 @@ struct _virNetworkForwardDef {
size_t nifs;
virNetworkForwardIfDefPtr ifs;
- /* adresses for SNAT */
+ /* ranges for NAT */
virSocketAddr addr_start, addr_end;
+ unsigned int port_start, port_end;
};
typedef struct _virPortGroupDef virPortGroupDef;
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index d444ddb..0ea49e8 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -1592,6 +1592,8 @@ networkAddMasqueradingIptablesRules(struct network_driver *driver,
forwardIf,
&network->def->forward.addr_start,
&network->def->forward.addr_end,
+ network->def->forward.port_start,
+ network->def->forward.port_end,
NULL) < 0) {
virReportError(VIR_ERR_SYSTEM_ERROR,
forwardIf ?
@@ -1608,6 +1610,8 @@ networkAddMasqueradingIptablesRules(struct network_driver *driver,
forwardIf,
&network->def->forward.addr_start,
&network->def->forward.addr_end,
+ network->def->forward.port_start,
+ network->def->forward.port_end,
"udp") < 0) {
virReportError(VIR_ERR_SYSTEM_ERROR,
forwardIf ?
@@ -1624,6 +1628,8 @@ networkAddMasqueradingIptablesRules(struct network_driver *driver,
forwardIf,
&network->def->forward.addr_start,
&network->def->forward.addr_end,
+ network->def->forward.port_start,
+ network->def->forward.port_end,
"tcp") < 0) {
virReportError(VIR_ERR_SYSTEM_ERROR,
forwardIf ?
@@ -1642,6 +1648,8 @@ networkAddMasqueradingIptablesRules(struct network_driver *driver,
forwardIf,
&network->def->forward.addr_start,
&network->def->forward.addr_end,
+ network->def->forward.port_start,
+ network->def->forward.port_end,
"udp");
masqerr4:
iptablesRemoveForwardMasquerade(driver->iptables,
@@ -1650,6 +1658,8 @@ networkAddMasqueradingIptablesRules(struct network_driver *driver,
forwardIf,
&network->def->forward.addr_start,
&network->def->forward.addr_end,
+ network->def->forward.port_start,
+ network->def->forward.port_end,
NULL);
masqerr3:
iptablesRemoveForwardAllowRelatedIn(driver->iptables,
@@ -1682,6 +1692,8 @@ networkRemoveMasqueradingIptablesRules(struct network_driver
*driver,
forwardIf,
&network->def->forward.addr_start,
&network->def->forward.addr_end,
+ network->def->forward.port_start,
+ network->def->forward.port_end,
"tcp");
iptablesRemoveForwardMasquerade(driver->iptables,
&ipdef->address,
@@ -1689,6 +1701,8 @@ networkRemoveMasqueradingIptablesRules(struct network_driver
*driver,
forwardIf,
&network->def->forward.addr_start,
&network->def->forward.addr_end,
+ network->def->forward.port_start,
+ network->def->forward.port_end,
"udp");
iptablesRemoveForwardMasquerade(driver->iptables,
&ipdef->address,
@@ -1696,6 +1710,8 @@ networkRemoveMasqueradingIptablesRules(struct network_driver
*driver,
forwardIf,
&network->def->forward.addr_start,
&network->def->forward.addr_end,
+ network->def->forward.port_start,
+ network->def->forward.port_end,
NULL);
iptablesRemoveForwardAllowRelatedIn(driver->iptables,
diff --git a/src/util/viriptables.c b/src/util/viriptables.c
index f2d15bf..3578ab8 100644
--- a/src/util/viriptables.c
+++ b/src/util/viriptables.c
@@ -807,6 +807,8 @@ iptablesForwardMasquerade(iptablesContext *ctx,
const char *physdev,
virSocketAddr *addr_start,
virSocketAddr *addr_end,
+ unsigned int port_start,
+ unsigned int port_end,
const char *protocol,
int action)
{
@@ -815,6 +817,7 @@ iptablesForwardMasquerade(iptablesContext *ctx,
char *addr_start_str = NULL;
char *addr_end_str = NULL;
virCommandPtr cmd = NULL;
+ char port_str[sizeof(":65535-65535")] = "";
if (!(networkstr = iptablesFormatNetwork(netaddr, prefix)))
return -1;
@@ -849,19 +852,27 @@ iptablesForwardMasquerade(iptablesContext *ctx,
if (physdev && physdev[0])
virCommandAddArgList(cmd, "--out-interface", physdev, NULL);
+ if (protocol && protocol[0]) {
+ if (port_start == 0 && port_end == 0) {
+ port_start = 1024;
+ port_end = 65535;
+ }
+
+ if (port_start < port_end && port_end < 65536)
+ snprintf(port_str, sizeof(port_str), ":%d-%d",
+ port_start, port_end);
+ }
+
/* Use --jump SNAT if public addr is specified */
if (addr_start_str && addr_start_str[0]) {
char tmpstr[sizeof("123.123.123.123-123.123.123.123:65535-65535")];
- const char *portstr = "";
memset(tmpstr, 0, sizeof(tmpstr));
- if (protocol && protocol[0])
- portstr = ":1024-65535";
if (addr_end_str && addr_end_str[0]) {
snprintf(tmpstr, sizeof(tmpstr), "%s-%s%s",
- addr_start_str, addr_end_str, portstr);
+ addr_start_str, addr_end_str, port_str);
} else {
- snprintf(tmpstr, sizeof(tmpstr), "%s%s", addr_start_str, portstr);
+ snprintf(tmpstr, sizeof(tmpstr), "%s%s", addr_start_str,
port_str);
}
virCommandAddArgList(cmd, "--jump", "SNAT",
@@ -869,8 +880,8 @@ iptablesForwardMasquerade(iptablesContext *ctx,
} else {
virCommandAddArgList(cmd, "--jump", "MASQUERADE", NULL);
- if (protocol && protocol[0])
- virCommandAddArgList(cmd, "--to-ports", "1024-65535",
NULL);
+ if (port_str[0])
+ virCommandAddArgList(cmd, "--to-ports", &port_str[1], NULL);
}
ret = iptablesCommandRunAndFree(cmd);
@@ -899,9 +910,14 @@ iptablesAddForwardMasquerade(iptablesContext *ctx,
const char *physdev,
virSocketAddr *addr_start,
virSocketAddr *addr_end,
+ unsigned int port_start,
+ unsigned int port_end,
const char *protocol)
{
- return iptablesForwardMasquerade(ctx, netaddr, prefix, physdev, addr_start, addr_end,
protocol, ADD);
+ return iptablesForwardMasquerade(ctx, netaddr, prefix, physdev,
+ addr_start, addr_end,
+ port_start, port_end,
+ protocol, ADD);
}
/**
@@ -924,9 +940,14 @@ iptablesRemoveForwardMasquerade(iptablesContext *ctx,
const char *physdev,
virSocketAddr *addr_start,
virSocketAddr *addr_end,
+ unsigned int port_start,
+ unsigned int port_end,
const char *protocol)
{
- return iptablesForwardMasquerade(ctx, netaddr, prefix, physdev, addr_start, addr_end,
protocol, REMOVE);
+ return iptablesForwardMasquerade(ctx, netaddr, prefix, physdev,
+ addr_start, addr_end,
+ port_start, port_end,
+ protocol, REMOVE);
}
diff --git a/src/util/viriptables.h b/src/util/viriptables.h
index 4241380..f2db368 100644
--- a/src/util/viriptables.h
+++ b/src/util/viriptables.h
@@ -109,6 +109,8 @@ int iptablesAddForwardMasquerade (iptablesContext
*ctx,
const char *physdev,
virSocketAddr *addr_start,
virSocketAddr *addr_end,
+ unsigned int port_start,
+ unsigned int port_end,
const char *protocol);
int iptablesRemoveForwardMasquerade (iptablesContext *ctx,
virSocketAddr *netaddr,
@@ -116,6 +118,8 @@ int iptablesRemoveForwardMasquerade (iptablesContext
*ctx,
const char *physdev,
virSocketAddr *addr_start,
virSocketAddr *addr_end,
+ unsigned int port_start,
+ unsigned int port_end,
const char *protocol);
int iptablesAddOutputFixUdpChecksum (iptablesContext *ctx,
const char *iface,
--
1.8.1.2