aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPau Espin Pedrol <pespin@sysmocom.de>2017-12-01 15:29:30 +0100
committerPau Espin Pedrol <pespin@sysmocom.de>2017-12-01 15:42:06 +0100
commitfad9ed431b545a8b314e952f50e7fefc49477553 (patch)
tree7d954c0c0d3e5a06f2d9372080cd36b0590ad8c7
parentb9ace14717a220edb380d21d849e95ae0c30784e (diff)
Split implementation of tun_setaddr6 into a separate modulepespin/split-ipv6
Some systems containing specific versions of libc and linux kernel can produce compilation errors due to conflicting definition of structures in different include files. This can be the case when including <netinet/in.h> and <linux/in6.h>. See for more information: https://sourceware.org/glibc/wiki/Synchronizing_Headers I hit this compilation error on the system I'm compiling osmo-ggsn with: arm-poky-linux-gnueabi-gcc ... -c in46_addr.c In file included from /usr/include/linux/ipv6.h:5:0, from tun.c:75: /usr/include/linux/in6.h:30:8: error: redefinition of 'struct in6_addr' struct in6_addr { ^ In file included from tun.c:24:0: /usr/include/netinet/in.h:196:8: note: originally defined here struct in6_addr ^ To fix the issue, this patch moves tun_setaddr6 to its own file which then includes <linux/ipv6.h> (which in turn includes in6.h). Change-Id: Ie161f376edda605e5cd87176169553176235fafd
-rw-r--r--lib/Makefile.am2
-rw-r--r--lib/tun.c91
-rw-r--r--lib/tun6.c96
3 files changed, 101 insertions, 88 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 632990c..6eb2a0f 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -4,4 +4,4 @@ noinst_HEADERS = gnugetopt.h ippool.h lookup.h syserr.h tun.h in46_addr.h
AM_CFLAGS = -O2 -fno-builtin -Wall -DSBINDIR='"$(sbindir)"' -ggdb $(LIBOSMOCORE_CFLAGS)
-libmisc_a_SOURCES = getopt1.c getopt.c ippool.c lookup.c tun.c debug.c in46_addr.c
+libmisc_a_SOURCES = getopt1.c getopt.c ippool.c lookup.c tun.c tun6.c debug.c in46_addr.c
diff --git a/lib/tun.c b/lib/tun.c
index d8e4b62..4052672 100644
--- a/lib/tun.c
+++ b/lib/tun.c
@@ -61,9 +61,6 @@
#include "syserr.h"
#if defined(__linux__)
-
-#include <linux/ipv6.h>
-
static int tun_nlattr(struct nlmsghdr *n, int nsize, int type, void *d, int dlen)
{
int len = RTA_LENGTH(dlen);
@@ -79,7 +76,7 @@ static int tun_nlattr(struct nlmsghdr *n, int nsize, int type, void *d, int dlen
}
#endif
-static int tun_sifflags(struct tun_t *this, int flags)
+int tun_sifflags(struct tun_t *this, int flags)
{
struct ifreq ifr;
int fd;
@@ -197,89 +194,9 @@ static int tun_setaddr4(struct tun_t *this, struct in_addr *addr,
return 0;
}
-static int tun_setaddr6(struct tun_t *this, struct in6_addr *addr, struct in6_addr *dstaddr,
- size_t prefixlen)
-{
- struct in6_ifreq ifr;
- int fd;
-
- memset(&ifr, 0, sizeof(ifr));
-
-#if defined(__linux__)
- ifr.ifr6_prefixlen = prefixlen;
- ifr.ifr6_ifindex = if_nametoindex(this->devname);
- if (ifr.ifr6_ifindex == 0) {
- SYS_ERR(DTUN, LOGL_ERROR, 0, "Error getting ifindex for %s\n", this->devname);
- return -1;
- }
-#elif defined(__FreeBSD__) || defined (__APPLE__)
- strncpy(ifr.ifr_name, this->devname, IFNAMSIZ);
-#endif
-
- /* Create a channel to the NET kernel */
- if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
- SYS_ERR(DTUN, LOGL_ERROR, 0, "socket() failed");
- return -1;
- }
-
-#if defined(__linux__)
- if (addr) {
- memcpy(&ifr.ifr6_addr, addr, sizeof(*addr));
- if (ioctl(fd, SIOCSIFADDR, (void *) &ifr) < 0) {
- if (errno != EEXIST) {
- SYS_ERR(DTUN, LOGL_ERROR, 0, "ioctl(SIOCSIFADDR) failed");
- } else {
- SYS_ERR(DTUN, LOGL_NOTICE, 0, "ioctl(SIOCSIFADDR): Address already exists");
- }
- close(fd);
- return -1;
- }
- }
-
-#if 0
- /* FIXME: looks like this is not possible/necessary for IPv6? */
- if (dstaddr) {
- memcpy(&this->dstaddr, dstaddr, sizeof(*dstaddr));
- memcpy(&ifr.ifr6_addr, dstaddr, sizeof(*dstaddr));
- if (ioctl(fd, SIOCSIFDSTADDR, (caddr_t *) &ifr) < 0) {
- SYS_ERR(DTUN, LOGL_ERROR, "ioctl(SIOCSIFDSTADDR) failed");
- close(fd);
- return -1;
- }
- }
-#endif
-
-#elif defined(__FreeBSD__) || defined (__APPLE__)
- if (addr)
- memcpy(&ifr.ifr_ifru.ifru_addr, addr, sizeof(ifr.ifr_ifru.ifru_addr));
- if (dstaddr)
- memcpy(&ifr.ifr_ifru.ifru_dstaddr, dstaddr, sizeof(ifr.ifr_ifru.ifru_dstaddr));
-
- if (ioctl(fd, SIOCSIFADDR_IN6, (struct ifreq *)&ifr) < 0) {
- SYS_ERR(DTUN, LOGL_ERROR, 0, "ioctl(SIOCSIFADDR_IN6) failed");
- close(fd);
- return -1;
- }
-#endif
-
- close(fd);
- this->addrs++;
-
- /* On linux the route to the interface is set automatically
- on FreeBSD we have to do this manually */
-
- /* TODO: How does it work on Solaris? */
-
- tun_sifflags(this, IFF_UP | IFF_RUNNING);
-
-#if 0 /* FIXME */
-//#if defined(__FreeBSD__) || defined (__APPLE__)
- tun_addroute6(this, dstaddr, addr, prefixlen);
- this->routes = 1;
-#endif
-
- return 0;
-}
+/* Implemented in tun6.c due to include issues between ip6.h/in6.h and in.h in some systems */
+int tun_setaddr6(struct tun_t *this, struct in6_addr *addr, struct in6_addr *dstaddr,
+ size_t prefixlen);
int tun_setaddr(struct tun_t *this, struct in46_addr *addr, struct in46_addr *dstaddr, size_t prefixlen)
{
diff --git a/lib/tun6.c b/lib/tun6.c
new file mode 100644
index 0000000..85139e5
--- /dev/null
+++ b/lib/tun6.c
@@ -0,0 +1,96 @@
+#include <unistd.h>
+#include <string.h>
+#include <stropts.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <linux/ipv6.h>
+
+#include "tun.h"
+#include "syserr.h"
+
+/* Defined in tun.c */
+int tun_sifflags(struct tun_t *this, int flags);
+
+int tun_setaddr6(struct tun_t *this, struct in6_addr *addr, struct in6_addr *dstaddr,
+ size_t prefixlen)
+{
+ struct in6_ifreq ifr;
+ int fd;
+
+ memset(&ifr, 0, sizeof(ifr));
+
+#if defined(__linux__)
+ ifr.ifr6_prefixlen = prefixlen;
+ ifr.ifr6_ifindex = if_nametoindex(this->devname);
+ if (ifr.ifr6_ifindex == 0) {
+ SYS_ERR(DTUN, LOGL_ERROR, 0, "Error getting ifindex for %s\n", this->devname);
+ return -1;
+ }
+#elif defined(__FreeBSD__) || defined (__APPLE__)
+ strncpy(ifr.ifr_name, this->devname, IFNAMSIZ);
+#endif
+
+ /* Create a channel to the NET kernel */
+ if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+ SYS_ERR(DTUN, LOGL_ERROR, 0, "socket() failed");
+ return -1;
+ }
+
+#if defined(__linux__)
+ if (addr) {
+ memcpy(&ifr.ifr6_addr, addr, sizeof(*addr));
+ if (ioctl(fd, SIOCSIFADDR, (void *) &ifr) < 0) {
+ if (errno != EEXIST) {
+ SYS_ERR(DTUN, LOGL_ERROR, 0, "ioctl(SIOCSIFADDR) failed");
+ } else {
+ SYS_ERR(DTUN, LOGL_NOTICE, 0, "ioctl(SIOCSIFADDR): Address already exists");
+ }
+ close(fd);
+ return -1;
+ }
+ }
+
+#if 0
+ /* FIXME: looks like this is not possible/necessary for IPv6? */
+ if (dstaddr) {
+ memcpy(&this->dstaddr, dstaddr, sizeof(*dstaddr));
+ memcpy(&ifr.ifr6_addr, dstaddr, sizeof(*dstaddr));
+ if (ioctl(fd, SIOCSIFDSTADDR, (caddr_t *) &ifr) < 0) {
+ SYS_ERR(DTUN, LOGL_ERROR, "ioctl(SIOCSIFDSTADDR) failed");
+ close(fd);
+ return -1;
+ }
+ }
+#endif
+
+#elif defined(__FreeBSD__) || defined (__APPLE__)
+ if (addr)
+ memcpy(&ifr.ifr_ifru.ifru_addr, addr, sizeof(ifr.ifr_ifru.ifru_addr));
+ if (dstaddr)
+ memcpy(&ifr.ifr_ifru.ifru_dstaddr, dstaddr, sizeof(ifr.ifr_ifru.ifru_dstaddr));
+
+ if (ioctl(fd, SIOCSIFADDR_IN6, (struct ifreq *)&ifr) < 0) {
+ SYS_ERR(DTUN, LOGL_ERROR, 0, "ioctl(SIOCSIFADDR_IN6) failed");
+ close(fd);
+ return -1;
+ }
+#endif
+
+ close(fd);
+ this->addrs++;
+
+ /* On linux the route to the interface is set automatically
+ on FreeBSD we have to do this manually */
+
+ /* TODO: How does it work on Solaris? */
+
+ tun_sifflags(this, IFF_UP | IFF_RUNNING);
+
+#if 0 /* FIXME */
+//#if defined(__FreeBSD__) || defined (__APPLE__)
+ tun_addroute6(this, dstaddr, addr, prefixlen);
+ this->routes = 1;
+#endif
+
+ return 0;
+}