diff options
author | Martin Szulecki | 2020-06-06 19:23:34 +0200 |
---|---|---|
committer | Martin Szulecki | 2020-06-06 19:23:34 +0200 |
commit | 9a7f686ce7f6dc5298cef8a6e665bee673b6139d (patch) | |
tree | ca35f83f8448180463cdb915dc05ad8bb996fada | |
parent | 574d7f82b78f7b5703eaaff227a5075aa2afb1a5 (diff) | |
download | libimobiledevice-9a7f686ce7f6dc5298cef8a6e665bee673b6139d.tar.gz libimobiledevice-9a7f686ce7f6dc5298cef8a6e665bee673b6139d.tar.bz2 |
socket: Improve IPv6 scope id detection to fix network devices on OSX
The helper should now also work for loopback addresses and prefer any initially
supplied scope id to maintain routing information if possible. Otherwise it
just picks the best suitable route. Let us see if this is stable enough to
prevent us from adding routing table parsing cruft and other logic...
-rw-r--r-- | common/socket.c | 30 |
1 files changed, 24 insertions, 6 deletions
diff --git a/common/socket.c b/common/socket.c index 26cf496..749e0ef 100644 --- a/common/socket.c +++ b/common/socket.c @@ -344,15 +344,14 @@ static uint32_t _in6_addr_scope(struct in6_addr* addr) return scope; } -static int32_t _in6_addr_scope_id(struct in6_addr* addr) +static int32_t _sockaddr_in6_scope_id(struct sockaddr_in6* addr) { int32_t res = -1; - struct ifaddrs *ifaddr, *ifa; uint32_t addr_scope; /* get scope for requested address */ - addr_scope = _in6_addr_scope(addr); + addr_scope = _in6_addr_scope(&addr->sin6_addr); if (addr_scope == 0) { /* global scope doesn't need a specific scope id */ return addr_scope; @@ -393,10 +392,29 @@ static int32_t _in6_addr_scope_id(struct in6_addr* addr) continue; } - /* use the scope id of this interface */ + /* use if address is equal */ + if (memcmp(&addr->sin6_addr.s6_addr, &addr_in->sin6_addr.s6_addr, sizeof(addr_in->sin6_addr.s6_addr)) == 0) { + res = addr_in->sin6_scope_id; + /* if scope id equals the requested one then assume it was valid */ + if (addr->sin6_scope_id == addr_in->sin6_scope_id) { + break; + } else { + continue; + } + } + + /* skip loopback interface if not already matched exactly above */ + if ((ifa->ifa_flags & IFF_LOOPBACK) != 0) { + continue; + } + + /* set the scope id of this interface as most likely candidate */ res = addr_in->sin6_scope_id; - break; + /* if scope id equals the requested one then assume it was valid */ + if (addr->sin6_scope_id == addr_in->sin6_scope_id) { + break; + } } freeifaddrs(ifaddr); @@ -442,7 +460,7 @@ int socket_connect_addr(struct sockaddr* addr, uint16_t port) * a scope id from a suitable interface on this system or routing might * fail. An IPv6 guru should have another look though... */ - addr_in->sin6_scope_id = _in6_addr_scope_id(&addr_in->sin6_addr); + addr_in->sin6_scope_id = _sockaddr_in6_scope_id(addr_in); addrlen = sizeof(struct sockaddr_in6); } |