Dual-family (IPv4+IPv6) support for wget 1.9 Without this patch, IPv6 support completely disables IPv4, since dual-family support was incomplete. Read MODIFICATIONS.ari for details. This patch also adds the configuration option --with-ipv4-default, which will sort resolved addresses so that those with the AF_INET family will be attempted first. Remember to run autoconf in the top-level wget source directory after patching. NOTE: I do not currently have an IPv6-enabled system on hand in order to properly test IPv6 functionality. If wget 1.9 had any problems communicating over IPv6, it is not likely that this patch will have corrected them. Until this functionality is committed into wget, please send any relevant IPv6 problems to me. ari edelkind (10/27/2003) last modified 10/27/2003 diff -ruN --exclude configure wget-1.9.orig/MODIFICATIONS.ari wget-1.9/MODIFICATIONS.ari --- wget-1.9.orig/MODIFICATIONS.ari Wed Dec 31 19:00:00 1969 +++ wget-1.9/MODIFICATIONS.ari Mon Oct 27 04:05:34 2003 @@ -0,0 +1,40 @@ + +- added an ip_addrset structure to host.h, containing an ip_address type and + a family. + +- Changed the address_list structure to use an array of ip_addrset types + instead of ip_address types. + +- Changed usage of ip_address type to ip_addrset type in any location where + it would be useful to have the family for a particular ip address or + connection. Modified all dereferences accordingly, and removed + ip_default_family altogether. + +- added a family option to the sockaddr_len() function in host.c, and the + bindport() function in connect.c. + +- Added --with-ipv4-default option to configure.in. If this option is set, + AF_INET will be used as the default domain, even when ipv6 is enabled. + This configure option defines the macro USE_IPV4_DEFAULT. + +- Changed the --disable-ipv6 comment in configure.in to --enable-ipv6. + Since ipv6 is currently enabled neither by default nor by configure + checks, and --enable-ipv6 must be passed in order to do so, this will make + the option more intuitive. When configure is modified to check for ipv6 + support by default, this comment should be reverted. Be sure to run + autoconf to recreate the configure file. + +- host.c: getaddrinfo functions were conditionally included depending on + whether ENABLE_IPV6 was defined, yet in lookup_host(), they are called + depending on whether HAVE_GETADDRINFO is defined. Switched the relevant + ENABLE_IPV6 conditional define to use HAVE_GETADDRINFO. + +- Added the function address_list_sort_family() to host.c if + USE_IPV4_DEFAULT is defined. When the address list is gathered from name + resolution, any addresses associated with an AF_INET family will be first + in the al->addrsets array. They will therefore be tried before AF_INET6 + types. + +- ftp.c, getftp(): Used conaddr() to initially populate passive_addrset with + RBUF_FD(&con->rbuf), so that the family of the requested connection may be + known to other functions. diff -ruN --exclude configure wget-1.9.orig/configure.in wget-1.9/configure.in --- wget-1.9.orig/configure.in Thu Oct 16 10:27:39 2003 +++ wget-1.9/configure.in Mon Oct 27 00:24:54 2003 @@ -59,6 +59,10 @@ [[ --with-ssl[=SSL-ROOT] link with SSL support [default=auto] --without-ssl disable SSL autodetection]]) +AC_ARG_WITH(ipv4-default, +[ --with-ipv4-default use IPv4 by default when IPv6 is enabled], +[AC_DEFINE(USE_IPV4_DEFAULT)]) + AC_ARG_ENABLE(opie, [ --disable-opie disable support for opie or s/key FTP login], USE_OPIE=$enableval, USE_OPIE=yes) @@ -455,7 +459,7 @@ ipv6= check_for_ipv6=no AC_ARG_ENABLE(ipv6, - AC_HELP_STRING([--disable-ipv6],[disable IPv6 support]), + AC_HELP_STRING([--enable-ipv6],[enable IPv6 support]), [case "${enable_ipv6}" in no) AC_MSG_NOTICE([Disabling IPv6 at user request]) diff -ruN --exclude configure wget-1.9.orig/src/config.h.in wget-1.9/src/config.h.in --- wget-1.9.orig/src/config.h.in Mon Oct 13 10:20:45 2003 +++ wget-1.9/src/config.h.in Mon Oct 27 00:24:54 2003 @@ -272,6 +272,9 @@ /* Define if you want to enable the IPv6 support. */ #undef ENABLE_IPV6 +/* Define if you want to use IPv4 by default when IPv6 is supported. */ +#undef USE_IPV4_DEFAULT + /* Defined to int or size_t on systems without socklen_t. */ #undef socklen_t diff -ruN --exclude configure wget-1.9.orig/src/connect.c wget-1.9/src/connect.c --- wget-1.9.orig/src/connect.c Fri Oct 10 21:39:07 2003 +++ wget-1.9/src/connect.c Mon Oct 27 00:24:54 2003 @@ -69,7 +69,7 @@ static int msock = -1; static struct sockaddr *addr; -static ip_address bind_address; +static ip_addrset bind_address; static int bind_address_resolved; static void @@ -149,17 +149,17 @@ /* Connect to a remote host whose address has been resolved. */ int -connect_to_one (ip_address *addr, unsigned short port, int silent) +connect_to_one (ip_addrset *addrset, unsigned short port, int silent) { wget_sockaddr sa; int sock, save_errno; /* Set port and protocol */ - wget_sockaddr_set_address (&sa, ip_default_family, port, addr); + wget_sockaddr_set_address (&sa, addrset->family, port, &addrset->addr); if (!silent) { - char *pretty_addr = pretty_print_address (addr); + char *pretty_addr = pretty_print_address (&addrset->addr); if (connection_host_name && 0 != strcmp (connection_host_name, pretty_addr)) logprintf (LOG_VERBOSE, _("Connecting to %s[%s]:%hu... "), @@ -170,7 +170,7 @@ } /* Make an internet socket, stream type. */ - sock = socket (ip_default_family, SOCK_STREAM, 0); + sock = socket (addrset->family, SOCK_STREAM, 0); if (sock < 0) goto out; @@ -196,8 +196,9 @@ { /* Bind the client side to the requested address. */ wget_sockaddr bsa; - wget_sockaddr_set_address (&bsa, ip_default_family, 0, &bind_address); - if (bind (sock, &bsa.sa, sockaddr_len ())) + wget_sockaddr_set_address (&bsa, bind_address.family, 0, + &bind_address.addr); + if (bind (sock, &bsa.sa, sockaddr_len (addrset->family))) { CLOSE (sock); sock = -1; @@ -206,7 +207,7 @@ } /* Connect the socket to the remote host. */ - if (connect_with_timeout (sock, &sa.sa, sockaddr_len (), + if (connect_with_timeout (sock, &sa.sa, sockaddr_len (addrset->family), opt.connect_timeout) < 0) { CLOSE (sock); @@ -233,20 +234,20 @@ return sock; } + /* Connect to a remote host whose address has been resolved. */ int connect_to_many (struct address_list *al, unsigned short port, int silent) { - int i, start, end; + int i, start, end, sock; + ip_addrset addrset; address_list_get_bounds (al, &start, &end); for (i = start; i < end; i++) { - ip_address addr; - int sock; - address_list_copy_one (al, i, &addr); + address_list_copy_one (al, i, &addrset); - sock = connect_to_one (&addr, port, silent); + sock = connect_to_one (&addrset, port, silent); if (sock >= 0) /* Success. */ return sock; @@ -298,7 +299,7 @@ internal variable MPORT is set to the value of the ensuing master socket. Call acceptport() to block for and accept a connection. */ uerr_t -bindport (unsigned short *port, int family) +bindport (unsigned short *port, int ip_family) { int optval = 1; wget_sockaddr srv; @@ -306,7 +307,7 @@ msock = -1; - if ((msock = socket (family, SOCK_STREAM, 0)) < 0) + if ((msock = socket (ip_family, SOCK_STREAM, 0)) < 0) return CONSOCKERR; #ifdef SO_REUSEADDR @@ -316,9 +317,9 @@ #endif resolve_bind_address (); - wget_sockaddr_set_address (&srv, ip_default_family, htons (*port), - bind_address_resolved ? &bind_address : NULL); - if (bind (msock, &srv.sa, sockaddr_len ()) < 0) + wget_sockaddr_set_address (&srv, ip_family, htons (*port), + bind_address_resolved ? &bind_address.addr : NULL); + if (bind (msock, &srv.sa, sockaddr_len (ip_family)) < 0) { CLOSE (msock); msock = -1; @@ -327,7 +328,7 @@ DEBUGP (("Master socket fd %d bound.\n", msock)); if (!*port) { - socklen_t sa_len = sockaddr_len (); + socklen_t sa_len = sockaddr_len (ip_family); if (getsockname (msock, &srv.sa, &sa_len) < 0) { CLOSE (msock); @@ -389,7 +390,13 @@ uerr_t acceptport (int *sock) { - socklen_t addrlen = sockaddr_len (); + socklen_t addrlen; + ip_addrset addrset; + + if (!conaddr (msock, &addrset)) + return ACCEPTERR; + + addrlen = sockaddr_len (addrset.family); #ifdef HAVE_SELECT if (select_fd (msock, opt.connect_timeout, 0) <= 0) @@ -417,22 +424,22 @@ /* Return the local IP address associated with the connection on FD. */ int -conaddr (int fd, ip_address *ip) +conaddr (int fd, ip_addrset *ip) { wget_sockaddr mysrv; socklen_t addrlen = sizeof (mysrv); if (getsockname (fd, &mysrv.sa, &addrlen) < 0) return 0; - switch (mysrv.sa.sa_family) + switch (ip->family = mysrv.sa.sa_family) { #ifdef ENABLE_IPV6 case AF_INET6: - memcpy (ip, &mysrv.sin6.sin6_addr, 16); + memcpy (&ip->addr, &mysrv.sin6.sin6_addr, 16); return 1; #endif case AF_INET: - map_ipv4_to_ip ((ip4_address *)&mysrv.sin.sin_addr, ip); + map_ipv4_to_ip ((ip4_address *)&mysrv.sin.sin_addr, &ip->addr); return 1; default: abort (); diff -ruN --exclude configure wget-1.9.orig/src/connect.h wget-1.9/src/connect.h --- wget-1.9.orig/src/connect.h Sat Sep 20 19:12:18 2003 +++ wget-1.9/src/connect.h Mon Oct 27 00:24:54 2003 @@ -34,7 +34,7 @@ /* Function declarations */ -int connect_to_one PARAMS ((ip_address *, unsigned short, int)); +int connect_to_one PARAMS ((ip_addrset *, unsigned short, int)); int connect_to_many PARAMS ((struct address_list *, unsigned short, int)); void set_connection_host_name PARAMS ((const char *)); @@ -43,7 +43,7 @@ uerr_t bindport PARAMS ((unsigned short *, int)); uerr_t acceptport PARAMS ((int *)); void closeport PARAMS ((int)); -int conaddr PARAMS ((int, ip_address *)); +int conaddr PARAMS ((int, ip_addrset *)); int iread PARAMS ((int, char *, int)); int iwrite PARAMS ((int, char *, int)); diff -ruN --exclude configure wget-1.9.orig/src/ftp-basic.c wget-1.9/src/ftp-basic.c --- wget-1.9.orig/src/ftp-basic.c Fri Oct 10 21:39:07 2003 +++ wget-1.9/src/ftp-basic.c Mon Oct 27 00:24:54 2003 @@ -259,23 +259,24 @@ uerr_t err; char *request, *respline; - ip_address in_addr; + ip_addrset in_addrset; unsigned short port; char ipv6 [8 * (4 * 3 + 3) + 8]; char *bytes; + /* Get the address of this side of the connection. */ + if (!conaddr (RBUF_FD (rbuf), &in_addrset)) + /* Huh? This is not BINDERR! */ + return BINDERR; + /* Setting port to 0 lets the system choose a free port. */ port = 0; - err = bindport (&port, ip_default_family); + err = bindport (&port, in_addrset.family); if (err != BINDOK) /* Bind the port. */ return err; - /* Get the address of this side of the connection. */ - if (!conaddr (RBUF_FD (rbuf), &in_addr)) - /* Huh? This is not BINDERR! */ - return BINDERR; - inet_ntop (AF_INET6, &in_addr, ipv6, sizeof (ipv6)); + inet_ntop (AF_INET6, &in_addrset.addr, ipv6, sizeof (ipv6)); /* Construct the argument of EPRT (of the form |2|IPv6.ascii|PORT.ascii|). */ bytes = alloca (3 + strlen (ipv6) + 1 + numdigit (port) + 1 + 1); @@ -318,17 +319,27 @@ char *request, *respline; char bytes[6 * 4 +1]; - ip_address in_addr; + ip_addrset in_addrset; ip4_address in_addr_4; unsigned char *in_addr4_ptr = (unsigned char *)&in_addr_4; int nwritten; unsigned short port; + + + /* Get the address of this side of the connection and convert it + (back) to IPv4. */ + if (!conaddr (RBUF_FD (rbuf), &in_addrset)) + /* Huh? This is not BINDERR! */ + return BINDERR; + if (!map_ip_to_ipv4 (&in_addrset.addr, &in_addr_4)) + return BINDERR; + #ifdef ENABLE_IPV6 /* Only try the Extented Version if we actually use IPv6 */ - if (ip_default_family == AF_INET6) + if (in_addrset.family == AF_INET6) { err = ftp_eprt (rbuf); if (err == FTPOK) @@ -338,18 +349,10 @@ /* Setting port to 0 lets the system choose a free port. */ port = 0; - err = bindport (&port, AF_INET); + err = bindport (&port, in_addrset.family); if (err != BINDOK) return err; - /* Get the address of this side of the connection and convert it - (back) to IPv4. */ - if (!conaddr (RBUF_FD (rbuf), &in_addr)) - /* Huh? This is not BINDERR! */ - return BINDERR; - if (!map_ip_to_ipv4 (&in_addr, &in_addr_4)) - return BINDERR; - /* Construct the argument of PORT (of the form a,b,c,d,e,f). Port is unsigned short so (unsigned) (port & 0xff000) >> 8 is the same like port >> 8 @@ -384,7 +387,7 @@ #ifdef ENABLE_IPV6 uerr_t -ftp_epsv (struct rbuf *rbuf, ip_address *addr, unsigned short *port, +ftp_epsv (struct rbuf *rbuf, ip_addrset *addrset, unsigned short *port, char *typ) { int err; @@ -423,13 +426,13 @@ socklen_t addrlen = sizeof (remote); struct sockaddr_in *ipv4_sock = (struct sockaddr_in *)&remote; getpeername (RBUF_FD (rbuf), (struct sockaddr *)&remote, &addrlen); - switch(remote.sa.sa_family) + switch(addrset->family = remote.sa.sa_family) { case AF_INET6: - memcpy (addr, &remote.sin6.sin6_addr, 16); + memcpy (&addrset->addr, &remote.sin6.sin6_addr, 16); break; case AF_INET: - map_ipv4_to_ip ((ip4_address *)&ipv4_sock->sin_addr, addr); + map_ipv4_to_ip ((ip4_address *)&ipv4_sock->sin_addr, &addrset->addr); break; default: abort(); @@ -446,7 +449,7 @@ transfer. Reads the response from server and parses it. Reads the host and port addresses and returns them. */ uerr_t -ftp_pasv (struct rbuf *rbuf, ip_address *addr, unsigned short *port) +ftp_pasv (struct rbuf *rbuf, ip_addrset *addrset, unsigned short *port) { char *request, *respline, *s; int nwritten, i; @@ -454,12 +457,12 @@ unsigned char addr4[4]; #ifdef ENABLE_IPV6 - if (ip_default_family == AF_INET6) + if (addrset->family == AF_INET6) { - err = ftp_epsv (rbuf, addr, port, "2"); /* try IPv6 with EPSV */ + err = ftp_epsv (rbuf, addrset, port, "2"); /* try IPv6 with EPSV */ if (FTPOK == err) return FTPOK; - err = ftp_epsv (rbuf, addr, port, "1"); /* try IPv4 with EPSV */ + err = ftp_epsv (rbuf, addrset, port, "1"); /* try IPv4 with EPSV */ if (FTPOK == err) return FTPOK; } @@ -507,7 +510,7 @@ } /* Eventually make an IPv4 in IPv6 adress if needed */ - map_ipv4_to_ip ((ip4_address *)addr4, addr); + map_ipv4_to_ip ((ip4_address *)addr4, &addrset->addr); *port=0; for (; ISDIGIT (*s); s++) diff -ruN --exclude configure wget-1.9.orig/src/ftp.c wget-1.9/src/ftp.c --- wget-1.9.orig/src/ftp.c Tue Oct 14 18:52:12 2003 +++ wget-1.9/src/ftp.c Mon Oct 27 00:24:54 2003 @@ -538,11 +538,15 @@ { if (opt.ftp_pasv > 0) { - ip_address passive_addr; + ip_addrset passive_addrset; unsigned short passive_port; if (!opt.server_response) logputs (LOG_VERBOSE, "==> PASV ... "); - err = ftp_pasv (&con->rbuf, &passive_addr, &passive_port); + + if (!conaddr (RBUF_FD (&con->rbuf), &passive_addrset)) + return HOSTERR; + + err = ftp_pasv (&con->rbuf, &passive_addrset, &passive_port); /* FTPRERR, WRITEFAILED, FTPNOPASV, FTPINVPASV */ switch (err) { @@ -579,14 +583,14 @@ } /* switch(err) */ if (err==FTPOK) { - dtsock = connect_to_one (&passive_addr, passive_port, 1); + dtsock = connect_to_one (&passive_addrset, passive_port, 1); if (dtsock < 0) { int save_errno = errno; CLOSE (csock); rbuf_uninitialize (&con->rbuf); logprintf (LOG_VERBOSE, _("couldn't connect to %s:%hu: %s\n"), - pretty_print_address (&passive_addr), passive_port, + pretty_print_address (&passive_addrset.addr), passive_port, strerror (save_errno)); return CONNECT_ERROR (save_errno); } diff -ruN --exclude configure wget-1.9.orig/src/ftp.h wget-1.9/src/ftp.h --- wget-1.9.orig/src/ftp.h Thu Sep 18 09:46:17 2003 +++ wget-1.9/src/ftp.h Mon Oct 27 00:24:54 2003 @@ -49,9 +49,9 @@ uerr_t ftp_response PARAMS ((struct rbuf *, char **)); uerr_t ftp_login PARAMS ((struct rbuf *, const char *, const char *)); uerr_t ftp_port PARAMS ((struct rbuf *)); -uerr_t ftp_pasv PARAMS ((struct rbuf *, ip_address *, unsigned short *)); +uerr_t ftp_pasv PARAMS ((struct rbuf *, ip_addrset *, unsigned short *)); #ifdef ENABLE_IPV6 -uerr_t ftp_epsv PARAMS ((struct rbuf *, ip_address *, unsigned short *, +uerr_t ftp_epsv PARAMS ((struct rbuf *, ip_addrset *, unsigned short *, char *)); #endif uerr_t ftp_type PARAMS ((struct rbuf *, int)); diff -ruN --exclude configure wget-1.9.orig/src/host.c wget-1.9/src/host.c --- wget-1.9.orig/src/host.c Fri Oct 10 22:27:41 2003 +++ wget-1.9/src/host.c Mon Oct 27 00:24:54 2003 @@ -81,11 +81,6 @@ # endif #endif -#ifdef ENABLE_IPV6 -int ip_default_family = AF_INET6; -#else -int ip_default_family = AF_INET; -#endif /* Mapping between known hosts and to lists of their addresses. */ @@ -96,7 +91,7 @@ struct address_list { int count; /* number of adrresses */ - ip_address *addresses; /* pointer to the string of addresses */ + ip_addrset *addrsets; /* pointer to the string of address sets */ int faulty; /* number of addresses known not to work. */ int refcount; /* so we know whether to free it or not. */ @@ -114,10 +109,10 @@ /* Copy address number INDEX to IP_STORE. */ void -address_list_copy_one (struct address_list *al, int index, ip_address *ip_store) +address_list_copy_one (struct address_list *al, int index, ip_addrset *ip_store) { assert (index >= al->faulty && index < al->count); - memcpy (ip_store, al->addresses + index, sizeof (ip_address)); + memcpy (ip_store, al->addrsets + index, sizeof (ip_addrset)); } /* Check whether two address lists have all their IPs in common. */ @@ -129,8 +124,8 @@ return 1; if (al1->count != al2->count) return 0; - return 0 == memcmp (al1->addresses, al2->addresses, - al1->count * sizeof (ip_address)); + return 0 == memcmp (al1->addrsets, al2->addrsets, + al1->count * sizeof (ip_addrset)); } /* Mark the INDEXth element of AL as faulty, so that the next time @@ -153,6 +148,36 @@ al->faulty = 0; } +#ifdef USE_IPV4_DEFAULT +static inline void +address_list_sort_family (struct address_list *al, int family) +{ + int i, j = 0, len; + ip_addrset *copysets; + + len = sizeof(ip_addrset) * al->count; + + if (!(copysets = malloc (len))) return; + + for (i = 0; i < al->count; i++) + { + if (al->addrsets[i].family == family) + address_list_copy_one (al, i, ©sets[j++]); + } + + if (j < al->count) { + for (i = 0; i < al->count; i++) + { + if (al->addrsets[i].family != family) + address_list_copy_one (al, i, ©sets[j++]); + } + } + + memcpy (al->addrsets, copysets, len); + free (copysets); +} +#endif + #ifdef HAVE_GETADDRINFO /** * address_list_from_addrinfo @@ -180,7 +205,7 @@ return NULL; al = xmalloc (sizeof (struct address_list)); - al->addresses = xmalloc (cnt * sizeof (ip_address)); + al->addrsets = xmalloc (cnt * sizeof (ip_addrset)); al->count = cnt; al->faulty = 0; al->refcount = 1; @@ -189,13 +214,15 @@ if (ai->ai_family == AF_INET6) { struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ai->ai_addr; - memcpy (al->addresses + i, &sin6->sin6_addr, 16); + memcpy (&al->addrsets[i].addr, &sin6->sin6_addr, 16); + al->addrsets[i].family = AF_INET6; ++i; } else if (ai->ai_family == AF_INET) { struct sockaddr_in *sin = (struct sockaddr_in *)ai->ai_addr; - map_ipv4_to_ip ((ip4_address *)&sin->sin_addr, al->addresses + i); + map_ipv4_to_ip ((ip4_address *)&sin->sin_addr, &al->addrsets[i].addr); + al->addrsets[i].family = AF_INET; ++i; } assert (i == cnt); @@ -216,11 +243,13 @@ assert (count > 0); al->count = count; al->faulty = 0; - al->addresses = xmalloc (count * sizeof (ip_address)); + al->addrsets = xmalloc (count * sizeof (ip_addrset)); al->refcount = 1; - for (i = 0; i < count; i++) - map_ipv4_to_ip ((ip4_address *)h_addr_list[i], al->addresses + i); + for (i = 0; i < count; i++) { + al->addrsets[i].family = AF_INET; + map_ipv4_to_ip ((ip4_address *)h_addr_list[i], &al->addrsets[i].addr); + } return al; } @@ -230,14 +259,15 @@ address. */ static struct address_list * -address_list_from_single (ip_address *addr) +address_list_from_single (ip_address *addr, int ip_family) { struct address_list *al = xmalloc (sizeof (struct address_list)); al->count = 1; al->faulty = 0; - al->addresses = xmalloc (sizeof (ip_address)); + al->addrsets = xmalloc (sizeof (ip_addrset)); al->refcount = 1; - memcpy (al->addresses, addr, sizeof (ip_address)); + memcpy (&al->addrsets->addr, addr, sizeof (ip_address)); + al->addrsets->family = ip_family; return al; } @@ -245,7 +275,7 @@ static void address_list_delete (struct address_list *al) { - xfree (al->addresses); + xfree (al->addrsets); xfree (al); } @@ -422,12 +452,12 @@ * socklen_t structure length for socket options */ socklen_t -sockaddr_len () +sockaddr_len (int ip_family) { - if (ip_default_family == AF_INET) + if (ip_family == AF_INET) return sizeof (struct sockaddr_in); #ifdef ENABLE_IPV6 - if (ip_default_family == AF_INET6) + if (ip_family == AF_INET6) return sizeof (struct sockaddr_in6); #endif abort(); @@ -474,7 +504,7 @@ /* Versions of gethostbyname and getaddrinfo that support timeout. */ -#ifndef ENABLE_IPV6 +#ifndef HAVE_GETADDRINFO struct ghbnwt_context { const char *host_name; @@ -509,7 +539,7 @@ return ctx.hptr; } -#else /* ENABLE_IPV6 */ +#else /* HAVE_GETADDRINFO */ struct gaiwt_context { const char *node; @@ -548,8 +578,7 @@ } return ctx.exit_code; } - -#endif /* ENABLE_IPV6 */ +#endif /* HAVE_GETADDRINFO */ /* Pretty-print ADDR. When compiled without IPv6, this is the same as inet_ntoa. With IPv6, it either prints an IPv6 address or an IPv4 @@ -591,7 +620,8 @@ int i; debug_logprintf ("Caching %s =>", host); for (i = 0; i < al->count; i++) - debug_logprintf (" %s", pretty_print_address (al->addresses + i)); + debug_logprintf (" %s", + pretty_print_address (&al->addrsets[i].addr)); debug_logprintf ("\n"); } #endif @@ -609,7 +639,7 @@ #ifdef ENABLE_IPV6 if (inet_pton (AF_INET6, host, &addr) > 0) - return address_list_from_single (&addr); + return address_list_from_single (&addr, AF_INET6); #endif addr_ipv4 = (u_int32_t)inet_addr (host); @@ -618,7 +648,7 @@ /* ADDR is defined to be in network byte order, which is what this returns, so we can just copy it to STORE_IP. */ map_ipv4_to_ip ((ip4_address *)&addr_ipv4, &addr); - return address_list_from_single (&addr); + return address_list_from_single (&addr, AF_INET); } if (host_name_addresses_map) @@ -643,11 +673,14 @@ int err; memset (&hints, 0, sizeof (hints)); - if (ip_default_family == AF_INET) - hints.ai_family = AF_INET; - else - hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; + +# if !defined (ENABLE_IPV6) + hints.ai_family = AF_INET; +# else + hints.ai_family = AF_UNSPEC; +# endif + err = getaddrinfo_with_timeout (host, NULL, &hints, &ai, opt.dns_timeout); if (err != 0 || ai == NULL) @@ -681,6 +714,10 @@ } #endif +#ifdef USE_IPV4_DEFAULT + address_list_sort_family (al, AF_INET); +#endif + /* Print the addresses determined by DNS lookup, but no more than three. */ if (!silent) @@ -690,7 +727,7 @@ for (i = 0; i < printmax; i++) { logprintf (LOG_VERBOSE, "%s", - pretty_print_address (al->addresses + i)); + pretty_print_address (&al->addrsets[i].addr)); if (i < printmax - 1) logputs (LOG_VERBOSE, ", "); } diff -ruN --exclude configure wget-1.9.orig/src/host.h wget-1.9/src/host.h --- wget-1.9.orig/src/host.h Fri Oct 10 21:39:07 2003 +++ wget-1.9/src/host.h Mon Oct 27 03:36:52 2003 @@ -73,13 +73,18 @@ unsigned char bytes[MAX_IP_ADDRESS_SIZE]; } ip_address; +typedef struct { + ip_address addr; + int family; +} ip_addrset; + /* Function declarations */ struct address_list *lookup_host PARAMS ((const char *, int)); char *herrmsg PARAMS ((int)); void address_list_get_bounds PARAMS ((struct address_list *, int *, int *)); void address_list_copy_one PARAMS ((struct address_list *, int, - ip_address *)); + ip_addrset *)); int address_list_match_all PARAMS ((struct address_list *, struct address_list *)); void address_list_set_faulty PARAMS ((struct address_list *, int)); @@ -97,11 +102,9 @@ void wget_sockaddr_set_port PARAMS((wget_sockaddr *, unsigned short)); void *wget_sockaddr_get_addr PARAMS((wget_sockaddr *)); unsigned short wget_sockaddr_get_port PARAMS((const wget_sockaddr *)); -socklen_t sockaddr_len PARAMS(()); +socklen_t sockaddr_len PARAMS((int)); void map_ipv4_to_ip PARAMS((ip4_address *, ip_address *)); int map_ip_to_ipv4 PARAMS((ip_address *, ip4_address *)); -extern int ip_default_family; /* defined in host.c */ - #endif /* HOST_H */