diff --git a/netsock.c b/netsock.c index 86db8a6..9b137f1 100644 --- a/netsock.c +++ b/netsock.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -210,6 +211,30 @@ out: return ret; } +static int get_link_local_addr(uint32_t scope_id, struct in6_addr *addr) +{ + struct ifaddrs *ifaddr, *ifa; + + if (getifaddrs(&ifaddr) == -1) { + perror("getifaddrs"); + return -1; + } + for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { + if (ifa->ifa_addr == NULL) + continue; + if (ifa->ifa_addr->sa_family != AF_INET6) + continue; + + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) ifa->ifa_addr; + if (sin6->sin6_scope_id == scope_id) { + memcpy(addr, &sin6->sin6_addr ,sizeof(struct in6_addr)); + break; + } + } + freeifaddrs(ifaddr); + return 0; +} + static int netsock_open(struct interface *interface) { int sock; @@ -256,7 +281,10 @@ static int netsock_open(struct interface *interface) memset(&sin6, 0, sizeof(sin6)); sin6.sin6_port = htons(ALFRED_PORT); sin6.sin6_family = AF_INET6; - memcpy(&sin6.sin6_addr, &interface->address, sizeof(sin6.sin6_addr)); + if (get_link_local_addr(interface->scope_id, &sin6.sin6_addr) < 0) { + perror("cannot get link local address"); + goto err; + } sin6.sin6_scope_id = interface->scope_id; memset(&sin6_mc, 0, sizeof(sin6_mc));