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

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@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;

On 05/15/2013 08:39 PM, Stefan Berger wrote:
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
s/Linux/libvirt/ ? ACK with that small nit fixed. (and thanks for putting up with our pickiness, by the way :-)
adapt the kernel version being tested for.
Signed-off-by: Stefan Berger <stefanb@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;

On 05/15/2013 06:58 PM, Laine Stump wrote:
On 05/15/2013 08:39 PM, Stefan Berger wrote:
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
s/Linux/libvirt/ ?
No, because that commit id is from linux.git, not libvirt.git. Anyone backporting _this_ commit (id unknown until after the commit is pushed) should also backport the kernel commit.
ACK with that small nit fixed. (and thanks for putting up with our pickiness, by the way :-)
Seconded for your patience in getting this solved :) -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org
participants (3)
-
Eric Blake
-
Laine Stump
-
Stefan Berger