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