[svn] Improve handling of numeric hosts when ENABLE_IPV6.

Published in <87psyr6jn7.fsf@xemacs.org>.
This commit is contained in:
hniksic 2005-03-04 11:21:02 -08:00
parent 3d04bb3a2c
commit 16c53cdf93
7 changed files with 201 additions and 188 deletions

View File

@ -1,3 +1,8 @@
2003-02-24 Hrvoje Niksic <hniksic@xemacs.org>
* configure.in: Don't check for AI_ADDRCONFIG here, it is checked
for in the source directly.
2003-02-25 Hrvoje Niksic <hniksic@xemacs.org>
* libtool.m4, ltmain.sh, config.sub, config.guess: Upgrade to

24
aclocal.m4 vendored
View File

@ -239,30 +239,6 @@ AC_DEFUN([PROTO_INET6],[
])
AC_DEFUN([GETADDRINFO_AI_ADDRCONFIG],[
AC_CACHE_CHECK([if getaddrinfo supports AI_ADDRCONFIG],
[wget_cv_gai_ai_addrconfig],[
AC_TRY_CPP([
#include <netdb.h>
#ifndef AI_ADDRCONFIG
#error Missing AI_ADDRCONFIG
#endif
],[
wget_cv_gai_ai_addrconfig=yes
],[
wget_cv_gai_ai_addrconfig=no
])
])
if test "X$wget_cv_gai_ai_addrconfig" = "Xyes"; then :
$1
else :
$2
fi
])
AC_DEFUN([WGET_STRUCT_SOCKADDR_STORAGE],[
AC_CHECK_TYPES([struct sockaddr_storage],[], [], [
#include <sys/types.h>

View File

@ -494,14 +494,7 @@ AC_ARG_ENABLE(ipv6,
)
if test "X$ipv6" = "Xyes" || test "X$check_for_ipv6" = "Xyes"; then
AC_CHECK_FUNCS(getaddrinfo, [
GETADDRINFO_AI_ADDRCONFIG([
AC_DEFINE(
[HAVE_GETADDRINFO_AI_ADDRCONFIG], 1,
[Define if the system headers support the AI_ADDRCONFIG flag.]
)
])
], [
AC_CHECK_FUNCS(getaddrinfo, [], [
AC_MSG_NOTICE([Disabling IPv6 support: your system does not support getaddrinfo(3)])
ipv6=no
])

View File

@ -1,3 +1,15 @@
2005-02-24 Hrvoje Niksic <hniksic@xemacs.org>
* host.c (lookup_host): Test for AI_ADDRCONFIG directly, instead
of checking for HAVE_GETADDRINFO_AI_ADDRCONFIG.
2005-02-23 Hrvoje Niksic <hniksic@xemacs.org>
* host.c (is_valid_ipv6_address): Move here from url.c.
(lookup_host): If the address is numeric, don't print the
"resolving..." line, don't set up DNS timeouts, and set the
AI_NUMERICHOST hint, where available.
2005-02-26 Gisle Vanem <giva@bgnett.no>
* utils.c: Use the nnnLL syntax under GCC. Define struct_stat to

View File

@ -428,6 +428,149 @@ pretty_print_address (const ip_address *addr)
abort ();
return NULL;
}
/* The following two functions were adapted from glibc. */
static int
is_valid_ipv4_address (const char *str, const char *end)
{
int saw_digit = 0;
int octets = 0;
int val = 0;
while (str < end)
{
int ch = *str++;
if (ch >= '0' && ch <= '9')
{
val = val * 10 + (ch - '0');
if (val > 255)
return 0;
if (saw_digit == 0)
{
if (++octets > 4)
return 0;
saw_digit = 1;
}
}
else if (ch == '.' && saw_digit == 1)
{
if (octets == 4)
return 0;
val = 0;
saw_digit = 0;
}
else
return 0;
}
if (octets < 4)
return 0;
return 1;
}
int
is_valid_ipv6_address (const char *str, const char *end)
{
enum {
NS_INADDRSZ = 4,
NS_IN6ADDRSZ = 16,
NS_INT16SZ = 2
};
const char *curtok;
int tp;
const char *colonp;
int saw_xdigit;
unsigned int val;
tp = 0;
colonp = NULL;
if (str == end)
return 0;
/* Leading :: requires some special handling. */
if (*str == ':')
{
++str;
if (str == end || *str != ':')
return 0;
}
curtok = str;
saw_xdigit = 0;
val = 0;
while (str < end)
{
int ch = *str++;
/* if ch is a number, add it to val. */
if (ISXDIGIT (ch))
{
val <<= 4;
val |= XDIGIT_TO_NUM (ch);
if (val > 0xffff)
return 0;
saw_xdigit = 1;
continue;
}
/* if ch is a colon ... */
if (ch == ':')
{
curtok = str;
if (saw_xdigit == 0)
{
if (colonp != NULL)
return 0;
colonp = str + tp;
continue;
}
else if (str == end)
return 0;
if (tp > NS_IN6ADDRSZ - NS_INT16SZ)
return 0;
tp += NS_INT16SZ;
saw_xdigit = 0;
val = 0;
continue;
}
/* if ch is a dot ... */
if (ch == '.' && (tp <= NS_IN6ADDRSZ - NS_INADDRSZ)
&& is_valid_ipv4_address (curtok, end) == 1)
{
tp += NS_INADDRSZ;
saw_xdigit = 0;
break;
}
return 0;
}
if (saw_xdigit == 1)
{
if (tp > NS_IN6ADDRSZ - NS_INT16SZ)
return 0;
tp += NS_INT16SZ;
}
if (colonp != NULL)
{
if (tp == NS_IN6ADDRSZ)
return 0;
tp = NS_IN6ADDRSZ;
}
if (tp != NS_IN6ADDRSZ)
return 0;
return 1;
}
/* Simple host cache, used by lookup_host to speed up resolving. The
cache doesn't handle TTL because Wget is a fairly short-lived
@ -521,12 +664,14 @@ lookup_host (const char *host, int flags)
struct address_list *al;
int silent = flags & LH_SILENT;
int use_cache;
int numeric_address = 0;
double timeout = opt.dns_timeout;
#ifndef ENABLE_IPV6
/* If we're not using getaddrinfo, first check if HOST specifies a
numeric IPv4 address. gethostbyname is not required to accept
dotted-decimal IPv4 addresses, and some implementations (e.g. the
Ultrix one and possibly Winsock) indeed don't. */
numeric IPv4 address. Some implementations of gethostbyname
(e.g. the Ultrix one and possibly Winsock) don't accept
dotted-decimal IPv4 addresses. */
{
uint32_t addr_ipv4 = (uint32_t)inet_addr (host);
if (addr_ipv4 != (uint32_t) -1)
@ -539,13 +684,24 @@ lookup_host (const char *host, int flags)
return address_list_from_ipv4_addresses (vec);
}
}
#else /* ENABLE_IPV6 */
/* If we're using getaddrinfo, at least check whether the address is
already numeric, in which case there is no need to print the
"Resolving..." output. (This comes at no additional cost since
the is_valid_ipv*_address are already required for
url_parse.) */
{
const char *end = host + strlen (host);
if (is_valid_ipv4_address (host, end) || is_valid_ipv6_address (host, end))
numeric_address = 1;
}
#endif
/* Cache is normally on, but can be turned off with --no-dns-cache.
Don't cache passive lookups under IPv6. */
use_cache = opt.dns_cache;
#ifdef ENABLE_IPV6
if (flags & LH_BIND)
if ((flags & LH_BIND) || numeric_address)
use_cache = 0;
#endif
@ -566,7 +722,7 @@ lookup_host (const char *host, int flags)
/* No luck with the cache; resolve HOST. */
if (!silent)
if (!silent && !numeric_address)
logprintf (LOG_VERBOSE, _("Resolving %s... "), host);
#ifdef ENABLE_IPV6
@ -583,7 +739,7 @@ lookup_host (const char *host, int flags)
else
{
hints.ai_family = AF_UNSPEC;
#ifdef HAVE_GETADDRINFO_AI_ADDRCONFIG
#ifdef AI_ADDRCONFIG
hints.ai_flags |= AI_ADDRCONFIG;
#else
/* On systems without AI_ADDRCONFIG, emulate it by manually
@ -595,7 +751,19 @@ lookup_host (const char *host, int flags)
if (flags & LH_BIND)
hints.ai_flags |= AI_PASSIVE;
err = getaddrinfo_with_timeout (host, NULL, &hints, &res, opt.dns_timeout);
#ifdef AI_NUMERICHOST
if (numeric_address)
{
/* Where available, the AI_NUMERICHOST hint can prevent costly
access to DNS servers. */
hints.ai_flags |= AI_NUMERICHOST;
timeout = 0; /* no timeout needed when "resolving"
numeric hosts -- avoid setting up
signal handlers and such. */
}
#endif
err = getaddrinfo_with_timeout (host, NULL, &hints, &res, timeout);
if (err != 0 || res == NULL)
{
if (!silent)
@ -612,9 +780,9 @@ lookup_host (const char *host, int flags)
return NULL;
}
}
#else
#else /* not ENABLE_IPV6 */
{
struct hostent *hptr = gethostbyname_with_timeout (host, opt.dns_timeout);
struct hostent *hptr = gethostbyname_with_timeout (host, timeout);
if (!hptr)
{
if (!silent)
@ -630,11 +798,11 @@ lookup_host (const char *host, int flags)
/* Do older systems have h_addr_list? */
al = address_list_from_ipv4_addresses (hptr->h_addr_list);
}
#endif
#endif /* not ENABLE_IPV6 */
/* Print the addresses determined by DNS lookup, but no more than
three. */
if (!silent)
if (!silent && !numeric_address)
{
int i;
int printmax = al->count <= 3 ? al->count : 3;

View File

@ -108,6 +108,9 @@ int address_list_connected_p PARAMS ((const struct address_list *));
void address_list_release PARAMS ((struct address_list *));
const char *pretty_print_address PARAMS ((const ip_address *));
#ifdef ENABLE_IPV6
int is_valid_ipv6_address PARAMS ((const char *, const char *));
#endif
int accept_domain PARAMS ((struct url *));
int sufmatch PARAMS ((const char **, const char *));

146
src/url.c
View File

@ -47,6 +47,7 @@ so, delete this exception statement from your version. */
#include "wget.h"
#include "utils.h"
#include "url.h"
#include "host.h" /* for is_valid_ipv6_address */
#ifndef errno
extern int errno;
@ -655,151 +656,6 @@ static const char *parse_errors[] = {
N_("Invalid IPv6 numeric address")
};
#ifdef ENABLE_IPV6
/* The following two functions were adapted from glibc. */
static int
is_valid_ipv4_address (const char *str, const char *end)
{
int saw_digit = 0;
int octets = 0;
int val = 0;
while (str < end)
{
int ch = *str++;
if (ch >= '0' && ch <= '9')
{
val = val * 10 + (ch - '0');
if (val > 255)
return 0;
if (saw_digit == 0)
{
if (++octets > 4)
return 0;
saw_digit = 1;
}
}
else if (ch == '.' && saw_digit == 1)
{
if (octets == 4)
return 0;
val = 0;
saw_digit = 0;
}
else
return 0;
}
if (octets < 4)
return 0;
return 1;
}
static int
is_valid_ipv6_address (const char *str, const char *end)
{
enum {
NS_INADDRSZ = 4,
NS_IN6ADDRSZ = 16,
NS_INT16SZ = 2
};
const char *curtok;
int tp;
const char *colonp;
int saw_xdigit;
unsigned int val;
tp = 0;
colonp = NULL;
if (str == end)
return 0;
/* Leading :: requires some special handling. */
if (*str == ':')
{
++str;
if (str == end || *str != ':')
return 0;
}
curtok = str;
saw_xdigit = 0;
val = 0;
while (str < end)
{
int ch = *str++;
/* if ch is a number, add it to val. */
if (ISXDIGIT (ch))
{
val <<= 4;
val |= XDIGIT_TO_NUM (ch);
if (val > 0xffff)
return 0;
saw_xdigit = 1;
continue;
}
/* if ch is a colon ... */
if (ch == ':')
{
curtok = str;
if (saw_xdigit == 0)
{
if (colonp != NULL)
return 0;
colonp = str + tp;
continue;
}
else if (str == end)
return 0;
if (tp > NS_IN6ADDRSZ - NS_INT16SZ)
return 0;
tp += NS_INT16SZ;
saw_xdigit = 0;
val = 0;
continue;
}
/* if ch is a dot ... */
if (ch == '.' && (tp <= NS_IN6ADDRSZ - NS_INADDRSZ)
&& is_valid_ipv4_address (curtok, end) == 1)
{
tp += NS_INADDRSZ;
saw_xdigit = 0;
break;
}
return 0;
}
if (saw_xdigit == 1)
{
if (tp > NS_IN6ADDRSZ - NS_INT16SZ)
return 0;
tp += NS_INT16SZ;
}
if (colonp != NULL)
{
if (tp == NS_IN6ADDRSZ)
return 0;
tp = NS_IN6ADDRSZ;
}
if (tp != NS_IN6ADDRSZ)
return 0;
return 1;
}
#endif
/* Parse a URL.
Return a new struct url if successful, NULL on error. In case of