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@xxxxxxxxxxxxxxxxxx> --- 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; -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list