|
|
|
@ -557,6 +557,13 @@ struct ETCP_SOCKET* etcp_socket_add(struct UTUN_INSTANCE* instance, struct CFG_S |
|
|
|
DEBUG_WARN(DEBUG_CATEGORY_CONNECTION, "Failed to set non-blocking mode"); |
|
|
|
DEBUG_WARN(DEBUG_CATEGORY_CONNECTION, "Failed to set non-blocking mode"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (family == AF_INET6) { |
|
|
|
|
|
|
|
int v6only = 1; |
|
|
|
|
|
|
|
if (setsockopt(e_sock->fd, IPPROTO_IPV6, IPV6_V6ONLY, &v6only, sizeof(v6only)) < 0) { |
|
|
|
|
|
|
|
DEBUG_WARN(DEBUG_CATEGORY_CONNECTION, "Failed to set IPV6_V6ONLY: %s", socket_strerror(socket_get_error())); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Set socket mark if specified (Linux only)
|
|
|
|
// Set socket mark if specified (Linux only)
|
|
|
|
if (so_mark > 0) { |
|
|
|
if (so_mark > 0) { |
|
|
|
socket_set_mark(e_sock->fd, so_mark); |
|
|
|
socket_set_mark(e_sock->fd, so_mark); |
|
|
|
@ -637,15 +644,28 @@ struct ETCP_SOCKET* etcp_socket_add(struct UTUN_INSTANCE* instance, struct CFG_S |
|
|
|
} else if (ip->ss_family == AF_INET6) { |
|
|
|
} else if (ip->ss_family == AF_INET6) { |
|
|
|
struct sockaddr_in6* sin6 = (struct sockaddr_in6*)ip; |
|
|
|
struct sockaddr_in6* sin6 = (struct sockaddr_in6*)ip; |
|
|
|
if (memcmp(&sin6->sin6_addr, &in6addr_any, sizeof(struct in6_addr)) == 0) { |
|
|
|
if (memcmp(&sin6->sin6_addr, &in6addr_any, sizeof(struct in6_addr)) == 0) { |
|
|
|
// :: — определяем через default route
|
|
|
|
// :: — приоритет: permanent > temporary > get_outgoing_local_ip
|
|
|
|
struct sockaddr_storage remote; |
|
|
|
uint16_t v6if = (netif_index > 0) ? netif_index : get_default_route_netif_index(AF_INET6); |
|
|
|
memset(&remote, 0, sizeof(remote)); |
|
|
|
if (v6if > 0) { |
|
|
|
struct sockaddr_in6* rem_sin6 = (struct sockaddr_in6*)&remote; |
|
|
|
uint8_t v6addr[16]; |
|
|
|
rem_sin6->sin6_family = AF_INET6; |
|
|
|
int got = get_interface_ipv6_by_index(v6if, 0, v6addr); |
|
|
|
rem_sin6->sin6_port = htons(53); |
|
|
|
if (got != 0) got = get_interface_ipv6_by_index(v6if, 1, v6addr); |
|
|
|
inet_pton(AF_INET6, "2001:4860:4860::8888", &rem_sin6->sin6_addr); |
|
|
|
if (got == 0) { |
|
|
|
if (get_outgoing_local_ip(ip, &remote, &e_sock->interface_addr) != 0) { |
|
|
|
struct sockaddr_in6* if6 = (struct sockaddr_in6*)&e_sock->interface_addr; |
|
|
|
DEBUG_WARN(DEBUG_CATEGORY_CONNECTION, "Failed to detect outgoing local IPv6 for socket %s", e_sock->name); |
|
|
|
if6->sin6_family = AF_INET6; |
|
|
|
|
|
|
|
memcpy(&if6->sin6_addr, v6addr, 16); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (e_sock->interface_addr.ss_family == 0) { |
|
|
|
|
|
|
|
struct sockaddr_storage remote; |
|
|
|
|
|
|
|
memset(&remote, 0, sizeof(remote)); |
|
|
|
|
|
|
|
struct sockaddr_in6* rem_sin6 = (struct sockaddr_in6*)&remote; |
|
|
|
|
|
|
|
rem_sin6->sin6_family = AF_INET6; |
|
|
|
|
|
|
|
rem_sin6->sin6_port = htons(53); |
|
|
|
|
|
|
|
inet_pton(AF_INET6, "2001:4860:4860::8888", &rem_sin6->sin6_addr); |
|
|
|
|
|
|
|
if (get_outgoing_local_ip(ip, &remote, &e_sock->interface_addr) != 0) { |
|
|
|
|
|
|
|
DEBUG_WARN(DEBUG_CATEGORY_CONNECTION, "Failed to detect outgoing local IPv6 for socket %s", e_sock->name); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|