pespin submitted this change.

View Change

Approvals: laforge: Looks good to me, but someone else must approve Jenkins Builder: Verified pespin: Looks good to me, approved
ggsn: use the runtime tun interface name

The IP pool of an APN excludes the addresses of its own tun interface.
alloc_ippool_blacklist() finds them with netdev_ip_local_get(), which
walks getifaddrs() and matches on the interface name, and it passes
apn->tun.cfg.dev_name, the name from the configuration file.
tun_ip_local_get() does the same with tun->devname when it looks up the
IPv6 link-local address.

The configured name is not always the name the interface ends up with.
libosmocore already knows this: osmo_tundev keeps dev_name current, and
tundev_dev_name_chg_cb() rewrites it on rename, logging "netdev changed
name". Once that happens, or wherever the kernel picks the name itself,
the lookup is done under a name getifaddrs() does not report, no
addresses are found, and the blacklist is empty.

An empty blacklist is not a harmless miss. The pool then hands out its
first address, which is the tun's own, so the first PDP context gets
the address of the GGSN side of the link and collides with it.

Observed on Darwin, where the kernel always names a utun itself and a
requested "tun4" comes back as "utun6": the first attached UE was given
10.45.0.1, the tun address. With the fix it gets 10.45.0.2.

Take the name from the open osmo_tundev with
osmo_tundev_get_dev_name(), which returns what the interface is called
now, in both places. Fall back to the configured name when there is no
tundev, which is the gtp kernel mode path. No change where the two
names agree, which is the normal case on Linux.

Change-Id: Ibd754ea3a5be4d5227488d0de571723b69e9d39d
Signed-off-by: Andrei Gosman <andrei.gosman@gmail.com>
---
M ggsn/ggsn.c
M lib/tun.c
2 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/ggsn/ggsn.c b/ggsn/ggsn.c
index 3177713..79efae3 100644
--- a/ggsn/ggsn.c
+++ b/ggsn/ggsn.c
@@ -174,23 +174,31 @@

static int alloc_ippool_blacklist(struct apn_ctx *apn, struct in46_prefix **blacklist, bool ipv6)
{
-
+ const char *dev_name = apn->tun.cfg.dev_name;
int flags, len, len2, i;

*blacklist = NULL;

+ /* The kernel may give the interface another name than the one that
+ * was configured (a Darwin utun: "tun4" requested, "utun6" assigned).
+ * getifaddrs() lists the addresses under the real name, so ask the
+ * open tun device for it; otherwise the blacklist stays empty and the
+ * pool hands the tun's own address to the first PDP context. */
+ if (apn->tun.tun && apn->tun.tun->tundev.tundev)
+ dev_name = osmo_tundev_get_dev_name(apn->tun.tun->tundev.tundev);
+
if (ipv6)
flags = IP_TYPE_IPv6_NONLINK;
else
flags = IP_TYPE_IPv4;

while (1) {
- len = netdev_ip_local_get(apn->tun.cfg.dev_name, NULL, 0, flags);
+ len = netdev_ip_local_get(dev_name, NULL, 0, flags);
if (len < 1)
return len;

*blacklist = talloc_zero_size(apn, len * sizeof(struct in46_prefix));
- len2 = netdev_ip_local_get(apn->tun.cfg.dev_name, *blacklist, len, flags);
+ len2 = netdev_ip_local_get(dev_name, *blacklist, len, flags);
if (len2 < 1) {
talloc_free(*blacklist);
*blacklist = NULL;
diff --git a/lib/tun.c b/lib/tun.c
index 60d9b5e..13a8b9d 100644
--- a/lib/tun.c
+++ b/lib/tun.c
@@ -279,5 +279,11 @@
*/
int tun_ip_local_get(const struct tun_t *tun, struct in46_prefix *prefix_list, size_t prefix_size, int flags)
{
- return netdev_ip_local_get(tun->devname, prefix_list, prefix_size, flags);
+ /* Ask the tun device for the name the kernel gave the interface; it can
+ * differ from the configured one (Darwin utun) and getifaddrs() only
+ * knows the real one. */
+ const char *devname = tun->devname;
+ if (tun->tundev.tundev)
+ devname = osmo_tundev_get_dev_name(tun->tundev.tundev);
+ return netdev_ip_local_get(devname, prefix_list, prefix_size, flags);
}

To view, visit change 43585. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-MessageType: merged
Gerrit-Project: osmo-ggsn
Gerrit-Branch: master
Gerrit-Change-Id: Ibd754ea3a5be4d5227488d0de571723b69e9d39d
Gerrit-Change-Number: 43585
Gerrit-PatchSet: 2
Gerrit-Owner: Andrei G <andrei.gosman@gmail.com>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <laforge@osmocom.org>
Gerrit-Reviewer: pespin <pespin@sysmocom.de>