adeaf8
From bcba68498f698dedfdc83687c72e0e6dd7dc0e96 Mon Sep 17 00:00:00 2001
adeaf8
From: Eric Blake <eblake@redhat.com>
adeaf8
Date: Fri, 13 Sep 2013 10:11:26 -0600
adeaf8
Subject: [PATCH] build: fix build with latest rawhide kernel headers
adeaf8
adeaf8
Bother those kernel developers.  In the latest rawhide, kernel
adeaf8
and glibc have now been unified so that <netinet/in.h> and
adeaf8
<linux/in6.h> no longer clash; but <linux/if_bridge.h> is still
adeaf8
not self-contained.  Because of the latest header change, the
adeaf8
build is failing with:
adeaf8
adeaf8
checking for linux/param.h... no
adeaf8
configure: error: You must install kernel-headers in order to compile libvirt with QEMU or LXC support
adeaf8
adeaf8
with details:
adeaf8
adeaf8
In file included from conftest.c:561:0:
adeaf8
/usr/include/linux/in6.h:71:18: error: field 'flr_dst' has incomplete type
adeaf8
  struct in6_addr flr_dst;
adeaf8
adeaf8
We need a workaround to avoid our workaround :)
adeaf8
adeaf8
* configure.ac (NETINET_LINUX_WORKAROUND): New test.
adeaf8
* src/util/virnetdevbridge.c (includes): Use it.
adeaf8
adeaf8
Signed-off-by: Eric Blake <eblake@redhat.com>
adeaf8
(cherry picked from commit e62e0094dcd0ca1484491a9cc62919473b647f11)
adeaf8
---
adeaf8
 configure.ac               | 39 +++++++++++++++++++++++++++++----------
adeaf8
 src/util/virnetdevbridge.c | 24 ++++++++++++++----------
adeaf8
 2 files changed, 43 insertions(+), 20 deletions(-)
adeaf8
adeaf8
diff --git a/configure.ac b/configure.ac
adeaf8
index f853e03..1956717 100644
adeaf8
--- a/configure.ac
adeaf8
+++ b/configure.ac
adeaf8
@@ -1003,18 +1003,37 @@ dnl check for kernel headers required by src/bridge.c
adeaf8
 dnl
adeaf8
 if test "$with_linux" = "yes"; then
adeaf8
   if test "$with_qemu" = "yes" || test "$with_lxc" = "yes" ; then
adeaf8
+    # Various kernel versions have headers that are not self-standing, but
adeaf8
+    # yet are incompatible with the corresponding glibc headers.  In order
adeaf8
+    # to guarantee compilation across a wide range of versions (from RHEL 5
adeaf8
+    # to rawhide), we first have to probe whether glibc and kernel can be
adeaf8
+    # used in tandem; and if not, provide workarounds that ensure that
adeaf8
+    # ABI-compatible IPv6 types are present for use by the kernel headers.
adeaf8
+    # These probes mirror the usage in virnetdevbridge.c
adeaf8
+    AC_CACHE_CHECK(
adeaf8
+      [whether <linux/*.h> and <netinet/*.h> headers are compatible],
adeaf8
+      [lv_cv_netinet_linux_compatible],
adeaf8
+      [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
adeaf8
+        #include <netinet/in.h>
adeaf8
+        #include <linux/in6.h>
adeaf8
+      ]])],
adeaf8
+      [lv_cv_netinet_linux_compatible=yes],
adeaf8
+      [lv_cv_netinet_linux_compatible=no])])
adeaf8
+    if test "x$lv_cv_netinet_linux_compatible" != xyes; then
adeaf8
+      AC_DEFINE([NETINET_LINUX_WORKAROUND], [1],
adeaf8
+        [define to 1 if Linux kernel headers require a workaround to avoid
adeaf8
+        compilation errors when mixed with glibc netinet headers])
adeaf8
+    fi
adeaf8
     AC_CHECK_HEADERS([linux/param.h linux/sockios.h linux/if_bridge.h linux/if_tun.h],,
adeaf8
       [AC_MSG_ERROR([You must install kernel-headers in order to compile libvirt with QEMU or LXC support])],
adeaf8
-      [[/* The kernel folks broke their headers when used with particular
adeaf8
-         * glibc versions; although the structs are ABI compatible, the
adeaf8
-         * C type system doesn't like struct redefinitions.  We work around
adeaf8
-         * the problem here in the same manner as in virnetdevbridge.c.  */
adeaf8
-        #include <netinet/in.h>
adeaf8
-        #define in6_addr in6_addr_
adeaf8
-        #define sockaddr_in6 sockaddr_in6_
adeaf8
-        #define ipv6_mreq ipv6_mreq_
adeaf8
-        #define in6addr_any in6addr_any_
adeaf8
-        #define in6addr_loopback in6addr_loopback_
adeaf8
+      [[#include <netinet/in.h>
adeaf8
+        #if NETINET_LINUX_WORKAROUND
adeaf8
+        # define in6_addr in6_addr_
adeaf8
+        # define sockaddr_in6 sockaddr_in6_
adeaf8
+        # define ipv6_mreq ipv6_mreq_
adeaf8
+        # define in6addr_any in6addr_any_
adeaf8
+        # define in6addr_loopback in6addr_loopback_
adeaf8
+        #endif
adeaf8
         #include <linux/in6.h>
adeaf8
       ]])
adeaf8
   fi
adeaf8
diff --git a/src/util/virnetdevbridge.c b/src/util/virnetdevbridge.c
adeaf8
index e4daa27..1a3740a 100644
adeaf8
--- a/src/util/virnetdevbridge.c
adeaf8
+++ b/src/util/virnetdevbridge.c
adeaf8
@@ -39,22 +39,26 @@
adeaf8
 #ifdef __linux__
adeaf8
 # include <linux/sockios.h>
adeaf8
 # include <linux/param.h>     /* HZ                 */
adeaf8
+# if NETINET_LINUX_WORKAROUND
adeaf8
 /* Depending on the version of kernel vs. glibc, there may be a collision
adeaf8
  * between <net/in.h> and kernel IPv6 structures.  The different types
adeaf8
  * are ABI compatible, but choke the C type system; work around it by
adeaf8
  * using temporary redefinitions.  */
adeaf8
-# define in6_addr in6_addr_
adeaf8
-# define sockaddr_in6 sockaddr_in6_
adeaf8
-# define ipv6_mreq ipv6_mreq_
adeaf8
-# define in6addr_any in6addr_any_
adeaf8
-# define in6addr_loopback in6addr_loopback_
adeaf8
+#  define in6_addr in6_addr_
adeaf8
+#  define sockaddr_in6 sockaddr_in6_
adeaf8
+#  define ipv6_mreq ipv6_mreq_
adeaf8
+#  define in6addr_any in6addr_any_
adeaf8
+#  define in6addr_loopback in6addr_loopback_
adeaf8
+# endif
adeaf8
 # include <linux/in6.h>
adeaf8
 # include <linux/if_bridge.h> /* SYSFS_BRIDGE_ATTR  */
adeaf8
-# undef in6_addr
adeaf8
-# undef sockaddr_in6
adeaf8
-# undef ipv6_mreq
adeaf8
-# undef in6addr_any
adeaf8
-# undef in6addr_loopback
adeaf8
+# if NETINET_LINUX_WORKAROUND
adeaf8
+#  undef in6_addr
adeaf8
+#  undef sockaddr_in6
adeaf8
+#  undef ipv6_mreq
adeaf8
+#  undef in6addr_any
adeaf8
+#  undef in6addr_loopback
adeaf8
+# endif
adeaf8
 
adeaf8
 # define JIFFIES_TO_MS(j) (((j)*1000)/HZ)
adeaf8
 # define MS_TO_JIFFIES(ms) (((ms)*HZ)/1000)