Try all addresses returned by getaddrinfo() until we find one that socket() is happy with

Someone reported being unable to connect with the error "Address family not
supported", which is probably being returned by socket().  It is likely a
system where getaddrinfo() is returning AF_INET6 addresses, but socket()
won't create AF_INET6 sockets.

To handle this case, we loop over all the addresses returned by getaddrinfo()
until we find one that socket() will accept.
This commit is contained in:
Kevin Easton
2016-03-08 23:53:16 +11:00
parent c2a2d68d8d
commit 9427b3db84
2 changed files with 40 additions and 29 deletions

View File

@@ -1,5 +1,8 @@
[Changes 1.2.2]
* If we can't create a socket for the first address returned by getaddrinfo(),
try the other returned addresses. (caf)
* Only show version once with -v option (reported by cpet). (caf)
* Drop group privileges before droppping user privileges when execing. (caf)

View File

@@ -509,13 +509,14 @@ int BX_connect_by_number(char *hostn, unsigned short *portnum, int service, int
{
struct sockaddr_foobar server;
socklen_t server_len;
struct hostent *hp;
#ifdef WINNT
char buf[BIG_BUFFER_SIZE+1];
#endif
#ifdef IPV6
struct addrinfo hints, *res;
struct addrinfo hints = { 0 };
struct addrinfo *res_list, *res;
#else
struct hostent *hp;
struct sockaddr_in localaddr;
if (LocalHostName)
{
@@ -532,18 +533,29 @@ int BX_connect_by_number(char *hostn, unsigned short *portnum, int service, int
#ifndef WINNT
#ifdef IPV6
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_flags = AI_ADDRCONFIG;
hints.ai_socktype = proto_type;
if (!getaddrinfo(hostn, NULL, &hints, &res) && res)
{
close(fd);
if (getaddrinfo(hostn, NULL, &hints, &res_list) != 0)
return close(fd), -6;
if ((fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) < 0)
close(fd);
fd = -1;
for (res = res_list; res; res = res->ai_next)
{
fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (fd >= 0)
break;
}
if (fd < 0)
{
freeaddrinfo(res_list);
return -1;
set_socket_options (fd);
}
set_socket_options(fd);
memcpy(&server, res->ai_addr, res->ai_addrlen);
server_len = res->ai_addrlen;
@@ -551,7 +563,7 @@ int BX_connect_by_number(char *hostn, unsigned short *portnum, int service, int
memset(&hints, 0, sizeof hints);
hints.ai_family = res->ai_family;
freeaddrinfo(res);
freeaddrinfo(res_list);
if (LocalHostName && !getaddrinfo(LocalHostName, NULL, &hints, &res) && res)
{
@@ -561,10 +573,6 @@ int BX_connect_by_number(char *hostn, unsigned short *portnum, int service, int
if (retval)
return close(fd), -2;
}
}
else
return close(fd), -6;
#else
if (isdigit((unsigned char)hostn[strlen(hostn)-1]))
inet_aton(hostn, (struct in_addr *)&server.sf_addr);