diff options
Diffstat (limited to 'common')
| -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) | |||
| 344 | return scope; | 344 | return scope; |
| 345 | } | 345 | } |
| 346 | 346 | ||
| 347 | static int32_t _in6_addr_scope_id(struct in6_addr* addr) | 347 | static 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 | } |
