]> sjero.net Git - wget/blob - src/host.c
[svn] Remove unreachable "break" statements.
[wget] / src / host.c
1 /* Host name resolution and matching.
2    Copyright (C) 1995, 1996, 1997, 2000, 2001 Free Software Foundation, Inc.
3
4 This file is part of GNU Wget.
5
6 GNU Wget is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10
11 GNU Wget is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with Wget; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
20 In addition, as a special exception, the Free Software Foundation
21 gives permission to link the code of its release of Wget with the
22 OpenSSL project's "OpenSSL" library (or with modified versions of it
23 that use the same license as the "OpenSSL" library), and distribute
24 the linked executables.  You must obey the GNU General Public License
25 in all respects for all of the code used other than "OpenSSL".  If you
26 modify this file, you may extend this exception to your version of the
27 file, but you are not obligated to do so.  If you do not wish to do
28 so, delete this exception statement from your version.  */
29
30 #include <config.h>
31
32 #ifndef WINDOWS
33 #include <netdb.h>
34 #endif
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #ifdef HAVE_STRING_H
39 # include <string.h>
40 #else
41 # include <strings.h>
42 #endif
43 #include <assert.h>
44 #include <sys/types.h>
45
46 #ifndef WINDOWS
47 # include <sys/socket.h>
48 # include <netinet/in.h>
49 # ifndef __BEOS__
50 #  include <arpa/inet.h>
51 # endif
52 # include <netdb.h>
53 # define SET_H_ERRNO(err) ((void)(h_errno = (err)))
54 #else  /* WINDOWS */
55 # define SET_H_ERRNO(err) WSASetLastError (err)
56 #endif /* WINDOWS */
57
58 #include <errno.h>
59
60 #include "wget.h"
61 #include "utils.h"
62 #include "host.h"
63 #include "url.h"
64 #include "hash.h"
65 #include "connect.h"            /* for socket_has_inet6 */
66
67 #ifndef errno
68 extern int errno;
69 #endif
70
71 #ifndef h_errno
72 # ifndef __CYGWIN__
73 extern int h_errno;
74 # endif
75 #endif
76
77 #ifndef NO_ADDRESS
78 # define NO_ADDRESS NO_DATA
79 #endif
80
81 /* Lists of IP addresses that result from running DNS queries.  See
82    lookup_host for details.  */
83
84 struct address_list {
85   int count;                    /* number of adrresses */
86   ip_address *addresses;        /* pointer to the string of addresses */
87
88   int faulty;                   /* number of addresses known not to work. */
89   int connected;                /* whether we were able to connect to
90                                    one of the addresses in the list,
91                                    at least once. */
92
93   int refcount;                 /* reference count; when it drops to
94                                    0, the entry is freed. */
95 };
96
97 /* Get the bounds of the address list.  */
98
99 void
100 address_list_get_bounds (const struct address_list *al, int *start, int *end)
101 {
102   *start = al->faulty;
103   *end   = al->count;
104 }
105
106 /* Return a pointer to the address at position POS.  */
107
108 const ip_address *
109 address_list_address_at (const struct address_list *al, int pos)
110 {
111   assert (pos >= al->faulty && pos < al->count);
112   return al->addresses + pos;
113 }
114
115 /* Return non-zero if AL contains IP, zero otherwise.  */
116
117 int
118 address_list_contains (const struct address_list *al, const ip_address *ip)
119 {
120   int i;
121   switch (ip->type)
122     {
123     case IPV4_ADDRESS:
124       for (i = 0; i < al->count; i++)
125         {
126           ip_address *cur = al->addresses + i;
127           if (cur->type == IPV4_ADDRESS
128               && (ADDRESS_IPV4_IN_ADDR (cur).s_addr
129                   ==
130                   ADDRESS_IPV4_IN_ADDR (ip).s_addr))
131             return 1;
132         }
133       return 0;
134 #ifdef ENABLE_IPV6
135     case IPV6_ADDRESS:
136       for (i = 0; i < al->count; i++)
137         {
138           ip_address *cur = al->addresses + i;
139           if (cur->type == IPV6_ADDRESS
140 #ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
141               && ADDRESS_IPV6_SCOPE (cur) == ADDRESS_IPV6_SCOPE (ip)
142 #endif
143               && IN6_ARE_ADDR_EQUAL (&ADDRESS_IPV6_IN6_ADDR (cur),
144                                      &ADDRESS_IPV6_IN6_ADDR (ip)))
145             return 1;
146         }
147       return 0;
148 #endif /* ENABLE_IPV6 */
149     default:
150       abort ();
151     }
152 }
153
154 /* Mark the INDEXth element of AL as faulty, so that the next time
155    this address list is used, the faulty element will be skipped.  */
156
157 void
158 address_list_set_faulty (struct address_list *al, int index)
159 {
160   /* We assume that the address list is traversed in order, so that a
161      "faulty" attempt is always preceded with all-faulty addresses,
162      and this is how Wget uses it.  */
163   assert (index == al->faulty);
164
165   ++al->faulty;
166   if (al->faulty >= al->count)
167     /* All addresses have been proven faulty.  Since there's not much
168        sense in returning the user an empty address list the next
169        time, we'll rather make them all clean, so that they can be
170        retried anew.  */
171     al->faulty = 0;
172 }
173
174 /* Set the "connected" flag to true.  This flag used by connect.c to
175    see if the host perhaps needs to be resolved again.  */
176
177 void
178 address_list_set_connected (struct address_list *al)
179 {
180   al->connected = 1;
181 }
182
183 /* Return the value of the "connected" flag. */
184
185 int
186 address_list_connected_p (const struct address_list *al)
187 {
188   return al->connected;
189 }
190
191 #ifdef ENABLE_IPV6
192
193 /* Create an address_list from the addresses in the given struct
194    addrinfo.  */
195
196 static struct address_list *
197 address_list_from_addrinfo (const struct addrinfo *ai)
198 {
199   struct address_list *al;
200   const struct addrinfo *ptr;
201   int cnt;
202   ip_address *ip;
203
204   cnt = 0;
205   for (ptr = ai; ptr != NULL ; ptr = ptr->ai_next)
206     if (ptr->ai_family == AF_INET || ptr->ai_family == AF_INET6)
207       ++cnt;
208   if (cnt == 0)
209     return NULL;
210
211   al = xnew0 (struct address_list);
212   al->addresses = xnew_array (ip_address, cnt);
213   al->count     = cnt;
214   al->refcount  = 1;
215
216   ip = al->addresses;
217   for (ptr = ai; ptr != NULL; ptr = ptr->ai_next)
218     if (ptr->ai_family == AF_INET6) 
219       {
220         const struct sockaddr_in6 *sin6 =
221           (const struct sockaddr_in6 *)ptr->ai_addr;
222         ip->type = IPV6_ADDRESS;
223         ADDRESS_IPV6_IN6_ADDR (ip) = sin6->sin6_addr;
224 #ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
225         ADDRESS_IPV6_SCOPE (ip) = sin6->sin6_scope_id;
226 #endif
227         ++ip;
228       } 
229     else if (ptr->ai_family == AF_INET)
230       {
231         const struct sockaddr_in *sin =
232           (const struct sockaddr_in *)ptr->ai_addr;
233         ip->type = IPV4_ADDRESS;
234         ADDRESS_IPV4_IN_ADDR (ip) = sin->sin_addr;
235         ++ip;
236       }
237   assert (ip - al->addresses == cnt);
238   return al;
239 }
240
241 #define IS_IPV4(addr) (((const ip_address *) addr)->type == IPV4_ADDRESS)
242
243 /* Compare two IP addresses by type, giving preference to the IPv4
244    address (sorting it first).  In other words, return -1 if ADDR1 is
245    IPv4 and ADDR2 is IPv6, +1 if ADDR1 is IPv6 and ADDR2 is IPv4, and
246    0 otherwise.
247
248    This is intended to be used as the comparator arg to a qsort-like
249    sorting function, which is why it accepts generic pointers.  */
250
251 static int
252 cmp_prefer_ipv4 (const void *addr1, const void *addr2)
253 {
254   return !IS_IPV4 (addr1) - !IS_IPV4 (addr2);
255 }
256
257 #define IS_IPV6(addr) (((const ip_address *) addr)->type == IPV6_ADDRESS)
258
259 /* Like the above, but give preference to the IPv6 address.  */
260
261 static int
262 cmp_prefer_ipv6 (const void *addr1, const void *addr2)
263 {
264   return !IS_IPV6 (addr1) - !IS_IPV6 (addr2);
265 }
266
267 #else  /* not ENABLE_IPV6 */
268
269 /* Create an address_list from a NULL-terminated vector of IPv4
270    addresses.  This kind of vector is returned by gethostbyname.  */
271
272 static struct address_list *
273 address_list_from_ipv4_addresses (char **vec)
274 {
275   int count, i;
276   struct address_list *al = xnew0 (struct address_list);
277
278   count = 0;
279   while (vec[count])
280     ++count;
281   assert (count > 0);
282
283   al->addresses = xnew_array (ip_address, count);
284   al->count     = count;
285   al->refcount  = 1;
286
287   for (i = 0; i < count; i++)
288     {
289       ip_address *ip = &al->addresses[i];
290       ip->type = IPV4_ADDRESS;
291       memcpy (ADDRESS_IPV4_DATA (ip), vec[i], 4);
292     }
293
294   return al;
295 }
296
297 #endif /* not ENABLE_IPV6 */
298
299 static void
300 address_list_delete (struct address_list *al)
301 {
302   xfree (al->addresses);
303   xfree (al);
304 }
305
306 /* Mark the address list as being no longer in use.  This will reduce
307    its reference count which will cause the list to be freed when the
308    count reaches 0.  */
309
310 void
311 address_list_release (struct address_list *al)
312 {
313   --al->refcount;
314   DEBUGP (("Releasing %p (new refcount %d).\n", al, al->refcount));
315   if (al->refcount <= 0)
316     {
317       DEBUGP (("Deleting unused %p.\n", al));
318       address_list_delete (al);
319     }
320 }
321 \f
322 /* Versions of gethostbyname and getaddrinfo that support timeout. */
323
324 #ifndef ENABLE_IPV6
325
326 struct ghbnwt_context {
327   const char *host_name;
328   struct hostent *hptr;
329 };
330
331 static void
332 gethostbyname_with_timeout_callback (void *arg)
333 {
334   struct ghbnwt_context *ctx = (struct ghbnwt_context *)arg;
335   ctx->hptr = gethostbyname (ctx->host_name);
336 }
337
338 /* Just like gethostbyname, except it times out after TIMEOUT seconds.
339    In case of timeout, NULL is returned and errno is set to ETIMEDOUT.
340    The function makes sure that when NULL is returned for reasons
341    other than timeout, errno is reset.  */
342
343 static struct hostent *
344 gethostbyname_with_timeout (const char *host_name, double timeout)
345 {
346   struct ghbnwt_context ctx;
347   ctx.host_name = host_name;
348   if (run_with_timeout (timeout, gethostbyname_with_timeout_callback, &ctx))
349     {
350       SET_H_ERRNO (HOST_NOT_FOUND);
351       errno = ETIMEDOUT;
352       return NULL;
353     }
354   if (!ctx.hptr)
355     errno = 0;
356   return ctx.hptr;
357 }
358
359 /* Print error messages for host errors.  */
360 static char *
361 host_errstr (int error)
362 {
363   /* Can't use switch since some of these constants can be equal,
364      which makes the compiler complain about duplicate case
365      values.  */
366   if (error == HOST_NOT_FOUND
367       || error == NO_RECOVERY
368       || error == NO_DATA
369       || error == NO_ADDRESS)
370     return _("Unknown host");
371   else if (error == TRY_AGAIN)
372     /* Message modeled after what gai_strerror returns in similar
373        circumstances.  */
374     return _("Temporary failure in name resolution");
375   else
376     return _("Unknown error");
377 }
378
379 #else  /* ENABLE_IPV6 */
380
381 struct gaiwt_context {
382   const char *node;
383   const char *service;
384   const struct addrinfo *hints;
385   struct addrinfo **res;
386   int exit_code;
387 };
388
389 static void
390 getaddrinfo_with_timeout_callback (void *arg)
391 {
392   struct gaiwt_context *ctx = (struct gaiwt_context *)arg;
393   ctx->exit_code = getaddrinfo (ctx->node, ctx->service, ctx->hints, ctx->res);
394 }
395
396 /* Just like getaddrinfo, except it times out after TIMEOUT seconds.
397    In case of timeout, the EAI_SYSTEM error code is returned and errno
398    is set to ETIMEDOUT.  */
399
400 static int
401 getaddrinfo_with_timeout (const char *node, const char *service,
402                           const struct addrinfo *hints, struct addrinfo **res,
403                           double timeout)
404 {
405   struct gaiwt_context ctx;
406   ctx.node = node;
407   ctx.service = service;
408   ctx.hints = hints;
409   ctx.res = res;
410
411   if (run_with_timeout (timeout, getaddrinfo_with_timeout_callback, &ctx))
412     {
413       errno = ETIMEDOUT;
414       return EAI_SYSTEM;
415     }
416   return ctx.exit_code;
417 }
418
419 #endif /* ENABLE_IPV6 */
420 \f
421 /* Pretty-print ADDR.  When compiled without IPv6, this is the same as
422    inet_ntoa.  With IPv6, it either prints an IPv6 address or an IPv4
423    address.  */
424
425 const char *
426 pretty_print_address (const ip_address *addr)
427 {
428   switch (addr->type) 
429     {
430     case IPV4_ADDRESS:
431       return inet_ntoa (ADDRESS_IPV4_IN_ADDR (addr));
432 #ifdef ENABLE_IPV6
433     case IPV6_ADDRESS:
434       {
435         static char buf[128];
436         inet_ntop (AF_INET6, &ADDRESS_IPV6_IN6_ADDR (addr), buf, sizeof (buf));
437 #if 0
438 #ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
439         {
440           /* append "%SCOPE_ID" for all ?non-global? addresses */
441           char *p = buf + strlen (buf);
442           *p++ = '%';
443           number_to_string (p, ADDRESS_IPV6_SCOPE (addr));
444         }
445 #endif
446 #endif
447         buf[sizeof (buf) - 1] = '\0';
448         return buf;
449       }
450 #endif
451     }
452   abort ();
453 }
454
455 /* The following two functions were adapted from glibc. */
456
457 static int
458 is_valid_ipv4_address (const char *str, const char *end)
459 {
460   int saw_digit = 0;
461   int octets = 0;
462   int val = 0;
463
464   while (str < end)
465     {
466       int ch = *str++;
467
468       if (ch >= '0' && ch <= '9')
469         {
470           val = val * 10 + (ch - '0');
471
472           if (val > 255)
473             return 0;
474           if (saw_digit == 0)
475             {
476               if (++octets > 4)
477                 return 0;
478               saw_digit = 1;
479             }
480         }
481       else if (ch == '.' && saw_digit == 1)
482         {
483           if (octets == 4)
484             return 0;
485           val = 0;
486           saw_digit = 0;
487         }
488       else
489         return 0;
490     }
491   if (octets < 4)
492     return 0;
493   
494   return 1;
495 }
496
497 int
498 is_valid_ipv6_address (const char *str, const char *end)
499 {
500   /* Use lower-case for these to avoid clash with system headers.  */
501   enum {
502     ns_inaddrsz  = 4,
503     ns_in6addrsz = 16,
504     ns_int16sz   = 2
505   };
506
507   const char *curtok;
508   int tp;
509   const char *colonp;
510   int saw_xdigit;
511   unsigned int val;
512
513   tp = 0;
514   colonp = NULL;
515
516   if (str == end)
517     return 0;
518   
519   /* Leading :: requires some special handling. */
520   if (*str == ':')
521     {
522       ++str;
523       if (str == end || *str != ':')
524         return 0;
525     }
526
527   curtok = str;
528   saw_xdigit = 0;
529   val = 0;
530
531   while (str < end)
532     {
533       int ch = *str++;
534
535       /* if ch is a number, add it to val. */
536       if (ISXDIGIT (ch))
537         {
538           val <<= 4;
539           val |= XDIGIT_TO_NUM (ch);
540           if (val > 0xffff)
541             return 0;
542           saw_xdigit = 1;
543           continue;
544         }
545
546       /* if ch is a colon ... */
547       if (ch == ':')
548         {
549           curtok = str;
550           if (saw_xdigit == 0)
551             {
552               if (colonp != NULL)
553                 return 0;
554               colonp = str + tp;
555               continue;
556             }
557           else if (str == end)
558             return 0;
559           if (tp > ns_in6addrsz - ns_int16sz)
560             return 0;
561           tp += ns_int16sz;
562           saw_xdigit = 0;
563           val = 0;
564           continue;
565         }
566
567       /* if ch is a dot ... */
568       if (ch == '.' && (tp <= ns_in6addrsz - ns_inaddrsz)
569           && is_valid_ipv4_address (curtok, end) == 1)
570         {
571           tp += ns_inaddrsz;
572           saw_xdigit = 0;
573           break;
574         }
575     
576       return 0;
577     }
578
579   if (saw_xdigit == 1)
580     {
581       if (tp > ns_in6addrsz - ns_int16sz) 
582         return 0;
583       tp += ns_int16sz;
584     }
585
586   if (colonp != NULL)
587     {
588       if (tp == ns_in6addrsz) 
589         return 0;
590       tp = ns_in6addrsz;
591     }
592
593   if (tp != ns_in6addrsz)
594     return 0;
595
596   return 1;
597 }
598 \f
599 /* Simple host cache, used by lookup_host to speed up resolving.  The
600    cache doesn't handle TTL because Wget is a fairly short-lived
601    application.  Refreshing is attempted when connect fails, though --
602    see connect_to_host.  */
603
604 /* Mapping between known hosts and to lists of their addresses. */
605 static struct hash_table *host_name_addresses_map;
606
607
608 /* Return the host's resolved addresses from the cache, if
609    available.  */
610
611 static struct address_list *
612 cache_query (const char *host)
613 {
614   struct address_list *al;
615   if (!host_name_addresses_map)
616     return NULL;
617   al = hash_table_get (host_name_addresses_map, host);
618   if (al)
619     {
620       DEBUGP (("Found %s in host_name_addresses_map (%p)\n", host, al));
621       ++al->refcount;
622       return al;
623     }
624   return NULL;
625 }
626
627 /* Cache the DNS lookup of HOST.  Subsequent invocations of
628    lookup_host will return the cached value.  */
629
630 static void
631 cache_store (const char *host, struct address_list *al)
632 {
633   if (!host_name_addresses_map)
634     host_name_addresses_map = make_nocase_string_hash_table (0);
635
636   ++al->refcount;
637   hash_table_put (host_name_addresses_map, xstrdup_lower (host), al);
638
639 #ifdef ENABLE_DEBUG
640   if (opt.debug)
641     {
642       int i;
643       debug_logprintf ("Caching %s =>", host);
644       for (i = 0; i < al->count; i++)
645         debug_logprintf (" %s", pretty_print_address (al->addresses + i));
646       debug_logprintf ("\n");
647     }
648 #endif
649 }
650
651 /* Remove HOST from the DNS cache.  Does nothing is HOST is not in
652    the cache.  */
653
654 static void
655 cache_remove (const char *host)
656 {
657   struct address_list *al;
658   if (!host_name_addresses_map)
659     return;
660   al = hash_table_get (host_name_addresses_map, host);
661   if (al)
662     {
663       address_list_release (al);
664       hash_table_remove (host_name_addresses_map, host);
665     }
666 }
667 \f
668 /* Look up HOST in DNS and return a list of IP addresses.
669
670    This function caches its result so that, if the same host is passed
671    the second time, the addresses are returned without DNS lookup.
672    (Use LH_REFRESH to force lookup, or set opt.dns_cache to 0 to
673    globally disable caching.)
674
675    The order of the returned addresses is affected by the setting of
676    opt.prefer_family: if it is set to prefer_ipv4, IPv4 addresses are
677    placed at the beginning; if it is prefer_ipv6, IPv6 ones are placed
678    at the beginning; otherwise, the order is left intact.  The
679    relative order of addresses with the same family is left
680    undisturbed in either case.
681
682    FLAGS can be a combination of:
683      LH_SILENT  - don't print the "resolving ... done" messages.
684      LH_BIND    - resolve addresses for use with bind, which under
685                   IPv6 means to use AI_PASSIVE flag to getaddrinfo.
686                   Passive lookups are not cached under IPv6.
687      LH_REFRESH - if HOST is cached, remove the entry from the cache
688                   and resolve it anew.  */
689
690 struct address_list *
691 lookup_host (const char *host, int flags)
692 {
693   struct address_list *al;
694   int silent = flags & LH_SILENT;
695   int use_cache;
696   int numeric_address = 0;
697   double timeout = opt.dns_timeout;
698
699 #ifndef ENABLE_IPV6
700   /* If we're not using getaddrinfo, first check if HOST specifies a
701      numeric IPv4 address.  Some implementations of gethostbyname
702      (e.g. the Ultrix one and possibly Winsock) don't accept
703      dotted-decimal IPv4 addresses.  */
704   {
705     uint32_t addr_ipv4 = (uint32_t)inet_addr (host);
706     if (addr_ipv4 != (uint32_t) -1)
707       {
708         /* No need to cache host->addr relation, just return the
709            address.  */
710         char *vec[2];
711         vec[0] = (char *)&addr_ipv4;
712         vec[1] = NULL;
713         return address_list_from_ipv4_addresses (vec);
714       }
715   }
716 #else  /* ENABLE_IPV6 */
717   /* If we're using getaddrinfo, at least check whether the address is
718      already numeric, in which case there is no need to print the
719      "Resolving..." output.  (This comes at no additional cost since
720      the is_valid_ipv*_address are already required for
721      url_parse.)  */
722   {
723     const char *end = host + strlen (host);
724     if (is_valid_ipv4_address (host, end) || is_valid_ipv6_address (host, end))
725       numeric_address = 1;
726   }
727 #endif
728
729   /* Cache is normally on, but can be turned off with --no-dns-cache.
730      Don't cache passive lookups under IPv6.  */
731   use_cache = opt.dns_cache;
732 #ifdef ENABLE_IPV6
733   if ((flags & LH_BIND) || numeric_address)
734     use_cache = 0;
735 #endif
736
737   /* Try to find the host in the cache so we don't need to talk to the
738      resolver.  If LH_REFRESH is requested, remove HOST from the cache
739      instead.  */
740   if (use_cache)
741     {
742       if (!(flags & LH_REFRESH))
743         {
744           al = cache_query (host);
745           if (al)
746             return al;
747         }
748       else
749         cache_remove (host);
750     }
751
752   /* No luck with the cache; resolve HOST. */
753
754   if (!silent && !numeric_address)
755     logprintf (LOG_VERBOSE, _("Resolving %s... "), escnonprint (host));
756
757 #ifdef ENABLE_IPV6
758   {
759     int err;
760     struct addrinfo hints, *res;
761
762     xzero (hints);
763     hints.ai_socktype = SOCK_STREAM;
764     if (opt.ipv4_only)
765       hints.ai_family = AF_INET;
766     else if (opt.ipv6_only)
767       hints.ai_family = AF_INET6;
768     else
769       {
770         hints.ai_family = AF_UNSPEC;
771 #ifdef AI_ADDRCONFIG
772         hints.ai_flags |= AI_ADDRCONFIG;
773 #else
774         /* On systems without AI_ADDRCONFIG, emulate it by manually
775            checking whether the system supports IPv6 sockets.  */
776         if (!socket_has_inet6 ())
777           hints.ai_family = AF_INET;
778 #endif
779       }
780     if (flags & LH_BIND)
781       hints.ai_flags |= AI_PASSIVE;
782
783 #ifdef AI_NUMERICHOST
784     if (numeric_address)
785       {
786         /* Where available, the AI_NUMERICHOST hint can prevent costly
787            access to DNS servers.  */
788         hints.ai_flags |= AI_NUMERICHOST;
789         timeout = 0;            /* no timeout needed when "resolving"
790                                    numeric hosts -- avoid setting up
791                                    signal handlers and such. */
792       }
793 #endif
794
795     err = getaddrinfo_with_timeout (host, NULL, &hints, &res, timeout);
796     if (err != 0 || res == NULL)
797       {
798         if (!silent)
799           logprintf (LOG_VERBOSE, _("failed: %s.\n"),
800                      err != EAI_SYSTEM ? gai_strerror (err) : strerror (errno));
801         return NULL;
802       }
803     al = address_list_from_addrinfo (res);
804     freeaddrinfo (res);
805     if (!al)
806       {
807         logprintf (LOG_VERBOSE,
808                    _("failed: No IPv4/IPv6 addresses for host.\n"));
809         return NULL;
810       }
811
812     /* Reorder addresses so that IPv4 ones (or IPv6 ones, as per
813        --prefer-family) come first.  Sorting is stable so the order of
814        the addresses with the same family is undisturbed.  */
815     if (al->count > 1 && opt.prefer_family != prefer_none)
816       stable_sort (al->addresses, al->count, sizeof (ip_address),
817                    opt.prefer_family == prefer_ipv4
818                    ? cmp_prefer_ipv4 : cmp_prefer_ipv6);
819   }
820 #else  /* not ENABLE_IPV6 */
821   {
822     struct hostent *hptr = gethostbyname_with_timeout (host, timeout);
823     if (!hptr)
824       {
825         if (!silent)
826           {
827             if (errno != ETIMEDOUT)
828               logprintf (LOG_VERBOSE, _("failed: %s.\n"),
829                          host_errstr (h_errno));
830             else
831               logputs (LOG_VERBOSE, _("failed: timed out.\n"));
832           }
833         return NULL;
834       }
835     /* Do older systems have h_addr_list?  */
836     al = address_list_from_ipv4_addresses (hptr->h_addr_list);
837   }
838 #endif /* not ENABLE_IPV6 */
839
840   /* Print the addresses determined by DNS lookup, but no more than
841      three.  */
842   if (!silent && !numeric_address)
843     {
844       int i;
845       int printmax = al->count <= 3 ? al->count : 3;
846       for (i = 0; i < printmax; i++)
847         {
848           logprintf (LOG_VERBOSE, "%s",
849                      pretty_print_address (al->addresses + i));
850           if (i < printmax - 1)
851             logputs (LOG_VERBOSE, ", ");
852         }
853       if (printmax != al->count)
854         logputs (LOG_VERBOSE, ", ...");
855       logputs (LOG_VERBOSE, "\n");
856     }
857
858   /* Cache the lookup information. */
859   if (use_cache)
860     cache_store (host, al);
861
862   return al;
863 }
864 \f
865 /* Determine whether a URL is acceptable to be followed, according to
866    a list of domains to accept.  */
867 int
868 accept_domain (struct url *u)
869 {
870   assert (u->host != NULL);
871   if (opt.domains)
872     {
873       if (!sufmatch ((const char **)opt.domains, u->host))
874         return 0;
875     }
876   if (opt.exclude_domains)
877     {
878       if (sufmatch ((const char **)opt.exclude_domains, u->host))
879         return 0;
880     }
881   return 1;
882 }
883
884 /* Check whether WHAT is matched in LIST, each element of LIST being a
885    pattern to match WHAT against, using backward matching (see
886    match_backwards() in utils.c).
887
888    If an element of LIST matched, 1 is returned, 0 otherwise.  */
889 int
890 sufmatch (const char **list, const char *what)
891 {
892   int i, j, k, lw;
893
894   lw = strlen (what);
895   for (i = 0; list[i]; i++)
896     {
897       for (j = strlen (list[i]), k = lw; j >= 0 && k >= 0; j--, k--)
898         if (TOLOWER (list[i][j]) != TOLOWER (what[k]))
899           break;
900       /* The domain must be first to reach to beginning.  */
901       if (j == -1)
902         return 1;
903     }
904   return 0;
905 }
906
907 static int
908 host_cleanup_mapper (void *key, void *value, void *arg_ignored)
909 {
910   struct address_list *al;
911
912   xfree (key);                  /* host */
913
914   al = (struct address_list *)value;
915   assert (al->refcount == 1);
916   address_list_delete (al);
917
918   return 0;
919 }
920
921 void
922 host_cleanup (void)
923 {
924   if (host_name_addresses_map)
925     {
926       hash_table_map (host_name_addresses_map, host_cleanup_mapper, NULL);
927       hash_table_destroy (host_name_addresses_map);
928       host_name_addresses_map = NULL;
929     }
930 }