1 /* Dealing with host names.
2 Copyright (C) 1995, 1996, 1997, 2000 Free Software Foundation, Inc.
4 This file is part of GNU Wget.
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.
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.
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. */
30 #include <sys/types.h>
35 # include <sys/socket.h>
36 # include <netinet/in.h>
38 # include <arpa/inet.h>
44 #define NO_ADDRESS NO_DATA
47 #ifdef HAVE_SYS_UTSNAME_H
48 # include <sys/utsname.h>
62 #define IP4_ADDRESS_LENGTH 4
64 /* Mapping between known hosts and to lists of their addresses. */
66 struct hash_table *host_name_addresses_map;
68 /* Lists of addresses. This should eventually be extended to handle
72 int count; /* number of adrresses */
73 unsigned char *buffer; /* buffer which holds all of them. */
75 int refcount; /* so we know whether to free it or
79 #define ADDR_LOCATION(al, index) ((al)->buffer + index * IP4_ADDRESS_LENGTH)
81 /* Return the number of addresses in the list. */
84 address_list_count (struct address_list *al)
89 /* Copy address number INDEX to IP_STORE. */
92 address_list_copy_one (struct address_list *al, int index,
93 unsigned char *ip_store)
95 memcpy (ip_store, ADDR_LOCATION (al, index), IP4_ADDRESS_LENGTH);
98 /* Check whether two address lists have all their IPs in common. */
101 address_list_match_all (struct address_list *al1, struct address_list *al2)
105 if (al1->count != al2->count)
107 return 0 == memcmp (al1->buffer, al2->buffer,
108 al1->count * IP4_ADDRESS_LENGTH);
111 /* Create an address_list out of a NULL-terminated list of addresses,
112 as returned by gethostbyname. */
114 static struct address_list *
115 address_list_new (char **h_addr_list)
119 struct address_list *al = xmalloc (sizeof (struct address_list));
121 while (h_addr_list[count])
125 al->buffer = xmalloc (count * IP4_ADDRESS_LENGTH);
128 for (i = 0; i < count; i++)
129 memcpy (ADDR_LOCATION (al, i), h_addr_list[i], IP4_ADDRESS_LENGTH);
135 address_list_delete (struct address_list *al)
142 address_list_release (struct address_list *al)
145 DEBUGP (("Releasing %p (new refcount %d).\n", al, al->refcount));
146 if (al->refcount <= 0)
148 DEBUGP (("Deleting unused %p.\n", al));
149 address_list_delete (al);
153 /* The same as inet_ntoa, but without the need for a cast, or for
154 #including the netinet stuff. */
157 pretty_print_address (const unsigned char *addr)
159 return inet_ntoa (*(struct in_addr *)addr);
162 /* Add host name HOST with the address ADDR_TEXT to the cache.
163 ADDR_LIST is a NULL-terminated list of addresses, as in struct
167 cache_host_lookup (const char *host, struct address_list *al)
169 if (!host_name_addresses_map)
170 host_name_addresses_map = make_nocase_string_hash_table (0);
173 hash_table_put (host_name_addresses_map, xstrdup_lower (host), al);
179 debug_logprintf ("Caching %s =>", host);
180 for (i = 0; i < al->count; i++)
181 debug_logprintf (" %s",
182 pretty_print_address (ADDR_LOCATION (al, i)));
183 debug_logprintf ("\n");
188 struct address_list *
189 lookup_host (const char *host, int silent)
191 struct address_list *al = NULL;
193 struct hostent *hptr;
195 /* If the address is of the form d.d.d.d, no further lookup is
197 addr = (unsigned long)inet_addr (host);
200 unsigned char tmpstore[IP4_ADDRESS_LENGTH];
201 char *lst[] = { tmpstore, NULL };
203 /* ADDR is defined to be in network byte order, which is what
204 this returns, so we can just copy it to STORE_IP. However,
205 on big endian 64-bit architectures the value will be stored
206 in the *last*, not first four bytes. OFFSET makes sure that
207 we copy the correct four bytes. */
209 #ifdef WORDS_BIGENDIAN
210 offset = sizeof (unsigned long) - IP4_ADDRESS_LENGTH;
214 memcpy (tmpstore, (char *)&addr + offset, IP4_ADDRESS_LENGTH);
215 return address_list_new (lst);
218 /* By now we know that the host name we got is not of the form
219 d.d.d.d. Try to find it in our cache of host names. */
220 if (host_name_addresses_map)
221 al = hash_table_get (host_name_addresses_map, host);
225 DEBUGP (("Found %s in host_name_addresses_map (%p)\n", host, al));
231 logprintf (LOG_VERBOSE, _("Resolving %s... "), host);
233 /* Look up the host using gethostbyname(). Note that we use
234 gethostbyname() rather than ngethostbyname(), because we already
235 know that the address is not numerical. */
236 hptr = gethostbyname (host);
240 logprintf (LOG_VERBOSE, _("failed: %s.\n"), herrmsg (h_errno));
245 logprintf (LOG_VERBOSE, _("done.\n"));
247 al = address_list_new (hptr->h_addr_list);
249 /* Cache the lookup information. */
250 cache_host_lookup (host, al);
255 /* Determine whether a URL is acceptable to be followed, according to
256 a list of domains to accept. */
258 accept_domain (struct url *u)
260 assert (u->host != NULL);
263 if (!sufmatch ((const char **)opt.domains, u->host))
266 if (opt.exclude_domains)
268 if (sufmatch ((const char **)opt.exclude_domains, u->host))
274 /* Check whether WHAT is matched in LIST, each element of LIST being a
275 pattern to match WHAT against, using backward matching (see
276 match_backwards() in utils.c).
278 If an element of LIST matched, 1 is returned, 0 otherwise. */
280 sufmatch (const char **list, const char *what)
285 for (i = 0; list[i]; i++)
287 for (j = strlen (list[i]), k = lw; j >= 0 && k >= 0; j--, k--)
288 if (TOLOWER (list[i][j]) != TOLOWER (what[k]))
290 /* The domain must be first to reach to beginning. */
297 /* Print error messages for host errors. */
301 /* Can't use switch since some constants are equal (at least on my
302 system), and the compiler signals "duplicate case value". */
303 if (error == HOST_NOT_FOUND
304 || error == NO_RECOVERY
306 || error == NO_ADDRESS
307 || error == TRY_AGAIN)
308 return _("Host not found");
310 return _("Unknown error");
314 host_cleanup_mapper (void *key, void *value, void *arg_ignored)
316 struct address_list *al;
318 xfree (key); /* host */
320 al = (struct address_list *)value;
321 assert (al->refcount == 1);
322 address_list_delete (al);
330 if (host_name_addresses_map)
332 hash_table_map (host_name_addresses_map, host_cleanup_mapper, NULL);
333 hash_table_destroy (host_name_addresses_map);
334 host_name_addresses_map = NULL;