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