diff options
Diffstat (limited to 'ggsn')
-rw-r--r-- | ggsn/Makefile.am | 5 | ||||
-rw-r--r-- | ggsn/ggsn.c | 38 | ||||
-rw-r--r-- | ggsn/ggsn_vty.c | 47 |
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); |