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:
@@ -1,5 +1,8 @@
|
|||||||
[Changes 1.2.2]
|
[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)
|
* Only show version once with -v option (reported by cpet). (caf)
|
||||||
|
|
||||||
* Drop group privileges before droppping user privileges when execing. (caf)
|
* Drop group privileges before droppping user privileges when execing. (caf)
|
||||||
|
|||||||
@@ -509,13 +509,14 @@ int BX_connect_by_number(char *hostn, unsigned short *portnum, int service, int
|
|||||||
{
|
{
|
||||||
struct sockaddr_foobar server;
|
struct sockaddr_foobar server;
|
||||||
socklen_t server_len;
|
socklen_t server_len;
|
||||||
struct hostent *hp;
|
|
||||||
#ifdef WINNT
|
#ifdef WINNT
|
||||||
char buf[BIG_BUFFER_SIZE+1];
|
char buf[BIG_BUFFER_SIZE+1];
|
||||||
#endif
|
#endif
|
||||||
#ifdef IPV6
|
#ifdef IPV6
|
||||||
struct addrinfo hints, *res;
|
struct addrinfo hints = { 0 };
|
||||||
|
struct addrinfo *res_list, *res;
|
||||||
#else
|
#else
|
||||||
|
struct hostent *hp;
|
||||||
struct sockaddr_in localaddr;
|
struct sockaddr_in localaddr;
|
||||||
if (LocalHostName)
|
if (LocalHostName)
|
||||||
{
|
{
|
||||||
@@ -532,39 +533,46 @@ int BX_connect_by_number(char *hostn, unsigned short *portnum, int service, int
|
|||||||
#ifndef WINNT
|
#ifndef WINNT
|
||||||
|
|
||||||
#ifdef IPV6
|
#ifdef IPV6
|
||||||
memset(&hints, 0, sizeof hints);
|
|
||||||
hints.ai_family = AF_UNSPEC;
|
hints.ai_family = AF_UNSPEC;
|
||||||
hints.ai_flags = AI_ADDRCONFIG;
|
hints.ai_flags = AI_ADDRCONFIG;
|
||||||
hints.ai_socktype = proto_type;
|
hints.ai_socktype = proto_type;
|
||||||
|
|
||||||
if (!getaddrinfo(hostn, NULL, &hints, &res) && res)
|
if (getaddrinfo(hostn, NULL, &hints, &res_list) != 0)
|
||||||
{
|
|
||||||
close(fd);
|
|
||||||
|
|
||||||
if ((fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) < 0)
|
|
||||||
return -1;
|
|
||||||
set_socket_options (fd);
|
|
||||||
|
|
||||||
memcpy(&server, res->ai_addr, res->ai_addrlen);
|
|
||||||
server_len = res->ai_addrlen;
|
|
||||||
server.sf_port = htons(*portnum);
|
|
||||||
|
|
||||||
memset(&hints, 0, sizeof hints);
|
|
||||||
hints.ai_family = res->ai_family;
|
|
||||||
freeaddrinfo(res);
|
|
||||||
|
|
||||||
if (LocalHostName && !getaddrinfo(LocalHostName, NULL, &hints, &res) && res)
|
|
||||||
{
|
|
||||||
int retval = bind(fd, (struct sockaddr *) res->ai_addr, res->ai_addrlen);
|
|
||||||
freeaddrinfo(res);
|
|
||||||
|
|
||||||
if (retval)
|
|
||||||
return close(fd), -2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return close(fd), -6;
|
return close(fd), -6;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
memcpy(&server, res->ai_addr, res->ai_addrlen);
|
||||||
|
server_len = res->ai_addrlen;
|
||||||
|
server.sf_port = htons(*portnum);
|
||||||
|
|
||||||
|
memset(&hints, 0, sizeof hints);
|
||||||
|
hints.ai_family = res->ai_family;
|
||||||
|
freeaddrinfo(res_list);
|
||||||
|
|
||||||
|
if (LocalHostName && !getaddrinfo(LocalHostName, NULL, &hints, &res) && res)
|
||||||
|
{
|
||||||
|
int retval = bind(fd, (struct sockaddr *) res->ai_addr, res->ai_addrlen);
|
||||||
|
freeaddrinfo(res);
|
||||||
|
|
||||||
|
if (retval)
|
||||||
|
return close(fd), -2;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
if (isdigit((unsigned char)hostn[strlen(hostn)-1]))
|
if (isdigit((unsigned char)hostn[strlen(hostn)-1]))
|
||||||
inet_aton(hostn, (struct in_addr *)&server.sf_addr);
|
inet_aton(hostn, (struct in_addr *)&server.sf_addr);
|
||||||
|
|||||||
Reference in New Issue
Block a user