]> sjero.net Git - wget/blob - src/host.c
[svn] Don't take the address of in.s_addr because that doesn't work on some
[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 #ifdef WINDOWS
47 # include <winsock.h>
48 # define SET_H_ERRNO(err) WSASetLastError (err)
49 #else
50 # include <sys/socket.h>
51 # include <netinet/in.h>
52 # ifndef __BEOS__
53 #  include <arpa/inet.h>
54 # endif
55 # include <netdb.h>
56 # define SET_H_ERRNO(err) ((void)(h_errno = (err)))
57 #endif /* WINDOWS */
58
59 #ifndef NO_ADDRESS
60 #define NO_ADDRESS NO_DATA
61 #endif
62
63 #ifdef HAVE_SYS_UTSNAME_H
64 # include <sys/utsname.h>
65 #endif
66 #include <errno.h>
67
68 #include "wget.h"
69 #include "utils.h"
70 #include "host.h"
71 #include "url.h"
72 #include "hash.h"
73
74 #ifndef errno
75 extern int errno;
76 #endif
77
78 #ifndef h_errno
79 # ifndef __CYGWIN__
80 extern int h_errno;
81 # endif
82 #endif
83
84 /* Mapping between known hosts and to lists of their addresses. */
85
86 static struct hash_table *host_name_addresses_map;
87 \f
88 /* Lists of addresses.  This should eventually be extended to handle
89    IPv6.  */
90
91 struct address_list {
92   int count;                    /* number of adrresses */
93   ip_address *addresses;        /* pointer to the string of addresses */
94
95   int faulty;                   /* number of addresses known not to work. */
96   int from_cache;               /* whether this entry was pulled from
97                                    cache or freshly looked up. */
98
99   int refcount;                 /* reference count; when it drops to
100                                    0, the entry is freed. */
101 };
102
103 /* Get the bounds of the address list.  */
104
105 void
106 address_list_get_bounds (const struct address_list *al, int *start, int *end)
107 {
108   *start = al->faulty;
109   *end   = al->count;
110 }
111
112 /* Return whether this address list entry has been obtained from the
113    cache.  */
114
115 int
116 address_list_cached_p (const struct address_list *al)
117 {
118   return al->from_cache;
119 }
120
121 /* Return a pointer to the address at position POS.  */
122
123 const ip_address *
124 address_list_address_at (const struct address_list *al, int pos)
125 {
126   assert (pos >= al->faulty && pos < al->count);
127   return al->addresses + pos;
128 }
129
130 /* Check whether two address lists have all their IPs in common.  */
131
132 int
133 address_list_match_all (const struct address_list *al1,
134                         const struct address_list *al2)
135 {
136 #ifdef ENABLE_IPV6
137   int i;
138 #endif
139   if (al1 == al2)
140     return 1;
141   if (al1->count != al2->count)
142     return 0;
143
144   /* For the comparison to be complete, we'd need to sort the IP
145      addresses first.  But that's not necessary because this is only
146      used as an optimization.  */
147
148 #ifndef ENABLE_IPV6
149   /* In the non-IPv6 case, there is only one address type, so we can
150      compare the whole array with memcmp.  */
151   return 0 == memcmp (al1->addresses, al2->addresses,
152                       al1->count * sizeof (ip_address));
153 #else  /* ENABLE_IPV6 */
154   for (i = 0; i < al1->count; ++i) 
155     {
156       const ip_address *ip1 = &al1->addresses[i];
157       const ip_address *ip2 = &al2->addresses[i];
158
159       if (ip1->type != ip2->type)
160         return 0;
161
162       switch (ip1->type)
163         {
164         case IPV4_ADDRESS:
165           if (ADDRESS_IPV4_IN_ADDR (ip1).s_addr
166               !=
167               ADDRESS_IPV4_IN_ADDR (ip2).s_addr)
168             return 0;
169           break;
170         case IPV6_ADDRESS:
171 #ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
172           if (ADDRESS_IPV6_SCOPE (ip1) != ADDRESS_IPV6_SCOPE (ip2))
173             return 0;
174 #endif /* HAVE_SOCKADDR_IN6_SCOPE_ID */
175           if (!IN6_ARE_ADDR_EQUAL (&ADDRESS_IPV6_IN6_ADDR (ip1),
176                                    &ADDRESS_IPV6_IN6_ADDR (ip2)))
177             return 0;
178           break;
179         default:
180           abort ();
181         }
182     }
183   return 1;
184 #endif /* ENABLE_IPV6 */
185 }
186
187 /* Mark the INDEXth element of AL as faulty, so that the next time
188    this address list is used, the faulty element will be skipped.  */
189
190 void
191 address_list_set_faulty (struct address_list *al, int index)
192 {
193   /* We assume that the address list is traversed in order, so that a
194      "faulty" attempt is always preceded with all-faulty addresses,
195      and this is how Wget uses it.  */
196   assert (index == al->faulty);
197
198   ++al->faulty;
199   if (al->faulty >= al->count)
200     /* All addresses have been proven faulty.  Since there's not much
201        sense in returning the user an empty address list the next
202        time, we'll rather make them all clean, so that they can be
203        retried anew.  */
204     al->faulty = 0;
205 }
206
207 #ifdef ENABLE_IPV6
208 /**
209   * address_list_from_addrinfo
210   *
211   * This function transform an addrinfo links list in and address_list.
212   *
213   * Input:
214   * addrinfo*           Linked list of addrinfo
215   *
216   * Output:
217   * address_list*       New allocated address_list
218   */
219 static struct address_list *
220 address_list_from_addrinfo (const struct addrinfo *ai)
221 {
222   struct address_list *al;
223   const struct addrinfo *ptr;
224   int cnt;
225   ip_address *ip;
226
227   cnt = 0;
228   for (ptr = ai; ptr != NULL ; ptr = ptr->ai_next)
229     if (ptr->ai_family == AF_INET || ptr->ai_family == AF_INET6)
230       ++cnt;
231   if (cnt == 0)
232     return NULL;
233
234   al = xnew0 (struct address_list);
235   al->addresses  = xnew_array (ip_address, cnt);
236   al->count      = cnt;
237   al->refcount   = 1;
238
239   ip = al->addresses;
240   for (ptr = ai; ptr != NULL; ptr = ptr->ai_next)
241     if (ptr->ai_family == AF_INET6) 
242       {
243         const struct sockaddr_in6 *sin6 =
244           (const struct sockaddr_in6 *)ptr->ai_addr;
245         ip->type = IPV6_ADDRESS;
246         ADDRESS_IPV6_IN6_ADDR (ip) = sin6->sin6_addr;
247 #ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
248         ADDRESS_IPV6_SCOPE (ip) = sin6->sin6_scope_id;
249 #endif
250         ++ip;
251       } 
252     else if (ptr->ai_family == AF_INET)
253       {
254         const struct sockaddr_in *sin =
255           (const struct sockaddr_in *)ptr->ai_addr;
256         ip->type = IPV4_ADDRESS;
257         ADDRESS_IPV4_IN_ADDR (ip) = sin->sin_addr;
258         ++ip;
259       }
260   assert (ip - al->addresses == cnt);
261   return al;
262 }
263 #else
264 /* Create an address_list from a NULL-terminated vector of IPv4
265    addresses.  This kind of vector is returned by gethostbyname.  */
266
267 static struct address_list *
268 address_list_from_ipv4_addresses (char **vec)
269 {
270   int count, i;
271   struct address_list *al = xnew0 (struct address_list);
272
273   count = 0;
274   while (vec[count])
275     ++count;
276   assert (count > 0);
277
278   al->addresses  = xnew_array (ip_address, count);
279   al->count      = count;
280   al->refcount   = 1;
281
282   for (i = 0; i < count; i++)
283     {
284       ip_address *ip = &al->addresses[i];
285       ip->type = IPV4_ADDRESS;
286       memcpy (ADDRESS_IPV4_DATA (ip), vec[i], 4);
287     }
288
289   return al;
290 }
291 #endif
292
293 static void
294 address_list_delete (struct address_list *al)
295 {
296   xfree (al->addresses);
297   xfree (al);
298 }
299
300 void
301 address_list_release (struct address_list *al)
302 {
303   --al->refcount;
304   DEBUGP (("Releasing %p (new refcount %d).\n", al, al->refcount));
305   if (al->refcount <= 0)
306     {
307       DEBUGP (("Deleting unused %p.\n", al));
308       address_list_delete (al);
309     }
310 }
311 \f
312 /* Versions of gethostbyname and getaddrinfo that support timeout. */
313
314 #ifndef ENABLE_IPV6
315
316 struct ghbnwt_context {
317   const char *host_name;
318   struct hostent *hptr;
319 };
320
321 static void
322 gethostbyname_with_timeout_callback (void *arg)
323 {
324   struct ghbnwt_context *ctx = (struct ghbnwt_context *)arg;
325   ctx->hptr = gethostbyname (ctx->host_name);
326 }
327
328 /* Just like gethostbyname, except it times out after TIMEOUT seconds.
329    In case of timeout, NULL is returned and errno is set to ETIMEDOUT.
330    The function makes sure that when NULL is returned for reasons
331    other than timeout, errno is reset.  */
332
333 static struct hostent *
334 gethostbyname_with_timeout (const char *host_name, double timeout)
335 {
336   struct ghbnwt_context ctx;
337   ctx.host_name = host_name;
338   if (run_with_timeout (timeout, gethostbyname_with_timeout_callback, &ctx))
339     {
340       SET_H_ERRNO (HOST_NOT_FOUND);
341       errno = ETIMEDOUT;
342       return NULL;
343     }
344   if (!ctx.hptr)
345     errno = 0;
346   return ctx.hptr;
347 }
348
349 #else  /* ENABLE_IPV6 */
350
351 struct gaiwt_context {
352   const char *node;
353   const char *service;
354   const struct addrinfo *hints;
355   struct addrinfo **res;
356   int exit_code;
357 };
358
359 static void
360 getaddrinfo_with_timeout_callback (void *arg)
361 {
362   struct gaiwt_context *ctx = (struct gaiwt_context *)arg;
363   ctx->exit_code = getaddrinfo (ctx->node, ctx->service, ctx->hints, ctx->res);
364 }
365
366 /* Just like getaddrinfo, except it times out after TIMEOUT seconds.
367    In case of timeout, the EAI_SYSTEM error code is returned and errno
368    is set to ETIMEDOUT.  */
369
370 static int
371 getaddrinfo_with_timeout (const char *node, const char *service,
372                           const struct addrinfo *hints, struct addrinfo **res,
373                           double timeout)
374 {
375   struct gaiwt_context ctx;
376   ctx.node = node;
377   ctx.service = service;
378   ctx.hints = hints;
379   ctx.res = res;
380
381   if (run_with_timeout (timeout, getaddrinfo_with_timeout_callback, &ctx))
382     {
383       errno = ETIMEDOUT;
384       return EAI_SYSTEM;
385     }
386   return ctx.exit_code;
387 }
388
389 #endif /* ENABLE_IPV6 */
390 \f
391 /* Pretty-print ADDR.  When compiled without IPv6, this is the same as
392    inet_ntoa.  With IPv6, it either prints an IPv6 address or an IPv4
393    address.  */
394
395 const char *
396 pretty_print_address (const ip_address *addr)
397 {
398   switch (addr->type) 
399     {
400     case IPV4_ADDRESS:
401       return inet_ntoa (ADDRESS_IPV4_IN_ADDR (addr));
402 #ifdef ENABLE_IPV6
403     case IPV6_ADDRESS:
404       {
405         static char buf[128];
406         inet_ntop (AF_INET6, &ADDRESS_IPV6_IN6_ADDR (addr), buf, sizeof (buf));
407 #if 0
408 #ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
409         {
410           /* append "%SCOPE_ID" for all ?non-global? addresses */
411           char *p = buf + strlen (buf);
412           *p++ = '%';
413           number_to_string (p, ADDRESS_IPV6_SCOPE (addr));
414         }
415 #endif
416 #endif
417         buf[sizeof (buf) - 1] = '\0';
418         return buf;
419       }
420 #endif
421     }
422   abort ();
423   return NULL;
424 }
425
426 /* Add host name HOST with the address ADDR_TEXT to the cache.
427    ADDR_LIST is a NULL-terminated list of addresses, as in struct
428    hostent.  */
429
430 static void
431 cache_host_lookup (const char *host, struct address_list *al)
432 {
433   if (!host_name_addresses_map)
434     host_name_addresses_map = make_nocase_string_hash_table (0);
435
436   ++al->refcount;
437   hash_table_put (host_name_addresses_map, xstrdup_lower (host), al);
438
439 #ifdef ENABLE_DEBUG
440   if (opt.debug)
441     {
442       int i;
443       debug_logprintf ("Caching %s =>", host);
444       for (i = 0; i < al->count; i++)
445         debug_logprintf (" %s", pretty_print_address (al->addresses + i));
446       debug_logprintf ("\n");
447     }
448 #endif
449 }
450
451 /* Remove HOST from Wget's DNS cache.  Does nothing is HOST is not in
452    the cache.  */
453
454 void
455 forget_host_lookup (const char *host)
456 {
457   struct address_list *al = hash_table_get (host_name_addresses_map, host);
458   if (al)
459     {
460       address_list_release (al);
461       hash_table_remove (host_name_addresses_map, host);
462     }
463 }
464
465 /* Look up HOST in DNS and return a list of IP addresses.
466
467    This function caches its result so that, if the same host is passed
468    the second time, the addresses are returned without the DNS lookup.
469    If you want to force lookup, call forget_host_lookup() prior to
470    this function, or set opt.dns_cache to 0 to globally disable
471    caching.
472
473    FLAGS can be a combination of:
474      LH_SILENT    - don't print the "resolving ... done" message.
475      LH_IPV4_ONLY - return only IPv4 addresses.
476      LH_IPV6_ONLY - return only IPv6 addresses.  */
477
478 struct address_list *
479 lookup_host (const char *host, int flags)
480 {
481   struct address_list *al = NULL;
482
483 #ifdef ENABLE_IPV6
484   int err;
485   struct addrinfo hints, *res;
486
487   xzero (hints);
488   hints.ai_socktype = SOCK_STREAM;
489
490   /* Should we inspect opt.<something> directly?  */
491   if (flags & LH_IPV4_ONLY)
492     hints.ai_family = AF_INET;
493   else if (flags & LH_IPV6_ONLY)
494     hints.ai_family = AF_INET6;
495   else
496     hints.ai_family = AF_UNSPEC;
497 #endif
498
499   /* First, try to check whether the address is already a numeric
500      address, in which case we don't want to cache it or bother with
501      setting up timeouts.  Plus, old (e.g. Ultrix) implementations of
502      gethostbyname can't handle numeric addresses (!).
503
504      Where getaddrinfo is available, we do it using the AI_NUMERICHOST
505      flag.  Without IPv6, we use inet_addr.  */
506
507 #ifdef ENABLE_IPV6
508   hints.ai_flags = AI_NUMERICHOST;
509   if (flags & LH_PASSIVE)
510     hints.ai_flags |= AI_PASSIVE;
511
512   /* No need to specify timeout, as we're not resolving HOST, but
513      merely translating it from the presentation (ASCII) to network
514      format.  */
515   err = getaddrinfo (host, NULL, &hints, &res);
516   if (err == 0 && res != NULL)
517     {
518       al = address_list_from_addrinfo (res);
519       freeaddrinfo (res);
520       return al;
521     }
522 #else
523   {
524     uint32_t addr_ipv4 = (uint32_t)inet_addr (host);
525     if (addr_ipv4 != (uint32_t) -1)
526       {
527         /* The return value of inet_addr is in network byte order, so
528            we can just copy it to IP.  */
529         char *vec[2];
530         vec[0] = (char *)&addr_ipv4;
531         vec[1] = NULL;
532         return address_list_from_ipv4_addresses (vec);
533       }
534   }
535 #endif
536
537   /* Then, try to find the host in the cache. */
538
539   if (host_name_addresses_map)
540     {
541       al = hash_table_get (host_name_addresses_map, host);
542       if (al)
543         {
544           DEBUGP (("Found %s in host_name_addresses_map (%p)\n", host, al));
545           ++al->refcount;
546           al->from_cache = 1;
547           return al;
548         }
549     }
550
551   if (!(flags & LH_SILENT))
552     logprintf (LOG_VERBOSE, _("Resolving %s... "), host);
553
554   /* Host name lookup goes on below. */
555
556 #ifdef ENABLE_IPV6
557   hints.ai_flags = 0;
558   if (flags & LH_PASSIVE) 
559     hints.ai_flags |= AI_PASSIVE;
560
561   err = getaddrinfo_with_timeout (host, NULL, &hints, &res, opt.dns_timeout);
562   if (err != 0 || res == NULL)
563     {
564       if (!(flags & LH_SILENT))
565         logprintf (LOG_VERBOSE, _("failed: %s.\n"),
566                    err != EAI_SYSTEM ? gai_strerror (err) : strerror (errno));
567       return NULL;
568     }
569   al = address_list_from_addrinfo (res);
570   freeaddrinfo (res);
571 #else
572   {
573     struct hostent *hptr = gethostbyname_with_timeout (host, opt.dns_timeout);
574     if (!hptr)
575       {
576         if (!(flags & LH_SILENT))
577           {
578             if (errno != ETIMEDOUT)
579               logprintf (LOG_VERBOSE, _("failed: %s.\n"), herrmsg (h_errno));
580             else
581               logputs (LOG_VERBOSE, _("failed: timed out.\n"));
582           }
583         return NULL;
584       }
585     assert (hptr->h_length == 4);
586     /* Do older systems have h_addr_list?  */
587     al = address_list_from_ipv4_addresses (hptr->h_addr_list);
588   }
589 #endif
590
591   /* Print the addresses determined by DNS lookup, but no more than
592      three.  */
593   if (!(flags & LH_SILENT))
594     {
595       int i;
596       int printmax = al->count <= 3 ? al->count : 3;
597       for (i = 0; i < printmax; i++)
598         {
599           logprintf (LOG_VERBOSE, "%s",
600                      pretty_print_address (al->addresses + i));
601           if (i < printmax - 1)
602             logputs (LOG_VERBOSE, ", ");
603         }
604       if (printmax != al->count)
605         logputs (LOG_VERBOSE, ", ...");
606       logputs (LOG_VERBOSE, "\n");
607     }
608
609   /* Cache the lookup information. */
610   if (opt.dns_cache)
611     cache_host_lookup (host, al);
612
613   return al;
614 }
615 \f
616 /* Determine whether a URL is acceptable to be followed, according to
617    a list of domains to accept.  */
618 int
619 accept_domain (struct url *u)
620 {
621   assert (u->host != NULL);
622   if (opt.domains)
623     {
624       if (!sufmatch ((const char **)opt.domains, u->host))
625         return 0;
626     }
627   if (opt.exclude_domains)
628     {
629       if (sufmatch ((const char **)opt.exclude_domains, u->host))
630         return 0;
631     }
632   return 1;
633 }
634
635 /* Check whether WHAT is matched in LIST, each element of LIST being a
636    pattern to match WHAT against, using backward matching (see
637    match_backwards() in utils.c).
638
639    If an element of LIST matched, 1 is returned, 0 otherwise.  */
640 int
641 sufmatch (const char **list, const char *what)
642 {
643   int i, j, k, lw;
644
645   lw = strlen (what);
646   for (i = 0; list[i]; i++)
647     {
648       for (j = strlen (list[i]), k = lw; j >= 0 && k >= 0; j--, k--)
649         if (TOLOWER (list[i][j]) != TOLOWER (what[k]))
650           break;
651       /* The domain must be first to reach to beginning.  */
652       if (j == -1)
653         return 1;
654     }
655   return 0;
656 }
657
658 /* Print error messages for host errors.  */
659 char *
660 herrmsg (int error)
661 {
662   /* Can't use switch since some constants are equal (at least on my
663      system), and the compiler signals "duplicate case value".  */
664   if (error == HOST_NOT_FOUND
665       || error == NO_RECOVERY
666       || error == NO_DATA
667       || error == NO_ADDRESS
668       || error == TRY_AGAIN)
669     return _("Host not found");
670   else
671     return _("Unknown error");
672 }
673
674 static int
675 host_cleanup_mapper (void *key, void *value, void *arg_ignored)
676 {
677   struct address_list *al;
678
679   xfree (key);                  /* host */
680
681   al = (struct address_list *)value;
682   assert (al->refcount == 1);
683   address_list_delete (al);
684
685   return 0;
686 }
687
688 void
689 host_cleanup (void)
690 {
691   if (host_name_addresses_map)
692     {
693       hash_table_map (host_name_addresses_map, host_cleanup_mapper, NULL);
694       hash_table_destroy (host_name_addresses_map);
695       host_name_addresses_map = NULL;
696     }
697 }