Commit 4a91cb61 authored by Mikko Rapeli's avatar Mikko Rapeli Committed by David S. Miller

uapi glibc compat: fix compile errors when glibc net/if.h included before linux/if.h

glibc's net/if.h contains copies of definitions from linux/if.h and these
conflict and cause build failures if both files are included by application
source code. Changes in uapi headers, which fixed header file dependencies to
include linux/if.h when it was needed, e.g. commit 1ffad83d, made the
net/if.h and linux/if.h incompatibilities visible as build failures for
userspace applications like iproute2 and xtables-addons.

This patch fixes compile errors when glibc net/if.h is included before
linux/if.h:

./linux/if.h:99:21: error: redeclaration of enumerator ‘IFF_NOARP’
./linux/if.h:98:23: error: redeclaration of enumerator ‘IFF_RUNNING’
./linux/if.h:97:26: error: redeclaration of enumerator ‘IFF_NOTRAILERS’
./linux/if.h:96:27: error: redeclaration of enumerator ‘IFF_POINTOPOINT’
./linux/if.h:95:24: error: redeclaration of enumerator ‘IFF_LOOPBACK’
./linux/if.h:94:21: error: redeclaration of enumerator ‘IFF_DEBUG’
./linux/if.h:93:25: error: redeclaration of enumerator ‘IFF_BROADCAST’
./linux/if.h:92:19: error: redeclaration of enumerator ‘IFF_UP’
./linux/if.h:252:8: error: redefinition of ‘struct ifconf’
./linux/if.h:203:8: error: redefinition of ‘struct ifreq’
./linux/if.h:169:8: error: redefinition of ‘struct ifmap’
./linux/if.h:107:23: error: redeclaration of enumerator ‘IFF_DYNAMIC’
./linux/if.h:106:25: error: redeclaration of enumerator ‘IFF_AUTOMEDIA’
./linux/if.h:105:23: error: redeclaration of enumerator ‘IFF_PORTSEL’
./linux/if.h:104:25: error: redeclaration of enumerator ‘IFF_MULTICAST’
./linux/if.h:103:21: error: redeclaration of enumerator ‘IFF_SLAVE’
./linux/if.h:102:22: error: redeclaration of enumerator ‘IFF_MASTER’
./linux/if.h:101:24: error: redeclaration of enumerator ‘IFF_ALLMULTI’
./linux/if.h:100:23: error: redeclaration of enumerator ‘IFF_PROMISC’

The cases where linux/if.h is included before net/if.h need a similar fix in
the glibc side, or the order of include files can be changed userspace
code as a workaround.

This change was tested in x86 userspace on Debian unstable with
scripts/headers_compile_test.sh:

$ make headers_install && \
  cd usr/include && ../../scripts/headers_compile_test.sh -l -k
...
cc -Wall -c -nostdinc -I /usr/lib/gcc/i586-linux-gnu/5/include -I /usr/lib/gcc/i586-linux-gnu/5/include-fixed -I . -I /home/mcfrisk/src/linux-2.6/usr/headers_compile_test_include.2uX2zH -I /home/mcfrisk/src/linux-2.6/usr/headers_compile_test_include.2uX2zH/i586-linux-gnu -o /dev/null ./linux/if.h_libc_before_kernel.h
PASSED libc before kernel test: ./linux/if.h
Reported-by: default avatarJan Engelhardt <jengelh@inai.de>
Reported-by: default avatarJosh Boyer <jwboyer@fedoraproject.org>
Reported-by: default avatarStephen Hemminger <shemming@brocade.com>
Reported-by: default avatarWaldemar Brodkorb <mail@waldemar-brodkorb.de>
Cc: Gabriel Laskar <gabriel@lse.epita.fr>
Signed-off-by: default avatarMikko Rapeli <mikko.rapeli@iki.fi>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b507146b
...@@ -19,14 +19,20 @@ ...@@ -19,14 +19,20 @@
#ifndef _LINUX_IF_H #ifndef _LINUX_IF_H
#define _LINUX_IF_H #define _LINUX_IF_H
#include <linux/libc-compat.h> /* for compatibility with glibc */
#include <linux/types.h> /* for "__kernel_caddr_t" et al */ #include <linux/types.h> /* for "__kernel_caddr_t" et al */
#include <linux/socket.h> /* for "struct sockaddr" et al */ #include <linux/socket.h> /* for "struct sockaddr" et al */
#include <linux/compiler.h> /* for "__user" et al */ #include <linux/compiler.h> /* for "__user" et al */
#if __UAPI_DEF_IF_IFNAMSIZ
#define IFNAMSIZ 16 #define IFNAMSIZ 16
#endif /* __UAPI_DEF_IF_IFNAMSIZ */
#define IFALIASZ 256 #define IFALIASZ 256
#include <linux/hdlc/ioctl.h> #include <linux/hdlc/ioctl.h>
/* For glibc compatibility. An empty enum does not compile. */
#if __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO != 0 && \
__UAPI_DEF_IF_NET_DEVICE_FLAGS != 0
/** /**
* enum net_device_flags - &struct net_device flags * enum net_device_flags - &struct net_device flags
* *
...@@ -68,6 +74,8 @@ ...@@ -68,6 +74,8 @@
* @IFF_ECHO: echo sent packets. Volatile. * @IFF_ECHO: echo sent packets. Volatile.
*/ */
enum net_device_flags { enum net_device_flags {
/* for compatibility with glibc net/if.h */
#if __UAPI_DEF_IF_NET_DEVICE_FLAGS
IFF_UP = 1<<0, /* sysfs */ IFF_UP = 1<<0, /* sysfs */
IFF_BROADCAST = 1<<1, /* volatile */ IFF_BROADCAST = 1<<1, /* volatile */
IFF_DEBUG = 1<<2, /* sysfs */ IFF_DEBUG = 1<<2, /* sysfs */
...@@ -84,11 +92,17 @@ enum net_device_flags { ...@@ -84,11 +92,17 @@ enum net_device_flags {
IFF_PORTSEL = 1<<13, /* sysfs */ IFF_PORTSEL = 1<<13, /* sysfs */
IFF_AUTOMEDIA = 1<<14, /* sysfs */ IFF_AUTOMEDIA = 1<<14, /* sysfs */
IFF_DYNAMIC = 1<<15, /* sysfs */ IFF_DYNAMIC = 1<<15, /* sysfs */
#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS */
#if __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO
IFF_LOWER_UP = 1<<16, /* volatile */ IFF_LOWER_UP = 1<<16, /* volatile */
IFF_DORMANT = 1<<17, /* volatile */ IFF_DORMANT = 1<<17, /* volatile */
IFF_ECHO = 1<<18, /* volatile */ IFF_ECHO = 1<<18, /* volatile */
#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO */
}; };
#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO != 0 && __UAPI_DEF_IF_NET_DEVICE_FLAGS != 0 */
/* for compatibility with glibc net/if.h */
#if __UAPI_DEF_IF_NET_DEVICE_FLAGS
#define IFF_UP IFF_UP #define IFF_UP IFF_UP
#define IFF_BROADCAST IFF_BROADCAST #define IFF_BROADCAST IFF_BROADCAST
#define IFF_DEBUG IFF_DEBUG #define IFF_DEBUG IFF_DEBUG
...@@ -105,9 +119,13 @@ enum net_device_flags { ...@@ -105,9 +119,13 @@ enum net_device_flags {
#define IFF_PORTSEL IFF_PORTSEL #define IFF_PORTSEL IFF_PORTSEL
#define IFF_AUTOMEDIA IFF_AUTOMEDIA #define IFF_AUTOMEDIA IFF_AUTOMEDIA
#define IFF_DYNAMIC IFF_DYNAMIC #define IFF_DYNAMIC IFF_DYNAMIC
#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS */
#if __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO
#define IFF_LOWER_UP IFF_LOWER_UP #define IFF_LOWER_UP IFF_LOWER_UP
#define IFF_DORMANT IFF_DORMANT #define IFF_DORMANT IFF_DORMANT
#define IFF_ECHO IFF_ECHO #define IFF_ECHO IFF_ECHO
#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO */
#define IFF_VOLATILE (IFF_LOOPBACK|IFF_POINTOPOINT|IFF_BROADCAST|IFF_ECHO|\ #define IFF_VOLATILE (IFF_LOOPBACK|IFF_POINTOPOINT|IFF_BROADCAST|IFF_ECHO|\
IFF_MASTER|IFF_SLAVE|IFF_RUNNING|IFF_LOWER_UP|IFF_DORMANT) IFF_MASTER|IFF_SLAVE|IFF_RUNNING|IFF_LOWER_UP|IFF_DORMANT)
...@@ -166,6 +184,8 @@ enum { ...@@ -166,6 +184,8 @@ enum {
* being very small might be worth keeping for clean configuration. * being very small might be worth keeping for clean configuration.
*/ */
/* for compatibility with glibc net/if.h */
#if __UAPI_DEF_IF_IFMAP
struct ifmap { struct ifmap {
unsigned long mem_start; unsigned long mem_start;
unsigned long mem_end; unsigned long mem_end;
...@@ -175,6 +195,7 @@ struct ifmap { ...@@ -175,6 +195,7 @@ struct ifmap {
unsigned char port; unsigned char port;
/* 3 bytes spare */ /* 3 bytes spare */
}; };
#endif /* __UAPI_DEF_IF_IFMAP */
struct if_settings { struct if_settings {
unsigned int type; /* Type of physical device or protocol */ unsigned int type; /* Type of physical device or protocol */
...@@ -200,6 +221,8 @@ struct if_settings { ...@@ -200,6 +221,8 @@ struct if_settings {
* remainder may be interface specific. * remainder may be interface specific.
*/ */
/* for compatibility with glibc net/if.h */
#if __UAPI_DEF_IF_IFREQ
struct ifreq { struct ifreq {
#define IFHWADDRLEN 6 #define IFHWADDRLEN 6
union union
...@@ -223,6 +246,7 @@ struct ifreq { ...@@ -223,6 +246,7 @@ struct ifreq {
struct if_settings ifru_settings; struct if_settings ifru_settings;
} ifr_ifru; } ifr_ifru;
}; };
#endif /* __UAPI_DEF_IF_IFREQ */
#define ifr_name ifr_ifrn.ifrn_name /* interface name */ #define ifr_name ifr_ifrn.ifrn_name /* interface name */
#define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */ #define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */
...@@ -249,6 +273,8 @@ struct ifreq { ...@@ -249,6 +273,8 @@ struct ifreq {
* must know all networks accessible). * must know all networks accessible).
*/ */
/* for compatibility with glibc net/if.h */
#if __UAPI_DEF_IF_IFCONF
struct ifconf { struct ifconf {
int ifc_len; /* size of buffer */ int ifc_len; /* size of buffer */
union { union {
...@@ -256,6 +282,8 @@ struct ifconf { ...@@ -256,6 +282,8 @@ struct ifconf {
struct ifreq __user *ifcu_req; struct ifreq __user *ifcu_req;
} ifc_ifcu; } ifc_ifcu;
}; };
#endif /* __UAPI_DEF_IF_IFCONF */
#define ifc_buf ifc_ifcu.ifcu_buf /* buffer address */ #define ifc_buf ifc_ifcu.ifcu_buf /* buffer address */
#define ifc_req ifc_ifcu.ifcu_req /* array of structures */ #define ifc_req ifc_ifcu.ifcu_req /* array of structures */
......
...@@ -51,6 +51,40 @@ ...@@ -51,6 +51,40 @@
/* We have included glibc headers... */ /* We have included glibc headers... */
#if defined(__GLIBC__) #if defined(__GLIBC__)
/* Coordinate with glibc net/if.h header. */
#if defined(_NET_IF_H)
/* GLIBC headers included first so don't define anything
* that would already be defined. */
#define __UAPI_DEF_IF_IFCONF 0
#define __UAPI_DEF_IF_IFMAP 0
#define __UAPI_DEF_IF_IFNAMSIZ 0
#define __UAPI_DEF_IF_IFREQ 0
/* Everything up to IFF_DYNAMIC, matches net/if.h until glibc 2.23 */
#define __UAPI_DEF_IF_NET_DEVICE_FLAGS 0
/* For the future if glibc adds IFF_LOWER_UP, IFF_DORMANT and IFF_ECHO */
#ifndef __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO
#define __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO 1
#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO */
#else /* _NET_IF_H */
/* Linux headers included first, and we must define everything
* we need. The expectation is that glibc will check the
* __UAPI_DEF_* defines and adjust appropriately. */
#define __UAPI_DEF_IF_IFCONF 1
#define __UAPI_DEF_IF_IFMAP 1
#define __UAPI_DEF_IF_IFNAMSIZ 1
#define __UAPI_DEF_IF_IFREQ 1
/* Everything up to IFF_DYNAMIC, matches net/if.h until glibc 2.23 */
#define __UAPI_DEF_IF_NET_DEVICE_FLAGS 1
/* For the future if glibc adds IFF_LOWER_UP, IFF_DORMANT and IFF_ECHO */
#define __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO 1
#endif /* _NET_IF_H */
/* Coordinate with glibc netinet/in.h header. */ /* Coordinate with glibc netinet/in.h header. */
#if defined(_NETINET_IN_H) #if defined(_NETINET_IN_H)
...@@ -117,6 +151,16 @@ ...@@ -117,6 +151,16 @@
* that we need. */ * that we need. */
#else /* !defined(__GLIBC__) */ #else /* !defined(__GLIBC__) */
/* Definitions for if.h */
#define __UAPI_DEF_IF_IFCONF 1
#define __UAPI_DEF_IF_IFMAP 1
#define __UAPI_DEF_IF_IFNAMSIZ 1
#define __UAPI_DEF_IF_IFREQ 1
/* Everything up to IFF_DYNAMIC, matches net/if.h until glibc 2.23 */
#define __UAPI_DEF_IF_NET_DEVICE_FLAGS 1
/* For the future if glibc adds IFF_LOWER_UP, IFF_DORMANT and IFF_ECHO */
#define __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO 1
/* Definitions for in.h */ /* Definitions for in.h */
#define __UAPI_DEF_IN_ADDR 1 #define __UAPI_DEF_IN_ADDR 1
#define __UAPI_DEF_IN_IPPROTO 1 #define __UAPI_DEF_IN_IPPROTO 1
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment