/**
 * Convert a string to an IP address.
 *
 * @param client where to send the IP address
 * @param hostname the hostname to resolve
 * @param af AF_INET or AF_INET6; use AF_UNSPEC for "any"
 */
static void
get_ip_from_hostname (struct GNUNET_SERVER_Client *client, const char *hostname,
                      int af)
{
  int ret;
  struct GNUNET_SERVER_TransmitContext *tc;

  tc = GNUNET_SERVER_transmit_context_create (client);
  ret = GNUNET_NO;
#if HAVE_GETADDRINFO
  if (ret == GNUNET_NO)
    ret = getaddrinfo_resolve (tc, hostname, af);
#endif
#if HAVE_GETHOSTBYNAME2
  if (ret == GNUNET_NO)
    ret = gethostbyname2_resolve (tc, hostname, af);
#endif
#if HAVE_GETHOSTBYNAME
  if ((ret == GNUNET_NO) && ((af == AF_UNSPEC) || (af == PF_INET)))
    gethostbyname_resolve (tc, hostname);
#endif
  GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
                                              GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE);
  GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
}
Beispiel #2
0
static int
getaddrinfo_resolve (struct GNUNET_SERVER_TransmitContext *tc,
                     const char *hostname, int af)
{
  int s;
  struct addrinfo hints;
  struct addrinfo *result;
  struct addrinfo *pos;

#ifdef WINDOWS
  /* Due to a bug, getaddrinfo will not return a mix of different families */
  if (AF_UNSPEC == af)
  {
    int ret1;
    int ret2;
    ret1 = getaddrinfo_resolve (tc, hostname, AF_INET);
    ret2 = getaddrinfo_resolve (tc, hostname, AF_INET6);
    if ((ret1 == GNUNET_OK) || (ret2 == GNUNET_OK))
      return GNUNET_OK;
    if ((ret1 == GNUNET_SYSERR) || (ret2 == GNUNET_SYSERR))
      return GNUNET_SYSERR;
    return GNUNET_NO;
  }
#endif

  memset (&hints, 0, sizeof (struct addrinfo));
  hints.ai_family = af;
  hints.ai_socktype = SOCK_STREAM;      /* go for TCP */

  if (0 != (s = getaddrinfo (hostname, NULL, &hints, &result)))
  {
    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                _("Could not resolve `%s' (%s): %s\n"),
                hostname,
                (af ==
                 AF_INET) ? "IPv4" : ((af == AF_INET6) ? "IPv6" : "any"),
                gai_strerror (s));
    if ((s == EAI_BADFLAGS) || (s == EAI_MEMORY)
#ifndef WINDOWS
        || (s == EAI_SYSTEM)
#else
        || 1
#endif
        )
      return GNUNET_NO;         /* other function may still succeed */
    return GNUNET_SYSERR;
  }
  if (NULL == result)
    return GNUNET_SYSERR;
  for (pos = result; pos != NULL; pos = pos->ai_next)
  {
    switch (pos->ai_family)
    {
    case AF_INET:
      GNUNET_SERVER_transmit_context_append_data (tc,
						  &((struct sockaddr_in*) pos->ai_addr)->sin_addr,
						  sizeof (struct in_addr),
						  GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE);
      break;
    case AF_INET6:
      GNUNET_SERVER_transmit_context_append_data (tc,
						  &((struct sockaddr_in6*) pos->ai_addr)->sin6_addr,
						  sizeof (struct in6_addr),
						  GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE);
      break;
    default:
      /* unsupported, skip */
      break;
    }
  }
  freeaddrinfo (result);
  return GNUNET_OK;
}