|
|
|
|
@ -60,6 +60,12 @@ int random_bytes(uint8_t *buffer, size_t len) {
|
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Глобальный unicast IPv6 (2000::/3). При выборе адреса интерфейса предпочитаем его
|
|
|
|
|
* ULA (fc00::/7) и link-local (fe80::/10). */ |
|
|
|
|
static int ipv6_is_global_unicast(const uint8_t* a) { |
|
|
|
|
return (a[0] & 0xe0) == 0x20; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#ifndef _WIN32 |
|
|
|
|
uint32_t get_interface_ip_by_index(uint32_t netif_index) { |
|
|
|
|
struct ifaddrs *ifaddr, *ifa; |
|
|
|
|
@ -89,7 +95,8 @@ int get_interface_ipv6_by_index(uint32_t netif_index, int temporary, uint8_t* ad
|
|
|
|
|
struct ifaddrs *ifaddr, *ifa; |
|
|
|
|
if (getifaddrs(&ifaddr) == -1) return -1; |
|
|
|
|
|
|
|
|
|
int found = 0; |
|
|
|
|
uint8_t global_match[16], local_match[16]; |
|
|
|
|
int has_global = 0, has_local = 0; |
|
|
|
|
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { |
|
|
|
|
if (ifa->ifa_addr == NULL) continue; |
|
|
|
|
if (ifa->ifa_name == NULL) continue; |
|
|
|
|
@ -100,20 +107,18 @@ int get_interface_ipv6_by_index(uint32_t netif_index, int temporary, uint8_t* ad
|
|
|
|
|
struct sockaddr_in6* sin6 = (struct sockaddr_in6*)ifa->ifa_addr; |
|
|
|
|
if ((sin6->sin6_addr.s6_addr[0] & 0xfe) == 0xfe && sin6->sin6_addr.s6_addr[1] == 0x80) continue; |
|
|
|
|
int is_temporary = (ifa->ifa_flags & IFA_F_TEMPORARY) ? 1 : 0; |
|
|
|
|
if (temporary && is_temporary) { |
|
|
|
|
memcpy(addr_out, &sin6->sin6_addr, 16); |
|
|
|
|
found = 1; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
if (!temporary && !is_temporary) { |
|
|
|
|
memcpy(addr_out, &sin6->sin6_addr, 16); |
|
|
|
|
found = 1; |
|
|
|
|
break; |
|
|
|
|
if ((temporary && !is_temporary) || (!temporary && is_temporary)) continue; |
|
|
|
|
if (ipv6_is_global_unicast(sin6->sin6_addr.s6_addr)) { |
|
|
|
|
if (!has_global) { memcpy(global_match, &sin6->sin6_addr, 16); has_global = 1; } |
|
|
|
|
} else { |
|
|
|
|
if (!has_local) { memcpy(local_match, &sin6->sin6_addr, 16); has_local = 1; } |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
freeifaddrs(ifaddr); |
|
|
|
|
return found ? 0 : -1; |
|
|
|
|
if (has_global) { memcpy(addr_out, global_match, 16); return 0; } |
|
|
|
|
if (has_local) { memcpy(addr_out, local_match, 16); return 0; } |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#ifdef __linux__ |
|
|
|
|
@ -151,8 +156,8 @@ int get_interface_ipv6_addr_nl(uint32_t netif_index, int prefer_stable, uint8_t*
|
|
|
|
|
|
|
|
|
|
if (send(nl_sock, &req, req.nlh.nlmsg_len, 0) < 0) { close(nl_sock); return -1; } |
|
|
|
|
|
|
|
|
|
uint8_t fallback[16], stable_addr[16], temp_addr[16]; |
|
|
|
|
int has_fallback = 0, has_stable = 0, has_temp = 0; |
|
|
|
|
uint8_t fallback[16], g_stable[16], g_temp[16], l_stable[16], l_temp[16]; |
|
|
|
|
int has_fallback = 0, has_g_stable = 0, has_g_temp = 0, has_l_stable = 0, has_l_temp = 0; |
|
|
|
|
|
|
|
|
|
char buf[8192]; |
|
|
|
|
int done = 0; |
|
|
|
|
@ -181,19 +186,32 @@ int get_interface_ipv6_addr_nl(uint32_t netif_index, int prefer_stable, uint8_t*
|
|
|
|
|
|
|
|
|
|
int is_temp = (ifa_flags & IFA_F_TEMPORARY) != 0; |
|
|
|
|
int is_mngtmp = (ifa_flags & IFA_F_MANAGETEMPADDR) != 0; |
|
|
|
|
int is_global = ipv6_is_global_unicast(addr); |
|
|
|
|
|
|
|
|
|
if (!has_fallback) { memcpy(fallback, addr, 16); has_fallback = 1; } |
|
|
|
|
|
|
|
|
|
if (!has_stable && (!is_temp || is_mngtmp)) { memcpy(stable_addr, addr, 16); has_stable = 1; } |
|
|
|
|
if (!has_temp && is_temp && !is_mngtmp) { memcpy(temp_addr, addr, 16); has_temp = 1; } |
|
|
|
|
if (is_global) { |
|
|
|
|
if (!has_g_stable && (!is_temp || is_mngtmp)) { memcpy(g_stable, addr, 16); has_g_stable = 1; } |
|
|
|
|
if (!has_g_temp && is_temp && !is_mngtmp) { memcpy(g_temp, addr, 16); has_g_temp = 1; } |
|
|
|
|
} else { |
|
|
|
|
if (!has_l_stable && (!is_temp || is_mngtmp)) { memcpy(l_stable, addr, 16); has_l_stable = 1; } |
|
|
|
|
if (!has_l_temp && is_temp && !is_mngtmp) { memcpy(l_temp, addr, 16); has_l_temp = 1; } |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
close(nl_sock); |
|
|
|
|
|
|
|
|
|
if (prefer_stable && has_stable) { memcpy(addr_out, stable_addr, 16); return 0; } |
|
|
|
|
if (!prefer_stable && has_temp) { memcpy(addr_out, temp_addr, 16); return 0; } |
|
|
|
|
if (has_stable) { memcpy(addr_out, stable_addr, 16); return 0; } |
|
|
|
|
if (has_temp) { memcpy(addr_out, temp_addr, 16); return 0; } |
|
|
|
|
if (prefer_stable) { |
|
|
|
|
if (has_g_stable) { memcpy(addr_out, g_stable, 16); return 0; } |
|
|
|
|
if (has_g_temp) { memcpy(addr_out, g_temp, 16); return 0; } |
|
|
|
|
if (has_l_stable) { memcpy(addr_out, l_stable, 16); return 0; } |
|
|
|
|
if (has_l_temp) { memcpy(addr_out, l_temp, 16); return 0; } |
|
|
|
|
} else { |
|
|
|
|
if (has_g_temp) { memcpy(addr_out, g_temp, 16); return 0; } |
|
|
|
|
if (has_g_stable) { memcpy(addr_out, g_stable, 16); return 0; } |
|
|
|
|
if (has_l_temp) { memcpy(addr_out, l_temp, 16); return 0; } |
|
|
|
|
if (has_l_stable) { memcpy(addr_out, l_stable, 16); return 0; } |
|
|
|
|
} |
|
|
|
|
if (has_fallback) { memcpy(addr_out, fallback, 16); return 0; } |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
@ -335,6 +353,7 @@ int get_interface_ipv6_addr_nl(uint32_t netif_index, int prefer_stable, uint8_t*
|
|
|
|
|
PIP_ADAPTER_ADDRESSES adapters = plat_win_get_adapters(AF_INET6); |
|
|
|
|
if (!adapters) return -1; |
|
|
|
|
int found = 0; |
|
|
|
|
uint8_t local_match[16]; int has_local = 0; |
|
|
|
|
PIP_ADAPTER_ADDRESSES a = plat_win_find_adapter(adapters, netif_index); |
|
|
|
|
if (a) { |
|
|
|
|
for (PIP_ADAPTER_UNICAST_ADDRESS u = a->FirstUnicastAddress; u; u = u->Next) { |
|
|
|
|
@ -344,12 +363,12 @@ int get_interface_ipv6_addr_nl(uint32_t netif_index, int prefer_stable, uint8_t*
|
|
|
|
|
{ static const uint8_t lb[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}; |
|
|
|
|
if (memcmp(b, lb, 16) == 0) continue; } /* loopback */ |
|
|
|
|
{ static const uint8_t z[16]; if (memcmp(b, z, 16) == 0) continue; } /* :: */ |
|
|
|
|
memcpy(addr_out, b, 16); |
|
|
|
|
found = 1; |
|
|
|
|
break; |
|
|
|
|
if (ipv6_is_global_unicast(b)) { memcpy(addr_out, b, 16); found = 1; break; } |
|
|
|
|
if (!has_local) { memcpy(local_match, b, 16); has_local = 1; } |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
free(adapters); |
|
|
|
|
if (!found && has_local) { memcpy(addr_out, local_match, 16); found = 1; } |
|
|
|
|
return found ? 0 : -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|