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
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 */