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