[libvirt] [PATCH v4] nwfilter: check for inverted ctdir

Stefan Berger stefanb at linux.vnet.ibm.com
Thu May 16 00:39:30 UTC 2013


Linux netfilter at some point (Linux 2.6.39) inverted the meaning of the
'--ctdir reply' and newer netfilter implementations now expect
'--ctdir original' instead and vice-versa.
We check for the kernel version and assume that all Linux kernels with version
2.6.39 have the newer inverted logic.

Any distro backporting the Linux kernel patch that inverts the --ctdir logic
(Linux commit 96120d86f) must also backport this patch for Linux and
adapt the kernel version being tested for.

Signed-off-by: Stefan Berger <stefanb at linux.vnet.ibm.com>

---
 v2->v3:
  - using uname now to check for Linux kernel version number

 v1->v2:
  - using virSocketAddrParseIPv4

---
 src/nwfilter/nwfilter_ebiptables_driver.c |   52 ++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

Index: libvirt-acl/src/nwfilter/nwfilter_ebiptables_driver.c
===================================================================
--- libvirt-acl.orig/src/nwfilter/nwfilter_ebiptables_driver.c
+++ libvirt-acl/src/nwfilter/nwfilter_ebiptables_driver.c
@@ -27,6 +27,7 @@
 #include <string.h>
 #include <sys/stat.h>
 #include <fcntl.h>
+#include <sys/utsname.h>
 
 #include "internal.h"
 
@@ -85,6 +86,17 @@ static char *iptables_cmd_path;
 static char *ip6tables_cmd_path;
 static char *grep_cmd_path;
 
+/*
+ * --ctdir original vs. --ctdir reply's meaning was inverted in netfilter
+ * at some point (Linux 2.6.39)
+ */
+enum ctdirStatus {
+    CTDIR_STATUS_UNKNOWN    = 0,
+    CTDIR_STATUS_CORRECTED  = 1,
+    CTDIR_STATUS_OLD        = 2,
+};
+static enum ctdirStatus iptables_ctdir_corrected;
+
 #define PRINT_ROOT_CHAIN(buf, prefix, ifname) \
     snprintf(buf, sizeof(buf), "libvirt-%c-%s", prefix, ifname)
 #define PRINT_CHAIN(buf, prefix, ifname, suffix) \
@@ -1262,6 +1274,17 @@ iptablesEnforceDirection(int directionIn
                          virNWFilterRuleDefPtr rule,
                          virBufferPtr buf)
 {
+    switch (iptables_ctdir_corrected) {
+    case CTDIR_STATUS_UNKNOWN:
+        /* could not be determined or s.th. is seriously wrong */
+        return;
+    case CTDIR_STATUS_CORRECTED:
+        directionIn = !directionIn;
+        break;
+    case CTDIR_STATUS_OLD:
+        break;
+    }
+
     if (rule->tt != VIR_NWFILTER_RULE_DIRECTION_INOUT)
         virBufferAsprintf(buf, " -m conntrack --ctdir %s",
                           (directionIn) ? "Original"
@@ -4304,6 +4327,32 @@ ebiptablesDriverTestCLITools(void)
     return ret;
 }
 
+static void
+ebiptablesDriverProbeCtdir(void)
+{
+    struct utsname utsname;
+    unsigned long thisversion;
+
+    iptables_ctdir_corrected = CTDIR_STATUS_UNKNOWN;
+
+    if (uname(&utsname) < 0) {
+        VIR_ERROR(_("Call to utsname failed: %d"), errno);
+        return;
+    }
+
+    /* following Linux lxr, the logic was inverted in 2.6.39 */
+    if (virParseVersionString(utsname.release, &thisversion, true) < 0) {
+        VIR_ERROR(_("Could not determine kernel version from string %s"),
+                  utsname.release);
+        return;
+    }
+
+    if (thisversion >= 2 * 1000000 + 6 * 1000 + 39)
+        iptables_ctdir_corrected = CTDIR_STATUS_CORRECTED;
+    else
+        iptables_ctdir_corrected = CTDIR_STATUS_OLD;
+}
+
 static int
 ebiptablesDriverInit(bool privileged)
 {
@@ -4341,6 +4390,9 @@ ebiptablesDriverInit(bool privileged)
         return -ENOTSUP;
     }
 
+    if (iptables_cmd_path)
+        ebiptablesDriverProbeCtdir();
+
     ebiptables_driver.flags = TECHDRV_FLAG_INITIALIZED;
 
     return 0;




More information about the libvir-list mailing list