-/* Dealing with host names.
- Copyright (C) 1995, 1996, 1997, 2000 Free Software Foundation, Inc.
+/* Host name resolution and matching.
+ Copyright (C) 1995, 1996, 1997, 2000, 2001 Free Software Foundation, Inc.
This file is part of GNU Wget.
extern int errno;
#endif
-#define IP4_ADDRESS_LENGTH 4
+#ifndef h_errno
+# ifndef __CYGWIN__
+extern int h_errno;
+# endif
+#endif
+
+/* An IPv4 address is simply a 4-byte quantity. */
+typedef unsigned char ipv4_address[4];
/* Mapping between known hosts and to lists of their addresses. */
-struct hash_table *host_name_addresses_map;
+static struct hash_table *host_name_addresses_map;
\f
/* Lists of addresses. This should eventually be extended to handle
IPv6. */
struct address_list {
int count; /* number of adrresses */
- unsigned char *buffer; /* buffer which holds all of them. */
+ ipv4_address *addresses; /* pointer to the string of addresses */
int faulty; /* number of addresses known not to
work. */
not. */
};
-#define ADDR_LOCATION(al, index) ((al)->buffer + index * IP4_ADDRESS_LENGTH)
-
/* Get the bounds of the address list. */
void
unsigned char *ip_store)
{
assert (index >= al->faulty && index < al->count);
- memcpy (ip_store, ADDR_LOCATION (al, index), IP4_ADDRESS_LENGTH);
+ memcpy (ip_store, al->addresses + index, sizeof (ipv4_address));
}
/* Check whether two address lists have all their IPs in common. */
return 1;
if (al1->count != al2->count)
return 0;
- return 0 == memcmp (al1->buffer, al2->buffer,
- al1->count * IP4_ADDRESS_LENGTH);
+ return 0 == memcmp (al1->addresses, al2->addresses,
+ al1->count * sizeof (ipv4_address));
}
/* Mark the INDEXth element of AL as faulty, so that the next time
void
address_list_set_faulty (struct address_list *al, int index)
{
+ /* We assume that the address list is traversed in order, so that a
+ "faulty" attempt is always preceded with all-faulty addresses,
+ and this is how Wget uses it. */
+ assert (index == al->faulty);
+
++al->faulty;
if (al->faulty >= al->count)
/* All addresses have been proven faulty. Since there's not much
while (h_addr_list[count])
++count;
assert (count > 0);
- al->count = count;
- al->faulty = 0;
- al->buffer = xmalloc (count * IP4_ADDRESS_LENGTH);
- al->refcount = 1;
+ al->count = count;
+ al->faulty = 0;
+ al->addresses = xmalloc (count * sizeof (ipv4_address));
+ al->refcount = 1;
for (i = 0; i < count; i++)
- memcpy (ADDR_LOCATION (al, i), h_addr_list[i], IP4_ADDRESS_LENGTH);
+ memcpy (al->addresses + i, h_addr_list[i], sizeof (ipv4_address));
+
+ return al;
+}
+
+/* Like address_list_new, but initialized with only one address. */
+
+static struct address_list *
+address_list_new_one (const char *addr)
+{
+ struct address_list *al = xmalloc (sizeof (struct address_list));
+ al->count = 1;
+ al->faulty = 0;
+ al->addresses = xmalloc (sizeof (ipv4_address));
+ al->refcount = 1;
+ memcpy (al->addresses, addr, sizeof (ipv4_address));
return al;
}
static void
address_list_delete (struct address_list *al)
{
- xfree (al->buffer);
+ xfree (al->addresses);
xfree (al);
}
#including the netinet stuff. */
char *
-pretty_print_address (const unsigned char *addr)
+pretty_print_address (const void *addr)
{
return inet_ntoa (*(struct in_addr *)addr);
}
int i;
debug_logprintf ("Caching %s =>", host);
for (i = 0; i < al->count; i++)
- debug_logprintf (" %s",
- pretty_print_address (ADDR_LOCATION (al, i)));
+ debug_logprintf (" %s", pretty_print_address (al->addresses + i));
debug_logprintf ("\n");
}
#endif
addr = (unsigned long)inet_addr (host);
if ((int)addr != -1)
{
- char tmpstore[IP4_ADDRESS_LENGTH];
- char *lst[] = { tmpstore, NULL };
-
/* ADDR is defined to be in network byte order, which is what
this returns, so we can just copy it to STORE_IP. However,
on big endian 64-bit architectures the value will be stored
we copy the correct four bytes. */
int offset;
#ifdef WORDS_BIGENDIAN
- offset = sizeof (unsigned long) - IP4_ADDRESS_LENGTH;
+ offset = sizeof (unsigned long) - sizeof (ipv4_address);
#else
offset = 0;
#endif
- memcpy (tmpstore, (char *)&addr + offset, IP4_ADDRESS_LENGTH);
- return address_list_new (lst);
+ return address_list_new_one ((char *)&addr + offset);
}
/* By now we know that the host name we got is not of the form
if (!silent)
logprintf (LOG_VERBOSE, _("Resolving %s... "), host);
- /* Look up the host using gethostbyname(). Note that we use
- gethostbyname() rather than ngethostbyname(), because we already
- know that the address is not numerical. */
+ /* Look up the host using gethostbyname(). */
hptr = gethostbyname (host);
if (!hptr)
{
if (!silent)
logprintf (LOG_VERBOSE, _("done.\n"));
+ /* Do all systems have h_addr_list, or is it a newer thing? If the
+ latter, use address_list_new_one. */
al = address_list_new (hptr->h_addr_list);
/* Cache the lookup information. */