This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[COMMITTED] Fix linux/in6.h and netinet/in.h coordination (Bug 20214)


In: https://sourceware.org/glibc/wiki/Synchronizing_Headers
we explain how we synchronize our headers with Linux kernel
headers.

In order to synchronize with the Linux linux/in6.h and
linux/ipv6.h headers we checked for their guard macros and
then defined __USE_KERNEL_IPV6_DEFS and conditionalized code
on this macro.

In upstream kernel 56c176c9 the _UAPI prefix was stripped and
this broke our synchronized headers again. We now need to check
for _LINUX_IN6_H and _IPV6_H, and keep checking the old versions
of the header guard checks for maximum backwards compatibility
with older Linux headers (the history is actually a bit muddled
here and it appears upstream linus kernel broke this 10 months
*before* our fix was ever applied to glibc, but without glibc
testing we didn't notice and distro kernels have their own
testing to fix this).

The use cases fixed by this patch are:
#include <linux/in6.h>
#include <netinet/in.h>

* Standard set of failures.
~~~
../inet/netinet/in.h:101:5: error: expected identifier before numeric constant
     IPPROTO_HOPOPTS = 0,   /* IPv6 Hop-by-Hop options.  */
     ^
In file included from ../include/netinet/in.h:3:0,
                 from ../sysdeps/unix/sysv/linux//tst-ipv6-compat2.c:2:
../inet/netinet/in.h:102:0: error: "IPPROTO_HOPOPTS" redefined [-Werror]
 #define IPPROTO_HOPOPTS  IPPROTO_HOPOPTS
 ^
In file included from ../sysdeps/unix/sysv/linux//tst-ipv6-compat2.c:1:0:
/home/carlos/build/glibc-headers/include/linux/in6.h:131:0: note: this is the location of the previous definition
 #define IPPROTO_HOPOPTS  0 /* IPv6 hop-by-hop options */
 ^
In file included from ../include/netinet/in.h:3:0,
                 from ../sysdeps/unix/sysv/linux//tst-ipv6-compat2.c:2:
../inet/netinet/in.h:104:0: error: "IPPROTO_ROUTING" redefined [-Werror]
 #define IPPROTO_ROUTING  IPPROTO_ROUTING
 ^
In file included from ../sysdeps/unix/sysv/linux//tst-ipv6-compat2.c:1:0:
/home/carlos/build/glibc-headers/include/linux/in6.h:132:0: note: this is the location of the previous definition
 #define IPPROTO_ROUTING  43 /* IPv6 routing header  */
 ^
In file included from ../include/netinet/in.h:3:0,
                 from ../sysdeps/unix/sysv/linux//tst-ipv6-compat2.c:2:
../inet/netinet/in.h:106:0: error: "IPPROTO_FRAGMENT" redefined [-Werror]
 #define IPPROTO_FRAGMENT IPPROTO_FRAGMENT
 ^
In file included from ../sysdeps/unix/sysv/linux//tst-ipv6-compat2.c:1:0:
/home/carlos/build/glibc-headers/include/linux/in6.h:133:0: note: this is the location of the previous definition
 #define IPPROTO_FRAGMENT 44 /* IPv6 fragmentation header */
 ^
In file included from ../include/netinet/in.h:3:0,
                 from ../sysdeps/unix/sysv/linux//tst-ipv6-compat2.c:2:
../inet/netinet/in.h:108:0: error: "IPPROTO_ICMPV6" redefined [-Werror]
 #define IPPROTO_ICMPV6  IPPROTO_ICMPV6
 ^
In file included from ../sysdeps/unix/sysv/linux//tst-ipv6-compat2.c:1:0:
/home/carlos/build/glibc-headers/include/linux/in6.h:134:0: note: this is the location of the previous definition
 #define IPPROTO_ICMPV6  58 /* ICMPv6   */
 ^
In file included from ../include/netinet/in.h:3:0,
                 from ../sysdeps/unix/sysv/linux//tst-ipv6-compat2.c:2:
../inet/netinet/in.h:110:0: error: "IPPROTO_NONE" redefined [-Werror]
 #define IPPROTO_NONE  IPPROTO_NONE
 ^
In file included from ../sysdeps/unix/sysv/linux//tst-ipv6-compat2.c:1:0:
/home/carlos/build/glibc-headers/include/linux/in6.h:135:0: note: this is the location of the previous definition
 #define IPPROTO_NONE  59 /* IPv6 no next header  */
 ^
In file included from ../include/netinet/in.h:3:0,
                 from ../sysdeps/unix/sysv/linux//tst-ipv6-compat2.c:2:
../inet/netinet/in.h:112:0: error: "IPPROTO_DSTOPTS" redefined [-Werror]
 #define IPPROTO_DSTOPTS  IPPROTO_DSTOPTS
 ^
In file included from ../sysdeps/unix/sysv/linux//tst-ipv6-compat2.c:1:0:
/home/carlos/build/glibc-headers/include/linux/in6.h:136:0: note: this is the location of the previous definition
 #define IPPROTO_DSTOPTS  60 /* IPv6 destination options */
 ^
In file included from ../include/netinet/in.h:3:0,
                 from ../sysdeps/unix/sysv/linux//tst-ipv6-compat2.c:2:
../inet/netinet/in.h:114:0: error: "IPPROTO_MH" redefined [-Werror]
 #define IPPROTO_MH  IPPROTO_MH
 ^
In file included from ../sysdeps/unix/sysv/linux//tst-ipv6-compat2.c:1:0:
/home/carlos/build/glibc-headers/include/linux/in6.h:137:0: note: this is the location of the previous definition
 #define IPPROTO_MH  135 /* IPv6 mobility header  */
 ^
In file included from ../include/netinet/in.h:3:0,
                 from ../sysdeps/unix/sysv/linux//tst-ipv6-compat2.c:2:
../inet/netinet/in.h:211:8: error: redefinition of âstruct in6_addrâ
 struct in6_addr
        ^
In file included from ../sysdeps/unix/sysv/linux//tst-ipv6-compat2.c:1:0:
/home/carlos/build/glibc-headers/include/linux/in6.h:32:8: note: originally defined here
 struct in6_addr {
        ^
In file included from ../include/netinet/in.h:3:0,
                 from ../sysdeps/unix/sysv/linux//tst-ipv6-compat2.c:2:
../inet/netinet/in.h:221:0: error: "s6_addr" redefined [-Werror]
 #define s6_addr   __in6_u.__u6_addr8
 ^
In file included from ../sysdeps/unix/sysv/linux//tst-ipv6-compat2.c:1:0:
/home/carlos/build/glibc-headers/include/linux/in6.h:40:0: note: this is the location of the previous definition
 #define s6_addr   in6_u.u6_addr8
 ^
In file included from ../include/netinet/in.h:3:0,
                 from ../sysdeps/unix/sysv/linux//tst-ipv6-compat2.c:2:
../inet/netinet/in.h:223:0: error: "s6_addr16" redefined [-Werror]
 # define s6_addr16  __in6_u.__u6_addr16
 ^
In file included from ../sysdeps/unix/sysv/linux//tst-ipv6-compat2.c:1:0:
/home/carlos/build/glibc-headers/include/linux/in6.h:42:0: note: this is the location of the previous definition
 #define s6_addr16  in6_u.u6_addr16
 ^
In file included from ../include/netinet/in.h:3:0,
                 from ../sysdeps/unix/sysv/linux//tst-ipv6-compat2.c:2:
../inet/netinet/in.h:224:0: error: "s6_addr32" redefined [-Werror]
 # define s6_addr32  __in6_u.__u6_addr32
 ^
In file included from ../sysdeps/unix/sysv/linux//tst-ipv6-compat2.c:1:0:
/home/carlos/build/glibc-headers/include/linux/in6.h:43:0: note: this is the location of the previous definition
 #define s6_addr32  in6_u.u6_addr32
 ^
In file included from ../include/netinet/in.h:3:0,
                 from ../sysdeps/unix/sysv/linux//tst-ipv6-compat2.c:2:
../inet/netinet/in.h:254:8: error: redefinition of âstruct sockaddr_in6â
 struct sockaddr_in6
        ^
In file included from ../sysdeps/unix/sysv/linux//tst-ipv6-compat2.c:1:0:
/home/carlos/build/glibc-headers/include/linux/in6.h:49:8: note: originally defined here
 struct sockaddr_in6 {
        ^
In file included from ../include/netinet/in.h:3:0,
                 from ../sysdeps/unix/sysv/linux//tst-ipv6-compat2.c:2:
../inet/netinet/in.h:290:8: error: redefinition of âstruct ipv6_mreqâ
 struct ipv6_mreq
        ^
In file included from ../sysdeps/unix/sysv/linux//tst-ipv6-compat2.c:1:0:
/home/carlos/build/glibc-headers/include/linux/in6.h:59:8: note: originally defined here
 struct ipv6_mreq {
        ^
cc1: all warnings being treated as errors
~~~

* New set of failures related to IPV6_ADD_MEMBERSHIP and IPV6_DROP_MEMBERSHIP:
~~~~
In file included from ../inet/netinet/in.h:37:0,
                 from ../include/netinet/in.h:3,
                 from ../sysdeps/unix/sysv/linux//tst-ipv6-compat2.c:2:
../sysdeps/unix/sysv/linux/bits/in.h:218:0: error: "IPV6_ADD_MEMBERSHIP" redefined [-Werror]
 # define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
 ^
In file included from ../sysdeps/unix/sysv/linux//tst-ipv6-compat2.c:1:0:
/home/carlos/build/glibc-headers/include/linux/in6.h:169:0: note: this is the location of the previous definition
 #define IPV6_ADD_MEMBERSHIP 20
 ^
In file included from ../inet/netinet/in.h:37:0,
                 from ../include/netinet/in.h:3,
                 from ../sysdeps/unix/sysv/linux//tst-ipv6-compat2.c:2:
../sysdeps/unix/sysv/linux/bits/in.h:219:0: error: "IPV6_DROP_MEMBERSHIP" redefined [-Werror]
 # define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP
 ^
In file included from ../sysdeps/unix/sysv/linux//tst-ipv6-compat2.c:1:0:
/home/carlos/build/glibc-headers/include/linux/in6.h:170:0: note: this is the location of the previous definition
 #define IPV6_DROP_MEMBERSHIP 21
 ^
cc1: all warnings being treated as errors
~~~~

Notice that in the case of xattr.h the Linux kernel headers
define the __USE_KERNEL_* macro themselves for glibc to use.
This has the added benefit of not needing consistent guard
macro names, just a consistent __USE_KERNEL_* macro name.
Sadly it's just a simple define, and doesn't set the value
of the macro to 0 or 1 (as it should to avoid typos).
Even if we wanted to do this also for linux/in6.h and
linux/ipv6.h, we would still need to support older headers
and define the value ourselves. Therefore the point is moot
but we should look to using a method like this for glibc
and linux with each side defining a __USE_LIBC_* and a
__USE_KERNEL_* feature macros respectively defined to 0
or 1 which avoids guard changes and complex conditionals
duplicated. I will look at proposing something like this.

Passes reg tests based on tests-compile support [1].

Committed.

-- 
Cheers,
Carlos.

[1] https://www.sourceware.org/ml/libc-alpha/2016-06/msg00162.html

2016-06-07  Carlos O'Donell  <carlos@redhat.com>

	[BZ #20214]
	* sysdeps/unix/sysv/linux/bits/in.h
	[defined _UAPI_LINUX_IN6_H || defined _UAPI_IPV6_H
	 || defined _LINUX_IN6_H || defined _IPV6_H] (__USE_KERNEL_IPV6_DEFS):
	Define to 1.
	[!(defined _UAPI_LINUX_IN6_H || defined _UAPI_IPV6_H
	 || defined _LINUX_IN6_H || defined _IPV6_H)] (__USE_KERNEL_IPV6_DEFS):
	Define to 0.
	[!__USE_KERNEL_IPV6_DEFS] (IPV6_ADD_MEMBERSHIP): Define.
	[!__USE_KERNEL_IPV6_DEFS] (IPV6_DROP_MEMBERSHIP): Define.

diff --git a/sysdeps/unix/sysv/linux/bits/in.h b/sysdeps/unix/sysv/linux/bits/in.h
index 9bdadf3..4d70a6b 100644
--- a/sysdeps/unix/sysv/linux/bits/in.h
+++ b/sysdeps/unix/sysv/linux/bits/in.h
@@ -25,8 +25,14 @@
    kernel then we will not define the IPv6 IPPROTO_* defines, in6_addr (nor the
    defines), sockaddr_in6, or ipv6_mreq. Same for in6_ptkinfo or ip6_mtuinfo
    in linux/ipv6.h. The ABI used by the linux-kernel and glibc match exactly.
-   Neither the linux kernel nor glibc should break this ABI without coordination.  */
-#if defined _UAPI_LINUX_IN6_H || defined _UAPI_IPV6_H
+   Neither the linux kernel nor glibc should break this ABI without coordination.
+   In upstream kernel 56c176c9 the _UAPI prefix was stripped so we need to check
+   for _LINUX_IN6_H and _IPV6_H now, and keep checking the old versions for
+   maximum backwards compatibility.  */
+#if defined _UAPI_LINUX_IN6_H \
+    || defined _UAPI_IPV6_H \
+    || defined _LINUX_IN6_H \
+    || defined _IPV6_H
 /* This is not quite the same API since the kernel always defines s6_addr16 and
    s6_addr32. This is not a violation of POSIX since POSIX says "at least the
    following member" and that holds true.  */
@@ -209,8 +215,10 @@ struct in_pktinfo
 #define IPV6_TCLASS            67
 
 /* Obsolete synonyms for the above.  */
-#define IPV6_ADD_MEMBERSHIP    IPV6_JOIN_GROUP
-#define IPV6_DROP_MEMBERSHIP   IPV6_LEAVE_GROUP
+#if !__USE_KERNEL_IPV6_DEFS
+# define IPV6_ADD_MEMBERSHIP   IPV6_JOIN_GROUP
+# define IPV6_DROP_MEMBERSHIP  IPV6_LEAVE_GROUP
+#endif
 #define IPV6_RXHOPOPTS         IPV6_HOPOPTS
 #define IPV6_RXDSTOPTS         IPV6_DSTOPTS


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]