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