[24/25] Minimize inclusion of netinet/in.h from public headers.

Message ID 20190626175029.4699-15-zackw@panix.com
State New
Headers show
Series
  • Public header file hygiene improvements for 2.30
Related show

Commit Message

Zack Weinberg June 26, 2019, 5:50 p.m.
As with sys/socket.h and struct sockaddr, most of the files including
netinet/in.h just want struct sockaddr_in or a related type, so
introduce bits/types headers for these.  POSIX specifically allows
arpa/inet.h to include netinet/in.h and I think it makes sense to
preserve that.  The definition of struct sockaddr_in had a dependence
on the definition of struct sockaddr; to avoid that, bits/sockaddr.h
grows a new macro, __SOCKADDR_DATA_SIZE, which is the declared size of
struct sockaddr.sa_data.

On Linux, some kernel headers (notably linux/in.h and linux/in6.h)
attempt to cooperate with a C library’s headers in defining types such
as struct sockaddr_in.  There is a set of macros whose names begin
with __UAPI_DEF_ that indicate that a type has already been defined.
This mechanism doesn’t actually work with the kernel headers as they
are in 5.0, as far as I can tell, but it could be made to work with
straightforward changes, so it makes sense for us to support it to the
extent we can.  To do this sensibly I need to introduce a new bits
header called bits/uapi-compat.h, with a trivial definition for
non-Linux.  This replaces the existing __USE_KERNEL_IPV6_DEFS macro.

	* bits/sockaddr.h (__SOCKADDR_DATA_SIZE): New macro.
	* sysdeps/unix/bsd/bits/sockaddr.h: Likewise.
	* sysdeps/unix/sysv/linux/m68k/bits/sockaddr.h: Likewise.
	* socket/bits/types/struct_sockaddr.h: Use __SOCKADDR_DATA_SIZE as
	array length of sa_data.

	* bits/in.h: Add multiple inclusion guard.
	(__USE_KERNEL_IPV6_DEFS): Don’t define.
	* sysdeps/unix/sysv/linux/bits/in.h: Similarly.
	(IPV6_ADD_MEMBERSHIP, IPV6_DROP_MEMBERSHIP): Define when not
	already defined, not conditional on __USE_KERNEL_IPV6_DEFS.

	* bits/uapi-compat.h: New file, trivial generic version.
	* sysdeps/unix/sysv/linux/bits/uapi-compat.h: New file,
	Linux-specific version which recognizes kernel header guard macros
	and defines __UAPI_DEF_* macros as appropriate.
	* misc/Makefile: Install bits/uapi-compat.h.

	* include/bits/types/in_addr_t.h, include/bits/types/in_port_t.h
	* include/bits/types/struct_in_addr.h
	* include/bits/types/struct_in6_addr.h
	* include/bits/types/struct_sockaddr_in.h
	* include/bits/types/struct_sockaddr_in6.h:
	New wrapper headers.

	* inet/bits/types/in_addr_t.h, inet/bits/types/in_port_t.h
	* inet/bits/types/struct_in_addr.h
	* inet/bits/types/struct_in6_addr.h
	* inet/bits/types/struct_sockaddr_in.h
	* inet/bits/types/struct_sockaddr_in6.h
	New single-type headers, factored out of inet/netinet/in.h.
	Add __UAPI_DEF_* conditionals where appropriate, and verify that
	all conditionalized definitions agree with the relevant
	OS-supplied header.  Use __SOCKADDR_DATA_SIZE to set size of sin_zero.
	* inet/Makefile: Install the new single-type headers.

	* inet/netinet/in.h: Include bits/uapi-compat.h.
	Define in_addr_t, in_port_t, struct in_addr, struct in6_addr,
	struct sockaddr_in, and struct sockaddr_in6 by including the
	above single-type headers, not directly.  Replace all
	__USE_KERNEL_IPV6_DEFS conditionals with appropriate __UAPI_DEF_*
	conditionals.  Add appropriate __UAPI_DEF_* conditionals around
	the definitions of the IPPROTO_* constants, the IN_CLASS
	macros, and struct ip_mreq.  Import IN_LOOPBACK macro from
	Linux 5.0 linux/in.h and verify all other conditionalized
	definitions agree with the relevant linux/ header.
	Define IPPORT_RESERVED only if not already defined, and make it a
	macro so we can tell.

	* inet/netinet/igmp.h, inet/netinet/ip.h, inet/netinet/ip_icmp.h:
	Include bits/types/struct_in_addr.h, not netinet/in.h.

	* inet/netinet/ip_icmp.h: Hoist all #includes to the top of the file.

	* inet/netinet/icmp6.h, inet/netinet/ip6.h
	* sysdeps/unix/sysv/linux/net/route.h:
	Include bits/types/struct_in6_addr.h, not netinet/in.h.

	* sysdeps/mach/hurd/net/route.h: Include bits/types.h and
	bits/types/struct_in6_addr.h, not netinet/in.h.  Use __uint16_t
	and __uint32_t instead of uint16_t and uint32_t.

	* resolv/bits/types/res_state.h: Include bits/types/struct_in_addr.h
	and bits/types/struct_sockaddr_in.h.  Forward declare struct
	sockaddr_in6.  Don’t include netinet/in.h.

	* resolv/netdb.h: Don’t include netinet/in.h.  Use socklen_t
	instead of __socklen_t.  Define IPPORT_RESERVED only if not
	already defined, with definition matching netinet/in.h.
	When __USE_MISC, include bits/sockaddr.h.
	* resolv/resolv.h: Don’t include netinet/in.h.

	* inet/tst-getni1.c, inet/tst-getni2.c
	* nss/tst-nss-files-hosts-erange.c, nss/tst-nss-files-hosts-getent.c
	* nss/tst-nss-files-hosts-multi.c, posix/tst-getaddrinfo2.c
	* resolv/tst-bug18665-tcp.c, resolv/tst-resolv-ai_idn-common.c
	* resolv/tst-resolv-canonname.c, resolv/tst-resolv-edns.c
	* resolv/tst-resolv-network.c, resolv/tst-resolv-nondecimal.c
	* resolv/tst-resolv-search.c, support/tst-support-namespace.c:
	Include netinet/in.h.
	* support/resolv_test.h: Include stdint.h, not sys/cdefs.h.

	* scripts/check-obsolete-constructs.py (HEADER_ALLOWED_INCLUDES):
	Update.
---
 bits/in.h                                    |   8 +-
 bits/sockaddr.h                              |   3 +
 bits/uapi-compat.h                           |  34 +++++
 include/bits/types/in_addr_t.h               |   1 +
 include/bits/types/in_port_t.h               |   1 +
 include/bits/types/struct_in6_addr.h         |   1 +
 include/bits/types/struct_in_addr.h          |   1 +
 include/bits/types/struct_sockaddr_in.h      |   1 +
 include/bits/types/struct_sockaddr_in6.h     |   1 +
 inet/Makefile                                |   5 +-
 inet/bits/types/in_addr_t.h                  |   9 ++
 inet/bits/types/in_port_t.h                  |   9 ++
 inet/bits/types/struct_in6_addr.h            |  30 ++++
 inet/bits/types/struct_in_addr.h             |  18 +++
 inet/bits/types/struct_sockaddr_in.h         |  28 ++++
 inet/bits/types/struct_sockaddr_in6.h        |  25 +++
 inet/netinet/icmp6.h                         |   2 +-
 inet/netinet/igmp.h                          |   2 +-
 inet/netinet/in.h                            | 102 +++++--------
 inet/netinet/ip.h                            |   2 +-
 inet/netinet/ip6.h                           |   2 +-
 inet/netinet/ip_icmp.h                       |   7 +-
 inet/tst-getni1.c                            |   1 +
 inet/tst-getni2.c                            |   1 +
 misc/Makefile                                |   2 +-
 nss/tst-nss-files-hosts-erange.c             |   1 +
 nss/tst-nss-files-hosts-getent.c             |   1 +
 nss/tst-nss-files-hosts-multi.c              |   1 +
 posix/tst-getaddrinfo2.c                     |   1 +
 resolv/bits/types/res_state.h                |   5 +-
 resolv/netdb.h                               |  12 +-
 resolv/resolv.h                              |   1 -
 resolv/tst-bug18665-tcp.c                    |   1 +
 resolv/tst-resolv-ai_idn-common.c            |   1 +
 resolv/tst-resolv-canonname.c                |   1 +
 resolv/tst-resolv-edns.c                     |   1 +
 resolv/tst-resolv-network.c                  |   1 +
 resolv/tst-resolv-nondecimal.c               |   1 +
 resolv/tst-resolv-search.c                   |   1 +
 scripts/check-obsolete-constructs.py         |  20 +--
 socket/bits/types/struct_sockaddr.h          |   2 +-
 support/resolv_test.h                        |   4 +-
 support/tst-support-namespace.c              |   1 +
 sysdeps/mach/hurd/net/route.h                |  15 +-
 sysdeps/unix/bsd/bits/sockaddr.h             |   3 +
 sysdeps/unix/sysv/linux/bits/in.h            |  33 ++--
 sysdeps/unix/sysv/linux/bits/uapi-compat.h   | 153 +++++++++++++++++++
 sysdeps/unix/sysv/linux/m68k/bits/sockaddr.h |   4 +-
 sysdeps/unix/sysv/linux/net/route.h          |   3 +-
 49 files changed, 429 insertions(+), 134 deletions(-)
 create mode 100644 bits/uapi-compat.h
 create mode 100644 include/bits/types/in_addr_t.h
 create mode 100644 include/bits/types/in_port_t.h
 create mode 100644 include/bits/types/struct_in6_addr.h
 create mode 100644 include/bits/types/struct_in_addr.h
 create mode 100644 include/bits/types/struct_sockaddr_in.h
 create mode 100644 include/bits/types/struct_sockaddr_in6.h
 create mode 100644 inet/bits/types/in_addr_t.h
 create mode 100644 inet/bits/types/in_port_t.h
 create mode 100644 inet/bits/types/struct_in6_addr.h
 create mode 100644 inet/bits/types/struct_in_addr.h
 create mode 100644 inet/bits/types/struct_sockaddr_in.h
 create mode 100644 inet/bits/types/struct_sockaddr_in6.h
 create mode 100644 sysdeps/unix/sysv/linux/bits/uapi-compat.h

-- 
2.20.1

Patch

diff --git a/bits/in.h b/bits/in.h
index 7652bc45d0..cc24174a45 100644
--- a/bits/in.h
+++ b/bits/in.h
@@ -15,15 +15,15 @@ 
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#ifndef _BITS_IN_H
+#define _BITS_IN_H 1
+
 /* Generic version.  */
 
 #ifndef _NETINET_IN_H
 # error "Never use <bits/in.h> directly; include <netinet/in.h> instead."
 #endif
 
-/* This is the generic version, do not assume a linux-based kernel.  */
-#define __USE_KERNEL_IPV6_DEFS 0
-
 /* To select the IP level.  */
 #define SOL_IP		0
 
@@ -115,3 +115,5 @@  struct ip_opts
 #define IPV6_RTHDR_STRICT	1	/* Hop must be a neighbour.  */
 
 #define IPV6_RTHDR_TYPE_0	0	/* IPv6 Routing header type 0.  */
+
+#endif /* bits/in.h.  */
diff --git a/bits/sockaddr.h b/bits/sockaddr.h
index 2505246ec5..b3434747b3 100644
--- a/bits/sockaddr.h
+++ b/bits/sockaddr.h
@@ -39,4 +39,7 @@  typedef unsigned short int sa_family_t;
 /* Size of struct sockaddr_storage.  */
 #define _SS_SIZE 128
 
+/* Size of struct sockaddr.sa_data.  */
+#define __SOCKADDR_DATA_SIZE 14
+
 #endif	/* bits/sockaddr.h */
diff --git a/bits/uapi-compat.h b/bits/uapi-compat.h
new file mode 100644
index 0000000000..afa9ddd5d3
--- /dev/null
+++ b/bits/uapi-compat.h
@@ -0,0 +1,34 @@ 
+/* Copyright (C) 2019 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/>.  */
+
+/* This header is internal to glibc and should not be included outside
+   of glibc headers.  It is included by each header that needs to make
+   global declarations that may or may not already have been made by a
+   header provided by the underlying operating system kernel.  All such
+   declarations are associated with macros named __UAPI_DEF_something,
+   which have three possible values:
+
+   If __UAPI_DEF_FOO is not defined, nobody has yet declared `foo'.
+   If __UAPI_DEF_FOO is defined to 0, glibc's headers have declared `foo'.
+   If __UAPI_DEF_FOO is defined to 1, the kernel's headers have declared `foo`.
+
+   This header cannot have a multiple-inclusion guard, because it needs
+   to recheck for additional declarations by kernel headers each time
+   a glibc header that uses it is included.
+
+   This generic version of uapi-compat.h is used on operating systems
+   where none of the above coordination is necessary.  */
diff --git a/include/bits/types/in_addr_t.h b/include/bits/types/in_addr_t.h
new file mode 100644
index 0000000000..a894f8bce2
--- /dev/null
+++ b/include/bits/types/in_addr_t.h
@@ -0,0 +1 @@ 
+#include <inet/bits/types/in_addr_t.h>
diff --git a/include/bits/types/in_port_t.h b/include/bits/types/in_port_t.h
new file mode 100644
index 0000000000..bea5710585
--- /dev/null
+++ b/include/bits/types/in_port_t.h
@@ -0,0 +1 @@ 
+#include <inet/bits/types/in_port_t.h>
diff --git a/include/bits/types/struct_in6_addr.h b/include/bits/types/struct_in6_addr.h
new file mode 100644
index 0000000000..61c35a118d
--- /dev/null
+++ b/include/bits/types/struct_in6_addr.h
@@ -0,0 +1 @@ 
+#include <inet/bits/types/struct_in6_addr.h>
diff --git a/include/bits/types/struct_in_addr.h b/include/bits/types/struct_in_addr.h
new file mode 100644
index 0000000000..c0835d01d0
--- /dev/null
+++ b/include/bits/types/struct_in_addr.h
@@ -0,0 +1 @@ 
+#include <inet/bits/types/struct_in_addr.h>
diff --git a/include/bits/types/struct_sockaddr_in.h b/include/bits/types/struct_sockaddr_in.h
new file mode 100644
index 0000000000..3bf048b832
--- /dev/null
+++ b/include/bits/types/struct_sockaddr_in.h
@@ -0,0 +1 @@ 
+#include <inet/bits/types/struct_sockaddr_in.h>
diff --git a/include/bits/types/struct_sockaddr_in6.h b/include/bits/types/struct_sockaddr_in6.h
new file mode 100644
index 0000000000..d0c30ec239
--- /dev/null
+++ b/include/bits/types/struct_sockaddr_in6.h
@@ -0,0 +1 @@ 
+#include <inet/bits/types/struct_sockaddr_in6.h>
diff --git a/inet/Makefile b/inet/Makefile
index a58278a1e1..a4392b6448 100644
--- a/inet/Makefile
+++ b/inet/Makefile
@@ -22,7 +22,10 @@  subdir	:= inet
 
 include ../Makeconfig
 
-headers	:= aliases.h ifaddrs.h bits/in.h				     \
+headers	:= aliases.h ifaddrs.h bits/in.h 				     \
+	   bits/types/in_addr_t.h bits/types/in_port_t.h		     \
+	   bits/types/struct_in_addr.h bits/types/struct_in6_addr.h	     \
+	   bits/types/struct_sockaddr_in.h bits/types/struct_sockaddr_in6.h  \
            netinet/ether.h netinet/icmp6.h netinet/if_ether.h netinet/igmp.h \
            netinet/in.h netinet/in_systm.h netinet/ip.h netinet/ip6.h	     \
 	   netinet/ip_icmp.h netinet/tcp.h netinet/udp.h		     \
diff --git a/inet/bits/types/in_addr_t.h b/inet/bits/types/in_addr_t.h
new file mode 100644
index 0000000000..63779bbd75
--- /dev/null
+++ b/inet/bits/types/in_addr_t.h
@@ -0,0 +1,9 @@ 
+#ifndef __in_addr_t_defined
+#define __in_addr_t_defined 1
+
+#include <bits/types.h>
+
+/* Type to represent an IPv4 address.  */
+typedef __uint32_t in_addr_t;
+
+#endif
diff --git a/inet/bits/types/in_port_t.h b/inet/bits/types/in_port_t.h
new file mode 100644
index 0000000000..8fa1a02fef
--- /dev/null
+++ b/inet/bits/types/in_port_t.h
@@ -0,0 +1,9 @@ 
+#ifndef __in_port_t_defined
+#define __in_port_t_defined 1
+
+#include <bits/types.h>
+
+/* Type to represent a TCP or UDP port.  */
+typedef __uint16_t in_port_t;
+
+#endif
diff --git a/inet/bits/types/struct_in6_addr.h b/inet/bits/types/struct_in6_addr.h
new file mode 100644
index 0000000000..5aaea39701
--- /dev/null
+++ b/inet/bits/types/struct_in6_addr.h
@@ -0,0 +1,30 @@ 
+#ifndef __struct_in6_addr_defined
+#define __struct_in6_addr_defined 1
+
+#include <features.h>
+#include <bits/types.h>
+#include <bits/uapi-compat.h>
+
+/* Kernel headers may already have defined this type.  */
+#if !defined __UAPI_DEF_IN6_ADDR || __UAPI_DEF_IN6_ADDR == 0
+#define __UAPI_DEF_IN6_ADDR 0
+#define __UAPI_DEF_IN6_ADDR_ALT 0
+
+/* Struct representing an IPv6 address.  */
+struct in6_addr
+{
+  union
+  {
+    __uint8_t  __u6_addr8[16];
+    __uint16_t __u6_addr16[8];
+    __uint32_t __u6_addr32[4];
+  } __in6_u;
+#define s6_addr			__in6_u.__u6_addr8
+#ifdef __USE_MISC
+# define s6_addr16		__in6_u.__u6_addr16
+# define s6_addr32		__in6_u.__u6_addr32
+#endif
+};
+
+#endif /* __UAPI_DEF_IN6_ADDR is zero or not defined.  */
+#endif /* struct_in6_addr.h.  */
diff --git a/inet/bits/types/struct_in_addr.h b/inet/bits/types/struct_in_addr.h
new file mode 100644
index 0000000000..0dbe57f0fd
--- /dev/null
+++ b/inet/bits/types/struct_in_addr.h
@@ -0,0 +1,18 @@ 
+#ifndef __struct_in_addr_defined
+#define __struct_in_addr_defined 1
+
+#include <bits/types/in_addr_t.h>
+#include <bits/uapi-compat.h>
+
+/* Kernel headers may already have defined this type.  */
+#if !defined __UAPI_DEF_IN_ADDR || __UAPI_DEF_IN_ADDR == 0
+#define __UAPI_DEF_IN_ADDR 0
+
+/* Struct representing an IPv4 address.  */
+struct in_addr
+{
+  in_addr_t s_addr;
+};
+
+#endif /* __UAPI_DEF_IN_ADDR is zero or not defined. */
+#endif /* struct_in_addr.h.  */
diff --git a/inet/bits/types/struct_sockaddr_in.h b/inet/bits/types/struct_sockaddr_in.h
new file mode 100644
index 0000000000..f2289eb0c6
--- /dev/null
+++ b/inet/bits/types/struct_sockaddr_in.h
@@ -0,0 +1,28 @@ 
+#ifndef __struct_sockaddr_in_defined
+#define __struct_sockaddr_in_defined 1
+
+#include <bits/types.h>
+#include <bits/types/struct_in_addr.h>
+#include <bits/types/in_port_t.h>
+#include <bits/sockaddr.h>
+#include <bits/uapi-compat.h>
+
+/* Kernel headers may already have defined this type.  */
+#if !defined __UAPI_DEF_SOCKADDR_IN || __UAPI_DEF_SOCKADDR_IN == 0
+#define __UAPI_DEF_SOCKADDR_IN 0
+
+/* Structure describing an IPv4 socket address.  */
+struct sockaddr_in
+{
+  __SOCKADDR_COMMON (sin_);
+  in_port_t sin_port;			/* Port number.  */
+  struct in_addr sin_addr;		/* IPv4 address.  */
+
+  /* Pad to size of `struct sockaddr'.  */
+  unsigned char sin_zero[__SOCKADDR_DATA_SIZE
+                         - sizeof (in_port_t)
+                         - sizeof (struct in_addr)];
+};
+
+#endif /* __UAPI_DEF_SOCKADDR_IN is zero or not defined.  */
+#endif /* struct_sockaddr_in.h.  */
diff --git a/inet/bits/types/struct_sockaddr_in6.h b/inet/bits/types/struct_sockaddr_in6.h
new file mode 100644
index 0000000000..7af109fc1e
--- /dev/null
+++ b/inet/bits/types/struct_sockaddr_in6.h
@@ -0,0 +1,25 @@ 
+#ifndef __struct_sockaddr_in6_defined
+#define __struct_sockaddr_in6_defined 1
+
+#include <bits/types.h>
+#include <bits/types/struct_in6_addr.h>
+#include <bits/types/in_port_t.h>
+#include <bits/sockaddr.h>
+#include <bits/uapi-compat.h>
+
+/* Kernel headers may already have defined this type.  */
+#if !defined __UAPI_DEF_SOCKADDR_IN6 || __UAPI_DEF_SOCKADDR_IN6 == 0
+#define __UAPI_DEF_SOCKADDR_IN6 0
+
+/* Structure describing an IPv6 socket address.  */
+struct sockaddr_in6
+{
+  __SOCKADDR_COMMON (sin6_);
+  in_port_t sin6_port;		/* Transport layer port # */
+  uint32_t sin6_flowinfo;	/* IPv6 flow information */
+  struct in6_addr sin6_addr;	/* IPv6 address */
+  uint32_t sin6_scope_id;	/* IPv6 scope-id */
+};
+
+#endif /* __UAPI_DEF_SOCKADDR_IN6 is zero or not defined.  */
+#endif /* struct_sockaddr_in6.h.  */
diff --git a/inet/netinet/icmp6.h b/inet/netinet/icmp6.h
index 5119085391..4e5da1d9ae 100644
--- a/inet/netinet/icmp6.h
+++ b/inet/netinet/icmp6.h
@@ -22,7 +22,7 @@ 
 #include <bits/endian.h>
 #include <bits/types.h>
 #include <bits/types/size_t.h>
-#include <netinet/in.h>
+#include <bits/types/struct_in6_addr.h>
 
 #define ICMP6_FILTER 1
 
diff --git a/inet/netinet/igmp.h b/inet/netinet/igmp.h
index 6eafc19a73..6a599d347d 100644
--- a/inet/netinet/igmp.h
+++ b/inet/netinet/igmp.h
@@ -22,8 +22,8 @@ 
 
 #ifdef __USE_MISC
 
-#include <netinet/in.h>
 #include <bits/types.h>
+#include <bits/types/struct_in_addr.h>
 
 __BEGIN_DECLS
 
diff --git a/inet/netinet/in.h b/inet/netinet/in.h
index b7a1d6a2e8..d691bd31b1 100644
--- a/inet/netinet/in.h
+++ b/inet/netinet/in.h
@@ -19,24 +19,28 @@ 
 #define	_NETINET_IN_H	1
 
 #include <features.h>
+
 #include <bits/types.h>
 #include <bits/stdint-uintn.h>
 #include <bits/sockaddr.h>
+#include <bits/uapi-compat.h>
+
+#include <bits/types/in_addr_t.h>
+#include <bits/types/in_port_t.h>
+#include <bits/types/struct_in_addr.h>
+#include <bits/types/struct_in6_addr.h>
 #include <bits/types/struct_sockaddr.h>
+#include <bits/types/struct_sockaddr_in.h>
+#include <bits/types/struct_sockaddr_in6.h>
 #include <bits/types/struct_sockaddr_storage.h>
 
-__BEGIN_DECLS
-
-/* Internet address.  */
-typedef uint32_t in_addr_t;
-struct in_addr
-  {
-    in_addr_t s_addr;
-  };
-
 /* Get system-specific definitions.  */
 #include <bits/in.h>
 
+__BEGIN_DECLS
+
+#if !defined __UAPI_DEF_IN_IPPROTO || __UAPI_DEF_IN_IPPROTO == 0
+#define __UAPI_DEF_IN_IPPROTO 0
 /* Standard well-defined IP protocols.  */
 enum
   {
@@ -92,11 +96,10 @@  enum
 #define IPPROTO_RAW		IPPROTO_RAW
     IPPROTO_MAX
   };
+#endif
 
-/* If __USE_KERNEL_IPV6_DEFS is 1 then the user has included the kernel
-   network headers first and we should use those ABI-identical definitions
-   instead of our own, otherwise 0.  */
-#if !__USE_KERNEL_IPV6_DEFS
+#if !defined __UAPI_DEF_IPPROTO_V6 || __UAPI_DEF_IPPROTO_V6 == 0
+#define __UAPI_DEF_IPPROTO_V6 0
 enum
   {
     IPPROTO_HOPOPTS = 0,   /* IPv6 Hop-by-Hop options.  */
@@ -114,10 +117,7 @@  enum
     IPPROTO_MH = 135       /* IPv6 mobility header.  */
 #define IPPROTO_MH		IPPROTO_MH
   };
-#endif /* !__USE_KERNEL_IPV6_DEFS */
-
-/* Type to represent a port.  */
-typedef uint16_t in_port_t;
+#endif
 
 /* Standard well-known ports.  */
 enum
@@ -153,7 +153,10 @@  enum
     IPPORT_ROUTESERVER = 520,
 
     /* Ports less than this value are reserved for privileged processes.  */
+#ifndef IPPORT_RESERVED /* also defined in netdb.h */
     IPPORT_RESERVED = 1024,
+#define IPPORT_RESERVED IPPORT_RESERVED
+#endif
 
     /* Ports greater this value are reserved for (non-privileged) servers.  */
     IPPORT_USERRESERVED = 5000
@@ -163,6 +166,8 @@  enum
 
    On subnets, host and network parts are found according to
    the subnet mask, not these masks.  */
+#if !defined __UAPI_DEF_IN_CLASS || __UAPI_DEF_IN_CLASS == 0
+#define __UAPI_DEF_IN_CLASS 0
 
 #define	IN_CLASSA(a)		((((in_addr_t)(a)) & 0x80000000) == 0)
 #define	IN_CLASSA_NET		0xff000000
@@ -200,6 +205,7 @@  enum
 #ifndef INADDR_LOOPBACK
 # define INADDR_LOOPBACK	((in_addr_t) 0x7f000001) /* Inet 127.0.0.1.  */
 #endif
+#define	IN_LOOPBACK(a)		((((in_addr_t) (a)) & 0xff000000) == 0x7f000000)
 
 /* Defines for Multicast INADDR.  */
 #define INADDR_UNSPEC_GROUP	((in_addr_t) 0xe0000000) /* 224.0.0.0 */
@@ -207,24 +213,7 @@  enum
 #define INADDR_ALLRTRS_GROUP    ((in_addr_t) 0xe0000002) /* 224.0.0.2 */
 #define INADDR_ALLSNOOPERS_GROUP ((in_addr_t) 0xe000006a) /* 224.0.0.106 */
 #define INADDR_MAX_LOCAL_GROUP  ((in_addr_t) 0xe00000ff) /* 224.0.0.255 */
-
-#if !__USE_KERNEL_IPV6_DEFS
-/* IPv6 address */
-struct in6_addr
-  {
-    union
-      {
-	uint8_t	__u6_addr8[16];
-	uint16_t __u6_addr16[8];
-	uint32_t __u6_addr32[4];
-      } __in6_u;
-#define s6_addr			__in6_u.__u6_addr8
-#ifdef __USE_MISC
-# define s6_addr16		__in6_u.__u6_addr16
-# define s6_addr32		__in6_u.__u6_addr32
-#endif
-  };
-#endif /* !__USE_KERNEL_IPV6_DEFS */
+#endif /* __UAPI_DEF_IN_CLASS is zero or not defined */
 
 extern const struct in6_addr in6addr_any;        /* :: */
 extern const struct in6_addr in6addr_loopback;   /* ::1 */
@@ -234,34 +223,9 @@  extern const struct in6_addr in6addr_loopback;   /* ::1 */
 #define INET_ADDRSTRLEN 16
 #define INET6_ADDRSTRLEN 46
 
-
-/* Structure describing an Internet socket address.  */
-struct sockaddr_in
-  {
-    __SOCKADDR_COMMON (sin_);
-    in_port_t sin_port;			/* Port number.  */
-    struct in_addr sin_addr;		/* Internet address.  */
-
-    /* Pad to size of `struct sockaddr'.  */
-    unsigned char sin_zero[sizeof (struct sockaddr)
-			   - __SOCKADDR_COMMON_SIZE
-			   - sizeof (in_port_t)
-			   - sizeof (struct in_addr)];
-  };
-
-#if !__USE_KERNEL_IPV6_DEFS
-/* Ditto, for IPv6.  */
-struct sockaddr_in6
-  {
-    __SOCKADDR_COMMON (sin6_);
-    in_port_t sin6_port;	/* Transport layer port # */
-    uint32_t sin6_flowinfo;	/* IPv6 flow information */
-    struct in6_addr sin6_addr;	/* IPv6 address */
-    uint32_t sin6_scope_id;	/* IPv6 scope-id */
-  };
-#endif /* !__USE_KERNEL_IPV6_DEFS */
-
 #ifdef __USE_MISC
+#if !defined __UAPI_DEF_IP_MREQ || __UAPI_DEF_IP_MREQ == 0
+#define __UAPI_DEF_IP_MREQ 0
 /* IPv4 multicast request.  */
 struct ip_mreq
   {
@@ -284,8 +248,10 @@  struct ip_mreq_source
     struct in_addr imr_sourceaddr;
   };
 #endif
+#endif
 
-#if !__USE_KERNEL_IPV6_DEFS
+#if !defined __UAPI_DEF_IPV6_MREQ || __UAPI_DEF_IP_MREQ == 0
+#define __UAPI_DEF_IPV6_MREQ 0
 /* Likewise, for IPv6.  */
 struct ipv6_mreq
   {
@@ -295,7 +261,7 @@  struct ipv6_mreq
     /* local interface */
     unsigned int ipv6mr_interface;
   };
-#endif /* !__USE_KERNEL_IPV6_DEFS */
+#endif
 
 #ifdef __USE_MISC
 /* Multicast group request.  */
@@ -533,21 +499,25 @@  extern int bindresvport6 (int __sockfd, struct sockaddr_in6 *__sock_in)
 #ifdef __USE_GNU
 struct cmsghdr;			/* Forward declaration.  */
 
-#if !__USE_KERNEL_IPV6_DEFS
+#if !defined __UAPI_DEF_IN6_PKTINFO || __UAPI_DEF_IN6_PKTINFO == 0
+#define __UAPI_DEF_IN6_PKTINFO 0
 /* IPv6 packet information.  */
 struct in6_pktinfo
   {
     struct in6_addr ipi6_addr;	/* src/dst IPv6 address */
     unsigned int ipi6_ifindex;	/* send/recv interface index */
   };
+#endif
 
+#if !defined __UAPI_DEF_IN6_MTUINFO || __UAPI_DEF_IN6_MTUINFO == 0
+#define __UAPI_DEF_IN6_MTUINFO 0
 /* IPv6 MTU information.  */
 struct ip6_mtuinfo
   {
     struct sockaddr_in6 ip6m_addr; /* dst address including zone ID */
     uint32_t ip6m_mtu;		   /* path MTU in host byte order */
   };
-#endif /* !__USE_KERNEL_IPV6_DEFS */
+#endif
 
 /* Obsolete hop-by-hop and Destination Options Processing (RFC 2292).  */
 extern int inet6_option_space (int __nbytes)
diff --git a/inet/netinet/ip.h b/inet/netinet/ip.h
index fa6b588c42..a3beca86b9 100644
--- a/inet/netinet/ip.h
+++ b/inet/netinet/ip.h
@@ -20,9 +20,9 @@ 
 
 #include <features.h>
 
-#include <netinet/in.h>
 #include <bits/endian.h>
 #include <bits/types.h>
+#include <bits/types/struct_in_addr.h>
 
 __BEGIN_DECLS
 
diff --git a/inet/netinet/ip6.h b/inet/netinet/ip6.h
index e2a8d2b356..b16e093394 100644
--- a/inet/netinet/ip6.h
+++ b/inet/netinet/ip6.h
@@ -19,9 +19,9 @@ 
 #define _NETINET_IP6_H 1
 
 #include <features.h>
-#include <netinet/in.h>
 #include <bits/endian.h>
 #include <bits/types.h>
+#include <bits/types/struct_in6_addr.h>
 
 struct ip6_hdr
   {
diff --git a/inet/netinet/ip_icmp.h b/inet/netinet/ip_icmp.h
index da7ff3b81b..54660e792b 100644
--- a/inet/netinet/ip_icmp.h
+++ b/inet/netinet/ip_icmp.h
@@ -20,6 +20,10 @@ 
 
 #include <features.h>
 #include <bits/types.h>
+#ifdef __USE_MISC
+#include <bits/types/struct_in_addr.h>
+#include <netinet/ip.h>
+#endif
 
 __BEGIN_DECLS
 
@@ -122,9 +126,6 @@  struct icmphdr
  *	@(#)ip_icmp.h	8.1 (Berkeley) 6/10/93
  */
 
-#include <netinet/in.h>
-#include <netinet/ip.h>
-
 /*
  * Internal of an ICMP Router Advertisement
  */
diff --git a/inet/tst-getni1.c b/inet/tst-getni1.c
index 3960f7112e..154ee200e6 100644
--- a/inet/tst-getni1.c
+++ b/inet/tst-getni1.c
@@ -1,6 +1,7 @@ 
 #include <netdb.h>
 #include <stdio.h>
 #include <sys/socket.h>
+#include <netinet/in.h>
 
 static int
 do_test (void)
diff --git a/inet/tst-getni2.c b/inet/tst-getni2.c
index 66e78062ba..0811e40a24 100644
--- a/inet/tst-getni2.c
+++ b/inet/tst-getni2.c
@@ -1,6 +1,7 @@ 
 #include <netdb.h>
 #include <stdio.h>
 #include <sys/socket.h>
+#include <netinet/in.h>
 
 static int
 do_test (void)
diff --git a/misc/Makefile b/misc/Makefile
index 106ce57776..6c0e4b4ede 100644
--- a/misc/Makefile
+++ b/misc/Makefile
@@ -33,7 +33,7 @@  headers :=								\
 	bits/mman.h bits/param.h bits/select.h bits/select2.h		\
 	bits/stab.def bits/syslog-ldbl.h bits/syslog-path.h		\
 	bits/syslog.h bits/sysmacros.h bits/types/struct_iovec.h	\
-	bits/uio-ext.h bits/uio_lim.h bits/xopen_lim.h			\
+	bits/uapi-compat.h bits/uio-ext.h bits/uio_lim.h bits/xopen_lim.h \
 	gnu/libc-version.h						\
 	sys/auxv.h sys/cdefs.h sys/dir.h sys/file.h sys/ioctl.h		\
 	sys/mman.h sys/mtio.h sys/param.h sys/ptrace.h sys/queue.h	\
diff --git a/nss/tst-nss-files-hosts-erange.c b/nss/tst-nss-files-hosts-erange.c
index bf77e23639..6b500cf617 100644
--- a/nss/tst-nss-files-hosts-erange.c
+++ b/nss/tst-nss-files-hosts-erange.c
@@ -23,6 +23,7 @@ 
 #include <netdb.h>
 #include <nss.h>
 #include <sys/socket.h>
+#include <netinet/in.h>
 #include <support/check.h>
 #include <support/check_nss.h>
 #include <support/namespace.h>
diff --git a/nss/tst-nss-files-hosts-getent.c b/nss/tst-nss-files-hosts-getent.c
index 001f6f1ede..3ba740c397 100644
--- a/nss/tst-nss-files-hosts-getent.c
+++ b/nss/tst-nss-files-hosts-getent.c
@@ -25,6 +25,7 @@ 
 #include <stdlib.h>
 #include <stdio.h>
 #include <sys/socket.h>
+#include <netinet/in.h>
 #include <support/check.h>
 #include <support/check_nss.h>
 #include <support/namespace.h>
diff --git a/nss/tst-nss-files-hosts-multi.c b/nss/tst-nss-files-hosts-multi.c
index 4862e84257..2467bdd291 100644
--- a/nss/tst-nss-files-hosts-multi.c
+++ b/nss/tst-nss-files-hosts-multi.c
@@ -25,6 +25,7 @@ 
 #include <stdlib.h>
 #include <string.h>
 #include <sys/socket.h>
+#include <netinet/in.h>
 #include <support/check.h>
 #include <support/check_nss.h>
 #include <support/namespace.h>
diff --git a/posix/tst-getaddrinfo2.c b/posix/tst-getaddrinfo2.c
index d8be4a8e8f..d0913790a9 100644
--- a/posix/tst-getaddrinfo2.c
+++ b/posix/tst-getaddrinfo2.c
@@ -6,6 +6,7 @@ 
 #include <stdlib.h>
 #include <string.h>
 #include <sys/socket.h>
+#include <netinet/in.h>
 
 static int
 do_test (void)
diff --git a/resolv/bits/types/res_state.h b/resolv/bits/types/res_state.h
index 81febe13b0..274e6a0a01 100644
--- a/resolv/bits/types/res_state.h
+++ b/resolv/bits/types/res_state.h
@@ -2,7 +2,10 @@ 
 #define __res_state_defined 1
 
 #include <bits/types.h>
-#include <netinet/in.h>
+#include <bits/types/struct_in_addr.h>
+#include <bits/types/struct_sockaddr_in.h>
+
+struct sockaddr_in6;
 
 /* res_state: the global state used by the resolver stub.  */
 #define MAXNS			3	/* max # name servers we'll track */
diff --git a/resolv/netdb.h b/resolv/netdb.h
index 1158864312..2be4ff9afa 100644
--- a/resolv/netdb.h
+++ b/resolv/netdb.h
@@ -24,7 +24,6 @@ 
 
 #include <features.h>
 
-#include <netinet/in.h>
 #include <bits/types/socklen_t.h>
 #include <bits/stdint-uintn.h>
 #ifdef __USE_MISC
@@ -77,7 +76,10 @@  extern int *__h_errno_location (void) __THROW __attribute__ ((__const__));
 
 #if defined __USE_XOPEN2K || defined __USE_XOPEN_EXTENDED
 /* Highest reserved Internet port number.  */
-# define IPPORT_RESERVED	1024
+# ifndef IPPORT_RESERVED /* also defined in netinet/in.h */
+enum { IPPORT_RESERVED = 1024 };
+#  define IPPORT_RESERVED IPPORT_RESERVED
+# endif
 #endif
 
 #ifdef __USE_GNU
@@ -133,7 +135,7 @@  extern struct hostent *gethostent (void);
 
    This function is a possible cancellation point and therefore not
    marked with __THROW.  */
-extern struct hostent *gethostbyaddr (const void *__addr, __socklen_t __len,
+extern struct hostent *gethostbyaddr (const void *__addr, socklen_t __len,
 				      int __type);
 
 /* Return entry from host data base for host with NAME.
@@ -168,7 +170,7 @@  extern int gethostent_r (struct hostent *__restrict __result_buf,
 			 struct hostent **__restrict __result,
 			 int *__restrict __h_errnop);
 
-extern int gethostbyaddr_r (const void *__restrict __addr, __socklen_t __len,
+extern int gethostbyaddr_r (const void *__restrict __addr, socklen_t __len,
 			    int __type,
 			    struct hostent *__restrict __result_buf,
 			    char *__restrict __buf, size_t __buflen,
@@ -436,6 +438,8 @@  extern int getnetgrent_r (char **__restrict __hostp,
 
 
 #ifdef __USE_MISC
+#include <bits/sockaddr.h> /* for sa_family_t */
+
 /* Call `rshd' at port RPORT on remote machine *AHOST to execute CMD.
    The local user is LOCUSER, on the remote machine the command is
    executed as REMUSER.  In *FD2P the descriptor to the socket for the
diff --git a/resolv/resolv.h b/resolv/resolv.h
index 5783de697d..c29a92ec8a 100644
--- a/resolv/resolv.h
+++ b/resolv/resolv.h
@@ -54,7 +54,6 @@ 
 
 #include <features.h>
 
-#include <netinet/in.h>
 #include <arpa/nameser.h>
 
 #include <bits/types.h>
diff --git a/resolv/tst-bug18665-tcp.c b/resolv/tst-bug18665-tcp.c
index 090ae0a86b..5760afa837 100644
--- a/resolv/tst-bug18665-tcp.c
+++ b/resolv/tst-bug18665-tcp.c
@@ -23,6 +23,7 @@ 
 #include <stdlib.h>
 #include <string.h>
 #include <sys/socket.h>
+#include <netinet/in.h>
 #include <support/check.h>
 #include <support/check_nss.h>
 #include <support/resolv_test.h>
diff --git a/resolv/tst-resolv-ai_idn-common.c b/resolv/tst-resolv-ai_idn-common.c
index f560ccf5cd..dcc01852c2 100644
--- a/resolv/tst-resolv-ai_idn-common.c
+++ b/resolv/tst-resolv-ai_idn-common.c
@@ -24,6 +24,7 @@ 
 #include <stdlib.h>
 #include <string.h>
 #include <sys/socket.h>
+#include <netinet/in.h>
 #include <support/check.h>
 #include <support/check_nss.h>
 #include <support/resolv_test.h>
diff --git a/resolv/tst-resolv-canonname.c b/resolv/tst-resolv-canonname.c
index 7379eee643..7da72a224b 100644
--- a/resolv/tst-resolv-canonname.c
+++ b/resolv/tst-resolv-canonname.c
@@ -20,6 +20,7 @@ 
 #include <errno.h>
 #include <gnu/lib-names.h>
 #include <netdb.h>
+#include <netinet/in.h>
 #include <nss.h>
 #include <stdio.h>
 #include <stdlib.h>
diff --git a/resolv/tst-resolv-edns.c b/resolv/tst-resolv-edns.c
index e88463ddff..fff61b063d 100644
--- a/resolv/tst-resolv-edns.c
+++ b/resolv/tst-resolv-edns.c
@@ -23,6 +23,7 @@ 
 #include <stdlib.h>
 #include <string.h>
 #include <sys/socket.h>
+#include <netinet/in.h>
 #include <support/check.h>
 #include <support/resolv_test.h>
 #include <support/support.h>
diff --git a/resolv/tst-resolv-network.c b/resolv/tst-resolv-network.c
index c4609a4db5..93fa4eeef4 100644
--- a/resolv/tst-resolv-network.c
+++ b/resolv/tst-resolv-network.c
@@ -20,6 +20,7 @@ 
 #include <stdlib.h>
 #include <string.h>
 #include <sys/socket.h>
+#include <netinet/in.h>
 #include <support/check.h>
 #include <support/check_nss.h>
 #include <support/resolv_test.h>
diff --git a/resolv/tst-resolv-nondecimal.c b/resolv/tst-resolv-nondecimal.c
index 61888eadd9..ffe9bfc00a 100644
--- a/resolv/tst-resolv-nondecimal.c
+++ b/resolv/tst-resolv-nondecimal.c
@@ -19,6 +19,7 @@ 
 #include <netdb.h>
 #include <stdlib.h>
 #include <sys/socket.h>
+#include <netinet/in.h>
 #include <support/check.h>
 #include <support/check_nss.h>
 #include <support/resolv_test.h>
diff --git a/resolv/tst-resolv-search.c b/resolv/tst-resolv-search.c
index bca1e1312d..9672012186 100644
--- a/resolv/tst-resolv-search.c
+++ b/resolv/tst-resolv-search.c
@@ -20,6 +20,7 @@ 
 #include <stdlib.h>
 #include <string.h>
 #include <sys/socket.h>
+#include <netinet/in.h>
 #include <support/check.h>
 #include <support/check_nss.h>
 #include <support/resolv_test.h>
diff --git a/scripts/check-obsolete-constructs.py b/scripts/check-obsolete-constructs.py
index 2ca83b90c7..95360158b5 100755
--- a/scripts/check-obsolete-constructs.py
+++ b/scripts/check-obsolete-constructs.py
@@ -538,10 +538,10 @@  HEADER_ALLOWED_INCLUDES = {
     "sys/types.h":                 [ "endian.h" ],
 
     # POSIX networking headers
-    # allowed: netdb.h -> netinet/in.h
-    #          arpa/inet.h -> netinet/in.h
-    "netdb.h":                     [ "netinet/in.h", "rpc/netdb.h" ],
+    # POSIX allows arpa/inet.h -> netinet/in.h
     "arpa/inet.h":                 [ "netinet/in.h" ],
+    # necessary for backward compatibility with Sun RPC
+    "netdb.h":                     [ "rpc/netdb.h" ],
 
     # Nonstandardized top-level headers
     "argp.h":                      [ "ctype.h", "errno.h", "getopt.h",
@@ -603,27 +603,20 @@  HEADER_ALLOWED_INCLUDES = {
     "wait.h":                      [ "sys/wait.h" ],
 
     # Nonstandardized networking headers
-
-    "resolv.h":                    [ "arpa/nameser.h", "netinet/in.h" ],
+    "resolv.h":                    [ "arpa/nameser.h" ],
     "arpa/nameser.h":              [ "arpa/nameser_compat.h" ],
 
     "net/ethernet.h":              [ "net/if_ether.h" ],
     "net/if_ppp.h":                [ "net/if.h", "net/ppp_defs.h",
                                      "sys/ioctl.h" ],
     "net/if_shaper.h":             [ "net/if.h", "sys/ioctl.h" ],
-    "net/route.h":                 [ "netinet/in.h" ],
     "netatalk/at.h":               [ "sys/ioctl.h" ],
-
     "netinet/ether.h":             [ "netinet/if_ether.h" ],
-    "netinet/icmp6.h":             [ "netinet/in.h" ],
     "netinet/if_ether.h":          [ "net/ethernet.h", "net/if_arp.h" ],
-    "netinet/igmp.h":              [ "netinet/in.h" ],
-    "netinet/ip.h":                [ "netinet/in.h" ],
-    "netinet/ip6.h":               [ "netinet/in.h" ],
-    "netinet/ip_icmp.h":           [ "netinet/in.h", "netinet/ip.h" ],
-
+    "netinet/ip_icmp.h":           [ "netinet/ip.h" ],
     "netrom/netrom.h":             [ "netax25/ax25.h" ],
     "netrose/rose.h":              [ "netax25/ax25.h" ],
+
     "protocols/rwhod.h":           [ "paths.h" ],
 
     # Internal headers
@@ -631,7 +624,6 @@  HEADER_ALLOWED_INCLUDES = {
                                      "sys/cdefs.h" ],
 
     "bits/procfs.h":               [ "signal.h", "sys/ucontext.h" ],
-    "bits/types/res_state.h":      [ "netinet/in.h" ],
 
     "bits/types/__va_list.h":      [ "stdarg.h" ],
     "bits/types/ptrdiff_t.h":      [ "stddef.h" ],
diff --git a/socket/bits/types/struct_sockaddr.h b/socket/bits/types/struct_sockaddr.h
index 86100142ca..34863beb05 100644
--- a/socket/bits/types/struct_sockaddr.h
+++ b/socket/bits/types/struct_sockaddr.h
@@ -9,7 +9,7 @@ 
 struct sockaddr
   {
     __SOCKADDR_COMMON (sa_);	/* Common data: family and perhaps length.  */
-    char sa_data[14];		/* Address data.  */
+    char sa_data[__SOCKADDR_DATA_SIZE];	/* Address data.  */
   };
 
 #endif
diff --git a/support/resolv_test.h b/support/resolv_test.h
index c9e48205ab..1557c51ee3 100644
--- a/support/resolv_test.h
+++ b/support/resolv_test.h
@@ -19,9 +19,9 @@ 
 #ifndef SUPPORT_RESOLV_TEST_H
 #define SUPPORT_RESOLV_TEST_H
 
-#include <arpa/nameser.h>
 #include <stdbool.h>
-#include <sys/cdefs.h>
+#include <stdint.h>
+#include <arpa/nameser.h>
 
 __BEGIN_DECLS
 
diff --git a/support/tst-support-namespace.c b/support/tst-support-namespace.c
index 02d9638e8c..d6338453f5 100644
--- a/support/tst-support-namespace.c
+++ b/support/tst-support-namespace.c
@@ -23,6 +23,7 @@ 
 #include <support/namespace.h>
 #include <support/xsocket.h>
 #include <support/xunistd.h>
+#include <netinet/in.h>
 
 /* Check that the loopback interface provides multiple addresses which
    can be used to run independent servers.  */
diff --git a/sysdeps/mach/hurd/net/route.h b/sysdeps/mach/hurd/net/route.h
index d288475426..666b7ab0f2 100644
--- a/sysdeps/mach/hurd/net/route.h
+++ b/sysdeps/mach/hurd/net/route.h
@@ -22,8 +22,9 @@ 
 
 #include <features.h>
 
+#include <bits/types.h>
 #include <bits/types/struct_sockaddr.h>
-#include <netinet/in.h>
+#include <bits/types/struct_in6_addr.h>
 
 
 /* This structure gets passed by the SIOCADDRT and SIOCDELRT calls. */
@@ -54,12 +55,12 @@  struct in6_rtmsg
     struct in6_addr rtmsg_dst;
     struct in6_addr rtmsg_src;
     struct in6_addr rtmsg_gateway;
-    uint32_t rtmsg_type;
-    uint16_t rtmsg_dst_len;
-    uint16_t rtmsg_src_len;
-    uint32_t rtmsg_metric;
+    __uint32_t rtmsg_type;
+    __uint16_t rtmsg_dst_len;
+    __uint16_t rtmsg_src_len;
+    __uint32_t rtmsg_metric;
     unsigned long int rtmsg_info;
-    uint32_t rtmsg_flags;
+    __uint32_t rtmsg_flags;
     int rtmsg_ifindex;
   };
 
@@ -108,7 +109,7 @@  struct in6_rtmsg
 #define RTF_NAT		0x08000000
 
 #define RTF_ADDRCLASSMASK	0xF8000000
-#define RT_ADDRCLASS(flags)	((uint32_t) flags >> 23)
+#define RT_ADDRCLASS(flags)	((__uint32_t) flags >> 23)
 
 #define RT_TOS(tos)		((tos) & IPTOS_TOS_MASK)
 
diff --git a/sysdeps/unix/bsd/bits/sockaddr.h b/sysdeps/unix/bsd/bits/sockaddr.h
index 723aaf3e3d..c4a3983ea3 100644
--- a/sysdeps/unix/bsd/bits/sockaddr.h
+++ b/sysdeps/unix/bsd/bits/sockaddr.h
@@ -51,4 +51,7 @@  typedef unsigned char sa_family_t;
 # define __ss_aligntype __uint32_t
 #endif
 
+/* Size of struct sockaddr.sa_data.  */
+#define __SOCKADDR_DATA_SIZE 14
+
 #endif	/* bits/sockaddr.h */
diff --git a/sysdeps/unix/sysv/linux/bits/in.h b/sysdeps/unix/sysv/linux/bits/in.h
index 71300fb81e..66a9f4d39c 100644
--- a/sysdeps/unix/sysv/linux/bits/in.h
+++ b/sysdeps/unix/sysv/linux/bits/in.h
@@ -15,32 +15,15 @@ 
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#ifndef _BITS_IN_H
+#define _BITS_IN_H 1
+
 /* Linux version.  */
 
 #ifndef _NETINET_IN_H
 # error "Never use <bits/in.h> directly; include <netinet/in.h> instead."
 #endif
 
-/* If the application has already included linux/in6.h from a linux-based
-   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.
-   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.  */
-# define __USE_KERNEL_IPV6_DEFS 1
-#else
-# define __USE_KERNEL_IPV6_DEFS 0
-#endif
-
 /* Options for use with `getsockopt' and `setsockopt' at the IP level.
    The first word in the comment at the right is the data type used;
    "bool" means a boolean value stored in an `int'.  */
@@ -233,9 +216,11 @@  struct in_pktinfo
 #define IPV6_FREEBIND		78
 
 /* Obsolete synonyms for the above.  */
-#if !__USE_KERNEL_IPV6_DEFS
-# define IPV6_ADD_MEMBERSHIP	IPV6_JOIN_GROUP
-# define IPV6_DROP_MEMBERSHIP	IPV6_LEAVE_GROUP
+#ifndef IPV6_ADD_MEMBERSHIP
+#define IPV6_ADD_MEMBERSHIP	IPV6_JOIN_GROUP
+#endif
+#ifndef IPV6_DROP_MEMBERSHIP
+#define IPV6_DROP_MEMBERSHIP	IPV6_LEAVE_GROUP
 #endif
 #define IPV6_RXHOPOPTS		IPV6_HOPOPTS
 #define IPV6_RXDSTOPTS		IPV6_DSTOPTS
@@ -257,3 +242,5 @@  struct in_pktinfo
 #define IPV6_RTHDR_STRICT	1	/* Hop must be a neighbour.  */
 
 #define IPV6_RTHDR_TYPE_0	0	/* IPv6 Routing header type 0.  */
+
+#endif /* bits/in.h.  */
diff --git a/sysdeps/unix/sysv/linux/bits/uapi-compat.h b/sysdeps/unix/sysv/linux/bits/uapi-compat.h
new file mode 100644
index 0000000000..08f85a61e7
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/bits/uapi-compat.h
@@ -0,0 +1,153 @@ 
+/* Copyright (C) 2019 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/>.  */
+
+/* This header is internal to glibc and should not be included outside
+   of glibc headers.  It is included by each header that needs to make
+   global declarations that may or may not already have been made by a
+   header provided by the underlying operating system kernel.  All such
+   declarations are associated with macros named __UAPI_DEF_something,
+   which have three possible values:
+
+   If __UAPI_DEF_FOO is not defined, nobody has yet declared `foo'.
+   If __UAPI_DEF_FOO is defined to 0, glibc's headers have declared `foo'.
+   If __UAPI_DEF_FOO is defined to 1, the kernel's headers have declared `foo`.
+
+   This header cannot have a multiple-inclusion guard, because it needs
+   to recheck for additional declarations by kernel headers each time
+   a glibc header that uses it is included.
+
+   This version of uapi-compat.h is used for Linux.  Sufficiently new
+   versions of the Linux kernel headers will define the __UAPI_DEF_*
+   macros themselves; this header's job is to preserve compatibility
+   with older versions of the headers that don't do this.
+
+   The guard macros on many of Linux's UAPI headers were changed in
+   kernel rev 56c176c9; we need to check them both with and without a
+   _UAPI_ prefix.  */
+
+#if defined _UAPI_LINUX_IF_H || defined _LINUX_IF_H
+
+#ifndef __UAPI_DEF_IF_IFCONF
+#define __UAPI_DEF_IF_IFCONF 1
+#endif
+#ifndef __UAPI_DEF_IF_IFMAP
+#define __UAPI_DEF_IF_IFMAP 1
+#endif
+#ifndef __UAPI_DEF_IF_IFNAMSIZ
+#define __UAPI_DEF_IF_IFNAMSIZ 1
+#endif
+#ifndef __UAPI_DEF_IF_IFREQ
+#define __UAPI_DEF_IF_IFREQ 1
+#endif
+#ifndef __UAPI_DEF_IF_NET_DEVICE_FLAGS
+#define __UAPI_DEF_IF_NET_DEVICE_FLAGS 1
+#endif
+#ifndef __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO
+#define __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO 1
+#endif
+
+#endif /* linux/if.h */
+
+#if defined _UAPI_LINUX_IN_H || defined _LINUX_IN_H
+
+#ifndef __UAPI_DEF_IN_ADDR
+#define __UAPI_DEF_IN_ADDR		1
+#endif
+#ifndef __UAPI_DEF_IN_IPPROTO
+#define __UAPI_DEF_IN_IPPROTO		1
+#endif
+#ifndef __UAPI_DEF_IN_PKTINFO
+#define __UAPI_DEF_IN_PKTINFO		1
+#endif
+#ifndef __UAPI_DEF_IP_MREQ
+#define __UAPI_DEF_IP_MREQ		1
+#endif
+#ifndef __UAPI_DEF_SOCKADDR_IN
+#define __UAPI_DEF_SOCKADDR_IN		1
+#endif
+#ifndef __UAPI_DEF_IN_CLASS
+#define __UAPI_DEF_IN_CLASS		1
+#endif
+
+#endif /* linux/in.h  */
+
+#if defined _UAPI_LINUX_IN6_H || defined _LINUX_IN6_H
+
+#ifndef __UAPI_DEF_IN6_ADDR
+#define __UAPI_DEF_IN6_ADDR 1
+#endif
+#ifndef __UAPI_DEF_IN6_ADDR_ALT
+# if defined __USE_MISC || defined __USE_GNU
+#  define __UAPI_DEF_IN6_ADDR_ALT 1
+# else
+#  define __UAPI_DEF_IN6_ADDR_ALT 0
+# endif
+#endif
+#ifndef __UAPI_DEF_SOCKADDR_IN6
+#define __UAPI_DEF_SOCKADDR_IN6 1
+#endif
+#ifndef __UAPI_DEF_IPV6_MREQ
+#define __UAPI_DEF_IPV6_MREQ 1
+#endif
+#ifndef __UAPI_DEF_IPPROTO_V6
+#define __UAPI_DEF_IPPROTO_V6 1
+#endif
+#ifndef __UAPI_DEF_IPV6_OPTIONS
+#define __UAPI_DEF_IPV6_OPTIONS 1
+#endif
+
+#endif /* linux/in6.h */
+
+#if defined _UAPI_IPV6_H || defined _IPV6_H
+
+#ifndef __UAPI_DEF_IN6_PKTINFO
+#define __UAPI_DEF_IN6_PKTINFO 1
+#endif
+#ifndef __UAPI_DEF_IP6_MTUINFO
+#define __UAPI_DEF_IP6_MTUINFO 1
+#endif
+
+#endif /* linux/ipv6.h */
+
+#if defined _UAPI_IPX_H_ || defined _IPX_H_
+
+#ifndef __UAPI_DEF_SOCKADDR_IPX
+#define __UAPI_DEF_SOCKADDR_IPX			1
+#endif
+#ifndef __UAPI_DEF_IPX_ROUTE_DEFINITION
+#define __UAPI_DEF_IPX_ROUTE_DEFINITION		1
+#endif
+#ifndef __UAPI_DEF_IPX_INTERFACE_DEFINITION
+#define __UAPI_DEF_IPX_INTERFACE_DEFINITION	1
+#endif
+#ifndef __UAPI_DEF_IPX_CONFIG_DATA
+#define __UAPI_DEF_IPX_CONFIG_DATA		1
+#endif
+#ifndef __UAPI_DEF_IPX_ROUTE_DEF
+#define __UAPI_DEF_IPX_ROUTE_DEF		1
+#endif
+
+#endif /* linux/ipx.h */
+
+#if defined _UAPI_LINUX_XATTR_H || defined _LINUX_XATTR_H \
+ || defined __USE_KERNEL_XATTR_DEFS
+
+#ifndef __UAPI_DEF_XATTR
+#define __UAPI_DEF_XATTR		1
+#endif
+
+#endif /* linux/xattr.h */
diff --git a/sysdeps/unix/sysv/linux/m68k/bits/sockaddr.h b/sysdeps/unix/sysv/linux/m68k/bits/sockaddr.h
index 15f5504755..8956ea7a0f 100644
--- a/sysdeps/unix/sysv/linux/m68k/bits/sockaddr.h
+++ b/sysdeps/unix/sysv/linux/m68k/bits/sockaddr.h
@@ -23,7 +23,6 @@ 
 #ifndef _BITS_SOCKADDR_H
 #define _BITS_SOCKADDR_H	1
 
-
 /* POSIX.1g specifies this type name for the `sa_family' member.  */
 typedef unsigned short int sa_family_t;
 
@@ -39,4 +38,7 @@  typedef unsigned short int sa_family_t;
 /* Size of struct sockaddr_storage.  */
 #define _SS_SIZE 126
 
+/* Size of struct sockaddr.sa_data.  */
+#define __SOCKADDR_DATA_SIZE 14
+
 #endif	/* bits/sockaddr.h */
diff --git a/sysdeps/unix/sysv/linux/net/route.h b/sysdeps/unix/sysv/linux/net/route.h
index edd4afd3b2..380f5d3759 100644
--- a/sysdeps/unix/sysv/linux/net/route.h
+++ b/sysdeps/unix/sysv/linux/net/route.h
@@ -23,11 +23,10 @@ 
 #include <features.h>
 
 #include <bits/types.h>
+#include <bits/types/struct_in6_addr.h>
 #include <bits/types/struct_sockaddr.h>
 #include <bits/wordsize.h>
 
-#include <netinet/in.h>
-
 /* This structure gets passed by the SIOCADDRT and SIOCDELRT calls. */
 struct rtentry
   {