c401cc
From 77a525dfe96728cbec38e78b8da457aa6955918e Mon Sep 17 00:00:00 2001
c401cc
Message-Id: <77a525dfe96728cbec38e78b8da457aa6955918e.1386932212.git.jdenemar@redhat.com>
c401cc
From: Laine Stump <laine@laine.org>
c401cc
Date: Wed, 11 Dec 2013 04:26:39 -0700
c401cc
Subject: [PATCH] network: properly update iptables rules during net-update
c401cc
c401cc
This patch resolves:
c401cc
c401cc
  https://bugzilla.redhat.com/show_bug.cgi?id=1035336
c401cc
c401cc
The basic problem is that during a network update, the required
c401cc
iptables rules sometimes change, and this was being handled by simply
c401cc
removing and re-adding the rules. However, the removal of the old
c401cc
rules was done based on the *new* state of the network, which would
c401cc
mean that some of the rules would not match those currently in the
c401cc
system, so the old rules wouldn't be removed.
c401cc
c401cc
This patch removes the old rules prior to updating the network
c401cc
definition then adds the new rules as soon as the definition is
c401cc
updated. Note that this could lead to a stray packet or two during the
c401cc
interim, but that was already a problem before (the period of limbo is
c401cc
now just slightly longer).
c401cc
c401cc
While moving the location for the rules, I added a few more sections
c401cc
that should result in the iptables rules being redone:
c401cc
c401cc
DHCP_RANGE and DHCP_HOST - these are needed because adding/removing a dhcp
c401cc
host entry could lead to the dhcp service being started/stopped, which
c401cc
would require that the mangle rule that fixes up dhcp response
c401cc
checksums sould need to be added/removed, and this wasn't being done.
c401cc
c401cc
(cherry picked from commit 54f9492353170b1ffc78a44c06ed3f9ecaab6ccf)
c401cc
c401cc
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
c401cc
---
c401cc
 src/network/bridge_driver.c | 48 ++++++++++++++++++++++++++++++++-------------
c401cc
 1 file changed, 34 insertions(+), 14 deletions(-)
c401cc
c401cc
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
c401cc
index 6e31840..54d388b 100644
c401cc
--- a/src/network/bridge_driver.c
c401cc
+++ b/src/network/bridge_driver.c
c401cc
@@ -3307,6 +3307,7 @@ networkUpdate(virNetworkPtr net,
c401cc
     size_t i;
c401cc
     virNetworkIpDefPtr ipdef;
c401cc
     bool oldDhcpActive = false;
c401cc
+    bool needFirewallRefresh = false;
c401cc
 
c401cc
 
c401cc
     virCheckFlags(VIR_NETWORK_UPDATE_AFFECT_LIVE |
c401cc
@@ -3348,8 +3349,40 @@ networkUpdate(virNetworkPtr net,
c401cc
             flags |= VIR_NETWORK_UPDATE_AFFECT_CONFIG;
c401cc
     }
c401cc
 
c401cc
+    if (isActive && (flags & VIR_NETWORK_UPDATE_AFFECT_LIVE)) {
c401cc
+        /* Take care of anything that must be done before updating the
c401cc
+         * live NetworkDef.
c401cc
+         */
c401cc
+        if (network->def->forward.type == VIR_NETWORK_FORWARD_NONE ||
c401cc
+            network->def->forward.type == VIR_NETWORK_FORWARD_NAT ||
c401cc
+            network->def->forward.type == VIR_NETWORK_FORWARD_ROUTE) {
c401cc
+            switch (section) {
c401cc
+            case VIR_NETWORK_SECTION_FORWARD:
c401cc
+            case VIR_NETWORK_SECTION_FORWARD_INTERFACE:
c401cc
+            case VIR_NETWORK_SECTION_IP:
c401cc
+            case VIR_NETWORK_SECTION_IP_DHCP_RANGE:
c401cc
+            case VIR_NETWORK_SECTION_IP_DHCP_HOST:
c401cc
+                /* these could affect the firewall rules, so remove the
c401cc
+                 * old rules (and remember to load new ones after the
c401cc
+                 * update).
c401cc
+                 */
c401cc
+                networkRemoveFirewallRules(network);
c401cc
+                needFirewallRefresh = true;
c401cc
+                break;
c401cc
+            default:
c401cc
+                break;
c401cc
+            }
c401cc
+        }
c401cc
+    }
c401cc
+
c401cc
     /* update the network config in memory/on disk */
c401cc
-    if (virNetworkObjUpdate(network, command, section, parentIndex, xml, flags) < 0)
c401cc
+    if (virNetworkObjUpdate(network, command, section, parentIndex, xml, flags) < 0) {
c401cc
+        if (needFirewallRefresh)
c401cc
+            ignore_value(networkAddFirewallRules(network));
c401cc
+        goto cleanup;
c401cc
+    }
c401cc
+
c401cc
+    if (needFirewallRefresh && networkAddFirewallRules(network) < 0)
c401cc
         goto cleanup;
c401cc
 
c401cc
     if (flags & VIR_NETWORK_UPDATE_AFFECT_CONFIG) {
c401cc
@@ -3419,19 +3452,6 @@ networkUpdate(virNetworkPtr net,
c401cc
                 goto cleanup;
c401cc
         }
c401cc
 
c401cc
-        if ((section == VIR_NETWORK_SECTION_IP ||
c401cc
-             section == VIR_NETWORK_SECTION_FORWARD ||
c401cc
-             section == VIR_NETWORK_SECTION_FORWARD_INTERFACE) &&
c401cc
-           (network->def->forward.type == VIR_NETWORK_FORWARD_NONE ||
c401cc
-            network->def->forward.type == VIR_NETWORK_FORWARD_NAT ||
c401cc
-            network->def->forward.type == VIR_NETWORK_FORWARD_ROUTE)) {
c401cc
-            /* these could affect the iptables rules */
c401cc
-            networkRemoveFirewallRules(network);
c401cc
-            if (networkAddFirewallRules(network) < 0)
c401cc
-                goto cleanup;
c401cc
-
c401cc
-        }
c401cc
-
c401cc
         /* save current network state to disk */
c401cc
         if ((ret = virNetworkSaveStatus(driverState->stateDir,
c401cc
                                         network)) < 0) {
c401cc
-- 
c401cc
1.8.5.1
c401cc