aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2017-09-24 20:00:34 +0800
committerHarald Welte <laforge@gnumonks.org>2017-09-24 20:51:47 +0800
commitf85fe9720be14acc1038ed400654d8ce336274a7 (patch)
treee12f5279f153547a1d5b433bfbd62c9ef7868831 /lib
parentfed598f41d85cef578925a4be6ce96a2c6afd3b3 (diff)
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
Diffstat (limited to 'lib')
-rw-r--r--lib/tun.c32
-rw-r--r--lib/tun.h2
2 files changed, 34 insertions, 0 deletions
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 @@ int tun_runscript(struct tun_t *tun, char *script)
}
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_set_cb_ind(struct tun_t *this,
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 */