diff --git a/Changelog b/Changelog index e4f6f21..0400d6b 100644 --- a/Changelog +++ b/Changelog @@ -1,5 +1,8 @@ [Changes 1.2c01] +* Use AI_ADDRCONFIG flag to improve server address selection when client + is built for IPv6 but we don't have an IPv6 address. (caf) + * Enable SSL support by default, if OpenSSL is present at build time. (caf) * Fix leak and potential crash in lame_resolv() using IPv6. (caf, snadge) @@ -7,8 +10,8 @@ * Apply patch from snadge defining BIND_4_COMPAT on OpenBSD, to allow /nslookup to build. (caf) -* Fix known problem with IPv6 on FreeBSD and enable IPv6 on all supporting - platforms. Thanks to brabes, snadge and packet. (caf) +* Fix problem connecting to IPv4 when IPv6 enabled on FreeBSD and enable + IPv6 on all supporting platforms. Thanks to brabes, snadge and packet. (caf) * Improve connect() error handling. (caf) diff --git a/include/irc.h b/include/irc.h index 2863ff0..d4f6fcc 100644 --- a/include/irc.h +++ b/include/irc.h @@ -99,6 +99,10 @@ extern char thing_star[4]; #include #endif +#ifndef AI_ADDRCONFIG +#define AI_ADDRCONFIG 0 +#endif + #include "bsdglob.h" #include "irc_std.h" diff --git a/source/network.c b/source/network.c index 2ffaa59..e71b024 100644 --- a/source/network.c +++ b/source/network.c @@ -506,7 +506,6 @@ int BX_connect_by_number(char *hostn, unsigned short *portnum, int service, int #endif #ifdef IPV6 struct addrinfo hints, *res; - struct sockaddr_foobar *sf = NULL; #else struct sockaddr_in localaddr; if (LocalHostName) @@ -524,39 +523,34 @@ int BX_connect_by_number(char *hostn, unsigned short *portnum, int service, int #ifndef WINNT #ifdef IPV6 - memset(&hints, 0, sizeof(hints)); + 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) { - sf = (struct sockaddr_foobar*) res->ai_addr; - close(fd); - proto_type = (protocol == PROTOCOL_TCP) ? SOCK_STREAM : SOCK_DGRAM; - if ((fd = socket(sf->sf_family, proto_type, 0)) < 0) + if ((fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) < 0) return -1; set_socket_options (fd); - if ((server.sf_family = sf->sf_family) == AF_INET) - { - memcpy(&server.sf_addr, &sf->sf_addr, sizeof(struct in_addr)); - server_len = sizeof server.sins.sin; - } - else - { - memcpy(&server.sf_addr6, &sf->sf_addr6, sizeof(struct in6_addr)); - server_len = sizeof server.sins.sin6; - } + memcpy(&server, res->ai_addr, res->ai_addrlen); + server_len = res->ai_addrlen; server.sf_port = htons(*portnum); - memset(&hints, 0, sizeof(struct addrinfo)); + memset(&hints, 0, sizeof hints); hints.ai_family = res->ai_family; freeaddrinfo(res); if (LocalHostName && !getaddrinfo(LocalHostName, NULL, &hints, &res) && res) { - if (bind(fd, (struct sockaddr *) res->ai_addr, res->ai_addrlen)) - return close(fd), -2; + int retval = bind(fd, (struct sockaddr *) res->ai_addr, res->ai_addrlen); freeaddrinfo(res); + + if (retval) + return close(fd), -2; } } else