Browse Source

Dual mode IPv4/IPv6 stack support

pull/237/head
KrazyIvan 10 years ago
parent
commit
013d3381c3
1 changed files with 36 additions and 3 deletions
  1. 39
      src/udprelay.c

39
src/udprelay.c

@ -312,26 +312,59 @@ int create_remote_socket(int ipv6)
int create_server_socket(const char *host, const char *port)
{
struct addrinfo hints;
struct addrinfo *result, *rp;
struct addrinfo *result, *rp, *ipv4v6bindall;
int s, server_sock;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC; /* Return IPv4 and IPv6 choices */
hints.ai_socktype = SOCK_DGRAM; /* We want a UDP socket */
hints.ai_flags = AI_ALL | AI_V4MAPPED | AI_PASSIVE | AI_ADDRCONFIG; /* For wildcard IP address */
hints.ai_protocol = IPPROTO_UDP;
s = getaddrinfo(host, port, &hints, &result);
if (s != 0) {
LOGE("[udp] getaddrinfo: %s", gai_strerror(s));
return -1;
}
for (rp = result; rp != NULL; rp = rp->ai_next) {
rp = result;
/*
On Linux, with net.ipv6.bindv6only = 0 (the default), getaddrinfo(NULL) with
AI_PASSIVE returns 0.0.0.0 and :: (in this order). AI_PASSIVE was meant to
return a list of addresses to listen on, but it is impossible to listen on
0.0.0.0 and :: at the same time, if :: implies dualstack mode.
*/
if (!host) {
ipv4v6bindall = result;
/* Loop over all address infos found until a IPV6 address is found. */
while (ipv4v6bindall) {
if (ipv4v6bindall->ai_family == AF_INET6) {
rp = ipv4v6bindall; /* Take first IPV6 address available */
break;
}
ipv4v6bindall = ipv4v6bindall->ai_next; /* Get next address info, if any */
}
}
for (/*rp = result*/; rp != NULL; rp = rp->ai_next) {
server_sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if (server_sock == -1) {
continue;
}
int opt = 1;
if (rp->ai_family == AF_INET6) {
int ipv6only = 0;
if (host) {
ipv6only = 1;
}
setsockopt(server_sock, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6only, sizeof(ipv6only));
}
setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
#ifdef SO_NOSIGPIPE
set_nosigpipe(server_sock);

Loading…
Cancel
Save