From 8e330fdba016c5e521ea8e9c11e6df011c8666b1 Mon Sep 17 00:00:00 2001 From: hniksic Date: Fri, 14 Nov 2003 17:49:52 -0800 Subject: [PATCH] [svn] Add support for -4/-6. --- src/ChangeLog | 17 ++++++ src/connect.c | 7 ++- src/host.c | 150 ++++++++++++++++++++++++++++---------------------- src/host.h | 9 +-- src/init.c | 2 +- 5 files changed, 110 insertions(+), 75 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index 7768b9a0..270d937c 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,20 @@ +2003-11-15 Hrvoje Niksic + + * init.c: Make sure the options are in alphabetic order! + + * host.c (lookup_host): Merge lookup_host_passive and lookup_host + after all -- having both would result in some code duplication. + (lookup_host): Set hints.ai_family to AF_INET if ipv4_only is + requested. Likewise, set it to AF_INET6 for ipv6_only. Specify + AI_ADDRCONFIG where available. + (lookup_host): New flag LH_REFRESH that specifies that a cached + entry for HOST should be refreshed. + (cache_query): New function. + (cache_store): Ditto. + (cache_remove): Ditto. + (forget_host_lookup): No longer necessary, replaced with static + function cache_remove. + 2003-11-14 Hrvoje Niksic * main.c: Enable -4 and -6 only if IPv6 is enabled. diff --git a/src/connect.c b/src/connect.c index 20538020..d309b272 100644 --- a/src/connect.c +++ b/src/connect.c @@ -182,7 +182,7 @@ resolve_bind_address (struct sockaddr *sa) } called = 1; - al = lookup_host_passive (opt.bind_address); + al = lookup_host (opt.bind_address, LH_BIND | LH_SILENT); if (!al) { /* #### We should be able to print the error message here. */ @@ -333,10 +333,11 @@ connect_to_host (const char *host, int port) { int i, start, end; struct address_list *al; + int lh_flags = 0; int sock = -1; again: - al = lookup_host (host, 0); + al = lookup_host (host, lh_flags); if (!al) return E_HOST; @@ -366,7 +367,7 @@ connect_to_host (const char *host, int port) we were previously able to connect to HOST. That might indicate that HOST is under dynamic DNS and the addresses we're connecting to have expired. Resolve it again. */ - forget_host_lookup (host); + lh_flags |= LH_REFRESH; goto again; } diff --git a/src/host.c b/src/host.c index d272c625..6274d0ec 100644 --- a/src/host.c +++ b/src/host.c @@ -78,10 +78,6 @@ extern int h_errno; # endif #endif -/* Mapping between known hosts and to lists of their addresses. */ - -static struct hash_table *host_name_addresses_map; - /* Lists of IP addresses that result from running DNS queries. See lookup_host for details. */ @@ -431,13 +427,40 @@ pretty_print_address (const ip_address *addr) abort (); return NULL; } + +/* Simple host cache, used by lookup_host to speed up resolving. The + cache doesn't handle TTL because Wget is a fairly short-lived + application. Refreshing is attempted when connect fails, though -- + see connect_to_host. */ + +/* Mapping between known hosts and to lists of their addresses. */ +static struct hash_table *host_name_addresses_map; + -/* Add host name HOST with the address ADDR_TEXT to the cache. - ADDR_LIST is a NULL-terminated list of addresses, as in struct - hostent. */ +/* Return the host's resolved addresses from the cache, if + available. */ + +static struct address_list * +cache_query (const char *host) +{ + struct address_list *al; + if (!host_name_addresses_map) + return NULL; + al = hash_table_get (host_name_addresses_map, host); + if (al) + { + DEBUGP (("Found %s in host_name_addresses_map (%p)\n", host, al)); + ++al->refcount; + return al; + } + return NULL; +} + +/* Cache the DNS lookup of HOST. Subsequent invocations of + lookup_host will return the cached value. */ static void -cache_host_lookup (const char *host, struct address_list *al) +cache_store (const char *host, struct address_list *al) { if (!host_name_addresses_map) host_name_addresses_map = make_nocase_string_hash_table (0); @@ -457,20 +480,23 @@ cache_host_lookup (const char *host, struct address_list *al) #endif } -/* Remove HOST from Wget's DNS cache. Does nothing is HOST is not in +/* Remove HOST from the DNS cache. Does nothing is HOST is not in the cache. */ -void -forget_host_lookup (const char *host) +static void +cache_remove (const char *host) { - struct address_list *al = hash_table_get (host_name_addresses_map, host); + struct address_list *al; + if (!host_name_addresses_map) + return; + al = hash_table_get (host_name_addresses_map, host); if (al) { address_list_release (al); hash_table_remove (host_name_addresses_map, host); } } - + /* Look up HOST in DNS and return a list of IP addresses. The addresses in the list are in the same order in which gethostbyname/getaddrinfo returned them. @@ -480,12 +506,20 @@ forget_host_lookup (const char *host) you want to force lookup, call forget_host_lookup() prior to this function, or set opt.dns_cache to 0 to globally disable caching. - If SILENT is non-zero, progress messages are not printed. */ + FLAGS can be a combination of: + LH_SILENT - don't print the "resolving ... done" messages. + LH_BIND - resolve addresses for use with bind, which under + IPv6 means to use AI_PASSIVE flag to getaddrinfo. + Passive lookups are not cached under IPv6. + LH_REFRESH - if HOST is cached, remove the entry from the cache + and resolve it anew. */ struct address_list * -lookup_host (const char *host, int silent) +lookup_host (const char *host, int flags) { struct address_list *al = NULL; + int silent = flags & LH_SILENT; + int use_cache; #ifndef ENABLE_IPV6 /* If we're not using getaddrinfo, first check if HOST specifies a @@ -506,20 +540,30 @@ lookup_host (const char *host, int silent) } #endif - /* Try to find the host in the cache. */ + /* 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) + use_cache = 0; +#endif - if (host_name_addresses_map) + /* Try to find the host in the cache so we don't need to talk to the + resolver. If LH_REFRESH is requested, remove HOST from the cache + instead. */ + if (use_cache) { - al = hash_table_get (host_name_addresses_map, host); - if (al) + if (!(flags & LH_REFRESH)) { - DEBUGP (("Found %s in host_name_addresses_map (%p)\n", host, al)); - ++al->refcount; - return al; + al = cache_query (host); + if (al) + return al; } + else + cache_remove (host); } - /* No luck with the cache; resolve the host name. */ + /* No luck with the cache; resolve HOST. */ if (!silent) logprintf (LOG_VERBOSE, _("Resolving %s... "), host); @@ -531,9 +575,18 @@ lookup_host (const char *host, int silent) xzero (hints); hints.ai_socktype = SOCK_STREAM; - hints.ai_family = AF_UNSPEC; /* #### should look at opt.ipv4_only - and opt.ipv6_only */ - hints.ai_flags = 0; + hints.ai_family = AF_UNSPEC; + if (opt.ipv4_only && !opt.ipv6_only) + hints.ai_family = AF_INET; + else if (opt.ipv6_only && !opt.ipv4_only) + hints.ai_family = AF_INET6; + +#ifdef HAVE_GETADDRINFO_AI_ADDRCONFIG + /* Use AI_ADDRCONFIG where available. See init.c:defaults(). */ + hints.ai_flags |= AI_ADDRCONFIG; +#endif + if (flags & LH_BIND) + hints.ai_flags |= AI_PASSIVE; err = getaddrinfo_with_timeout (host, NULL, &hints, &res, opt.dns_timeout); if (err != 0 || res == NULL) @@ -547,7 +600,8 @@ lookup_host (const char *host, int silent) freeaddrinfo (res); if (!al) { - logprintf (LOG_VERBOSE, _("failed: No IPv4/IPv6 addresses.\n")); + logprintf (LOG_VERBOSE, + _("failed: No IPv4/IPv6 addresses for host.\n")); return NULL; } } @@ -590,49 +644,11 @@ lookup_host (const char *host, int silent) } /* Cache the lookup information. */ - if (opt.dns_cache) - cache_host_lookup (host, al); + if (use_cache) + cache_store (host, al); return al; } - -/* Resolve HOST to get an address for use with bind(2). Do *not* use - this for sockets to be used with connect(2). - - This is a function separate from lookup_host because the results it - returns are different -- it uses the AI_PASSIVE flag to - getaddrinfo. Because of this distinction, it doesn't store the - results in the cache. It prints nothing and implements no timeouts - because it should normally only be used with local addresses - (typically "localhost" or numeric addresses of different local - interfaces.) - - Without IPv6, this function just calls lookup_host. */ - -struct address_list * -lookup_host_passive (const char *host) -{ -#ifdef ENABLE_IPV6 - struct address_list *al = NULL; - int err; - struct addrinfo hints, *res; - - xzero (hints); - hints.ai_socktype = SOCK_STREAM; - hints.ai_family = AF_UNSPEC; /* #### should look at opt.ipv4_only - and opt.ipv6_only */ - hints.ai_flags = AI_PASSIVE; - - err = getaddrinfo (host, NULL, &hints, &res); - if (err != 0 || res == NULL) - return NULL; - al = address_list_from_addrinfo (res); - freeaddrinfo (res); - return al; -#else - return lookup_host (host, 1); -#endif -} /* Determine whether a URL is acceptable to be followed, according to a list of domains to accept. */ diff --git a/src/host.h b/src/host.h index 7790c8b8..4f37d2fe 100644 --- a/src/host.h +++ b/src/host.h @@ -90,11 +90,12 @@ typedef struct { #define ADDRESS_IPV6_DATA(x) ((void *)&(x)->u.ipv6.addr) #define ADDRESS_IPV6_SCOPE(x) ((x)->u.ipv6.scope_id) -/* Function declarations */ +enum { + LH_SILENT = 1, + LH_BIND = 2, + LH_REFRESH = 4 +}; struct address_list *lookup_host PARAMS ((const char *, int)); -struct address_list *lookup_host_passive PARAMS ((const char *)); - -void forget_host_lookup PARAMS ((const char *)); void address_list_get_bounds PARAMS ((const struct address_list *, int *, int *)); diff --git a/src/init.c b/src/init.c index 74e49cc1..e93d6226 100644 --- a/src/init.c +++ b/src/init.c @@ -166,11 +166,11 @@ static struct { { "ignorelength", &opt.ignore_length, cmd_boolean }, { "ignoretags", &opt.ignore_tags, cmd_vector }, { "includedirectories", &opt.includes, cmd_directory_vector }, - { "input", &opt.input_filename, cmd_file }, #ifdef ENABLE_IPV6 { "inet4only", &opt.ipv4_only, cmd_boolean }, { "inet6only", &opt.ipv6_only, cmd_boolean }, #endif + { "input", &opt.input_filename, cmd_file }, { "keepsessioncookies", &opt.keep_session_cookies, cmd_boolean }, { "killlonger", &opt.kill_longer, cmd_boolean }, { "limitrate", &opt.limit_rate, cmd_bytes }, -- 2.39.2