Blob Blame History Raw
commit 18990db7b05a3d81145b41e7cfe64ebbb958aa1a
Author: Thomas Woerner <twoerner@redhat.com>
Date:   Thu Apr 27 13:15:36 2017 +0200

    firewall.core.ipXtables: Use new wait option for restore commands if available
    
    The iptables restore commands in the next iptables release will support the
    wait option. This is very useful and results in less likely collisions with
    iptables commands used by other services or the user.

diff --git a/src/firewall/core/ipXtables.py b/src/firewall/core/ipXtables.py
index 2ae0000..9f051d3 100644
--- a/src/firewall/core/ipXtables.py
+++ b/src/firewall/core/ipXtables.py
@@ -157,6 +157,7 @@ class ip4tables(object):
         self._command = config.COMMANDS[self.ipv]
         self._restore_command = config.COMMANDS["%s-restore" % self.ipv]
         self.wait_option = self._detect_wait_option()
+        self.restore_wait_option = self._detect_restore_wait_option()
         self.fill_exists()
 
     def fill_exists(self):
@@ -251,6 +252,8 @@ class ip4tables(object):
         log.debug2("%s: %s %s", self.__class__, self._restore_command,
                    "%s: %d" % (temp_file.name, stat.st_size))
         args = [ ]
+        if self.restore_wait_option:
+            args.append(self.restore_wait_option)
         if not flush:
             args.append("-n")
 
@@ -320,6 +323,24 @@ class ip4tables(object):
 
         return wait_option
 
+    def _detect_restore_wait_option(self):
+        temp_file = tempFile()
+        temp_file.write("#foo")
+        temp_file.close()
+
+        wait_option = ""
+        ret = runProg(self._restore_command, ["-w"], stdin=temp_file.name)  # proposed for iptables-1.6.2
+        if ret[0] == 0:
+            wait_option = "-w"  # wait for xtables lock
+            ret = runProg(self._restore_command, ["--wait=2"], stdin=temp_file.name)  # since iptables > 1.4.21
+            if ret[0] == 0:
+                wait_option = "--wait=2"  # wait max 2 seconds
+            log.debug2("%s: %s will be using %s option.", self.__class__, self._restore_command, wait_option)
+
+        os.unlink(temp_file.name)
+
+        return wait_option
+
     def flush(self, transaction=None):
         tables = self.used_tables()
         for table in tables: