struct address_list * lookup_host (const char *host, int silent) { struct address_list *al = NULL; uint32_t addr_ipv4; ip_address addr; /* First, try to check whether the address is already a numeric address. */ #ifdef ENABLE_IPV6 if (inet_pton (AF_INET6, host, &addr) > 0) return address_list_from_single (&addr); #endif addr_ipv4 = (uint32_t)inet_addr (host); if (addr_ipv4 != (uint32_t)-1) { /* ADDR is defined to be in network byte order, which is what this returns, so we can just copy it to STORE_IP. */ map_ipv4_to_ip ((ip4_address *)&addr_ipv4, &addr); return address_list_from_single (&addr); } if (host_name_addresses_map) { 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; } } if (!silent) logprintf (LOG_VERBOSE, _("Resolving %s... "), host); /* Host name lookup goes on below. */ #ifdef HAVE_GETADDRINFO { struct addrinfo hints, *ai; int err; memset (&hints, 0, sizeof (hints)); if (ip_default_family == AF_INET) hints.ai_family = AF_INET; else hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; err = getaddrinfo_with_timeout (host, NULL, &hints, &ai, opt.dns_timeout); if (err != 0 || ai == NULL) { if (!silent) logprintf (LOG_VERBOSE, _("failed: %s.\n"), err != EAI_SYSTEM ? gai_strerror (err) : strerror (errno)); return NULL; } al = address_list_from_addrinfo (ai); freeaddrinfo (ai); } #else { struct hostent *hptr; hptr = gethostbyname_with_timeout (host, opt.dns_timeout); if (!hptr) { if (!silent) { if (errno != ETIMEDOUT) logprintf (LOG_VERBOSE, _("failed: %s.\n"), herrmsg (h_errno)); else logputs (LOG_VERBOSE, _("failed: timed out.\n")); } return NULL; } /* Do all systems have h_addr_list, or is it a newer thing? If the latter, use address_list_from_single. */ al = address_list_from_vector (hptr->h_addr_list); } #endif /* Print the addresses determined by DNS lookup, but no more than three. */ if (!silent) { int i; int printmax = al->count <= 3 ? al->count : 3; for (i = 0; i < printmax; i++) { logprintf (LOG_VERBOSE, "%s", pretty_print_address (al->addresses + i)); if (i < printmax - 1) logputs (LOG_VERBOSE, ", "); } if (printmax != al->count) logputs (LOG_VERBOSE, ", ..."); logputs (LOG_VERBOSE, "\n"); } /* Cache the lookup information. */ if (opt.dns_cache) cache_host_lookup (host, al); return al; }
struct address_list * lookup_host (const char *host, int silent) { struct address_list *al = NULL; unsigned long addr; struct hostent *hptr; /* If the address is of the form d.d.d.d, no further lookup is needed. */ addr = (unsigned long)inet_addr (host); if ((int)addr != -1) { /* ADDR is defined to be in network byte order, which is what this returns, so we can just copy it to STORE_IP. However, on big endian 64-bit architectures the value will be stored in the *last*, not first four bytes. OFFSET makes sure that we copy the correct four bytes. */ int offset; #ifdef WORDS_BIGENDIAN offset = sizeof (unsigned long) - IP4_ADDRESS_LENGTH; #else offset = 0; #endif return address_list_new_one ((char *)&addr + offset); } /* By now we know that the host name we got is not of the form d.d.d.d. Try to find it in our cache of host names. */ if (host_name_addresses_map) 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; } if (!silent) logprintf (LOG_VERBOSE, _("Resolving %s... "), host); /* Look up the host using gethostbyname(). */ hptr = gethostbyname (host); if (!hptr) { if (!silent) logprintf (LOG_VERBOSE, _("failed: %s.\n"), herrmsg (h_errno)); return NULL; } if (!silent) logprintf (LOG_VERBOSE, _("done.\n")); /* Do all systems have h_addr_list, or is it a newer thing? If the latter, use address_list_new_one. */ al = address_list_new (hptr->h_addr_list); /* Cache the lookup information. */ cache_host_lookup (host, al); return al; }