⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dns.c

📁 GNUnet是一个安全的点对点网络框架
💻 C
📖 第 1 页 / 共 2 页
字号:
getaddrinfo_resolve (struct GNUNET_GE_Context *ectx,
                     const char *hostname,
                     int domain, struct sockaddr **sa, socklen_t * socklen)
{
  int s;
  struct addrinfo hints;
  struct addrinfo *result;
  struct in6_addr *out;

  memset (&hints, 0, sizeof (struct addrinfo));
// FIXME in PlibC
#ifndef MINGW
  hints.ai_family = domain;
#else
  hints.ai_family = AF_INET;
#endif
  hints.ai_socktype = 0;
  hints.ai_protocol = 0;        /* Any protocol */
  hints.ai_canonname = NULL;
  hints.ai_addr = NULL;
  hints.ai_next = NULL;

  if (0 != (s = getaddrinfo (hostname, NULL, &hints, &result)))
    {
      if (domain == AF_INET6)
        {
          /* try v4 resolving + mapping */
          hints.ai_family = AF_INET;
          if (0 == getaddrinfo (hostname, NULL, &hints, &result))
            {
              GNUNET_GE_ASSERT (NULL,
                                result->ai_addrlen ==
                                sizeof (struct sockaddr_in));
              if (NULL == *sa)
                {
                  *sa = GNUNET_malloc (sizeof (struct sockaddr_in6));
                  *socklen = sizeof (struct sockaddr_in6);
                  memset (*sa, 0, sizeof (struct sockaddr_in6));
                  (*sa)->sa_family = AF_INET6;
                  out = &((struct sockaddr_in6 *) *sa)->sin6_addr;
                  memcpy (*sa, result->ai_addr, result->ai_addrlen);
                  ((unsigned int *) out)[2] = htonl (0xffff);
                  memcpy (&((char *) out)[sizeof (struct in6_addr) -
                                          sizeof (struct in_addr)],
                          &result->ai_addr, sizeof (struct in_addr));
                  freeaddrinfo (result);
                  return GNUNET_OK;
                }
              if (result->ai_addrlen > *socklen)
                {
                  freeaddrinfo (result);
                  return GNUNET_SYSERR;
                }
              *socklen = sizeof (struct sockaddr_in6);
              memset (*sa, 0, sizeof (struct sockaddr_in6));
              (*sa)->sa_family = AF_INET6;
              out = &((struct sockaddr_in6 *) *sa)->sin6_addr;
              memcpy (*sa, result->ai_addr, result->ai_addrlen);
              ((unsigned int *) out)[2] = htonl (0xffff);
              memcpy (&((char *) out)[sizeof (struct in6_addr) -
                                      sizeof (struct in_addr)],
                      &result->ai_addr, sizeof (struct in_addr));
              freeaddrinfo (result);
              return GNUNET_OK;
            }
        }
      GNUNET_GE_LOG (ectx,
                     GNUNET_GE_WARNING | GNUNET_GE_USER |
                     GNUNET_GE_BULK,
                     _("Could not resolve `%s' (%s): %s\n"), hostname,
                     (domain ==
                      AF_INET) ? "IPv4" : ((domain ==
                                            AF_INET6) ? "IPv6" : "any"),
                     gai_strerror (s));
      return GNUNET_SYSERR;
    }
  if (result == NULL)
    return GNUNET_SYSERR;
  if (NULL == *sa)
    {
      *sa = GNUNET_malloc (result->ai_addrlen);
      *socklen = result->ai_addrlen;
      memcpy (*sa, result->ai_addr, result->ai_addrlen);
      freeaddrinfo (result);
      return GNUNET_OK;
    }
  if (result->ai_addrlen > *socklen)
    {
      freeaddrinfo (result);
      return GNUNET_SYSERR;
    }
  *socklen = result->ai_addrlen;
  memcpy (*sa, result->ai_addr, result->ai_addrlen);
  freeaddrinfo (result);
  return GNUNET_OK;
}
#else

#if HAVE_GETHOSTBYNAME2
static int
gethostbyname2_resolve (struct GNUNET_GE_Context *ectx,
                        const char *hostname,
                        int domain, struct sockaddr **sa, socklen_t * socklen)
{
  struct hostent *hp;

  if (domain == AF_UNSPEC)
    {
      hp = gethostbyname2 (hostname, AF_INET);
      if (hp == NULL)
        hp = gethostbyname2 (hostname, AF_INET6);
    }
  else
    {
      hp = gethostbyname2 (hostname, domain);
    }
  if (hp == NULL)
    {
      GNUNET_GE_LOG (ectx,
                     GNUNET_GE_WARNING | GNUNET_GE_ADMIN | GNUNET_GE_BULK,
                     _("Could not find IP of host `%s': %s\n"),
                     hostname, hstrerror (h_errno));
      return GNUNET_SYSERR;
    }
  if ((hp->h_addrtype != domain) && (domain != 0))
    {
      GNUNET_GE_BREAK (ectx, 0);
      return GNUNET_SYSERR;
    }
  domain = hp->h_addrtype;
  if (domain == AF_INET)
    {
      GNUNET_GE_ASSERT (NULL, hp->h_length == sizeof (struct in_addr));
      if (NULL == *sa)
        {
          *sa = GNUNET_malloc (sizeof (struct sockaddr_in));
          memset (*sa, 0, sizeof (struct sockaddr_in));
          *socklen = sizeof (struct sockaddr_in);
        }
      else
        {
          if (sizeof (struct sockaddr_in) > *socklen)
            return GNUNET_SYSERR;
          *socklen = sizeof (struct sockaddr_in);
        }
      memset (*sa, 0, sizeof (struct sockaddr_in));
      (*sa)->sa_family = AF_INET;
      memcpy (&((struct sockaddr_in *) (*sa))->sin_addr,
              hp->h_addr_list[0], hp->h_length);
    }
  else
    {
      GNUNET_GE_ASSERT (NULL, hp->h_length == sizeof (struct in6_addr));
      if (NULL == *sa)
        {
          *sa = GNUNET_malloc (sizeof (struct sockaddr_in6));
          memset (*sa, 0, sizeof (struct sockaddr_in6));
          *socklen = sizeof (struct sockaddr_in6);
        }
      else
        {
          if (sizeof (struct sockaddr_in6) > *socklen)
            return GNUNET_SYSERR;
          *socklen = sizeof (struct sockaddr_in6);
        }
      memset (*sa, 0, sizeof (struct sockaddr_in6));
      (*sa)->sa_family = AF_INET6;
      memcpy (&((struct sockaddr_in6 *) (*sa))->sin6_addr,
              hp->h_addr_list[0], hp->h_length);
    }
  return GNUNET_OK;
}
#else

#if HAVE_GETHOSTBYNAME
static int
gethostbyname_resolve (struct GNUNET_GE_Context *ectx,
                       const char *hostname,
                       struct sockaddr **sa, socklen_t * socklen)
{
  struct hostent *hp;
  struct sockaddr_in *addr;

  hp = GETHOSTBYNAME (hostname);
  if (hp == NULL)
    {
      GNUNET_GE_LOG (ectx,
                     GNUNET_GE_WARNING | GNUNET_GE_ADMIN | GNUNET_GE_BULK,
                     _("Could not find IP of host `%s': %s\n"),
                     hostname, hstrerror (h_errno));
      return GNUNET_SYSERR;
    }
  if (hp->h_addrtype != AF_INET)
    {
      GNUNET_GE_BREAK (ectx, 0);
      return GNUNET_SYSERR;
    }
  GNUNET_GE_ASSERT (NULL, hp->h_length == sizeof (struct in_addr));
  if (NULL == *sa)
    {
      *sa = GNUNET_malloc (sizeof (struct sockaddr_in));
      memset (*sa, 0, sizeof (struct sockaddr_in));
      *socklen = sizeof (struct sockaddr_in);
    }
  else
    {
      if (sizeof (struct sockaddr_in) > *socklen)
        return GNUNET_SYSERR;
      *socklen = sizeof (struct sockaddr_in);
    }
  addr = (struct sockaddr_in *) *sa;
  memset (addr, 0, sizeof (struct sockaddr_in));
  addr->sin_family = AF_INET;
  memcpy (&addr->sin_addr, hp->h_addr_list[0], hp->h_length);
  return GNUNET_OK;
}
#endif
#endif
#endif


/**
 * Convert a string to an IP address.
 *
 * @param hostname the hostname to resolve
 * @param domain AF_INET or AF_INET6; use AF_UNSPEC for "any"
 * @param *sa should be of type "struct sockaddr*" and
 *        will be set to the IP address on success;
 *        if *sa is NULL, sufficient space will be
 *        allocated.
 * @param socklen will be set to the length of *sa.
 *        If *sa is not NULL, socklen will be checked
 *        to see if sufficient space is provided and
 *        updated to the amount of space actually
 *        required/used.
 * @return GNUNET_OK on success, GNUNET_SYSERR on error
 */
int
GNUNET_get_ip_from_hostname (struct GNUNET_GE_Context *ectx,
                             const char *hostname,
                             int domain,
                             struct sockaddr **sa, unsigned int *socklen)
{
  int ret;

  ret = GNUNET_NO;              /* NO: continue trying, OK: success, SYSERR: failure */
  GNUNET_mutex_lock (lock);
#if HAVE_GETADDRINFO
  if (ret == GNUNET_NO)
    ret = getaddrinfo_resolve (ectx, hostname, domain, sa, socklen);
#else
#if HAVE_GETHOSTBYNAME2
  if (ret == GNUNET_NO)
    ret = gethostbyname2_resolve (ectx, hostname, domain, sa, socklen);
#else
#if HAVE_GETHOSTBYNAME
  if ((ret == GNUNET_NO) && ((domain == AF_UNSPEC) || (domain == PF_INET)))
    ret = gethostbyname_resolve (ectx, hostname, sa, socklen);
#else
#error No resolver function available
#endif
#endif
#endif
  GNUNET_mutex_unlock (lock);
  if (ret == GNUNET_NO)
    ret = GNUNET_SYSERR;        /* no further options */
  return ret;
}

void __attribute__ ((constructor)) GNUNET_dns_ltdl_init ()
{
  lock = GNUNET_mutex_create (GNUNET_NO);
}

void __attribute__ ((destructor)) GNUNET_dns_ltdl_fini ()
{
  struct IPCache *pos;
  while (head != NULL)
    {
      pos = head->next;
#if HAVE_ADNS
      if (head->posted == GNUNET_YES)
        {
          adns_cancel (head->query);
          head->posted = GNUNET_NO;
        }
#endif
      GNUNET_free_non_null (head->addr);
      GNUNET_free (head->sa);
      GNUNET_free (head);
      head = pos;
    }
#if HAVE_ADNS
  if (a_init != 0)
    {
      a_init = 0;
      adns_finish (a_state);
    }
#endif
  GNUNET_mutex_destroy (lock);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -