use LinkLocal address for HTTP when needed
should fix
should be tested...
/* $Id: minissdp.c,v 1.77 2015/08/26 07:36:52 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
- * (c) 2006-2016 Thomas Bernard
+ * (c) 2006-2017 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
#include <syslog.h>
#include "config.h"
+#if defined(ENABLE_IPV6) && defined(UPNP_STRICT)
+#include <ifaddrs.h>
+#endif /* defined(ENABLE_IPV6) && defined(UPNP_STRICT) */
+
#include "upnpdescstrings.h"
#include "miniupnpdpath.h"
#include "upnphttp.h"
@@ -116,6 +120,29 @@ AddMulticastMembershipIPv6(int s, unsigned int ifindex)
}
#endif
+
+#if defined(ENABLE_IPV6) && defined(UPNP_STRICT)
+static int get_link_local_addr(unsigned scope_id, struct in6_addr * addr6)
+{
+ struct ifaddrs * ifap;
+ struct ifaddrs * ife;
+ if(getifaddrs(&ifap)<0) {
+ syslog(LOG_ERR, "getifaddrs: %m");
+ return -1;
+ }
+ for(ife = ifap; ife != NULL; ife = ife->ifa_next) {
+ if(ife->ifa_addr == NULL) continue;
+ if(ife->ifa_addr->sa_family != AF_INET6) continue;
+ if(!IN6_IS_ADDR_LINKLOCAL(&(((const struct sockaddr_in6 *)ife->ifa_addr)->sin6_addr))) continue;
+ if(scope_id != if_nametoindex(ife->ifa_name)) continue;
+ memcpy(addr6, &(((const struct sockaddr_in6 *)ife->ifa_addr)->sin6_addr), sizeof(struct in6_addr));
+ break;
+ }
+ freeifaddrs(ifap);
+ return 0;
+}
+#endif /* defined(ENABLE_IPV6) && defined(UPNP_STRICT) */
+
/* Open and configure the socket listening for
* SSDP udp packets sent on 239.255.255.250 port 1900
* SSDP v6 udp packets sent on FF02::C, or FF05::C, port 1900 */
@@ -962,10 +989,13 @@ ProcessSSDPData(int s, const char *bufr, int n,
/* retrieve the IPv6 address which
* will be used locally to reach sender */
memset(&addr6, 0, sizeof(addr6));
- if(get_src_for_route_to (sender, &addr6, &addr6_len, &index) < 0) {
+ if(IN6_IS_ADDR_LINKLOCAL(&(((struct sockaddr_in6 *)sender)->sin6_addr))) {
+ get_link_local_addr(((struct sockaddr_in6 *)sender)->sin6_scope_id, &addr6);
+ } else if(get_src_for_route_to (sender, &addr6, &addr6_len, &index) < 0) {
syslog(LOG_WARNING, "get_src_for_route_to() failed, using %s", ipv6_addr_for_http_with_brackets);
announced_host = ipv6_addr_for_http_with_brackets;
- } else {
+ }
+ if(announced_host == NULL) {
if(inet_ntop(AF_INET6, &addr6,
announced_host_buf+1,
sizeof(announced_host_buf) - 2)) {
