aboutsummaryrefslogtreecommitdiffstats
path: root/ggsn/ggsn.c
diff options
context:
space:
mode:
Diffstat (limited to 'ggsn/ggsn.c')
-rw-r--r--ggsn/ggsn.c142
1 files changed, 73 insertions, 69 deletions
diff --git a/ggsn/ggsn.c b/ggsn/ggsn.c
index 85a2211..4636c04 100644
--- a/ggsn/ggsn.c
+++ b/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",