Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: sync some IP headers with glibc

Solution:
=========

- Synchronize linux's `include/uapi/linux/in6.h'
with glibc's `inet/netinet/in.h'.
- Synchronize glibc's `inet/netinet/in.h with linux's
`include/uapi/linux/in6.h'.
- Allow including the headers in either other.
- First header included defines the structures and macros.

Details:
========

The kernel promises not to break the UAPI ABI so I don't
see why we can't just have the two userspace headers
coordinate?

If you include the kernel headers first you get those,
and if you include the glibc headers first you get those,
and the following patch arranges a coordination and
synchronization between the two.

Let's handle `include/uapi/linux/in6.h' from linux,
and `inet/netinet/in.h' from glibc and ensure they compile
in any order and preserve the required ABI.

These two patches pass the following compile tests:

cat >> test1.c <<EOF
int main (void) {
return 0;
}
EOF
gcc -c test1.c

cat >> test2.c <<EOF
int main (void) {
return 0;
}
EOF
gcc -c test2.c

One wrinkle is that the kernel has a different name for one of
the members in ipv6_mreq. In the kernel patch we create a macro
to cover the uses of the old name, and while that's not entirely
clean it's one of the best solutions (aside from an anonymous
union which has other issues).

I've reviewed the code and it looks to me like the ABI is
assured and everything matches on both sides.

Notes:
- You want netinet/in.h to include bits/in.h as early as possible,
but it needs in_addr so define in_addr early.
- You want bits/in.h included as early as possible so you can use
the linux specific code to define __USE_KERNEL_DEFS based on
the _UAPI_* macro definition and use those to cull in.h.
- glibc was missing IPPROTO_MH, added here.

Compile tested and inspected.

Reported-by: Thomas Backlund <tmb@mageia.org>
Cc: Thomas Backlund <tmb@mageia.org>
Cc: libc-alpha@sourceware.org
Cc: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Cc: David S. Miller <davem@davemloft.net>
Tested-by: Cong Wang <amwang@redhat.com>
Signed-off-by: Carlos O'Donell <carlos@redhat.com>
Signed-off-by: Cong Wang <amwang@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Carlos O'Donell and committed by
David S. Miller
cfd280c9 42a5a5c1

+169 -20
+1
include/uapi/linux/Kbuild
··· 227 227 endif 228 228 229 229 header-y += l2tp.h 230 + header-y += libc-compat.h 230 231 header-y += limits.h 231 232 header-y += llc.h 232 233 header-y += loop.h
+36 -13
include/uapi/linux/in.h
··· 24 24 /* Standard well-defined IP protocols. */ 25 25 enum { 26 26 IPPROTO_IP = 0, /* Dummy protocol for TCP */ 27 + #define IPPROTO_IP IPPROTO_IP 27 28 IPPROTO_ICMP = 1, /* Internet Control Message Protocol */ 29 + #define IPPROTO_ICMP IPPROTO_ICMP 28 30 IPPROTO_IGMP = 2, /* Internet Group Management Protocol */ 31 + #define IPPROTO_IGMP IPPROTO_IGMP 29 32 IPPROTO_IPIP = 4, /* IPIP tunnels (older KA9Q tunnels use 94) */ 33 + #define IPPROTO_IPIP IPPROTO_IPIP 30 34 IPPROTO_TCP = 6, /* Transmission Control Protocol */ 35 + #define IPPROTO_TCP IPPROTO_TCP 31 36 IPPROTO_EGP = 8, /* Exterior Gateway Protocol */ 37 + #define IPPROTO_EGP IPPROTO_EGP 32 38 IPPROTO_PUP = 12, /* PUP protocol */ 39 + #define IPPROTO_PUP IPPROTO_PUP 33 40 IPPROTO_UDP = 17, /* User Datagram Protocol */ 41 + #define IPPROTO_UDP IPPROTO_UDP 34 42 IPPROTO_IDP = 22, /* XNS IDP protocol */ 43 + #define IPPROTO_IDP IPPROTO_IDP 44 + IPPROTO_TP = 29, /* SO Transport Protocol Class 4 */ 45 + #define IPPROTO_TP IPPROTO_TP 35 46 IPPROTO_DCCP = 33, /* Datagram Congestion Control Protocol */ 36 - IPPROTO_RSVP = 46, /* RSVP protocol */ 47 + #define IPPROTO_DCCP IPPROTO_DCCP 48 + IPPROTO_IPV6 = 41, /* IPv6-in-IPv4 tunnelling */ 49 + #define IPPROTO_IPV6 IPPROTO_IPV6 50 + IPPROTO_RSVP = 46, /* RSVP Protocol */ 51 + #define IPPROTO_RSVP IPPROTO_RSVP 37 52 IPPROTO_GRE = 47, /* Cisco GRE tunnels (rfc 1701,1702) */ 38 - 39 - IPPROTO_IPV6 = 41, /* IPv6-in-IPv4 tunnelling */ 40 - 41 - IPPROTO_ESP = 50, /* Encapsulation Security Payload protocol */ 42 - IPPROTO_AH = 51, /* Authentication Header protocol */ 43 - IPPROTO_BEETPH = 94, /* IP option pseudo header for BEET */ 44 - IPPROTO_PIM = 103, /* Protocol Independent Multicast */ 45 - 46 - IPPROTO_COMP = 108, /* Compression Header protocol */ 47 - IPPROTO_SCTP = 132, /* Stream Control Transport Protocol */ 53 + #define IPPROTO_GRE IPPROTO_GRE 54 + IPPROTO_ESP = 50, /* Encapsulation Security Payload protocol */ 55 + #define IPPROTO_ESP IPPROTO_ESP 56 + IPPROTO_AH = 51, /* Authentication Header protocol */ 57 + #define IPPROTO_AH IPPROTO_AH 58 + IPPROTO_MTP = 92, /* Multicast Transport Protocol */ 59 + #define IPPROTO_MTP IPPROTO_MTP 60 + IPPROTO_BEETPH = 94, /* IP option pseudo header for BEET */ 61 + #define IPPROTO_BEETPH IPPROTO_BEETPH 62 + IPPROTO_ENCAP = 98, /* Encapsulation Header */ 63 + #define IPPROTO_ENCAP IPPROTO_ENCAP 64 + IPPROTO_PIM = 103, /* Protocol Independent Multicast */ 65 + #define IPPROTO_PIM IPPROTO_PIM 66 + IPPROTO_COMP = 108, /* Compression Header Protocol */ 67 + #define IPPROTO_COMP IPPROTO_COMP 68 + IPPROTO_SCTP = 132, /* Stream Control Transport Protocol */ 69 + #define IPPROTO_SCTP IPPROTO_SCTP 48 70 IPPROTO_UDPLITE = 136, /* UDP-Lite (RFC 3828) */ 49 - 50 - IPPROTO_RAW = 255, /* Raw IP packets */ 71 + #define IPPROTO_UDPLITE IPPROTO_UDPLITE 72 + IPPROTO_RAW = 255, /* Raw IP packets */ 73 + #define IPPROTO_RAW IPPROTO_RAW 51 74 IPPROTO_MAX 52 75 }; 53 76
+29 -7
include/uapi/linux/in6.h
··· 22 22 #define _UAPI_LINUX_IN6_H 23 23 24 24 #include <linux/types.h> 25 + #include <linux/libc-compat.h> 25 26 26 27 /* 27 28 * IPv6 address structure 28 29 */ 29 30 31 + #if __UAPI_DEF_IN6_ADDR 30 32 struct in6_addr { 31 33 union { 32 34 __u8 u6_addr8[16]; 35 + #if __UAPI_DEF_IN6_ADDR_ALT 33 36 __be16 u6_addr16[8]; 34 37 __be32 u6_addr32[4]; 38 + #endif 35 39 } in6_u; 36 40 #define s6_addr in6_u.u6_addr8 41 + #if __UAPI_DEF_IN6_ADDR_ALT 37 42 #define s6_addr16 in6_u.u6_addr16 38 43 #define s6_addr32 in6_u.u6_addr32 44 + #endif 39 45 }; 46 + #endif /* __UAPI_DEF_IN6_ADDR */ 40 47 48 + #if __UAPI_DEF_SOCKADDR_IN6 41 49 struct sockaddr_in6 { 42 50 unsigned short int sin6_family; /* AF_INET6 */ 43 51 __be16 sin6_port; /* Transport layer port # */ ··· 53 45 struct in6_addr sin6_addr; /* IPv6 address */ 54 46 __u32 sin6_scope_id; /* scope id (new in RFC2553) */ 55 47 }; 48 + #endif /* __UAPI_DEF_SOCKADDR_IN6 */ 56 49 50 + #if __UAPI_DEF_IPV6_MREQ 57 51 struct ipv6_mreq { 58 52 /* IPv6 multicast address of group */ 59 53 struct in6_addr ipv6mr_multiaddr; ··· 63 53 /* local IPv6 address of interface */ 64 54 int ipv6mr_ifindex; 65 55 }; 56 + #endif /* __UAPI_DEF_IVP6_MREQ */ 66 57 67 58 #define ipv6mr_acaddr ipv6mr_multiaddr 68 59 ··· 125 114 /* 126 115 * IPV6 extension headers 127 116 */ 128 - #define IPPROTO_HOPOPTS 0 /* IPv6 hop-by-hop options */ 129 - #define IPPROTO_ROUTING 43 /* IPv6 routing header */ 130 - #define IPPROTO_FRAGMENT 44 /* IPv6 fragmentation header */ 131 - #define IPPROTO_ICMPV6 58 /* ICMPv6 */ 132 - #define IPPROTO_NONE 59 /* IPv6 no next header */ 133 - #define IPPROTO_DSTOPTS 60 /* IPv6 destination options */ 134 - #define IPPROTO_MH 135 /* IPv6 mobility header */ 117 + #if __UAPI_DEF_IPPROTO_V6 118 + enum { 119 + IPPROTO_HOPOPTS = 0, /* IPv6 hop-by-hop options */ 120 + #define IPPROTO_HOPOPTS IPPROTO_HOPOPTS 121 + IPPROTO_ROUTING = 43, /* IPv6 routing header */ 122 + #define IPPROTO_ROUTING IPPROTO_ROUTING 123 + IPPROTO_FRAGMENT = 44, /* IPv6 fragmentation header */ 124 + #define IPPROTO_FRAGMENT IPPROTO_FRAGMENT 125 + IPPROTO_ICMPV6 = 58, /* ICMPv6 */ 126 + #define IPPROTO_ICMPV6 IPPROTO_ICMPV6 127 + IPPROTO_NONE = 59, /* IPv6 no next header */ 128 + #define IPPROTO_NONE IPPROTO_NONE 129 + IPPROTO_DSTOPTS = 60, /* IPv6 destination options */ 130 + #define IPPROTO_DSTOPTS IPPROTO_DSTOPTS 131 + IPPROTO_MH = 135, /* IPv6 mobility header */ 132 + #define IPPROTO_MH IPPROTO_MH 133 + }; 134 + #endif /* __UAPI_DEF_IPPROTO_V6 */ 135 135 136 136 /* 137 137 * IPv6 TLV options.
+103
include/uapi/linux/libc-compat.h
··· 1 + /* 2 + * Compatibility interface for userspace libc header coordination: 3 + * 4 + * Define compatibility macros that are used to control the inclusion or 5 + * exclusion of UAPI structures and definitions in coordination with another 6 + * userspace C library. 7 + * 8 + * This header is intended to solve the problem of UAPI definitions that 9 + * conflict with userspace definitions. If a UAPI header has such conflicting 10 + * definitions then the solution is as follows: 11 + * 12 + * * Synchronize the UAPI header and the libc headers so either one can be 13 + * used and such that the ABI is preserved. If this is not possible then 14 + * no simple compatibility interface exists (you need to write translating 15 + * wrappers and rename things) and you can't use this interface. 16 + * 17 + * Then follow this process: 18 + * 19 + * (a) Include libc-compat.h in the UAPI header. 20 + * e.g. #include <linux/libc-compat.h> 21 + * This include must be as early as possible. 22 + * 23 + * (b) In libc-compat.h add enough code to detect that the comflicting 24 + * userspace libc header has been included first. 25 + * 26 + * (c) If the userspace libc header has been included first define a set of 27 + * guard macros of the form __UAPI_DEF_FOO and set their values to 1, else 28 + * set their values to 0. 29 + * 30 + * (d) Back in the UAPI header with the conflicting definitions, guard the 31 + * definitions with: 32 + * #if __UAPI_DEF_FOO 33 + * ... 34 + * #endif 35 + * 36 + * This fixes the situation where the linux headers are included *after* the 37 + * libc headers. To fix the problem with the inclusion in the other order the 38 + * userspace libc headers must be fixed like this: 39 + * 40 + * * For all definitions that conflict with kernel definitions wrap those 41 + * defines in the following: 42 + * #if !__UAPI_DEF_FOO 43 + * ... 44 + * #endif 45 + * 46 + * This prevents the redefinition of a construct already defined by the kernel. 47 + */ 48 + #ifndef _UAPI_LIBC_COMPAT_H 49 + #define _UAPI_LIBC_COMPAT_H 50 + 51 + /* We have included glibc headers... */ 52 + #if defined(__GLIBC__) 53 + 54 + /* Coordinate with glibc netinet/in.h header. */ 55 + #if defined(_NETINET_IN_H) 56 + 57 + /* GLIBC headers included first so don't define anything 58 + * that would already be defined. */ 59 + #define __UAPI_DEF_IN6_ADDR 0 60 + /* The exception is the in6_addr macros which must be defined 61 + * if the glibc code didn't define them. This guard matches 62 + * the guard in glibc/inet/netinet/in.h which defines the 63 + * additional in6_addr macros e.g. s6_addr16, and s6_addr32. */ 64 + #if defined(__USE_MISC) || defined (__USE_GNU) 65 + #define __UAPI_DEF_IN6_ADDR_ALT 0 66 + #else 67 + #define __UAPI_DEF_IN6_ADDR_ALT 1 68 + #endif 69 + #define __UAPI_DEF_SOCKADDR_IN6 0 70 + #define __UAPI_DEF_IPV6_MREQ 0 71 + #define __UAPI_DEF_IPPROTO_V6 0 72 + 73 + #else 74 + 75 + /* Linux headers included first, and we must define everything 76 + * we need. The expectation is that glibc will check the 77 + * __UAPI_DEF_* defines and adjust appropriately. */ 78 + #define __UAPI_DEF_IN6_ADDR 1 79 + /* We unconditionally define the in6_addr macros and glibc must 80 + * coordinate. */ 81 + #define __UAPI_DEF_IN6_ADDR_ALT 1 82 + #define __UAPI_DEF_SOCKADDR_IN6 1 83 + #define __UAPI_DEF_IPV6_MREQ 1 84 + #define __UAPI_DEF_IPPROTO_V6 1 85 + 86 + #endif /* _NETINET_IN_H */ 87 + 88 + 89 + /* If we did not see any headers from any supported C libraries, 90 + * or we are being included in the kernel, then define everything 91 + * that we need. */ 92 + #else /* !defined(__GLIBC__) */ 93 + 94 + /* Definitions for in6.h */ 95 + #define __UAPI_DEF_IN6_ADDR 1 96 + #define __UAPI_DEF_IN6_ADDR_ALT 1 97 + #define __UAPI_DEF_SOCKADDR_IN6 1 98 + #define __UAPI_DEF_IPV6_MREQ 1 99 + #define __UAPI_DEF_IPPROTO_V6 1 100 + 101 + #endif /* __GLIBC__ */ 102 + 103 + #endif /* _UAPI_LIBC_COMPAT_H */