[MERGED] osmo-ggsn[master]: ICMPv6: Send router advertisement from own link-local address

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

Harald Welte gerrit-no-reply at lists.osmocom.org
Sun Sep 24 12:55:25 UTC 2017


Harald Welte has submitted this change and it was merged.

Change subject: ICMPv6: Send router advertisement from own link-local address
......................................................................


ICMPv6: Send router advertisement from own link-local address

I'm not quite sure how I ended up doing this, but for some strange
reason the code before this commit is sending the ICMPv6 Router
Advertisements from some weird non-standard source address.  This is
a violation of RFC4861 which clearly states that the source address
of router advertisements "MUST be the link-local address assigned to the
interface from which this message is sent."

Change-Id: Ib444af70fc8f0b433d371281601fd5a37b29039e
---
M ggsn/ggsn.c
M ggsn/ggsn.h
M ggsn/icmpv6.c
M ggsn/icmpv6.h
M lib/tun.c
M lib/tun.h
6 files changed, 59 insertions(+), 10 deletions(-)

Approvals:
  Harald Welte: Looks good to me, approved
  Jenkins Builder: Verified



diff --git a/ggsn/ggsn.c b/ggsn/ggsn.c
index 46850a6..d521e57 100644
--- a/ggsn/ggsn.c
+++ b/ggsn/ggsn.c
@@ -202,6 +202,16 @@
 				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 (tun_ipv6_linklocal_get(apn->tun.tun, &apn->v6_lladdr) < 0) {
+				LOGPAPN(LOGL_ERROR, apn, "Cannot obtain IPv6 link-local address of "
+					"interface: %s\n", strerror(errno));
+				apn_stop(apn, false);
+				return -1;
+			}
+		}
+
 		/* set back-pointer from TUN device to APN */
 		apn->tun.tun->priv = apn;
 		break;
@@ -573,6 +583,11 @@
 {
 	struct iphdr *iph = (struct iphdr *)pack;
 	struct ip6_hdr *ip6h = (struct ip6_hdr *)pack;
+	struct tun_t *tun = (struct tun_t *)pdp->ipif;
+	struct apn_ctx *apn = tun->priv;
+
+	OSMO_ASSERT(tun);
+	OSMO_ASSERT(apn);
 
 	LOGPPDP(LOGL_DEBUG, pdp, "Packet received: forwarding to tun\n");
 
@@ -580,7 +595,7 @@
 	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, pack, len);
+			return handle_router_mcast(pdp->gsn, pdp, &apn->v6_lladdr, pack, len);
 		break;
 	case 4:
 		break;
diff --git a/ggsn/ggsn.h b/ggsn/ggsn.h
index 2dd963c..42f8e1c 100644
--- a/ggsn/ggsn.h
+++ b/ggsn/ggsn.h
@@ -78,6 +78,9 @@
 		struct osmo_fd fd;
 	} tun;
 
+	/* ipv6 link-local address */
+	struct in6_addr v6_lladdr;
+
 	struct apn_ctx_ip v4;
 	struct apn_ctx_ip v6;
 };
diff --git a/ggsn/icmpv6.c b/ggsn/icmpv6.c
index ac51bb1..11ced24 100644
--- a/ggsn/icmpv6.c
+++ b/ggsn/icmpv6.c
@@ -179,13 +179,9 @@
 	return true;
 }
 
-/* RFC3307 link-local scope multicast address */
-static const struct in6_addr my_local_addr = {
-	.s6_addr = { 0x01,0x02,0,0,  0,0,0,0, 0,0,0,0,  0,0,0,0xff }
-};
-
 /* handle incoming packets to the all-routers multicast address */
-int handle_router_mcast(struct gsn_t *gsn, struct pdp_t *pdp, const uint8_t *pack, unsigned len)
+int handle_router_mcast(struct gsn_t *gsn, struct pdp_t *pdp, const struct in6_addr *own_ll_addr,
+			const uint8_t *pack, unsigned len)
 {
 	struct ippoolm_t *member = pdp->peer;
 	const struct ip6_hdr *ip6h = (struct ip6_hdr *)pack;
@@ -222,10 +218,10 @@
 				osmo_hexdump(pack, len));
 			return -1;
 		}
-		/* FIXME: Send router advertisement from GGSN link-local
+		/* Send router advertisement from GGSN link-local
 		 * address to MS link-local address, including prefix
 		 * allocated to this PDP context */
-		msg = icmpv6_construct_ra(&my_local_addr, &ip6h->ip6_src, &member->addr.v6);
+		msg = icmpv6_construct_ra(own_ll_addr, &ip6h->ip6_src, &member->addr.v6);
 		/* Send the constructed RA to the MS */
 		gtp_data_req(gsn, pdp, msgb_data(msg), msgb_length(msg));
 		msgb_free(msg);
diff --git a/ggsn/icmpv6.h b/ggsn/icmpv6.h
index ebff04e..b6eec63 100644
--- a/ggsn/icmpv6.h
+++ b/ggsn/icmpv6.h
@@ -3,4 +3,5 @@
 #include "../gtp/gtp.h"
 #include "../gtp/pdp.h"
 
-int handle_router_mcast(struct gsn_t *gsn, struct pdp_t *pdp, const uint8_t *pack, unsigned len);
+int handle_router_mcast(struct gsn_t *gsn, struct pdp_t *pdp, const struct in6_addr *own_ll_addr,
+			const uint8_t *pack, unsigned len);
diff --git a/lib/tun.c b/lib/tun.c
index 76ac379..32a8d2d 100644
--- a/lib/tun.c
+++ b/lib/tun.c
@@ -748,3 +748,35 @@
 	}
 	return 0;
 }
+
+#include <ifaddrs.h>
+
+/* obtain the link-local address of the tun device */
+int tun_ipv6_linklocal_get(const struct tun_t *tun, struct in6_addr *ia)
+{
+	struct ifaddrs *ifaddr, *ifa;
+	static const uint8_t ll_prefix[] = { 0xfe,0x80, 0,0, 0,0, 0,0 };
+
+	if (getifaddrs(&ifaddr) == -1) {
+		return -1;
+	}
+
+	for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
+		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) ifa->ifa_addr;
+		if (ifa->ifa_addr == NULL)
+			continue;
+
+		if (ifa->ifa_addr->sa_family != AF_INET6)
+			continue;
+
+		if (strcmp(ifa->ifa_name, tun->devname))
+			continue;
+
+		if (memcmp(sin6->sin6_addr.s6_addr, ll_prefix, sizeof(ll_prefix)))
+			continue;
+
+		*ia = sin6->sin6_addr;
+		return 0;
+	}
+	return -1;
+}
diff --git a/lib/tun.h b/lib/tun.h
index 50ac806..95fff26 100644
--- a/lib/tun.h
+++ b/lib/tun.h
@@ -85,4 +85,6 @@
 
 extern int tun_runscript(struct tun_t *tun, char *script);
 
+int tun_ipv6_linklocal_get(const struct tun_t *tun, struct in6_addr *ia);
+
 #endif /* !_TUN_H */

-- 
To view, visit https://gerrit.osmocom.org/4044
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: Ib444af70fc8f0b433d371281601fd5a37b29039e
Gerrit-PatchSet: 1
Gerrit-Project: osmo-ggsn
Gerrit-Branch: master
Gerrit-Owner: Harald Welte <laforge at gnumonks.org>
Gerrit-Reviewer: Harald Welte <laforge at gnumonks.org>
Gerrit-Reviewer: Jenkins Builder



More information about the gerrit-log mailing list