From 9b1705382577e3fc203ebf6c290999bfe6010dc2 Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Thu, 14 Dec 2017 14:09:13 +0100 Subject: ggsn: Add 'ipv6 link-local' vty cmd This vty cmd let's you set up a new link-local IP for a specific APN to be used during ICMPv6 Router Advertisement procedure. osmo-ggsn hence requires a link-local IPv6 address to be added to the tun interface, otherwise the apn will not be configured correctly and it won't be able to allocate addresses from the ipv6 pool later on. This feature is useful in case your OS doesn't support autoconfiguring link-local IPs when the interface is brought up (some linux versions are known to fail at this) or in case you configured your OS specifically to avoid automatic set up (sysctl net.ipv6.conf.*.autoconf). If "no ipv6 link-local" is provided (default), osmo-ggsn will rely on the OS or the ipup-script setting up the link-local IP for the tun interface at creation time, then fetching it after ipup-script time and using the first link-local ip found. On the other hand, if the "ipv6 link-local" cmd is provided, osmo-ggsn will add the link-local IP to the interface manually and use that one for later Router Advertisement procedures. Change-Id: I09ef27f54940d4c47150e5f9016d1cd4298c16b5 --- ggsn/ggsn.c | 17 ++++++++++++++++- ggsn/ggsn.h | 1 + ggsn/ggsn_vty.c | 20 ++++++++++++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/ggsn/ggsn.c b/ggsn/ggsn.c index ef2357b..3e095f0 100644 --- a/ggsn/ggsn.c +++ b/ggsn/ggsn.c @@ -241,13 +241,28 @@ int apn_start(struct apn_ctx *apn) } } + 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)) { + 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", diff --git a/ggsn/ggsn.h b/ggsn/ggsn.h index c0774c4..e252548 100644 --- a/ggsn/ggsn.h +++ b/ggsn/ggsn.h @@ -22,6 +22,7 @@ struct ggsn_ctx; struct apn_ctx_ip { struct { struct in46_prefix ifconfig_prefix; + struct in46_prefix ll_prefix; struct in46_prefix static_prefix; struct in46_prefix dynamic_prefix; /* v4 DNS server names */ diff --git a/ggsn/ggsn_vty.c b/ggsn/ggsn_vty.c index 6e15ae4..db392fa 100644 --- a/ggsn/ggsn_vty.c +++ b/ggsn/ggsn_vty.c @@ -513,6 +513,24 @@ DEFUN(cfg_apn_no_ipv6_ifconfig, cfg_apn_no_ipv6_ifconfig_cmd, return CMD_SUCCESS; } +DEFUN(cfg_apn_ipv6_linklocal, cfg_apn_ipv6_linklocal_cmd, + "ipv6 link-local X:X::X:X/M", + IP6_STR IFCONFIG_STR "IPv6 Link-local Adress/Prefix-Length\n") +{ + struct apn_ctx *apn = (struct apn_ctx *) vty->index; + str2prefix(&apn->v6.cfg.ll_prefix, argv[0]); + return CMD_SUCCESS; +} + +DEFUN(cfg_apn_no_ipv6_linklocal, cfg_apn_no_ipv6_linklocal_cmd, + "no ipv6 link-local", + NO_STR IP6_STR IFCONFIG_STR) +{ + struct apn_ctx *apn = (struct apn_ctx *) vty->index; + memset(&apn->v6.cfg.ll_prefix, 0, sizeof(apn->v6.cfg.ll_prefix)); + return CMD_SUCCESS; +} + #define DNS_STRINGS "Configure DNS Server\n" "primary/secondary DNS\n" "IP address of DNS Sever\n" DEFUN(cfg_apn_ip_dns, cfg_apn_ip_dns_cmd, @@ -893,6 +911,8 @@ int ggsn_vty_init(void) install_element(APN_NODE, &cfg_apn_no_ip_ifconfig_cmd); install_element(APN_NODE, &cfg_apn_ipv6_ifconfig_cmd); install_element(APN_NODE, &cfg_apn_no_ipv6_ifconfig_cmd); + install_element(APN_NODE, &cfg_apn_ipv6_linklocal_cmd); + install_element(APN_NODE, &cfg_apn_no_ipv6_linklocal_cmd); install_element(APN_NODE, &cfg_apn_gpdu_seq_cmd); install_element(APN_NODE, &cfg_apn_no_gpdu_seq_cmd); -- cgit v1.2.3