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