From 8ccc51e5afc854116094d9d827209218b1f47174 Mon Sep 17 00:00:00 2001 From: hniksic Date: Sun, 9 Nov 2003 17:38:09 -0800 Subject: [PATCH] [svn] Split passive host lookups to a separate function. --- src/ChangeLog | 10 +++++ src/connect.c | 35 ++++++++++----- src/connect.h | 4 -- src/host.c | 117 ++++++++++++++++++++++++++++++++------------------ src/host.h | 9 +--- 5 files changed, 110 insertions(+), 65 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index 52ac37a0..3aadeb37 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,13 @@ +2003-11-10 Hrvoje Niksic + + * connect.c (resolve_bind_address): Call lookup_host_passive. + Make sure that opt.bind_address is resolved only once. + + * host.c (lookup_host_passive): New function, handles "passive" + lookups. + (lookup_host): Remove the passive flags. Remove the + family-related flags -- use ip_default_family instead. + 2003-11-09 Hrvoje Niksic * html-url.c: Get URLs from . diff --git a/src/connect.c b/src/connect.c index 25c15962..3ed03c71 100644 --- a/src/connect.c +++ b/src/connect.c @@ -166,28 +166,41 @@ sockaddr_size (const struct sockaddr *sa) } static int -resolve_bind_address (const char *host, struct sockaddr *sa, int flags) +resolve_bind_address (struct sockaddr *sa) { struct address_list *al; - /* #### Shouldn't we do this only once? opt.bind_address won't - change during a Wget run! */ - - al = lookup_host (host, flags | LH_SILENT | LH_PASSIVE); - if (al == NULL) + /* Make sure this is called only once. opt.bind_address doesn't + change during a Wget run. */ + static int called, should_bind; + static ip_address ip; + if (called) { - /* #### We should print the error message here. */ + if (should_bind) + sockaddr_set_data (sa, &ip, 0); + return should_bind; + } + called = 1; + + al = lookup_host_passive (opt.bind_address); + if (!al) + { + /* #### We should be able to print the error message here. */ logprintf (LOG_NOTQUIET, _("%s: unable to resolve bind address `%s'; disabling bind.\n"), exec_name, opt.bind_address); + should_bind = 0; return 0; } /* Pick the first address in the list and use it as bind address. - Perhaps we should try multiple addresses, but I don't think - that's necessary in practice. */ - sockaddr_set_data (sa, address_list_address_at (al, 0), 0); + Perhaps we should try multiple addresses in succession, but I + don't think that's necessary in practice. */ + ip = *address_list_address_at (al, 0); address_list_release (al); + + sockaddr_set_data (sa, &ip, 0); + should_bind = 1; return 1; } @@ -280,7 +293,7 @@ connect_to_ip (const ip_address *ip, int port, const char *print) address. */ struct sockaddr_storage bind_ss; struct sockaddr *bind_sa = (struct sockaddr *)&bind_ss; - if (resolve_bind_address (opt.bind_address, bind_sa, 0)) + if (resolve_bind_address (bind_sa)) { if (bind (sock, bind_sa, sockaddr_size (bind_sa)) < 0) goto err; diff --git a/src/connect.h b/src/connect.h index aa485c1c..a0c830c6 100644 --- a/src/connect.h +++ b/src/connect.h @@ -32,10 +32,6 @@ so, delete this exception statement from your version. */ #include "host.h" /* for definition of ip_address */ -/* bindport flags */ -#define BIND_ON_IPV4_ONLY LH_IPV4_ONLY -#define BIND_ON_IPV6_ONLY LH_IPV6_ONLY - #ifndef ENABLE_IPV6 # ifndef HAVE_SOCKADDR_STORAGE # define sockaddr_storage sockaddr_in diff --git a/src/host.c b/src/host.c index 81483572..93a6f8f7 100644 --- a/src/host.c +++ b/src/host.c @@ -81,6 +81,13 @@ extern int h_errno; /* Mapping between known hosts and to lists of their addresses. */ static struct hash_table *host_name_addresses_map; + +#ifdef ENABLE_IPV6 +/* The default IP family for looking up host names. This should be + moved to an entry in struct options when we implement the + --inet4/--inet6 flags. */ +static int ip_default_family = AF_UNSPEC; +#endif /* Lists of addresses. This should eventually be extended to handle IPv6. */ @@ -326,6 +333,26 @@ gethostbyname_with_timeout (const char *host_name, double timeout) return ctx.hptr; } +/* Print error messages for host errors. */ +static char * +host_errstr (int error) +{ + /* Can't use switch since some of these constants can be equal, + which makes the compiler complain about duplicate case + values. */ + if (error == HOST_NOT_FOUND + || error == NO_RECOVERY + || error == NO_DATA + || error == NO_ADDRESS) + return _("Host not found"); + else if (error == TRY_AGAIN) + /* Message modeled after what gai_strerror returns in similar + circumstances. */ + return _("Temporary failure in name resolution"); + else + return _("Unknown error"); +} + #else /* ENABLE_IPV6 */ struct gaiwt_context { @@ -450,30 +477,19 @@ forget_host_lookup (const char *host) this function, or set opt.dns_cache to 0 to globally disable caching. - FLAGS can be a combination of: - LH_SILENT - don't print the "resolving ... done" message. - LH_IPV4_ONLY - return only IPv4 addresses. - LH_IPV6_ONLY - return only IPv6 addresses. */ + If SILENT is non-zero, progress messages are not printed. */ struct address_list * -lookup_host (const char *host, int flags) +lookup_host (const char *host, int silent) { struct address_list *al = NULL; #ifdef ENABLE_IPV6 int err; struct addrinfo hints, *res; - xzero (hints); hints.ai_socktype = SOCK_STREAM; - - /* Should we inspect opt. directly? */ - if (flags & LH_IPV4_ONLY) - hints.ai_family = AF_INET; - else if (flags & LH_IPV6_ONLY) - hints.ai_family = AF_INET6; - else - hints.ai_family = AF_UNSPEC; + hints.ai_family = ip_default_family; #endif /* First, try to check whether the address is already a numeric @@ -486,8 +502,6 @@ lookup_host (const char *host, int flags) #ifdef ENABLE_IPV6 hints.ai_flags = AI_NUMERICHOST; - if (flags & LH_PASSIVE) - hints.ai_flags |= AI_PASSIVE; /* No need to specify timeout, as we're not resolving HOST, but merely translating it from the presentation (ASCII) to network @@ -528,20 +542,18 @@ lookup_host (const char *host, int flags) } } - if (!(flags & LH_SILENT)) - logprintf (LOG_VERBOSE, _("Resolving %s... "), host); + /* No luck with the cache; resolve the host name. */ - /* Host name lookup goes on below. */ + if (!silent) + logprintf (LOG_VERBOSE, _("Resolving %s... "), host); #ifdef ENABLE_IPV6 hints.ai_flags = 0; - if (flags & LH_PASSIVE) - hints.ai_flags |= AI_PASSIVE; err = getaddrinfo_with_timeout (host, NULL, &hints, &res, opt.dns_timeout); if (err != 0 || res == NULL) { - if (!(flags & LH_SILENT)) + if (!silent) logprintf (LOG_VERBOSE, _("failed: %s.\n"), err != EAI_SYSTEM ? gai_strerror (err) : strerror (errno)); return NULL; @@ -553,16 +565,16 @@ lookup_host (const char *host, int flags) struct hostent *hptr = gethostbyname_with_timeout (host, opt.dns_timeout); if (!hptr) { - if (!(flags & LH_SILENT)) + if (!silent) { if (errno != ETIMEDOUT) - logprintf (LOG_VERBOSE, _("failed: %s.\n"), herrmsg (h_errno)); + logprintf (LOG_VERBOSE, _("failed: %s.\n"), + host_errstr (h_errno)); else logputs (LOG_VERBOSE, _("failed: timed out.\n")); } return NULL; } - assert (hptr->h_length == 4); /* Do older systems have h_addr_list? */ al = address_list_from_ipv4_addresses (hptr->h_addr_list); } @@ -570,7 +582,7 @@ lookup_host (const char *host, int flags) /* Print the addresses determined by DNS lookup, but no more than three. */ - if (!(flags & LH_SILENT)) + if (!silent) { int i; int printmax = al->count <= 3 ? al->count : 3; @@ -592,6 +604,43 @@ lookup_host (const char *host, int flags) 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 = ip_default_family; + 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. */ @@ -635,22 +684,6 @@ sufmatch (const char **list, const char *what) return 0; } -/* Print error messages for host errors. */ -char * -herrmsg (int error) -{ - /* Can't use switch since some constants are equal (at least on my - system), and the compiler signals "duplicate case value". */ - if (error == HOST_NOT_FOUND - || error == NO_RECOVERY - || error == NO_DATA - || error == NO_ADDRESS - || error == TRY_AGAIN) - return _("Host not found"); - else - return _("Unknown error"); -} - static int host_cleanup_mapper (void *key, void *value, void *arg_ignored) { diff --git a/src/host.h b/src/host.h index 1bb514ca..8666c08c 100644 --- a/src/host.h +++ b/src/host.h @@ -90,16 +90,9 @@ typedef struct { #define ADDRESS_IPV6_DATA(x) ((void *)&(x)->u.ipv6.addr) #define ADDRESS_IPV6_SCOPE(x) ((x)->u.ipv6.scope_id) - -/* Flags for lookup_host */ -#define LH_SILENT 0x0001 -#define LH_PASSIVE 0x0002 -#define LH_IPV4_ONLY 0x0004 -#define LH_IPV6_ONLY 0x0008 - /* Function declarations */ struct address_list *lookup_host PARAMS ((const char *, int)); -char *herrmsg PARAMS ((int)); +struct address_list *lookup_host_passive PARAMS ((const char *)); void forget_host_lookup PARAMS ((const char *));