add_host (const char *name, int is_pool,
          const dns_addrinfo_t ai,
          enum ks_protocol protocol, unsigned short port)
{
  gpg_error_t tmperr;
  char *tmphost;
  int idx, tmpidx;
  hostinfo_t host;
  int i;

  idx = find_hostinfo (name);
  host = hosttable[idx];

  if (is_pool)
    {
      /* For a pool immediately convert the address to a string.  */
      tmperr = resolve_dns_addr (ai->addr, ai->addrlen,
                                 (DNS_NUMERICHOST | DNS_WITHBRACKET), &tmphost);
    }
  else if (!is_ip_address (name))
    {
      /* This is a hostname.  Use the name as given without going
       * through resolve_dns_addr.  */
      tmphost = xtrystrdup (name);
      if (!tmphost)
        tmperr = gpg_error_from_syserror ();
      else
        tmperr = 0;
    }
  else
    {
      /* Do a PTR lookup on AI.  If a name was not found the function
       * returns the numeric address (with brackets).  */
      tmperr = resolve_dns_addr (ai->addr, ai->addrlen,
                                 DNS_WITHBRACKET, &tmphost);
    }

  if (tmperr)
    {
      log_info ("resolve_dns_addr failed while checking '%s': %s\n",
                name, gpg_strerror (tmperr));
    }
  else if (host->pool_len + 1 >= MAX_POOL_SIZE)
    {
      log_error ("resolve_dns_addr for '%s': '%s'"
                 " [index table full - ignored]\n", name, tmphost);
    }
  else
    {
      if (!is_pool && is_ip_address (name))
        /* Update the original entry.  */
        tmpidx = idx;
      else
        tmpidx = find_hostinfo (tmphost);
      log_info ("resolve_dns_addr for '%s': '%s'%s\n",
                name, tmphost,
                tmpidx == -1? "" : " [already known]");

      if (tmpidx == -1) /* Create a new entry.  */
        tmpidx = create_new_hostinfo (tmphost);

      if (tmpidx == -1)
        {
          log_error ("map_host for '%s' problem: %s - '%s' [ignored]\n",
                     name, strerror (errno), tmphost);
        }
      else  /* Set or update the entry. */
        {
          if (port)
            hosttable[tmpidx]->port[protocol] = port;

          if (ai->family == AF_INET6)
            {
              hosttable[tmpidx]->v6 = 1;
            }
          else if (ai->family == AF_INET)
            {
              hosttable[tmpidx]->v4 = 1;
            }
          else
            BUG ();

          /* If we updated the main entry, we're done.  */
          if (idx == tmpidx)
            goto leave;

          /* If we updated an existing entry, we're done.  */
          for (i = 0; i < host->pool_len; i++)
            if (host->pool[i] == tmpidx)
              goto leave;

          /* Otherwise, we need to add it to the pool.  Check if there
             is space.  */
          if (host->pool_len + 1 > host->pool_size)
            {
              int *new_pool;
              size_t new_size;

              if (host->pool_size == 0)
                new_size = 4;
              else
                new_size = host->pool_size * 2;

              new_pool = xtryrealloc (host->pool,
                                      new_size * sizeof *new_pool);

              if (new_pool == NULL)
                goto leave;

              host->pool = new_pool;
              host->pool_size = new_size;
            }

          /* Finally, add it.  */
          log_assert (host->pool_len < host->pool_size);
          host->pool[host->pool_len++] = tmpidx;
        }
    }
 leave:
  xfree (tmphost);
}