diff options
Diffstat (limited to 'ggsn/ggsn.c')
-rw-r--r-- | ggsn/ggsn.c | 142 |
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", |