Move kernel GTP support from ggsn/ to lib/
This way, the IP address / route handling between TUN devices and kernel GTP can be shared, which will provide not only a unified codebase but also a more consistent behavior. This also paves the road for to use kernel GTP from sgsnemu in the future. Related: OS#3214 Change-Id: Ic53a971136edd0d8871fbd6746d7b0090ce3a188
This commit is contained in:
parent
9eebe15cd1
commit
f2286395e9
|
@ -12,8 +12,4 @@ osmo_ggsn_LDADD += $(LIBGTPNL_LIBS)
|
|||
endif
|
||||
|
||||
osmo_ggsn_DEPENDENCIES = ../gtp/libgtp.la ../lib/libmisc.a
|
||||
osmo_ggsn_SOURCES = ggsn_vty.c ggsn.c ggsn.h gtp-kernel.h icmpv6.c icmpv6.h checksum.c checksum.h
|
||||
|
||||
if ENABLE_GTP_KERNEL
|
||||
osmo_ggsn_SOURCES += gtp-kernel.c
|
||||
endif
|
||||
osmo_ggsn_SOURCES = ggsn_vty.c ggsn.c ggsn.h icmpv6.c icmpv6.h checksum.c checksum.h
|
||||
|
|
142
ggsn/ggsn.c
142
ggsn/ggsn.c
|
@ -63,9 +63,9 @@
|
|||
#include "../lib/ippool.h"
|
||||
#include "../lib/syserr.h"
|
||||
#include "../lib/in46_addr.h"
|
||||
#include "../lib/gtp-kernel.h"
|
||||
#include "../gtp/pdp.h"
|
||||
#include "../gtp/gtp.h"
|
||||
#include "gtp-kernel.h"
|
||||
#include "icmpv6.h"
|
||||
#include "ggsn.h"
|
||||
|
||||
|
@ -125,13 +125,14 @@ int apn_stop(struct apn_ctx *apn, bool force)
|
|||
LOGPAPN( LOGL_INFO, apn, "Running %s\n", apn->tun.cfg.ipdown_script);
|
||||
tun_runscript(apn->tun.tun, apn->tun.cfg.ipdown_script);
|
||||
}
|
||||
/* release tun device */
|
||||
LOGPAPN(LOGL_INFO, apn, "Closing TUN device %s\n", apn->tun.tun->devname);
|
||||
osmo_fd_unregister(&apn->tun.fd);
|
||||
if (apn->cfg.gtpu_mode == APN_GTPU_MODE_TUN) {
|
||||
/* release tun device */
|
||||
LOGPAPN(LOGL_INFO, apn, "Closing TUN device %s\n", apn->tun.tun->devname);
|
||||
osmo_fd_unregister(&apn->tun.fd);
|
||||
}
|
||||
tun_free(apn->tun.tun);
|
||||
apn->tun.tun = NULL;
|
||||
}
|
||||
gtp_kernel_stop(apn->tun.cfg.dev_name);
|
||||
|
||||
if (apn->v4.pool) {
|
||||
LOGPAPN(LOGL_INFO, apn, "Releasing IPv4 pool\n");
|
||||
|
@ -195,6 +196,7 @@ int apn_start(struct apn_ctx *apn)
|
|||
struct in46_prefix ipv6_tun_linklocal_ip;
|
||||
struct in46_prefix *blacklist;
|
||||
int blacklist_size;
|
||||
struct gsn_t *gsn = apn->ggsn->gsn;
|
||||
int rc;
|
||||
|
||||
if (apn->started)
|
||||
|
@ -204,7 +206,7 @@ int apn_start(struct apn_ctx *apn)
|
|||
switch (apn->cfg.gtpu_mode) {
|
||||
case APN_GTPU_MODE_TUN:
|
||||
LOGPAPN(LOGL_INFO, apn, "Opening TUN device %s\n", apn->tun.cfg.dev_name);
|
||||
if (tun_new(&apn->tun.tun, apn->tun.cfg.dev_name)) {
|
||||
if (tun_new(&apn->tun.tun, apn->tun.cfg.dev_name, false, -1, -1)) {
|
||||
LOGPAPN(LOGL_ERROR, apn, "Failed to configure tun device\n");
|
||||
return -1;
|
||||
}
|
||||
|
@ -216,66 +218,6 @@ int apn_start(struct apn_ctx *apn)
|
|||
|
||||
/* Set TUN library callback */
|
||||
tun_set_cb_ind(apn->tun.tun, cb_tun_ind);
|
||||
|
||||
if (apn->v4.cfg.ifconfig_prefix.addr.len) {
|
||||
LOGPAPN(LOGL_INFO, apn, "Setting tun IP address %s\n",
|
||||
in46p_ntoa(&apn->v4.cfg.ifconfig_prefix));
|
||||
if (tun_addaddr(apn->tun.tun, &apn->v4.cfg.ifconfig_prefix.addr, NULL,
|
||||
apn->v4.cfg.ifconfig_prefix.prefixlen)) {
|
||||
LOGPAPN(LOGL_ERROR, apn, "Failed to set tun IPv4 address %s: %s\n",
|
||||
in46p_ntoa(&apn->v4.cfg.ifconfig_prefix), strerror(errno));
|
||||
apn_stop(apn, false);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (apn->v6.cfg.ifconfig_prefix.addr.len) {
|
||||
LOGPAPN(LOGL_INFO, apn, "Setting tun IPv6 address %s\n",
|
||||
in46p_ntoa(&apn->v6.cfg.ifconfig_prefix));
|
||||
if (tun_addaddr(apn->tun.tun, &apn->v6.cfg.ifconfig_prefix.addr, NULL,
|
||||
apn->v6.cfg.ifconfig_prefix.prefixlen)) {
|
||||
LOGPAPN(LOGL_ERROR, apn, "Failed to set tun IPv6 address %s: %s. "
|
||||
"Ensure you have ipv6 support and not used the disable_ipv6 sysctl?\n",
|
||||
in46p_ntoa(&apn->v6.cfg.ifconfig_prefix), strerror(errno));
|
||||
apn_stop(apn, false);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (apn->v6.cfg.ll_prefix.addr.len) {
|
||||
LOGPAPN(LOGL_INFO, apn, "Setting tun IPv6 link-local address %s\n",
|
||||
in46p_ntoa(&apn->v6.cfg.ll_prefix));
|
||||
if (tun_addaddr(apn->tun.tun, &apn->v6.cfg.ll_prefix.addr, NULL,
|
||||
apn->v6.cfg.ll_prefix.prefixlen)) {
|
||||
LOGPAPN(LOGL_ERROR, apn, "Failed to set tun IPv6 link-local address %s: %s. "
|
||||
"Ensure you have ipv6 support and not used the disable_ipv6 sysctl?\n",
|
||||
in46p_ntoa(&apn->v6.cfg.ll_prefix), strerror(errno));
|
||||
apn_stop(apn, false);
|
||||
return -1;
|
||||
}
|
||||
apn->v6_lladdr = apn->v6.cfg.ll_prefix.addr.v6;
|
||||
}
|
||||
|
||||
if (apn->tun.cfg.ipup_script) {
|
||||
LOGPAPN(LOGL_INFO, apn, "Running ip-up script %s\n",
|
||||
apn->tun.cfg.ipup_script);
|
||||
tun_runscript(apn->tun.tun, apn->tun.cfg.ipup_script);
|
||||
}
|
||||
|
||||
if (apn->cfg.apn_type_mask & (APN_TYPE_IPv6|APN_TYPE_IPv4v6) &&
|
||||
apn->v6.cfg.ll_prefix.addr.len == 0) {
|
||||
rc = tun_ip_local_get(apn->tun.tun, &ipv6_tun_linklocal_ip, 1, IP_TYPE_IPv6_LINK);
|
||||
if (rc < 1) {
|
||||
LOGPAPN(LOGL_ERROR, apn, "Cannot obtain IPv6 link-local address of interface: %s\n",
|
||||
rc ? strerror(errno) : "tun interface has no link-local IP assigned");
|
||||
apn_stop(apn, false);
|
||||
return -1;
|
||||
}
|
||||
apn->v6_lladdr = ipv6_tun_linklocal_ip.addr.v6;
|
||||
}
|
||||
|
||||
/* set back-pointer from TUN device to APN */
|
||||
apn->tun.tun->priv = apn;
|
||||
break;
|
||||
case APN_GTPU_MODE_KERNEL_GTP:
|
||||
LOGPAPN(LOGL_INFO, apn, "Opening Kernel GTP device %s\n", apn->tun.cfg.dev_name);
|
||||
|
@ -284,7 +226,7 @@ int apn_start(struct apn_ctx *apn)
|
|||
apn_stop(apn, false);
|
||||
return -1;
|
||||
}
|
||||
if (apn->ggsn->gsn == NULL) {
|
||||
if (gsn == NULL) {
|
||||
/* skip bringing up the APN now if the GSN is not initialized yet.
|
||||
* This happens during initial load of the config file, as the
|
||||
* "no shutdown" in the ggsn node only happens after the "apn" nodes
|
||||
|
@ -293,8 +235,8 @@ int apn_start(struct apn_ctx *apn)
|
|||
return 0;
|
||||
}
|
||||
/* use GTP kernel module for data packet encapsulation */
|
||||
if (gtp_kernel_init(apn->ggsn->gsn, apn->tun.cfg.dev_name,
|
||||
&apn->v4.cfg.ifconfig_prefix, apn->tun.cfg.ipup_script) < 0) {
|
||||
if (tun_new(&apn->tun.tun, apn->tun.cfg.dev_name, true, gsn->fd0, gsn->fd1u)) {
|
||||
LOGPAPN(LOGL_ERROR, apn, "Failed to configure Kernel GTP device\n");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
@ -303,6 +245,68 @@ int apn_start(struct apn_ctx *apn)
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* common initialization below */
|
||||
|
||||
/* set back-pointer from TUN device to APN */
|
||||
apn->tun.tun->priv = apn;
|
||||
|
||||
if (apn->v4.cfg.ifconfig_prefix.addr.len) {
|
||||
LOGPAPN(LOGL_INFO, apn, "Setting tun IP address %s\n",
|
||||
in46p_ntoa(&apn->v4.cfg.ifconfig_prefix));
|
||||
if (tun_addaddr(apn->tun.tun, &apn->v4.cfg.ifconfig_prefix.addr, NULL,
|
||||
apn->v4.cfg.ifconfig_prefix.prefixlen)) {
|
||||
LOGPAPN(LOGL_ERROR, apn, "Failed to set tun IPv4 address %s: %s\n",
|
||||
in46p_ntoa(&apn->v4.cfg.ifconfig_prefix), strerror(errno));
|
||||
apn_stop(apn, false);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (apn->v6.cfg.ifconfig_prefix.addr.len) {
|
||||
LOGPAPN(LOGL_INFO, apn, "Setting tun IPv6 address %s\n",
|
||||
in46p_ntoa(&apn->v6.cfg.ifconfig_prefix));
|
||||
if (tun_addaddr(apn->tun.tun, &apn->v6.cfg.ifconfig_prefix.addr, NULL,
|
||||
apn->v6.cfg.ifconfig_prefix.prefixlen)) {
|
||||
LOGPAPN(LOGL_ERROR, apn, "Failed to set tun IPv6 address %s: %s. "
|
||||
"Ensure you have ipv6 support and not used the disable_ipv6 sysctl?\n",
|
||||
in46p_ntoa(&apn->v6.cfg.ifconfig_prefix), strerror(errno));
|
||||
apn_stop(apn, false);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (apn->v6.cfg.ll_prefix.addr.len) {
|
||||
LOGPAPN(LOGL_INFO, apn, "Setting tun IPv6 link-local address %s\n",
|
||||
in46p_ntoa(&apn->v6.cfg.ll_prefix));
|
||||
if (tun_addaddr(apn->tun.tun, &apn->v6.cfg.ll_prefix.addr, NULL,
|
||||
apn->v6.cfg.ll_prefix.prefixlen)) {
|
||||
LOGPAPN(LOGL_ERROR, apn, "Failed to set tun IPv6 link-local address %s: %s. "
|
||||
"Ensure you have ipv6 support and not used the disable_ipv6 sysctl?\n",
|
||||
in46p_ntoa(&apn->v6.cfg.ll_prefix), strerror(errno));
|
||||
apn_stop(apn, false);
|
||||
return -1;
|
||||
}
|
||||
apn->v6_lladdr = apn->v6.cfg.ll_prefix.addr.v6;
|
||||
}
|
||||
|
||||
if (apn->tun.cfg.ipup_script) {
|
||||
LOGPAPN(LOGL_INFO, apn, "Running ip-up script %s\n",
|
||||
apn->tun.cfg.ipup_script);
|
||||
tun_runscript(apn->tun.tun, apn->tun.cfg.ipup_script);
|
||||
}
|
||||
|
||||
if (apn->cfg.apn_type_mask & (APN_TYPE_IPv6|APN_TYPE_IPv4v6) &&
|
||||
apn->v6.cfg.ll_prefix.addr.len == 0) {
|
||||
rc = tun_ip_local_get(apn->tun.tun, &ipv6_tun_linklocal_ip, 1, IP_TYPE_IPv6_LINK);
|
||||
if (rc < 1) {
|
||||
LOGPAPN(LOGL_ERROR, apn, "Cannot obtain IPv6 link-local address of interface: %s\n",
|
||||
rc ? strerror(errno) : "tun interface has no link-local IP assigned");
|
||||
apn_stop(apn, false);
|
||||
return -1;
|
||||
}
|
||||
apn->v6_lladdr = ipv6_tun_linklocal_ip.addr.v6;
|
||||
}
|
||||
|
||||
/* Create IPv4 pool */
|
||||
if (apn->v4.cfg.dynamic_prefix.addr.len) {
|
||||
LOGPAPN(LOGL_INFO, apn, "Creating IPv4 pool %s\n",
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
noinst_LIBRARIES = libmisc.a
|
||||
|
||||
noinst_HEADERS = gnugetopt.h ippool.h lookup.h syserr.h tun.h in46_addr.h netdev.h
|
||||
noinst_HEADERS = gnugetopt.h ippool.h lookup.h syserr.h tun.h in46_addr.h netdev.h gtp-kernel.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 netdev.c
|
||||
|
||||
if ENABLE_GTP_KERNEL
|
||||
AM_CFLAGS += -DGTP_KERNEL $(LIBGTPNL_CFLAGS)
|
||||
libmisc_a_SOURCES += gtp-kernel.c
|
||||
endif
|
||||
|
|
|
@ -77,56 +77,20 @@ static int gtp_kernel_init_once(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int gtp_kernel_init(struct gsn_t *gsn, const char *devname, struct in46_prefix *prefix, const char *ipup)
|
||||
int gtp_kernel_create(int dest_ns, const char *devname, int fd0, int fd1u)
|
||||
{
|
||||
struct in_addr net;
|
||||
const char *net_arg;
|
||||
|
||||
if (!gtp_nl.nl)
|
||||
gtp_kernel_init_once();
|
||||
|
||||
if (prefix->addr.len != 4) {
|
||||
LOGP(DGGSN, LOGL_ERROR, "we only support IPv4 in this path :/");
|
||||
if (gtp_kernel_init_once() < 0)
|
||||
return -1;
|
||||
}
|
||||
net = prefix->addr.v4;
|
||||
|
||||
if (gtp_dev_create(-1, devname, gsn->fd0, gsn->fd1u) < 0) {
|
||||
LOGP(DGGSN, LOGL_ERROR, "cannot create GTP tunnel device: %s\n",
|
||||
strerror(errno));
|
||||
return gtp_dev_create(dest_ns, devname, fd0, fd1u);
|
||||
}
|
||||
|
||||
int gtp_kernel_create_sgsn(int dest_ns, const char *devname, int fd0, int fd1u)
|
||||
{
|
||||
if (gtp_kernel_init_once() < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
net_arg = in46p_ntoa(prefix);
|
||||
|
||||
DEBUGP(DGGSN, "Setting route to reach %s via %s\n", net_arg, devname);
|
||||
|
||||
if (gtp_dev_config(devname, &net, prefix->prefixlen) < 0) {
|
||||
LOGP(DGGSN, LOGL_ERROR, "Cannot add route to reach network %s\n", net_arg);
|
||||
}
|
||||
|
||||
/* launch script if it is set to bring up the route to reach
|
||||
* the MS, eg. ip ro add 10.0.0.0/8 dev gtp0. Better add this
|
||||
* using native rtnetlink interface given that we know the
|
||||
* MS network mask, later.
|
||||
*/
|
||||
if (ipup) {
|
||||
char cmd[1024];
|
||||
int err;
|
||||
|
||||
/* eg. /home/ggsn/ipup gtp0 10.0.0.0/8 */
|
||||
snprintf(cmd, sizeof(cmd), "%s %s %s", ipup, devname, net_arg);
|
||||
cmd[sizeof(cmd)-1] = '\0';
|
||||
|
||||
err = system(cmd);
|
||||
if (err < 0) {
|
||||
LOGP(DGGSN, LOGL_ERROR, "Failed to launch script `%s'\n", ipup);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
LOGP(DGGSN, LOGL_NOTICE, "GTP kernel configured\n");
|
||||
|
||||
return 0;
|
||||
return gtp_dev_create_sgsn(dest_ns, devname, fd0, fd1u);
|
||||
}
|
||||
|
||||
void gtp_kernel_stop(const char *devname)
|
|
@ -7,18 +7,20 @@ extern int debug;
|
|||
extern char *ipup;
|
||||
|
||||
#ifdef GTP_KERNEL
|
||||
int gtp_kernel_init(struct gsn_t *gsn, const char *devname, struct in46_prefix *prefix, const char *ipup);
|
||||
int gtp_kernel_create(int dest_ns, const char *devname, int fd0, int fd1u);
|
||||
int gtp_kernel_create_sgsn(int dest_ns, const char *devname, int fd0, int fd1u);
|
||||
void gtp_kernel_stop(const char *devname);
|
||||
|
||||
int gtp_kernel_tunnel_add(struct pdp_t *pdp, const char *devname);
|
||||
int gtp_kernel_tunnel_del(struct pdp_t *pdp, const char *devname);
|
||||
|
||||
#else
|
||||
static inline int gtp_kernel_init(struct gsn_t *gsn, const char *devname, struct in46_prefix *prefix, const char *ipup)
|
||||
static inline int gtp_kernel_create(int dest_ns, const char *devname, int fd0, int fd1u)
|
||||
{
|
||||
SYS_ERR(DGGSN, LOGL_ERROR, 0, "ggsn compiled without GTP kernel support!\n");
|
||||
return -1;
|
||||
}
|
||||
#define gtp_kernel_create_sgsn gtp_kernel_create
|
||||
|
||||
static inline void gtp_kernel_stop(const char *devname) {}
|
||||
|
73
lib/tun.c
73
lib/tun.c
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
|
@ -57,6 +58,7 @@
|
|||
|
||||
#include "tun.h"
|
||||
#include "syserr.h"
|
||||
#include "gtp-kernel.h"
|
||||
|
||||
static int tun_setaddr4(struct tun_t *this, struct in_addr *addr,
|
||||
struct in_addr *dstaddr, struct in_addr *netmask)
|
||||
|
@ -147,7 +149,7 @@ int tun_addaddr(struct tun_t *this, struct in46_addr *addr, struct in46_addr *ds
|
|||
}
|
||||
}
|
||||
|
||||
int tun_new(struct tun_t **tun, const char *dev_name)
|
||||
int tun_new(struct tun_t **tun, const char *dev_name, bool use_kernel, int fd0, int fd1u)
|
||||
{
|
||||
|
||||
#if defined(__linux__)
|
||||
|
@ -170,31 +172,50 @@ int tun_new(struct tun_t **tun, const char *dev_name)
|
|||
(*tun)->routes = 0;
|
||||
|
||||
#if defined(__linux__)
|
||||
/* Open the actual tun device */
|
||||
if (((*tun)->fd = open("/dev/net/tun", O_RDWR)) < 0) {
|
||||
SYS_ERR(DTUN, LOGL_ERROR, errno, "open() failed");
|
||||
goto err_free;
|
||||
if (!use_kernel) {
|
||||
/* Open the actual tun device */
|
||||
if (((*tun)->fd = open("/dev/net/tun", O_RDWR)) < 0) {
|
||||
SYS_ERR(DTUN, LOGL_ERROR, errno, "open() failed");
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
/* Set device flags. For some weird reason this is also the method
|
||||
used to obtain the network interface name */
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
if (dev_name)
|
||||
strcpy(ifr.ifr_name, dev_name);
|
||||
ifr.ifr_flags = IFF_TUN | IFF_NO_PI; /* Tun device, no packet info */
|
||||
if (ioctl((*tun)->fd, TUNSETIFF, (void *)&ifr) < 0) {
|
||||
SYS_ERR(DTUN, LOGL_ERROR, errno, "ioctl() failed");
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
strncpy((*tun)->devname, ifr.ifr_name, IFNAMSIZ);
|
||||
(*tun)->devname[IFNAMSIZ - 1] = 0;
|
||||
|
||||
ioctl((*tun)->fd, TUNSETNOCSUM, 1); /* Disable checksums */
|
||||
return 0;
|
||||
} else {
|
||||
strncpy((*tun)->devname, dev_name, IFNAMSIZ);
|
||||
(*tun)->devname[IFNAMSIZ - 1] = 0;
|
||||
(*tun)->fd = -1;
|
||||
|
||||
if (gtp_kernel_create(-1, dev_name, fd0, fd1u) < 0) {
|
||||
LOGP(DTUN, LOGL_ERROR, "cannot create GTP tunnel device: %s\n",
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
LOGP(DTUN, LOGL_NOTICE, "GTP kernel configured\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set device flags. For some weird reason this is also the method
|
||||
used to obtain the network interface name */
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
if (dev_name)
|
||||
strcpy(ifr.ifr_name, dev_name);
|
||||
ifr.ifr_flags = IFF_TUN | IFF_NO_PI; /* Tun device, no packet info */
|
||||
if (ioctl((*tun)->fd, TUNSETIFF, (void *)&ifr) < 0) {
|
||||
SYS_ERR(DTUN, LOGL_ERROR, errno, "ioctl() failed");
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
strncpy((*tun)->devname, ifr.ifr_name, IFNAMSIZ);
|
||||
(*tun)->devname[IFNAMSIZ - 1] = 0;
|
||||
|
||||
ioctl((*tun)->fd, TUNSETNOCSUM, 1); /* Disable checksums */
|
||||
return 0;
|
||||
|
||||
#elif defined(__FreeBSD__) || defined (__APPLE__)
|
||||
|
||||
if (use_kernel) {
|
||||
LOGP(DTUN, LOGL_ERROR, "No kernel GTP-U support in FreeBSD!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Find suitable device */
|
||||
for (devnum = 0; devnum < 255; devnum++) { /* TODO 255 */
|
||||
snprintf(devname, sizeof(devname), "/dev/tun%d", devnum);
|
||||
|
@ -249,10 +270,14 @@ int tun_free(struct tun_t *tun)
|
|||
netdev_delroute(&tun->dstaddr, &tun->addr, &tun->netmask);
|
||||
}
|
||||
|
||||
if (close(tun->fd)) {
|
||||
SYS_ERR(DTUN, LOGL_ERROR, errno, "close() failed");
|
||||
if (tun->fd >= 0) {
|
||||
if (close(tun->fd)) {
|
||||
SYS_ERR(DTUN, LOGL_ERROR, errno, "close() failed");
|
||||
}
|
||||
}
|
||||
|
||||
gtp_kernel_stop(tun->devname);
|
||||
|
||||
/* TODO: For solaris we need to unlink streams */
|
||||
|
||||
free(tun);
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#ifndef _TUN_H
|
||||
#define _TUN_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <net/if.h>
|
||||
|
||||
#include "../lib/in46_addr.h"
|
||||
|
@ -41,7 +42,7 @@ struct tun_t {
|
|||
void *priv;
|
||||
};
|
||||
|
||||
extern int tun_new(struct tun_t **tun, const char *dev_name);
|
||||
extern int tun_new(struct tun_t **tun, const char *dev_name, bool use_kernel, int fd0, int fd1u);
|
||||
extern int tun_free(struct tun_t *tun);
|
||||
extern int tun_decaps(struct tun_t *this);
|
||||
extern int tun_encaps(struct tun_t *tun, void *pack, unsigned len);
|
||||
|
|
|
@ -5,5 +5,11 @@ AM_LDFLAGS = @EXEC_LDFLAGS@
|
|||
AM_CFLAGS = -O2 -D_GNU_SOURCE -fno-builtin -Wall -DSBINDIR='"$(sbindir)"' -ggdb $(LIBOSMOCORE_CFLAGS)
|
||||
|
||||
sgsnemu_LDADD = @EXEC_LDADD@ -lgtp -L../gtp ../lib/libmisc.a $(LIBOSMOCORE_LIBS)
|
||||
|
||||
if ENABLE_GTP_KERNEL
|
||||
AM_CFLAGS += -DGTP_KERNEL $(LIBGTPNL_CFLAGS)
|
||||
sgsnemu_LDADD += $(LIBGTPNL_LIBS)
|
||||
endif
|
||||
|
||||
sgsnemu_DEPENDENCIES = ../gtp/libgtp.la ../lib/libmisc.a
|
||||
sgsnemu_SOURCES = sgsnemu.c cmdline.c cmdline.h
|
||||
|
|
|
@ -1571,7 +1571,7 @@ int main(int argc, char **argv)
|
|||
if (options.createif) {
|
||||
printf("Setting up interface\n");
|
||||
/* Create a tunnel interface */
|
||||
if (tun_new((struct tun_t **)&tun, options.tun_dev_name)) {
|
||||
if (tun_new((struct tun_t **)&tun, options.tun_dev_name, false, -1, -1)) {
|
||||
SYS_ERR(DSGSN, LOGL_ERROR, 0,
|
||||
"Failed to create tun");
|
||||
exit(1);
|
||||
|
|
Loading…
Reference in New Issue