summaryrefslogtreecommitdiff
blob: 6f0849e4cbd8cdc6b26b3bd619e785e297b12f54 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
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, &copysets[j++]);
+  }
+
+  if (j < al->count) {
+    for (i = 0; i < al->count; i++)
+    {
+      if (al->addrsets[i].family != family)
+        address_list_copy_one (al, i, &copysets[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 */