Feature: Added a way to prefer IPv6 for binding sockets
This commit is contained in:
parent
87ac18cd2c
commit
265f4eb61e
51
net/sock.c
51
net/sock.c
|
@ -712,7 +712,7 @@ sock_t sock_connect_wto_bind (const char *hostname, int port, const char *bnd, i
|
|||
}
|
||||
|
||||
|
||||
sock_t sock_get_server_socket (int port, const char *sinterface)
|
||||
sock_t sock_get_server_socket (int port, const char *sinterface, bool prefer_inet6)
|
||||
{
|
||||
struct sockaddr_storage sa;
|
||||
struct addrinfo hints, *res, *ai;
|
||||
|
@ -722,6 +722,10 @@ sock_t sock_get_server_socket (int port, const char *sinterface)
|
|||
if (port < 0)
|
||||
return SOCK_ERROR;
|
||||
|
||||
#ifndef AF_INET6
|
||||
prefer_inet6 = false;
|
||||
#endif
|
||||
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
|
||||
|
@ -733,27 +737,38 @@ sock_t sock_get_server_socket (int port, const char *sinterface)
|
|||
if (getaddrinfo(sinterface, service, &hints, &res))
|
||||
return SOCK_ERROR;
|
||||
|
||||
for (ai = res; ai; ai = ai->ai_next) {
|
||||
int on = 1;
|
||||
while (true) {
|
||||
for (ai = res; ai; ai = ai->ai_next) {
|
||||
int on = 1;
|
||||
|
||||
sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
|
||||
if (sock < 0)
|
||||
continue;
|
||||
|
||||
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const void *)&on, sizeof(on));
|
||||
|
||||
#ifdef IPV6_V6ONLY
|
||||
on = 0;
|
||||
setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on));
|
||||
#ifdef AF_INET6
|
||||
if (prefer_inet6 && ai->ai_family != AF_INET6)
|
||||
continue;
|
||||
#endif
|
||||
|
||||
if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0){
|
||||
sock_close(sock);
|
||||
continue;
|
||||
sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
|
||||
if (sock < 0)
|
||||
continue;
|
||||
|
||||
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const void *)&on, sizeof(on));
|
||||
|
||||
#ifdef IPV6_V6ONLY
|
||||
on = 0;
|
||||
setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on));
|
||||
#endif
|
||||
|
||||
if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0){
|
||||
sock_close(sock);
|
||||
continue;
|
||||
}
|
||||
|
||||
freeaddrinfo(res);
|
||||
return sock;
|
||||
}
|
||||
|
||||
freeaddrinfo(res);
|
||||
return sock;
|
||||
if (!prefer_inet6)
|
||||
break;
|
||||
prefer_inet6 = false;
|
||||
}
|
||||
|
||||
freeaddrinfo(res);
|
||||
|
@ -971,7 +986,7 @@ bool sock_is_ipv4_mapped_supported(void)
|
|||
sock_t csock;
|
||||
char ip[MAX_ADDR_LEN+1];
|
||||
|
||||
ssock = sock_get_server_socket(0, "::");
|
||||
ssock = sock_get_server_socket(0, "::", true);
|
||||
|
||||
if (ssock == SOCK_ERROR)
|
||||
return false;
|
||||
|
|
|
@ -153,7 +153,7 @@ int sock_read_bytes(sock_t sock, char *buff, size_t len);
|
|||
int sock_read_line(sock_t sock, char *string, const int len);
|
||||
|
||||
/* server socket functions */
|
||||
sock_t sock_get_server_socket(int port, const char *sinterface);
|
||||
sock_t sock_get_server_socket(int port, const char *sinterface, bool prefer_inet6);
|
||||
int sock_listen(sock_t serversock, int backlog);
|
||||
sock_t sock_accept(sock_t serversock, char *ip, size_t len);
|
||||
|
||||
|
|
Loading…
Reference in New Issue