]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
util/viriptables: add/remove rules that short-circuit masquerading
authorLaszlo Ersek <lersek@redhat.com>
Wed, 25 Sep 2013 10:45:25 +0000 (12:45 +0200)
committerLaine Stump <laine@laine.org>
Wed, 25 Sep 2013 12:24:09 +0000 (08:24 -0400)
The functions
- iptablesAddForwardDontMasquerade(),
- iptablesRemoveForwardDontMasquerade
handle exceptions in the masquerading implemented in the POSTROUTING chain
of the "nat" table. Such exceptions should be added as chronologically
latest, logically top-most rules.

The bridge driver will call these functions beginning with the next patch:
some special destination IP addresses always refer to the local
subnetwork, even though they don't match any practical subnetwork's
netmask. Packets from virbrN targeting such IP addresses are never routed
outwards, but the current rules treat them as non-virbrN-destined packets
and masquerade them. This causes problems for some receivers on virbrN.

Signed-off-by: Laszlo Ersek <lersek@redhat.com>
src/libvirt_private.syms
src/util/viriptables.c
src/util/viriptables.h

index 1ecee4c2fdf883c9e5bb2e3b947b788e9fbb8473..48e4b047c8666104c32e8cb54254611952680476 100644 (file)
@@ -1448,6 +1448,7 @@ virInitctlSetRunLevel;
 
 
 # util/viriptables.h
+iptablesAddDontMasquerade;
 iptablesAddForwardAllowCross;
 iptablesAddForwardAllowIn;
 iptablesAddForwardAllowOut;
@@ -1458,6 +1459,7 @@ iptablesAddForwardRejectOut;
 iptablesAddOutputFixUdpChecksum;
 iptablesAddTcpInput;
 iptablesAddUdpInput;
+iptablesRemoveDontMasquerade;
 iptablesRemoveForwardAllowCross;
 iptablesRemoveForwardAllowIn;
 iptablesRemoveForwardAllowOut;
index 0f57d664b68d08a730e7c43d9c6a22145e6fe532..16f571ea7a6ceb2f4760f62636dc2fca560853c0 100644 (file)
@@ -832,6 +832,94 @@ iptablesRemoveForwardMasquerade(virSocketAddr *netaddr,
 }
 
 
+/* Don't masquerade traffic coming from the network associated with the bridge
+ * if said traffic targets @destaddr.
+ */
+static int
+iptablesForwardDontMasquerade(virSocketAddr *netaddr,
+                              unsigned int prefix,
+                              const char *physdev,
+                              const char *destaddr,
+                              int action)
+{
+    int ret = -1;
+    char *networkstr = NULL;
+    virCommandPtr cmd = NULL;
+
+    if (!(networkstr = iptablesFormatNetwork(netaddr, prefix)))
+        return -1;
+
+    if (!VIR_SOCKET_ADDR_IS_FAMILY(netaddr, AF_INET)) {
+        /* Higher level code *should* guaranteee it's impossible to get here. */
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Attempted to NAT '%s'. NAT is only supported for IPv4."),
+                       networkstr);
+        goto cleanup;
+    }
+
+    cmd = iptablesCommandNew("nat", "POSTROUTING", AF_INET, action);
+
+    if (physdev && physdev[0])
+        virCommandAddArgList(cmd, "--out-interface", physdev, NULL);
+
+    virCommandAddArgList(cmd, "--source", networkstr,
+                         "--destination", destaddr, "--jump", "RETURN", NULL);
+    ret = virCommandRun(cmd, NULL);
+cleanup:
+    virCommandFree(cmd);
+    VIR_FREE(networkstr);
+    return ret;
+}
+
+/**
+ * iptablesAddDontMasquerade:
+ * @netaddr: the source network name
+ * @prefix: prefix (# of 1 bits) of netmask to apply to @netaddr
+ * @physdev: the physical output device or NULL
+ * @destaddr: the destination network not to masquerade for
+ *
+ * Add rules to the IP table context to avoid masquerading from
+ * @netaddr/@prefix to @destaddr on @physdev. @destaddr must be in a format
+ * directly consumable by iptables, it must not depend on user input or
+ * configuration.
+ *
+ * Returns 0 in case of success or an error code otherwise.
+ */
+int
+iptablesAddDontMasquerade(virSocketAddr *netaddr,
+                          unsigned int prefix,
+                          const char *physdev,
+                          const char *destaddr)
+{
+    return iptablesForwardDontMasquerade(netaddr, prefix, physdev, destaddr,
+                                         ADD);
+}
+
+/**
+ * iptablesRemoveDontMasquerade:
+ * @netaddr: the source network name
+ * @prefix: prefix (# of 1 bits) of netmask to apply to @netaddr
+ * @physdev: the physical output device or NULL
+ * @destaddr: the destination network not to masquerade for
+ *
+ * Remove rules from the IP table context that prevent masquerading from
+ * @netaddr/@prefix to @destaddr on @physdev. @destaddr must be in a format
+ * directly consumable by iptables, it must not depend on user input or
+ * configuration.
+ *
+ * Returns 0 in case of success or an error code otherwise.
+ */
+int
+iptablesRemoveDontMasquerade(virSocketAddr *netaddr,
+                             unsigned int prefix,
+                             const char *physdev,
+                             const char *destaddr)
+{
+    return iptablesForwardDontMasquerade(netaddr, prefix, physdev, destaddr,
+                                         REMOVE);
+}
+
+
 static int
 iptablesOutputFixUdpChecksum(const char *iface,
                              int port,
index 447f4a824afabb23d6b53237475b6c80483d7d9e..6dfb9920c6ce170f913e7eee12d978e74b06cc6a 100644 (file)
@@ -94,6 +94,14 @@ int              iptablesRemoveForwardMasquerade (virSocketAddr *netaddr,
                                                   virSocketAddrRangePtr addr,
                                                   virPortRangePtr port,
                                                   const char *protocol);
+int              iptablesAddDontMasquerade       (virSocketAddr *netaddr,
+                                                  unsigned int prefix,
+                                                  const char *physdev,
+                                                  const char *destaddr);
+int              iptablesRemoveDontMasquerade    (virSocketAddr *netaddr,
+                                                  unsigned int prefix,
+                                                  const char *physdev,
+                                                  const char *destaddr);
 int              iptablesAddOutputFixUdpChecksum (const char *iface,
                                                   int port);
 int              iptablesRemoveOutputFixUdpChecksum (const char *iface,