summaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/socket.c30
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)
344 return scope; 344 return scope;
345} 345}
346 346
347static int32_t _in6_addr_scope_id(struct in6_addr* addr) 347static int32_t _sockaddr_in6_scope_id(struct sockaddr_in6* addr)
348{ 348{
349 int32_t res = -1; 349 int32_t res = -1;
350
351 struct ifaddrs *ifaddr, *ifa; 350 struct ifaddrs *ifaddr, *ifa;
352 uint32_t addr_scope; 351 uint32_t addr_scope;
353 352
354 /* get scope for requested address */ 353 /* get scope for requested address */
355 addr_scope = _in6_addr_scope(addr); 354 addr_scope = _in6_addr_scope(&addr->sin6_addr);
356 if (addr_scope == 0) { 355 if (addr_scope == 0) {
357 /* global scope doesn't need a specific scope id */ 356 /* global scope doesn't need a specific scope id */
358 return addr_scope; 357 return addr_scope;
@@ -393,10 +392,29 @@ static int32_t _in6_addr_scope_id(struct in6_addr* addr)
393 continue; 392 continue;
394 } 393 }
395 394
396 /* use the scope id of this interface */ 395 /* use if address is equal */
396 if (memcmp(&addr->sin6_addr.s6_addr, &addr_in->sin6_addr.s6_addr, sizeof(addr_in->sin6_addr.s6_addr)) == 0) {
397 res = addr_in->sin6_scope_id;
398 /* if scope id equals the requested one then assume it was valid */
399 if (addr->sin6_scope_id == addr_in->sin6_scope_id) {
400 break;
401 } else {
402 continue;
403 }
404 }
405
406 /* skip loopback interface if not already matched exactly above */
407 if ((ifa->ifa_flags & IFF_LOOPBACK) != 0) {
408 continue;
409 }
410
411 /* set the scope id of this interface as most likely candidate */
397 res = addr_in->sin6_scope_id; 412 res = addr_in->sin6_scope_id;
398 413
399 break; 414 /* if scope id equals the requested one then assume it was valid */
415 if (addr->sin6_scope_id == addr_in->sin6_scope_id) {
416 break;
417 }
400 } 418 }
401 419
402 freeifaddrs(ifaddr); 420 freeifaddrs(ifaddr);
@@ -442,7 +460,7 @@ int socket_connect_addr(struct sockaddr* addr, uint16_t port)
442 * a scope id from a suitable interface on this system or routing might 460 * a scope id from a suitable interface on this system or routing might
443 * fail. An IPv6 guru should have another look though... 461 * fail. An IPv6 guru should have another look though...
444 */ 462 */
445 addr_in->sin6_scope_id = _in6_addr_scope_id(&addr_in->sin6_addr); 463 addr_in->sin6_scope_id = _sockaddr_in6_scope_id(addr_in);
446 464
447 addrlen = sizeof(struct sockaddr_in6); 465 addrlen = sizeof(struct sockaddr_in6);
448 } 466 }