/* 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
\f
/* Lists of addresses. This should eventually be extended to handle
IPv6. */
ip_address *addresses; /* pointer to the string of addresses */
int faulty; /* number of addresses known not to work. */
- int from_cache; /* whether this entry was pulled from
- cache or freshly looked up. */
+ int connected; /* whether we were able to connect to
+ one of the addresses in the list,
+ at least once. */
int refcount; /* reference count; when it drops to
0, the entry is freed. */
*end = al->count;
}
-/* Return whether this address list entry has been obtained from the
- cache. */
-
-int
-address_list_cached_p (const struct address_list *al)
-{
- return al->from_cache;
-}
-
/* Return a pointer to the address at position POS. */
const ip_address *
al->faulty = 0;
}
+/* Set the "connected" flag to true. This flag used by connect.c to
+ see if the host perhaps needs to be resolved again. */
+
+void
+address_list_set_connected (struct address_list *al)
+{
+ al->connected = 1;
+}
+
+/* Return the value of the "connected" flag. */
+
+int
+address_list_connected_p (const struct address_list *al)
+{
+ return al->connected;
+}
+
#ifdef ENABLE_IPV6
-/**
- * address_list_from_addrinfo
- *
- * This function transform an addrinfo links list in and address_list.
- *
- * Input:
- * addrinfo* Linked list of addrinfo
- *
- * Output:
- * address_list* New allocated address_list
- */
+
+/* Create an address_list from the addresses in the given struct
+ addrinfo. */
+
static struct address_list *
address_list_from_addrinfo (const struct addrinfo *ai)
{
assert (ip - al->addresses == cnt);
return al;
}
-#else
+
+#else /* not ENABLE_IPV6 */
+
/* Create an address_list from a NULL-terminated vector of IPv4
addresses. This kind of vector is returned by gethostbyname. */
return al;
}
-#endif
+
+#endif /* not ENABLE_IPV6 */
static void
address_list_delete (struct address_list *al)
xfree (al);
}
+/* Mark the address list as being no longer in use. This will reduce
+ its reference count which will cause the list to be freed when the
+ count reaches 0. */
+
void
address_list_release (struct address_list *al)
{
|| error == NO_RECOVERY
|| error == NO_DATA
|| error == NO_ADDRESS)
- return _("Host not found");
+ return _("Unknown host");
else if (error == TRY_AGAIN)
/* Message modeled after what gai_strerror returns in similar
circumstances. */
{
struct address_list *al = NULL;
-#ifdef ENABLE_IPV6
- int err;
- struct addrinfo hints, *res;
- xzero (hints);
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_family = ip_default_family;
-#endif
-
- /* First, try to check whether the address is already a numeric
- address, in which case we don't want to cache it or bother with
- setting up timeouts. Plus, old (e.g. Ultrix) implementations of
- gethostbyname can't handle numeric addresses (!).
-
- Where getaddrinfo is available, we do it using the AI_NUMERICHOST
- flag. Without IPv6, we use inet_addr. */
-
-#ifdef ENABLE_IPV6
- hints.ai_flags = AI_NUMERICHOST;
-
- /* No need to specify timeout, as we're not resolving HOST, but
- merely translating it from the presentation (ASCII) to network
- format. */
- err = getaddrinfo (host, NULL, &hints, &res);
- if (err == 0 && res != NULL)
- {
- al = address_list_from_addrinfo (res);
- freeaddrinfo (res);
- return al;
- }
-#else
+#ifndef ENABLE_IPV6
+ /* If we're not using getaddrinfo, first check if HOST names a
+ numeric IPv4 address. gethostbyname is not required to accept
+ dotted-decimal IPv4 addresses, and some older implementations
+ (e.g. the Ultrix one) indeed didn't. */
{
uint32_t addr_ipv4 = (uint32_t)inet_addr (host);
if (addr_ipv4 != (uint32_t) -1)
{
- /* The return value of inet_addr is in network byte order, so
- we can just copy it to IP. */
+ /* No need to cache host->addr relation, just return the
+ address. */
char *vec[2];
vec[0] = (char *)&addr_ipv4;
vec[1] = NULL;
}
#endif
- /* Then, try to find the host in the cache. */
+ /* Try to find the host in the cache. */
if (host_name_addresses_map)
{
{
DEBUGP (("Found %s in host_name_addresses_map (%p)\n", host, al));
++al->refcount;
- al->from_cache = 1;
return al;
}
}
logprintf (LOG_VERBOSE, _("Resolving %s... "), host);
#ifdef ENABLE_IPV6
- hints.ai_flags = 0;
+ {
+ int err;
+ struct addrinfo hints, *res;
- err = getaddrinfo_with_timeout (host, NULL, &hints, &res, opt.dns_timeout);
- if (err != 0 || res == NULL)
- {
- if (!silent)
- logprintf (LOG_VERBOSE, _("failed: %s.\n"),
- err != EAI_SYSTEM ? gai_strerror (err) : strerror (errno));
- return NULL;
- }
- al = address_list_from_addrinfo (res);
- freeaddrinfo (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 = 0;
+
+ err = getaddrinfo_with_timeout (host, NULL, &hints, &res, opt.dns_timeout);
+ if (err != 0 || res == NULL)
+ {
+ if (!silent)
+ logprintf (LOG_VERBOSE, _("failed: %s.\n"),
+ err != EAI_SYSTEM ? gai_strerror (err) : strerror (errno));
+ return NULL;
+ }
+ al = address_list_from_addrinfo (res);
+ freeaddrinfo (res);
+ if (!al)
+ {
+ logprintf (LOG_VERBOSE, _("failed: No IPv4/IPv6 addresses.\n"));
+ return NULL;
+ }
+ }
#else
{
struct hostent *hptr = gethostbyname_with_timeout (host, opt.dns_timeout);
xzero (hints);
hints.ai_socktype = SOCK_STREAM;
- hints.ai_family = ip_default_family;
+ 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);