From 16c53cdf93b484f0ea5de207166ac2e57b48444f Mon Sep 17 00:00:00 2001 From: hniksic Date: Fri, 4 Mar 2005 11:21:02 -0800 Subject: [PATCH] [svn] Improve handling of numeric hosts when ENABLE_IPV6. Published in <87psyr6jn7.fsf@xemacs.org>. --- ChangeLog | 5 ++ aclocal.m4 | 24 ------- configure.in | 9 +-- src/ChangeLog | 12 ++++ src/host.c | 190 +++++++++++++++++++++++++++++++++++++++++++++++--- src/host.h | 3 + src/url.c | 146 +------------------------------------- 7 files changed, 201 insertions(+), 188 deletions(-) diff --git a/ChangeLog b/ChangeLog index 218fd9ef..5f1cbb08 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2003-02-24 Hrvoje Niksic + + * configure.in: Don't check for AI_ADDRCONFIG here, it is checked + for in the source directly. + 2003-02-25 Hrvoje Niksic * libtool.m4, ltmain.sh, config.sub, config.guess: Upgrade to diff --git a/aclocal.m4 b/aclocal.m4 index 9a2a0666..805c4bbb 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -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 - -#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 diff --git a/configure.in b/configure.in index f2872f78..03dd4342 100644 --- a/configure.in +++ b/configure.in @@ -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 ]) diff --git a/src/ChangeLog b/src/ChangeLog index 9c250660..90a79d4d 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,15 @@ +2005-02-24 Hrvoje Niksic + + * host.c (lookup_host): Test for AI_ADDRCONFIG directly, instead + of checking for HAVE_GETADDRINFO_AI_ADDRCONFIG. + +2005-02-23 Hrvoje Niksic + + * 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 * utils.c: Use the nnnLL syntax under GCC. Define struct_stat to diff --git a/src/host.c b/src/host.c index 9d83e038..6f96845c 100644 --- a/src/host.c +++ b/src/host.c @@ -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; diff --git a/src/host.h b/src/host.h index abe086b9..495f701d 100644 --- a/src/host.h +++ b/src/host.h @@ -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 *)); diff --git a/src/url.c b/src/url.c index 8aed967d..7762473f 100644 --- a/src/url.c +++ b/src/url.c @@ -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 -- 2.39.2