diff --git a/Changelog b/Changelog index 1db6adb..5687f22 100644 --- a/Changelog +++ b/Changelog @@ -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) diff --git a/source/network.c b/source/network.c index 51c5427..182d8c2 100644 --- a/source/network.c +++ b/source/network.c @@ -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,39 +533,46 @@ 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 ((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 + if (getaddrinfo(hostn, NULL, &hints, &res_list) != 0) 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 if (isdigit((unsigned char)hostn[strlen(hostn)-1])) inet_aton(hostn, (struct in_addr *)&server.sf_addr);