[WIP] Fix more if.h issues with glibc and the linux kernel.

Message ID 417162a8-65a5-a146-d546-40fb2abd4cb0@redhat.com
State New
Headers show
Series
  • [WIP] Fix more if.h issues with glibc and the linux kernel.
Related show

Commit Message

Carlos O'Donell April 3, 2018, 5:15 p.m.
Jose,

Attached is my WIP patch for fixing more of the if.h issues with the linux
kernel headers.

I would like to see the work in this area have 3 key properties:

1. Harmonization:

   There should be changes to glibc *and* the linux kernel to ensure that
   the API/ABI stays as close to the same as possible regardless of the
   header inclusion ordering.

   To achieve this you need to get patches into both glibc and linux
   kernel headers.

2. Isolation:

   The changes should live in libc-compat.h to isolate the coordination
   issues to just one file you have to change for each C library.

   There have been other proposed plans from musl, but I have yet to see
   a complete proposal from Rich which addresses my concerns and *experience*
   that we have users including headers in both directions and that this
   deserves consideration for the sake of users. There has been recent
   activity in this area upstream but I haven't had time to review.

   Note: I think the xattr.h fixes were flawed in that they are not well isolated.
   Isolation makes it easier to update all the libc-related logic and keeps
   the headers themselves clean. So these are not a good example.

3. Testing:

   Add test cases which compile with headers in both orders as I've shown
   in my WIP patch. I tried initially to do a compile-time test framework
   but Joseph Myers did not think it was worth it and it was actually hard
   to bend the existing build system to that, so this is just easier.

Please find attached my WIP patches.

I don't have the time to drive this forward right now, but if this is something
that is impacting Oracle, please feel free to move forward with these patches.
Please also feel free to throw all of this away if you think there is a better
way to do this.

Please update the wiki "Synchronizing Headers" if you make progress or have
updated state on which headers work and against which commits:
https://sourceware.org/glibc/wiki/Synchronizing_Headers

Lastly, I think it is the *wrong* approach to randomly test header inclusion
ordering, we need to be tactical and cleanup the common headers used together.

Comments

Jose E. Marchesi April 4, 2018, 1:03 p.m. | #1
Hi Carlos.
    
    Attached is my WIP patch for fixing more of the if.h issues with the linux
    kernel headers.

Thanks for the patches, and the hints.  Will give it a try and will be
back as soon as I have something useful.

Patch

From 8e9a1435a3f3c9c73bf3a4ea4e8fb0fd54c356c6 Mon Sep 17 00:00:00 2001
From: Carlos O'Donell <carlos@redhat.com>
Date: Tue, 3 Apr 2018 11:50:46 -0500
Subject: [PATCH] Fix if.h header ordering issues with testing.

---
 bits/if.h                                  | 24 +++++++++
 inet/tst-inet6_scopeid_pton.c              |  2 +-
 sysdeps/gnu/net/if.h                       | 14 +++--
 sysdeps/unix/sysv/linux/Makefile           | 12 ++++-
 sysdeps/unix/sysv/linux/bits/if.h          | 36 +++++++++++++
 sysdeps/unix/sysv/linux/kernel-features.h  | 18 +++++++
 sysdeps/unix/sysv/linux/netipx/ipx.h       | 67 +++++++++++++++---------
 sysdeps/unix/sysv/linux/tst-if-compat1.c   | 56 ++++++++++++++++++++
 sysdeps/unix/sysv/linux/tst-if-compat2.c   |  2 +
 sysdeps/unix/sysv/linux/tst-ipv4-compat1.c | 55 ++++++++++++++++++++
 sysdeps/unix/sysv/linux/tst-ipv4-compat2.c |  2 +
 sysdeps/unix/sysv/linux/tst-ipv6-compat1.c | 83 ++++++++++++++++++++++++++++++
 sysdeps/unix/sysv/linux/tst-ipv6-compat2.c |  2 +
 sysdeps/unix/sysv/linux/tst-ipv6-compat3.c |  2 +
 sysdeps/unix/sysv/linux/tst-ipv6-compat4.c |  2 +
 sysdeps/unix/sysv/linux/tst-ipv6-compat5.c |  2 +
 sysdeps/unix/sysv/linux/tst-ipv6-compat6.c |  2 +
 sysdeps/unix/sysv/linux/tst-ipx-compat1.c  | 55 ++++++++++++++++++++
 sysdeps/unix/sysv/linux/tst-ipx-compat2.c  |  2 +
 19 files changed, 408 insertions(+), 30 deletions(-)
 create mode 100644 bits/if.h
 create mode 100644 sysdeps/unix/sysv/linux/bits/if.h
 create mode 100644 sysdeps/unix/sysv/linux/tst-if-compat1.c
 create mode 100644 sysdeps/unix/sysv/linux/tst-if-compat2.c
 create mode 100644 sysdeps/unix/sysv/linux/tst-ipv4-compat1.c
 create mode 100644 sysdeps/unix/sysv/linux/tst-ipv4-compat2.c
 create mode 100644 sysdeps/unix/sysv/linux/tst-ipv6-compat1.c
 create mode 100644 sysdeps/unix/sysv/linux/tst-ipv6-compat2.c
 create mode 100644 sysdeps/unix/sysv/linux/tst-ipv6-compat3.c
 create mode 100644 sysdeps/unix/sysv/linux/tst-ipv6-compat4.c
 create mode 100644 sysdeps/unix/sysv/linux/tst-ipv6-compat5.c
 create mode 100644 sysdeps/unix/sysv/linux/tst-ipv6-compat6.c
 create mode 100644 sysdeps/unix/sysv/linux/tst-ipx-compat1.c
 create mode 100644 sysdeps/unix/sysv/linux/tst-ipx-compat2.c

diff --git a/bits/if.h b/bits/if.h
new file mode 100644
index 0000000000..525e80ff62
--- /dev/null
+++ b/bits/if.h
@@ -0,0 +1,24 @@ 
+/* Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* Generic version.  */
+
+#ifndef _NET_IF_H
+# error "Never use <bits/if.h> directly; include <net/if.h> instead."
+#endif
+
+/* Nothing in the generic version.  */
diff --git a/inet/tst-inet6_scopeid_pton.c b/inet/tst-inet6_scopeid_pton.c
index 61d4b24d09..023060a627 100644
--- a/inet/tst-inet6_scopeid_pton.c
+++ b/inet/tst-inet6_scopeid_pton.c
@@ -18,7 +18,6 @@ 
 
 #include <arpa/inet.h>
 #include <inttypes.h>
-#include <net-internal.h>
 #include <net/if.h>
 #include <netdb.h>
 #include <stdio.h>
@@ -27,6 +26,7 @@ 
 #include <support/check.h>
 #include <support/support.h>
 #include <support/test-driver.h>
+#include "net-internal.h"
 
 /* An interface which is known to the system.  */
 static const char *interface_name;
diff --git a/sysdeps/gnu/net/if.h b/sysdeps/gnu/net/if.h
index 89e55dad02..ffe948ca1a 100644
--- a/sysdeps/gnu/net/if.h
+++ b/sysdeps/gnu/net/if.h
@@ -20,6 +20,7 @@ 
 #define _NET_IF_H	1
 
 #include <features.h>
+#include <bits/if.h>
 
 #ifdef __USE_MISC
 # include <sys/types.h>
@@ -39,6 +40,7 @@  struct if_nameindex
 
 #ifdef __USE_MISC
 /* Standard interface flags. */
+#if !__USE_KERNEL_IF_DEFS
 enum
   {
     IFF_UP = 0x1,		/* Interface is up.  */
@@ -79,6 +81,7 @@  enum
     IFF_DYNAMIC = 0x8000	/* Dialup device with changing addresses.  */
 # define IFF_DYNAMIC	IFF_DYNAMIC
   };
+#endif /* !__USE_KERNEL_IF_DEFS  */
 
 /* The ifaddr structure contains information about one address of an
    interface.  They are maintained by the different address families,
@@ -107,7 +110,7 @@  struct ifaddr
    Ah well. The get() side of this is good for WDSETUP, and it'll be
    handy for debugging things. The set side is fine for now and being
    very small might be worth keeping for clean configuration.  */
-
+#if !__USE_KERNEL_IF_DEFS
 struct ifmap
   {
     unsigned long int mem_start;
@@ -118,11 +121,12 @@  struct ifmap
     unsigned char port;
     /* 3 bytes spare */
   };
+#endif
 
 /* Interface request structure used for socket ioctl's.  All interface
    ioctl's must have parameter definitions which begin with ifr_name.
    The remainder may be interface specific.  */
-
+#if !__USE_KERNEL_IF_DEFS
 struct ifreq
   {
 # define IFHWADDRLEN	6
@@ -167,12 +171,12 @@  struct ifreq
 # define _IOT_ifreq	_IOT(_IOTS(char),IFNAMSIZ,_IOTS(char),16,0,0)
 # define _IOT_ifreq_short _IOT(_IOTS(char),IFNAMSIZ,_IOTS(short),1,0,0)
 # define _IOT_ifreq_int	_IOT(_IOTS(char),IFNAMSIZ,_IOTS(int),1,0,0)
-
+#endif /* !__USE_KERNEL_IF_DEFS  */
 
 /* Structure used in SIOCGIFCONF request.  Used to retrieve interface
    configuration for machine (useful for programs which must know all
    networks accessible).  */
-
+#if !__USE_KERNEL_IF_DEFS
 struct ifconf
   {
     int	ifc_len;			/* Size of buffer.  */
@@ -185,6 +189,8 @@  struct ifconf
 # define ifc_buf	ifc_ifcu.ifcu_buf	/* Buffer address.  */
 # define ifc_req	ifc_ifcu.ifcu_req	/* Array of structures.  */
 # define _IOT_ifconf _IOT(_IOTS(struct ifconf),1,0,0,0,0) /* not right */
+#endif
+
 #endif	/* Misc.  */
 
 __BEGIN_DECLS
diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
index 8f19e0efc3..bd5db54e46 100644
--- a/sysdeps/unix/sysv/linux/Makefile
+++ b/sysdeps/unix/sysv/linux/Makefile
@@ -118,7 +118,7 @@  $(objpfx)tst-signal-numbers.out: \
 endif
 
 ifeq ($(subdir),socket)
-sysdep_headers += net/if_ppp.h net/ppp-comp.h \
+sysdep_headers += bits/if.h net/if_ppp.h net/ppp-comp.h \
 		  net/ppp_defs.h net/if_arp.h net/route.h net/ethernet.h \
 		  net/if_slip.h net/if_packet.h net/if_shaper.h
 sysdep_routines += cmsg_nxthdr
@@ -200,3 +200,13 @@  tests += tst-align-clone tst-getpid1 \
 	tst-thread-affinity-sched
 tests-internal += tst-setgetname
 endif
+
+# Add testing of the header coordination with the Linux kernel
+# by attempting to compile headers in various specific orders.
+# Randomly including headers is not the best solution to this
+# problem since some headers are not designed to be used together.
+ifeq ($(subdir),inet)
+tests += tst-ipv4-compat1 tst-ipv4-compat2 tst-ipv6-compat1 tst-ipv6-compat2 \
+	tst-ipv6-compat3 tst-ipv6-compat4 tst-ipv6-compat5 tst-ipv6-compat6 \
+	tst-ipx-compat1 tst-ipx-compat2 tst-if-compat1 tst-if-compat2
+endif
diff --git a/sysdeps/unix/sysv/linux/bits/if.h b/sysdeps/unix/sysv/linux/bits/if.h
new file mode 100644
index 0000000000..76a35d1d6d
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/bits/if.h
@@ -0,0 +1,36 @@ 
+/* Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* Linux version.  */
+
+#ifndef _NET_IF_H
+# error "Never use <bits/if.h> directly; include <net/if.h> instead."
+#endif
+
+/* If the application has already included linux/if.h from a linux-based
+   kernel then we will not define IFF_* constants, struct ifmap, struct
+   ifreq, IFHWADDRLEN, IFNAMSIZ, ifr_* accesors, _IOT_ifreq* accessors,
+   struct ifconf, ifc_* accesors, or _IOT_ifconf* accessors.  */
+#ifdef __UAPI_DEF_IF_IFCONF
+# if __UAPI_DEF_IF_IFCONF
+#  define __USE_KERNEL_IF_DEFS	1
+# else
+#  define __USE_KERNEL_IF_DEFS	0
+# endif
+#else
+# define __USE_KERNEL_IF_DEFS	0
+#endif
diff --git a/sysdeps/unix/sysv/linux/kernel-features.h b/sysdeps/unix/sysv/linux/kernel-features.h
index f65a262994..008abc1cd4 100644
--- a/sysdeps/unix/sysv/linux/kernel-features.h
+++ b/sysdeps/unix/sysv/linux/kernel-features.h
@@ -17,6 +17,9 @@ 
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+/* Provide LINUX_VERSION_CODE.  */
+#include <linux/version.h>
+
 /* This file must not contain any C code.  At least it must be protected
    to allow using the file also in assembler files.  */
 
@@ -150,3 +153,18 @@ 
    */
 
 #define __ASSUME_CLONE_DEFAULT 1
+
+/* On Linux kernel 3.12 or newer the IPv6/IPv4 headers are guarded to
+   ensure compatibiltiy with glibc INET headers. You need at least
+   Linux kernel 3.19 to get the full set of compatible headers for
+   glibc inet/in.h.  */
+#define __TEST_USE_KERNEL_IPV6_DEFS	(LINUX_VERSION_CODE >= 0x031300)
+#define __TEST_USE_KERNEL_INET_DEFS	(LINUX_VERSION_CODE >= 0x031300)
+
+/* On Linux kernel 4.6 or newer the IF headers are guarded to
+   ensure compatibility with the glibc IF headers.  */
+#define __TEST_USE_KERNEL_IF_DEFS	(LINUX_VERSION_CODE >= 0x040600)
+
+/* On Linux kernel 4.8 or newer the IPX headers are guarded to
+   ensure compatibility with the glibc IPX headers.  */
+#define __TEST_USE_KERNEL_IPX_DEFS	(LINUX_VERSION_CODE >= 0x040800)
diff --git a/sysdeps/unix/sysv/linux/netipx/ipx.h b/sysdeps/unix/sysv/linux/netipx/ipx.h
index bacea41718..57cf9af9b3 100644
--- a/sysdeps/unix/sysv/linux/netipx/ipx.h
+++ b/sysdeps/unix/sysv/linux/netipx/ipx.h
@@ -22,13 +22,31 @@ 
 #include <stdint.h>
 #include <bits/sockaddr.h>
 
+/* If the application has already included linux/ipx.h from a linux-based
+   kernel then we will not define the struct sockaddr_ipx, sipx_special,
+   sipx_action, IPX_DLTITF, IPX_CRTITF, struct ipx_route_definition,
+   struct ipx_interface_definition, IPX_FRAME_*, IPX_SPECIAL_NONE,
+   IPX_PRIMARY, IPX_INETERNAL, struct ipx_config_data, struct ipx_route_def,
+   IPX_RT_*, IPX_ROUTE_NO_ROUTER, and SIOC*.  */
+#ifdef __UAPI_DEF_SOCKADDR_IPX
+# if __UAPI_DEF_SOCKADDR_IPX
+#  define __USE_KERNEL_IPX_DEFS		1
+# else
+#  define __USE_KERNEL_IPX_DEFS		0
+# endif
+#else
+# define __USE_KERNEL_IPX_DEFS		0
+#endif
+
 __BEGIN_DECLS
 
 #define SOL_IPX    256          /* sockopt level */
 
 #define IPX_TYPE        1
-#define IPX_NODE_LEN	6
-#define IPX_MTU		576
+
+#if !__USE_KERNEL_IPX_DEFS
+# define IPX_NODE_LEN	6
+# define IPX_MTU	576
 
 struct sockaddr_ipx
   {
@@ -44,10 +62,10 @@  struct sockaddr_ipx
  *	So we can fit the extra info for SIOCSIFADDR into the address nicely
  */
 
-#define sipx_special	sipx_port
-#define sipx_action	sipx_zero
-#define IPX_DLTITF	0
-#define IPX_CRTITF	1
+# define sipx_special	sipx_port
+# define sipx_action	sipx_zero
+# define IPX_DLTITF	0
+# define IPX_CRTITF	1
 
 typedef struct ipx_route_definition
   {
@@ -62,16 +80,16 @@  typedef struct ipx_interface_definition
     unsigned long ipx_network;
     unsigned char ipx_device[16];
     unsigned char ipx_dlink_type;
-#define IPX_FRAME_NONE		0
-#define IPX_FRAME_SNAP		1
-#define IPX_FRAME_8022		2
-#define IPX_FRAME_ETHERII	3
-#define IPX_FRAME_8023		4
-#define IPX_FRAME_TR_8022	5
+# define IPX_FRAME_NONE		0
+# define IPX_FRAME_SNAP		1
+# define IPX_FRAME_8022		2
+# define IPX_FRAME_ETHERII	3
+# define IPX_FRAME_8023		4
+# define IPX_FRAME_TR_8022	5
     unsigned char ipx_special;
-#define IPX_SPECIAL_NONE	0
-#define IPX_PRIMARY		1
-#define IPX_INTERNAL		2
+# define IPX_SPECIAL_NONE	0
+# define IPX_PRIMARY		1
+# define IPX_INTERNAL		2
     unsigned char ipx_node[IPX_NODE_LEN];
   }
 ipx_interface_definition;
@@ -91,20 +109,21 @@  struct ipx_route_def
   {
     unsigned long ipx_network;
     unsigned long ipx_router_network;
-#define IPX_ROUTE_NO_ROUTER	0
+# define IPX_ROUTE_NO_ROUTER	0
     unsigned char ipx_router_node[IPX_NODE_LEN];
     unsigned char ipx_device[16];
     unsigned short ipx_flags;
-#define IPX_RT_SNAP		8
-#define IPX_RT_8022		4
-#define IPX_RT_BLUEBOOK		2
-#define IPX_RT_ROUTED		1
+# define IPX_RT_SNAP		8
+# define IPX_RT_8022		4
+# define IPX_RT_BLUEBOOK	2
+# define IPX_RT_ROUTED		1
   };
 
-#define SIOCAIPXITFCRT		(SIOCPROTOPRIVATE)
-#define SIOCAIPXPRISLT		(SIOCPROTOPRIVATE + 1)
-#define SIOCIPXCFGDATA		(SIOCPROTOPRIVATE + 2)
-#define SIOCIPXNCPCONN		(SIOCPROTOPRIVATE + 3)
+# define SIOCAIPXITFCRT		(SIOCPROTOPRIVATE)
+# define SIOCAIPXPRISLT		(SIOCPROTOPRIVATE + 1)
+# define SIOCIPXCFGDATA		(SIOCPROTOPRIVATE + 2)
+# define SIOCIPXNCPCONN		(SIOCPROTOPRIVATE + 3)
+#endif /* !__USE_KERNEL_IPX_DEFS  */
 
 __END_DECLS
 
diff --git a/sysdeps/unix/sysv/linux/tst-if-compat1.c b/sysdeps/unix/sysv/linux/tst-if-compat1.c
new file mode 100644
index 0000000000..c04ae07c90
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/tst-if-compat1.c
@@ -0,0 +1,56 @@ 
+/* Test IF linux kernel and glibc header interoperability.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+#include <kernel-features.h>
+#include <sys/socket.h>
+
+/* Run the first test by default.  */
+#ifndef TST_IF_COMPAT
+# define TST_IF_COMPAT 1
+#endif
+
+#if __TEST_USE_KERNEL_IF_DEFS
+
+/* Application has to compile and run successfully.  */
+# define RET 0
+
+# if TST_IF_COMPAT == 1
+/* Test the basic coordinated IF definitions:
+   Test net/if.h (glibc) coordinates with linux/if.h (linux) (1/2).  */
+#  include <net/if.h>
+#  include <linux/if.h>
+# endif
+
+# if TST_IF_COMPAT == 2
+/* Test the coordinated IF definitions.
+   Test net/if.h (glibc) coordinates with linux/if.h (linux) (2/2).  */
+#  include <linux/if.h>
+#  include <net/if.h>
+# endif
+
+#else
+
+/* The kernel headers don't support coordinated IF definitions.  */
+# define RET 77 /* UNSUPPORTED.  */
+
+#endif
+
+int
+main (void)
+{
+  return RET;
+}
diff --git a/sysdeps/unix/sysv/linux/tst-if-compat2.c b/sysdeps/unix/sysv/linux/tst-if-compat2.c
new file mode 100644
index 0000000000..1a9cd901fd
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/tst-if-compat2.c
@@ -0,0 +1,2 @@ 
+#define TST_IF_COMPAT 2
+#include "tst-if-compat1.c"
diff --git a/sysdeps/unix/sysv/linux/tst-ipv4-compat1.c b/sysdeps/unix/sysv/linux/tst-ipv4-compat1.c
new file mode 100644
index 0000000000..8dd6cf0f4e
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/tst-ipv4-compat1.c
@@ -0,0 +1,55 @@ 
+/* Test INET linux kernel and glibc header interoperability.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+#include <kernel-features.h>
+
+/* Run the first test by default.  */
+#ifndef TST_INET_COMPAT
+# define TST_INET_COMPAT 1
+#endif
+
+#if __TEST_USE_KERNEL_INET_DEFS
+
+/* Application has to compile and run successfully.  */
+# define RET 0
+
+# if TST_INET_COMPAT == 1
+/* Test the basic coordinated INET definitions:
+   Test netinet/in.h (glibc) coordinates with linux/in.h (linux) (1/2).  */
+#  include <netinet/in.h>
+#  include <linux/in.h>
+# endif
+
+# if TST_INET_COMPAT == 2
+/* Test the coordinated INET definitions.
+   Test netinet/in.h (glibc) coordinates with linux/in.h (linux) (2/2).  */
+#  include <linux/in.h>
+#  include <netinet/in.h>
+# endif
+
+#else
+
+/* The kernel headers don't support coordinated INET definitions.  */
+# define RET 77 /* UNSUPPORTED.  */
+
+#endif
+
+int
+main (void)
+{
+  return RET;
+}
diff --git a/sysdeps/unix/sysv/linux/tst-ipv4-compat2.c b/sysdeps/unix/sysv/linux/tst-ipv4-compat2.c
new file mode 100644
index 0000000000..4f56b4daf2
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/tst-ipv4-compat2.c
@@ -0,0 +1,2 @@ 
+#define TST_IPV4_COMPAT 2
+#include "tst-ipv4-compat1.c"
diff --git a/sysdeps/unix/sysv/linux/tst-ipv6-compat1.c b/sysdeps/unix/sysv/linux/tst-ipv6-compat1.c
new file mode 100644
index 0000000000..5ee59aec1b
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/tst-ipv6-compat1.c
@@ -0,0 +1,83 @@ 
+/* Test IPv6 linux kernel and glibc header interoperability.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+#include <kernel-features.h>
+
+/* Run the first test by default.  */
+#ifndef TST_IPV6_COMPAT
+# define TST_IPV6_COMPAT 1
+#endif
+
+#if __TEST_USE_KERNEL_IPV6_DEFS
+
+/* Application has to compile and run successfully.  */
+# define RET 0
+
+# if TST_IPV6_COMPAT == 1
+/* Test the basic coordinated IPv6 definitions:
+   Test netinet/in.h (glibc) coordinates with linux/in6.h (linux) (1/2).  */
+#  include <netinet/in.h>
+#  include <linux/in6.h>
+# endif
+
+# if TST_IPV6_COMPAT == 2
+/* Test the basic coordinated IPv6 definitions.
+   Test netinet/in.h (glibc) coordinates with linux/in6.h (linux) (2/2).  */
+#  include <linux/in6.h>
+#  include <netinet/in.h>
+# endif
+
+# if TST_IPV6_COMPAT == 3
+/* Test the coordinated IPv6 definitions:
+   Test netdb.h (glibc) coordinates with linux/xfrm.h (linux) (1/2).  */
+#  include <netdb.h>
+#  include <linux/xfrm.h>
+# endif
+
+# if TST_IPV6_COMPAT == 4
+/* Test the coordinated IPv6 definitions:
+   Test netdb.h (glibc) coordinates with linux/xfrm.h (linux) (2/2).  */
+#  include <linux/xfrm.h>
+#  include <netdb.h>
+# endif
+
+# if TST_IPV6_COMPAT == 5
+/* Test the coordinated IPv6 definitions:
+   Test netinet/in.h (glibc) coordinates with linux/ipv6.h (linux) (2/2).  */
+#  include <netinet/in.h>
+#  include <linux/ipv6.h>
+# endif
+
+# if TST_IPV6_COMPAT == 6
+/* Test the coordinated IPv6 definitions:
+   Test netdb.h (glibc) coordinates with linux/xfrm.h (linux) (2/2).  */
+#  include <linux/ipv6.h>
+#  include <netinet/in.h>
+# endif
+
+#else
+
+/* The kernel headers don't support coordinated IPv6 definitions.  */
+# define RET 77  /* UNSUPPORTED.  */
+
+#endif
+
+int
+main (void)
+{
+  return RET;
+}
diff --git a/sysdeps/unix/sysv/linux/tst-ipv6-compat2.c b/sysdeps/unix/sysv/linux/tst-ipv6-compat2.c
new file mode 100644
index 0000000000..7bdad6fe7a
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/tst-ipv6-compat2.c
@@ -0,0 +1,2 @@ 
+#define TST_IPV6_COMPAT 2
+#include "tst-ipv6-compat1.c"
diff --git a/sysdeps/unix/sysv/linux/tst-ipv6-compat3.c b/sysdeps/unix/sysv/linux/tst-ipv6-compat3.c
new file mode 100644
index 0000000000..474ef74810
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/tst-ipv6-compat3.c
@@ -0,0 +1,2 @@ 
+#define TST_IPV6_COMPAT 3
+#include "tst-ipv6-compat1.c"
diff --git a/sysdeps/unix/sysv/linux/tst-ipv6-compat4.c b/sysdeps/unix/sysv/linux/tst-ipv6-compat4.c
new file mode 100644
index 0000000000..3f00979059
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/tst-ipv6-compat4.c
@@ -0,0 +1,2 @@ 
+#define TST_IPV6_COMPAT 4
+#include "tst-ipv6-compat1.c"
diff --git a/sysdeps/unix/sysv/linux/tst-ipv6-compat5.c b/sysdeps/unix/sysv/linux/tst-ipv6-compat5.c
new file mode 100644
index 0000000000..95dfce93ef
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/tst-ipv6-compat5.c
@@ -0,0 +1,2 @@ 
+#define TST_IPV6_COMPAT 5
+#include "tst-ipv6-compat1.c"
diff --git a/sysdeps/unix/sysv/linux/tst-ipv6-compat6.c b/sysdeps/unix/sysv/linux/tst-ipv6-compat6.c
new file mode 100644
index 0000000000..2129955831
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/tst-ipv6-compat6.c
@@ -0,0 +1,2 @@ 
+#define TST_IPV6_COMPAT 6
+#include "tst-ipv6-compat1.c"
diff --git a/sysdeps/unix/sysv/linux/tst-ipx-compat1.c b/sysdeps/unix/sysv/linux/tst-ipx-compat1.c
new file mode 100644
index 0000000000..3e82528dac
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/tst-ipx-compat1.c
@@ -0,0 +1,55 @@ 
+/* Test IPX linux kernel and glibc header interoperability.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+#include <kernel-features.h>
+
+/* Run the first test by default.  */
+#ifndef TST_IPX_COMPAT
+# define TST_IPX_COMPAT 1
+#endif
+
+#if __TEST_USE_KERNEL_IPX_DEFS
+
+/* Application has to compile and run successfully.  */
+# define RET 0
+
+# if TST_IPX_COMPAT == 1
+/* Test the basic coordinated IPX definitions:
+   Test netipx/ipx.h (glibc) coordinates with linux/ipx.h (linux) (1/2).  */
+#  include <netipx/ipx.h>
+#  include <linux/ipx.h>
+# endif
+
+# if TST_IPX_COMPAT == 2
+/* Test the coordinated IPX definitions.
+   Test netipx/in.h (glibc) coordinates with linux/ipx.h (linux) (2/2).  */
+#  include <linux/ipx.h>
+#  include <netipx/ipx.h>
+# endif
+
+#else
+
+/* The kernel headers don't support coordinated IPX definitions.  */
+# define RET 77 /* UNSUPPORTED.  */
+
+#endif
+
+int
+main (void)
+{
+  return RET;
+}
diff --git a/sysdeps/unix/sysv/linux/tst-ipx-compat2.c b/sysdeps/unix/sysv/linux/tst-ipx-compat2.c
new file mode 100644
index 0000000000..77c63eaf9a
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/tst-ipx-compat2.c
@@ -0,0 +1,2 @@ 
+#define TST_IPX_COMPAT 2
+#include "tst-ipx-compat1.c"
-- 
2.14.3