diff options
author | Harald Welte <laforge@gnumonks.org> | 2017-09-24 20:00:34 +0800 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2017-09-24 20:51:47 +0800 |
commit | f85fe9720be14acc1038ed400654d8ce336274a7 (patch) | |
tree | e12f5279f153547a1d5b433bfbd62c9ef7868831 /lib | |
parent | fed598f41d85cef578925a4be6ce96a2c6afd3b3 (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.c | 32 | ||||
-rw-r--r-- | lib/tun.h | 2 |
2 files changed, 34 insertions, 0 deletions
@@ -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; +} @@ -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 */ |