]> sjero.net Git - wget/blob - src/host.c
[svn] Remove host canonicalization code.
[wget] / src / host.c
1 /* Dealing with host names.
2    Copyright (C) 1995, 1996, 1997, 2000 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 #include <config.h>
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #ifdef HAVE_STRING_H
25 # include <string.h>
26 #else
27 # include <strings.h>
28 #endif
29 #include <assert.h>
30 #include <sys/types.h>
31
32 #ifdef WINDOWS
33 # include <winsock.h>
34 #else
35 # include <sys/socket.h>
36 # include <netinet/in.h>
37 #ifndef __BEOS__
38 # include <arpa/inet.h>
39 #endif
40 # include <netdb.h>
41 #endif /* WINDOWS */
42
43 #ifndef NO_ADDRESS
44 #define NO_ADDRESS NO_DATA
45 #endif
46
47 #ifdef HAVE_SYS_UTSNAME_H
48 # include <sys/utsname.h>
49 #endif
50 #include <errno.h>
51
52 #include "wget.h"
53 #include "utils.h"
54 #include "host.h"
55 #include "url.h"
56 #include "hash.h"
57
58 #ifndef errno
59 extern int errno;
60 #endif
61
62 /* Mapping between all known hosts to their addresses (n.n.n.n). */
63
64 /* #### We should map to *lists* of IP addresses. */
65
66 struct hash_table *host_name_address_map;
67 \f
68 #if 0
69
70 /* This function is no longer used. */
71
72 /* The same as gethostbyname, but supports internet addresses of the
73    form `N.N.N.N'.  On some systems gethostbyname() knows how to do
74    this automatically.  */
75 struct hostent *
76 ngethostbyname (const char *name)
77 {
78   struct hostent *hp;
79   unsigned long addr;
80
81   addr = (unsigned long)inet_addr (name);
82   if ((int)addr != -1)
83     hp = gethostbyaddr ((char *)&addr, sizeof (addr), AF_INET);
84   else
85     hp = gethostbyname (name);
86   return hp;
87 }
88 #endif
89
90 /* Add host name HOST with the address ADDR_TEXT to the cache.  */
91
92 static void
93 add_host_to_cache (const char *host, const char *addr_text)
94 {
95   DEBUGP (("Caching %s => %s\n", host, addr_text));
96
97   if (!host_name_address_map)
98     host_name_address_map = make_nocase_string_hash_table (0);
99
100   hash_table_put (host_name_address_map,
101                   xstrdup_lower (host), xstrdup (addr_text));
102 }
103
104 /* Store the address of HOSTNAME, internet-style (four octets in
105    network order), to WHERE.  First try to get the address from the
106    cache; if it is not available, call the DNS functions and update
107    the cache.
108
109    Return 1 on successful finding of the hostname, 0 otherwise.  */
110 int
111 lookup_host (const char *hostname, unsigned char *store_ip)
112 {
113   unsigned long addr;
114   char *addr_text = NULL;
115   struct hostent *hptr;
116   struct in_addr in;
117   char *inet_s;
118
119   /* If the address is of the form d.d.d.d, no further lookup is
120      needed.  */
121   addr = (unsigned long)inet_addr (hostname);
122   if ((int)addr != -1)
123     {
124       /* ADDR is defined to be in network byte order, which is what
125          this returns, so we can just copy it to STORE_IP.  However,
126          on big endian 64-bit architectures the value will be stored
127          in the *last*, not first four bytes.  OFFSET makes sure that
128          we copy the correct four bytes.  */
129       int offset;
130     have_addr:
131 #ifdef WORDS_BIGENDIAN
132       offset = sizeof (unsigned long) - 4;
133 #else
134       offset = 0;
135 #endif
136       memcpy (store_ip, (char *)&addr + offset, 4);
137       return 1;
138     }
139
140   /* By now we know that the host name we got is not of the form
141      d.d.d.d.  Try to find it in our cache of host names.  */
142   if (host_name_address_map)
143     addr_text = hash_table_get (host_name_address_map, hostname);
144
145   if (addr_text)
146     {
147       DEBUGP (("Found %s in host_name_address_map: %s\n",
148                hostname, addr_text));
149       addr = (unsigned long)inet_addr (addr_text);
150       goto have_addr;
151     }
152
153   /* Look up the host using gethostbyname().  Note that we use
154      gethostbyname() rather than ngethostbyname(), because we already
155      know that the address is not numerical.  */
156   hptr = gethostbyname (hostname);
157   if (!hptr)
158     return 0;
159
160   /* Store the IP address to the desired location. */
161   assert (hptr->h_length == 4);
162   memcpy (store_ip, hptr->h_addr_list[0], hptr->h_length);
163
164   /* Now that we've successfully looked up the host, store this
165      information in the cache.  */
166
167   /* Originally, we copied to in.s_addr, but it appears to be missing
168      on some systems.  */
169   memcpy (&in, *hptr->h_addr_list, sizeof (in));
170   inet_s = inet_ntoa (in);
171   add_host_to_cache (hostname, inet_s);
172
173   return 1;
174 }
175
176 /* Determine whether a URL is acceptable to be followed, according to
177    a list of domains to accept.  */
178 int
179 accept_domain (struct url *u)
180 {
181   assert (u->host != NULL);
182   if (opt.domains)
183     {
184       if (!sufmatch ((const char **)opt.domains, u->host))
185         return 0;
186     }
187   if (opt.exclude_domains)
188     {
189       if (sufmatch ((const char **)opt.exclude_domains, u->host))
190         return 0;
191     }
192   return 1;
193 }
194
195 /* Check whether WHAT is matched in LIST, each element of LIST being a
196    pattern to match WHAT against, using backward matching (see
197    match_backwards() in utils.c).
198
199    If an element of LIST matched, 1 is returned, 0 otherwise.  */
200 int
201 sufmatch (const char **list, const char *what)
202 {
203   int i, j, k, lw;
204
205   lw = strlen (what);
206   for (i = 0; list[i]; i++)
207     {
208       for (j = strlen (list[i]), k = lw; j >= 0 && k >= 0; j--, k--)
209         if (TOLOWER (list[i][j]) != TOLOWER (what[k]))
210           break;
211       /* The domain must be first to reach to beginning.  */
212       if (j == -1)
213         return 1;
214     }
215   return 0;
216 }
217
218 /* Print error messages for host errors.  */
219 char *
220 herrmsg (int error)
221 {
222   /* Can't use switch since some constants are equal (at least on my
223      system), and the compiler signals "duplicate case value".  */
224   if (error == HOST_NOT_FOUND
225       || error == NO_RECOVERY
226       || error == NO_DATA
227       || error == NO_ADDRESS
228       || error == TRY_AGAIN)
229     return _("Host not found");
230   else
231     return _("Unknown error");
232 }
233
234 void
235 host_cleanup (void)
236 {
237   free_keys_and_values (host_name_address_map);
238   hash_table_destroy (host_name_address_map);
239 }