Esempio n. 1
0
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;
}
Esempio n. 2
0
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;
}