From 6dce477aef000041b9ad2a6b5e1716cfa3ef298a Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 15 Dec 2016 10:09:55 +0800 Subject: [PATCH] ipv6-allow-binding-to-ipv6-address-in-iface ipv4 and ipv6 binding to a named interface works OK. ipv4 binding to an IP also works, but we need some extra ipv6 magic to identify the ipv6 interface from an ipv6 address. This patch based on code from "user3546716" at http://stackoverflow.com/questions/13504934/binding-sockets-to-ipv6-addresses adds the necessary magic. https://github.com/warmcat/libwebsockets/issues/717 --- lib/libwebsockets.c | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/lib/libwebsockets.c b/lib/libwebsockets.c index f8c879a3..36fb4711 100755 --- a/lib/libwebsockets.c +++ b/lib/libwebsockets.c @@ -30,6 +30,14 @@ #include #endif +#ifdef LWS_USE_IPV6 +#if defined(WIN32) || defined(_WIN32) +#include +#else +#include +#endif +#endif + int log_level = LLL_ERR | LLL_WARN | LLL_NOTICE; static void (*lwsl_emit)(int level, const char *line) = lwsl_emit_stderr; @@ -1517,6 +1525,39 @@ lws_socket_bind(struct lws_vhost *vhost, lws_sockfd_type sockfd, int port, lwsl_err("Unable to find interface %s\n", iface); return -1; } + + if (iface) { + struct ifaddrs *addrs, *addr; + char ip[NI_MAXHOST]; + unsigned int i; + + getifaddrs(&addrs); + for (addr = addrs; addr; addr = addr->ifa_next) { + if (!addr->ifa_addr || + addr->ifa_addr->sa_family != AF_INET6) + continue; + + getnameinfo(addr->ifa_addr, + sizeof(struct sockaddr_in6), + ip, sizeof(ip), + NULL, 0, NI_NUMERICHOST); + + i = 0; + while (ip[i]) + if (ip[i++] == '%') { + ip[i - 1] = '\0'; + break; + } + + if (!strcmp(ip, iface)) { + serv_addr6.sin6_scope_id = + if_nametoindex(addr->ifa_name); + break; + } + } + freeifaddrs(addrs); + } + serv_addr6.sin6_family = AF_INET6; serv_addr6.sin6_port = htons(port); } else