aboutsummaryrefslogtreecommitdiffstats
path: root/ggsn
diff options
context:
space:
mode:
Diffstat (limited to 'ggsn')
-rw-r--r--ggsn/Makefile.am5
-rw-r--r--ggsn/ggsn.c38
-rw-r--r--ggsn/ggsn_vty.c47
3 files changed, 74 insertions, 16 deletions
diff --git a/ggsn/Makefile.am b/ggsn/Makefile.am
index 8a468a9..07adf80 100644
--- a/ggsn/Makefile.am
+++ b/ggsn/Makefile.am
@@ -12,7 +12,10 @@ osmo_ggsn_LDADD += -lgtpnl
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
+osmo_ggsn_SOURCES = ggsn_vty.c ggsn.c ggsn.h gtp-kernel.h checksum.c checksum.h
+if BUILD_IPv6
+osmo_ggsn_SOURCES += icmpv6.c icmpv6.h
+endif
if ENABLE_GTP_KERNEL
osmo_ggsn_SOURCES += gtp-kernel.c
diff --git a/ggsn/ggsn.c b/ggsn/ggsn.c
index 0beaef7..3018af4 100644
--- a/ggsn/ggsn.c
+++ b/ggsn/ggsn.c
@@ -65,7 +65,9 @@
#include "../gtp/pdp.h"
#include "../gtp/gtp.h"
#include "gtp-kernel.h"
+#if defined(BUILD_IPv6)
#include "icmpv6.h"
+#endif
#include "ggsn.h"
void *tall_ggsn_ctx;
@@ -115,7 +117,9 @@ int apn_stop(struct apn_ctx *apn, bool force)
LOGPAPN(LOGL_NOTICE, apn, "%sStopping\n", force ? "FORCED " : "");
/* check if pools have any active PDP contexts and bail out */
pool_close_all_pdp(apn->v4.pool);
+#if defined(BUILD_IPv6)
pool_close_all_pdp(apn->v6.pool);
+#endif
/* shutdown whatever old state might be left */
if (apn->tun.tun) {
@@ -137,12 +141,13 @@ int apn_stop(struct apn_ctx *apn, bool force)
ippool_free(apn->v4.pool);
apn->v4.pool = NULL;
}
+#if defined(BUILD_IPv6)
if (apn->v6.pool) {
LOGPAPN(LOGL_INFO, apn, "Releasing IPv6 pool\n");
ippool_free(apn->v6.pool);
apn->v6.pool = NULL;
}
-
+#endif
apn->started = false;
return 0;
}
@@ -155,9 +160,11 @@ static int alloc_ippool_blacklist(struct apn_ctx *apn, struct in46_prefix **blac
*blacklist = NULL;
+#if defined(BUILD_IPv6)
if (ipv6)
flags = IP_TYPE_IPv6_NONLINK;
else
+#endif
flags = IP_TYPE_IPv4;
while (1) {
@@ -191,7 +198,9 @@ static int alloc_ippool_blacklist(struct apn_ctx *apn, struct in46_prefix **blac
int apn_start(struct apn_ctx *apn)
{
int ippool_flags = IPPOOL_NONETWORK | IPPOOL_NOBROADCAST;
+#if defined(BUILD_IPv6)
struct in46_prefix ipv6_tun_linklocal_ip;
+#endif
struct in46_prefix *blacklist;
int blacklist_size;
@@ -226,7 +235,7 @@ int apn_start(struct apn_ctx *apn)
return -1;
}
}
-
+#if defined(BUILD_IPv6)
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));
@@ -239,13 +248,13 @@ int apn_start(struct apn_ctx *apn)
return -1;
}
}
-
+#endif
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 defined(BUILD_IPv6)
if (apn->cfg.apn_type_mask & (APN_TYPE_IPv6|APN_TYPE_IPv4v6)) {
if (tun_ip_local_get(apn->tun.tun, &ipv6_tun_linklocal_ip, 1, IP_TYPE_IPv6_LINK) < 1) {
LOGPAPN(LOGL_ERROR, apn, "Cannot obtain IPv6 link-local address of "
@@ -255,17 +264,20 @@ int apn_start(struct apn_ctx *apn)
}
apn->v6_lladdr = ipv6_tun_linklocal_ip.addr.v6;
}
+#endif
/* 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);
+#if defined(BUILD_IPv6)
if (apn->cfg.apn_type_mask & (APN_TYPE_IPv6|APN_TYPE_IPv4v6)) {
LOGPAPN(LOGL_ERROR, apn, "Kernel GTP currently supports only IPv4\n");
apn_stop(apn, false);
return -1;
}
+#endif
/* 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) {
@@ -294,6 +306,7 @@ int apn_start(struct apn_ctx *apn)
talloc_free(blacklist);
}
+#if defined(BUILD_IPv6)
/* Create IPv6 pool */
if (apn->v6.cfg.dynamic_prefix.addr.len) {
LOGPAPN(LOGL_INFO, apn, "Creating IPv6 pool %s\n",
@@ -310,6 +323,7 @@ int apn_start(struct apn_ctx *apn)
}
talloc_free(blacklist);
}
+#endif
LOGPAPN(LOGL_NOTICE, apn, "Successfully started\n");
apn->started = true;
@@ -468,6 +482,7 @@ static void process_pco(struct apn_ctx *apn, struct pdp_t *pdp)
build_ipcp_pco(msg, 0, &apn->v4.cfg.dns[0], &apn->v4.cfg.dns[1]);
}
+#if defined(BUILD_IPv6)
if (pco_contains_proto(&pdp->pco_req, PCO_P_DNS_IPv6_ADDR)) {
for (i = 0; i < ARRAY_SIZE(apn->v6.cfg.dns); i++) {
struct in46_addr *i46a = &apn->v6.cfg.dns[i];
@@ -476,6 +491,7 @@ static void process_pco(struct apn_ctx *apn, struct pdp_t *pdp)
msgb_t16lv_put(msg, PCO_P_DNS_IPv6_ADDR, i46a->len, i46a->v6.s6_addr);
}
}
+#endif
if (pco_contains_proto(&pdp->pco_req, PCO_P_DNS_IPv4_ADDR)) {
for (i = 0; i < ARRAY_SIZE(apn->v4.cfg.dns); i++) {
@@ -502,12 +518,14 @@ static bool apn_supports_ipv4(const struct apn_ctx *apn)
return false;
}
+#if defined(BUILD_IPv6)
static bool apn_supports_ipv6(const struct apn_ctx *apn)
{
if (apn->v6.cfg.static_prefix.addr.len || apn->v6.cfg.dynamic_prefix.addr.len)
return true;
return false;
}
+#endif
int create_context_ind(struct pdp_t *pdp)
{
@@ -575,6 +593,7 @@ int create_context_ind(struct pdp_t *pdp)
gtp_create_context_resp(gsn, pdp, GTPCAUSE_SYS_FAIL);
return 0;
}
+#if defined(BUILD_IPv6)
} else if (addr.len == sizeof(struct in6_addr)) {
struct in46_addr tmp;
@@ -594,6 +613,7 @@ int create_context_ind(struct pdp_t *pdp)
/* use allocated 64bit prefix as lower 64bit, used as link id by MS */
memcpy(tmp.v6.s6_addr+8, &member->addr.v6, 8);
in46a_to_eua(&tmp, &pdp->eua);
+#endif
} else
OSMO_ASSERT(0);
@@ -635,7 +655,9 @@ static int cb_tun_ind(struct tun_t *tun, void *pack, unsigned len)
struct ippoolm_t *ipm;
struct in46_addr dst;
struct iphdr *iph = (struct iphdr *)pack;
+#if defined(BUILD_IPv6)
struct ip6_hdr *ip6h = (struct ip6_hdr *)pack;
+#endif
struct ippool_t *pool;
if (iph->version == 4) {
@@ -644,6 +666,7 @@ static int cb_tun_ind(struct tun_t *tun, void *pack, unsigned len)
dst.len = 4;
dst.v4.s_addr = iph->daddr;
pool = apn->v4.pool;
+#if defined(BUILD_IPv6)
} else if (iph->version == 6) {
/* Due to the fact that 3GPP requires an allocation of a
* /64 prefix to each MS, we must instruct
@@ -652,6 +675,7 @@ static int cb_tun_ind(struct tun_t *tun, void *pack, unsigned len)
dst.len = 8;
dst.v6 = ip6h->ip6_dst;
pool = apn->v6.pool;
+#endif
} else {
LOGP(DTUN, LOGL_NOTICE, "non-IPv packet received from tun\n");
return -1;
@@ -673,16 +697,20 @@ static int cb_tun_ind(struct tun_t *tun, void *pack, unsigned len)
return 0;
}
+#if defined(BUILD_IPv6)
/* RFC3307 link-local scope multicast address */
static const struct in6_addr all_router_mcast_addr = {
.s6_addr = { 0xff,0x02,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,2 }
};
+#endif
/* MS-originated GTP1-U packet, needs to be sent via TUN device */
static int encaps_tun(struct pdp_t *pdp, void *pack, unsigned len)
{
struct iphdr *iph = (struct iphdr *)pack;
+#if defined(BUILD_IPv6)
struct ip6_hdr *ip6h = (struct ip6_hdr *)pack;
+#endif
struct tun_t *tun = (struct tun_t *)pdp->ipif;
struct apn_ctx *apn = tun->priv;
@@ -692,11 +720,13 @@ static int encaps_tun(struct pdp_t *pdp, void *pack, unsigned len)
LOGPPDP(LOGL_DEBUG, pdp, "Packet received: forwarding to tun\n");
switch (iph->version) {
+#if defined(BUILD_IPv6)
case 6:
/* daddr: all-routers multicast addr */
if (IN6_ARE_ADDR_EQUAL(&ip6h->ip6_dst, &all_router_mcast_addr))
return handle_router_mcast(pdp->gsn, pdp, &apn->v6_lladdr, pack, len);
break;
+#endif
case 4:
break;
default:
diff --git a/ggsn/ggsn_vty.c b/ggsn/ggsn_vty.c
index 6e15ae4..4932c20 100644
--- a/ggsn/ggsn_vty.c
+++ b/ggsn/ggsn_vty.c
@@ -334,8 +334,10 @@ static struct cmd_node apn_node = {
static const struct value_string pdp_type_names[] = {
{ APN_TYPE_IPv4, "v4" },
+#if defined(BUILD_IPv6)
{ APN_TYPE_IPv6, "v6" },
{ APN_TYPE_IPv4v6, "v4v6" },
+#endif
{ 0, NULL }
};
@@ -345,13 +347,17 @@ static const struct value_string apn_gtpu_mode_names[] = {
{ 0, NULL }
};
-
+#if defined(BUILD_IPv6)
+#define V4V6V46_ARGS "(v4|v6|v4v6)"
#define V4V6V46_STRING "IPv4(-only) PDP Type\n" \
"IPv6(-only) PDP Type\n" \
"IPv4v6 (dual-stack) PDP Type\n"
-
+#else
+#define V4V6V46_ARGS "(v4)"
+#define V4V6V46_STRING "IPv4(-only) PDP Type\n"
+#endif
DEFUN(cfg_apn_type_support, cfg_apn_type_support_cmd,
- "type-support (v4|v6|v4v6)",
+ "type-support " V4V6V46_ARGS,
"Enable support for PDP Type\n"
V4V6V46_STRING)
{
@@ -363,7 +369,7 @@ DEFUN(cfg_apn_type_support, cfg_apn_type_support_cmd,
}
DEFUN(cfg_apn_no_type_support, cfg_apn_no_type_support_cmd,
- "no type-support (v4|v6|v4v6)",
+ "no type-support " V4V6V46_ARGS,
NO_STR "Disable support for PDP Type\n"
V4V6V46_STRING)
{
@@ -480,6 +486,7 @@ DEFUN(cfg_apn_no_ip_ifconfig, cfg_apn_no_ip_ifconfig_cmd,
return CMD_SUCCESS;
}
+#if defined(BUILD_IPv6)
DEFUN(cfg_apn_ipv6_prefix, cfg_apn_ipv6_prefix_cmd,
"ipv6 prefix (static|dynamic) X:X::X:X/M",
IP6_STR PREFIX_STR "IPv6 Address/Prefix-Length\n")
@@ -512,6 +519,7 @@ DEFUN(cfg_apn_no_ipv6_ifconfig, cfg_apn_no_ipv6_ifconfig_cmd,
memset(&apn->v6.cfg.ifconfig_prefix, 0, sizeof(apn->v6.cfg.ifconfig_prefix));
return CMD_SUCCESS;
}
+#endif
#define DNS_STRINGS "Configure DNS Server\n" "primary/secondary DNS\n" "IP address of DNS Sever\n"
@@ -528,6 +536,7 @@ DEFUN(cfg_apn_ip_dns, cfg_apn_ip_dns_cmd,
return CMD_SUCCESS;
}
+#if defined(BUILD_IPv6)
DEFUN(cfg_apn_ipv6_dns, cfg_apn_ipv6_dns_cmd,
"ipv6 dns <0-1> X:X::X:X",
IP6_STR DNS_STRINGS)
@@ -540,20 +549,27 @@ DEFUN(cfg_apn_ipv6_dns, cfg_apn_ipv6_dns_cmd,
return CMD_SUCCESS;
}
+#endif
+#if defined(BUILD_IPv6)
+#define IPV46_ARGS "(ip|ipv6)"
+#else
+#define IPV46_ARGS "(ip)"
+#endif
DEFUN(cfg_apn_no_dns, cfg_apn_no_dns_cmd,
- "no (ip|ipv6) dns <0-1>",
+ "no " IPV46_ARGS " dns <0-1>",
NO_STR IP_STR IP6_STR "Disable DNS Server\n" "primary/secondary DNS\n")
{
struct apn_ctx *apn = (struct apn_ctx *) vty->index;
- struct in46_addr *a;
+ struct in46_addr *a = NULL;
int idx = atoi(argv[1]);
if (!strcmp(argv[0], "ip"))
a = &apn->v4.cfg.dns[idx];
+#if defined(BUILD_IPv6)
else
a = &apn->v6.cfg.dns[idx];
-
+#endif
memset(a, 0, sizeof(*a));
return CMD_SUCCESS;
@@ -656,6 +672,7 @@ static void config_write_apn(struct vty *vty, struct apn_ctx *apn)
if (apn->v4.cfg.ifconfig_prefix.addr.len)
vty_dump_prefix(vty, " ip ifconfig", &apn->v4.cfg.ifconfig_prefix);
+#if defined(BUILD_IPv6)
/* IPv6 prefixes + DNS */
if (apn->v6.cfg.static_prefix.addr.len)
vty_dump_prefix(vty, " ipv6 prefix static", &apn->v6.cfg.static_prefix);
@@ -668,7 +685,7 @@ static void config_write_apn(struct vty *vty, struct apn_ctx *apn)
}
if (apn->v6.cfg.ifconfig_prefix.addr.len)
vty_dump_prefix(vty, " ipv6 ifconfig", &apn->v6.cfg.ifconfig_prefix);
-
+#endif
/* must be last */
vty_out(vty, " %sshutdown%s", apn->cfg.shutdown ? "" : "no ", VTY_NEWLINE);
}
@@ -704,8 +721,12 @@ static const char *print_gsnaddr(const struct ul16_t *in)
struct in46_addr in46;
in46.len = in->l;
+#if defined(BUILD_IPv6)
OSMO_ASSERT(in->l <= sizeof(in46.v6));
- memcpy(&in46.v6, in->v, in->l);
+#else
+ OSMO_ASSERT(in->l <= sizeof(in46.v4));
+#endif
+ memcpy(&in46.v4, in->v, in->l);
return in46a_ntoa(&in46);
}
@@ -781,7 +802,9 @@ static void ippool_show_pdp_contexts(struct vty *vty, struct ippool_t *pool)
static void apn_show_pdp_contexts(struct vty *vty, struct apn_ctx *apn)
{
ippool_show_pdp_contexts(vty, apn->v4.pool);
+#if defined(BUILD_IPv6)
ippool_show_pdp_contexts(vty, apn->v6.pool);
+#endif
}
DEFUN(show_pdpctx, show_pdpctx_cmd,
@@ -885,14 +908,16 @@ int ggsn_vty_init(void)
install_element(APN_NODE, &cfg_apn_ipdown_script_cmd);
install_element(APN_NODE, &cfg_apn_no_ipdown_script_cmd);
install_element(APN_NODE, &cfg_apn_ip_prefix_cmd);
- install_element(APN_NODE, &cfg_apn_ipv6_prefix_cmd);
install_element(APN_NODE, &cfg_apn_ip_dns_cmd);
- install_element(APN_NODE, &cfg_apn_ipv6_dns_cmd);
install_element(APN_NODE, &cfg_apn_no_dns_cmd);
install_element(APN_NODE, &cfg_apn_ip_ifconfig_cmd);
install_element(APN_NODE, &cfg_apn_no_ip_ifconfig_cmd);
+#if defined(BUILD_IPv6)
+ install_element(APN_NODE, &cfg_apn_ipv6_prefix_cmd);
+ install_element(APN_NODE, &cfg_apn_ipv6_dns_cmd);
install_element(APN_NODE, &cfg_apn_ipv6_ifconfig_cmd);
install_element(APN_NODE, &cfg_apn_no_ipv6_ifconfig_cmd);
+#endif
install_element(APN_NODE, &cfg_apn_gpdu_seq_cmd);
install_element(APN_NODE, &cfg_apn_no_gpdu_seq_cmd);