1bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// Copyright 2013 The Chromium Authors. All rights reserved.
2bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// found in the LICENSE file.
4bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
56d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#ifndef __STDC_LIMIT_MACROS
66d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#define __STDC_LIMIT_MACROS
76d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#endif
86d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
9bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#include "nacl_io/host_resolver.h"
10bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <assert.h>
126d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include <stdint.h>
13bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#include <stdlib.h>
14bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#include <string.h>
15bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
16bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#include "nacl_io/kernel_proxy.h"
17116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "nacl_io/log.h"
18bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#include "nacl_io/ossocket.h"
19bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#include "nacl_io/pepper_interface.h"
20bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
21bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#ifdef PROVIDES_SOCKET_API
22bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace {
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void HintsToPPHints(const addrinfo* hints, PP_HostResolver_Hint* pp_hints) {
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  memset(pp_hints, 0, sizeof(*pp_hints));
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (hints->ai_family == AF_INET)
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    pp_hints->family = PP_NETADDRESS_FAMILY_IPV4;
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  else if (hints->ai_family == AF_INET6)
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    pp_hints->family = PP_NETADDRESS_FAMILY_IPV6;
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (hints->ai_flags & AI_CANONNAME)
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    pp_hints->flags = PP_HOSTRESOLVER_FLAG_CANONNAME;
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CreateAddrInfo(const addrinfo* hints,
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    struct sockaddr* addr,
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    const char* name,
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    addrinfo** list_start,
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    addrinfo** list_end) {
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  addrinfo* ai = static_cast<addrinfo*>(malloc(sizeof(addrinfo)));
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  memset(ai, 0, sizeof(*ai));
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (hints && hints->ai_socktype)
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ai->ai_socktype = hints->ai_socktype;
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  else
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ai->ai_socktype = SOCK_STREAM;
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (hints && hints->ai_protocol)
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ai->ai_protocol = hints->ai_protocol;
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (name)
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ai->ai_canonname = strdup(name);
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  switch (addr->sa_family) {
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case AF_INET6: {
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      sockaddr_in6* in =
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          static_cast<sockaddr_in6*>(malloc(sizeof(sockaddr_in6)));
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      *in = *(sockaddr_in6*)addr;
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ai->ai_family = AF_INET6;
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ai->ai_addr = reinterpret_cast<sockaddr*>(in);
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ai->ai_addrlen = sizeof(*in);
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      break;
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case AF_INET: {
6746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      sockaddr_in* in = static_cast<sockaddr_in*>(malloc(sizeof(sockaddr_in)));
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      *in = *(sockaddr_in*)addr;
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ai->ai_family = AF_INET;
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ai->ai_addr = reinterpret_cast<sockaddr*>(in);
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ai->ai_addrlen = sizeof(*in);
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      break;
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    default:
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      assert(0);
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return;
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (*list_start == NULL) {
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    *list_start = ai;
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    *list_end = ai;
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  (*list_end)->ai_next = ai;
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  *list_end = ai;
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
91bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochnamespace nacl_io {
92bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
93bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben MurdochHostResolver::HostResolver() : hostent_(), ppapi_(NULL) {
94bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
95bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
96bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben MurdochHostResolver::~HostResolver() {
97bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  hostent_cleanup();
98bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
99bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
100bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochvoid HostResolver::Init(PepperInterface* ppapi) {
101bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  ppapi_ = ppapi;
102bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
103bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
104bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochstruct hostent* HostResolver::gethostbyname(const char* name) {
105bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  h_errno = NETDB_INTERNAL;
106bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  struct addrinfo* ai;
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  struct addrinfo hints;
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  memset(&hints, 0, sizeof(hints));
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  hints.ai_flags = AI_CANONNAME;
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  hints.ai_family = AF_INET;
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int err = getaddrinfo(name, NULL, &hints, &ai);
113bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (err) {
114bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    switch (err) {
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case EAI_SYSTEM:
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        h_errno = NO_RECOVERY;
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        break;
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case EAI_NONAME:
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        h_errno = HOST_NOT_FOUND;
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        break;
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      default:
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        h_errno = NETDB_INTERNAL;
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        break;
124bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    }
125bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return NULL;
126bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
127bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
128bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // We use a single hostent struct for all calls to to gethostbyname
129bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // (as explicitly permitted by the spec - gethostbyname is NOT supposed to
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // be threadsafe!).  However by using a lock around all the global data
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // manipulation we can at least ensure that the call doesn't crash.
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AUTO_LOCK(gethostbyname_lock_);
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The first thing we do is free any malloced data left over from
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // the last call.
136bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  hostent_cleanup();
137bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  switch (ai->ai_family) {
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case AF_INET:
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      hostent_.h_addrtype = AF_INET;
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      hostent_.h_length = sizeof(in_addr);
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      break;
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case AF_INET6:
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      hostent_.h_addrtype = AF_INET6;
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      hostent_.h_length = sizeof(in6_addr);
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      break;
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    default:
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return NULL;
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
150bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (ai->ai_canonname != NULL)
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    hostent_.h_name = strdup(ai->ai_canonname);
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  else
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    hostent_.h_name = strdup(name);
155bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
156bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // Aliases aren't supported at the moment, so we just make an empty list.
157bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  hostent_.h_aliases = static_cast<char**>(malloc(sizeof(char*)));
158bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (NULL == hostent_.h_aliases)
159bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return NULL;
160bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  hostent_.h_aliases[0] = NULL;
161bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Count number of address in list
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int num_addresses = 0;
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  struct addrinfo* current = ai;
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  while (current != NULL) {
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Only count address that have the same type as first address
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (current->ai_family == hostent_.h_addrtype)
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      num_addresses++;
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    current = current->ai_next;
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Allocate address list
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  hostent_.h_addr_list = static_cast<char**>(calloc(num_addresses + 1,
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                    sizeof(char*)));
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (NULL == hostent_.h_addr_list)
176bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return NULL;
177bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Copy all addresses of the relevant family.
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  current = ai;
1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  char** hostent_addr = hostent_.h_addr_list;
1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  while (current != NULL) {
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (current->ai_family != hostent_.h_addrtype) {
1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      current = current->ai_next;
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      continue;
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    *hostent_addr = static_cast<char*>(malloc(hostent_.h_length));
1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    switch (current->ai_family) {
1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case AF_INET: {
1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        sockaddr_in* in = reinterpret_cast<sockaddr_in*>(current->ai_addr);
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        memcpy(*hostent_addr, &in->sin_addr.s_addr, hostent_.h_length);
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        break;
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case AF_INET6: {
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        sockaddr_in6* in6 = reinterpret_cast<sockaddr_in6*>(current->ai_addr);
1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        memcpy(*hostent_addr, &in6->sin6_addr.s6_addr, hostent_.h_length);
1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        break;
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    current = current->ai_next;
2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    hostent_addr++;
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  freeaddrinfo(ai);
204cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
205cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#if !defined(h_addr)
206cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Copy element zero of h_addr_list to h_addr when h_addr is not defined
207cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // as in some libc's h_addr may be a separate member instead of a macro.
208cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  hostent_.h_addr = hostent_.h_addr_list[0];
209cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#endif
210cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return &hostent_;
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
21446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void HostResolver::freeaddrinfo(struct addrinfo* res) {
2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  while (res) {
2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    struct addrinfo* cur = res;
2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    res = res->ai_next;
2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    free(cur->ai_addr);
2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    free(cur->ai_canonname);
2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    free(cur);
2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciint HostResolver::getnameinfo(const struct sockaddr *sa,
2251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                              socklen_t salen,
2261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                              char *host,
2271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                              size_t hostlen,
2281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                              char *serv,
2291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                              size_t servlen,
2301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                              int flags) {
2311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return ENOSYS;
2321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
2331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
23446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)int HostResolver::getaddrinfo(const char* node,
23546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                              const char* service,
2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              const struct addrinfo* hints_in,
2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              struct addrinfo** result) {
2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  *result = NULL;
2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  struct addrinfo* end = NULL;
2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
241116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (node == NULL && service == NULL) {
242116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    LOG_TRACE("node and service are NULL.");
2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return EAI_NONAME;
244116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Check the service name (port).  Currently we only handle numeric
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // services.
2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  long port = 0;
2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (service != NULL) {
2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    char* cp;
2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    port = strtol(service, &cp, 10);
2526d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    if (port >= 0 && port <= UINT16_MAX && *cp == '\0') {
2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      port = htons(port);
2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    } else {
255116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      LOG_TRACE("Service \"%s\" not supported.", service);
2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return EAI_SERVICE;
2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  struct addrinfo default_hints;
2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  memset(&default_hints, 0, sizeof(default_hints));
2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const struct addrinfo* hints = hints_in ? hints_in : &default_hints;
2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Verify values passed in hints structure
2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  switch (hints->ai_family) {
2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case AF_INET6:
2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case AF_INET:
2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case AF_UNSPEC:
269bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      break;
270bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    default:
271116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      LOG_TRACE("Unknown family: %d.", hints->ai_family);
2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return EAI_FAMILY;
2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  struct sockaddr_in addr_in;
2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  memset(&addr_in, 0, sizeof(addr_in));
2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  addr_in.sin_family = AF_INET;
2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  addr_in.sin_port = port;
2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  struct sockaddr_in6 addr_in6;
2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  memset(&addr_in6, 0, sizeof(addr_in6));
2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  addr_in6.sin6_family = AF_INET6;
2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  addr_in6.sin6_port = port;
2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (node) {
2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Handle numeric node name.
2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (hints->ai_family == AF_INET || hints->ai_family == AF_UNSPEC) {
2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      in_addr in;
2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (inet_pton(AF_INET, node, &in)) {
2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        addr_in.sin_addr = in;
2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        CreateAddrInfo(hints, (sockaddr*)&addr_in, node, result, &end);
2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return 0;
2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (hints->ai_family == AF_INET6 || hints->ai_family == AF_UNSPEC) {
2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      in6_addr in6;
2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (inet_pton(AF_INET6, node, &in6)) {
2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        addr_in6.sin6_addr = in6;
3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        CreateAddrInfo(hints, (sockaddr*)&addr_in6, node, result, &end);
3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return 0;
3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Handle AI_PASSIVE (used for listening sockets, e.g. INADDR_ANY)
3075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (node == NULL && (hints->ai_flags & AI_PASSIVE)) {
3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (hints->ai_family == AF_INET6 || hints->ai_family == AF_UNSPEC) {
3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const in6_addr in6addr_any = IN6ADDR_ANY_INIT;
3105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      memcpy(&addr_in6.sin6_addr.s6_addr, &in6addr_any, sizeof(in6addr_any));
3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      CreateAddrInfo(hints, (sockaddr*)&addr_in6, NULL, result, &end);
3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (hints->ai_family == AF_INET || hints->ai_family == AF_UNSPEC) {
3155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      addr_in.sin_addr.s_addr = INADDR_ANY;
3165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      CreateAddrInfo(hints, (sockaddr*)&addr_in, NULL, result, &end);
3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return 0;
3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
321116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (NULL == ppapi_) {
322116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    LOG_ERROR("ppapi_ is NULL.");
3235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return EAI_SYSTEM;
324116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Use PPAPI interface to resolve nodename
3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  HostResolverInterface* resolver_iface = ppapi_->GetHostResolverInterface();
328116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  VarInterface* var_iface = ppapi_->GetVarInterface();
3295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  NetAddressInterface* netaddr_iface = ppapi_->GetNetAddressInterface();
3305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
331116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!(resolver_iface && var_iface && netaddr_iface)) {
332116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    LOG_ERROR("Got NULL interface(s): %s%s%s",
333116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch              resolver_iface ? "" : "HostResolver ",
334116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch              var_iface ? "" : "Var ",
335116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch              netaddr_iface ? "" : "NetAddress");
3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return EAI_SYSTEM;
337116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedResource scoped_resolver(ppapi_,
3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 resolver_iface->Create(ppapi_->GetInstance()));
3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PP_Resource resolver = scoped_resolver.pp_resource();
3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  struct PP_HostResolver_Hint pp_hints;
3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  HintsToPPHints(hints, &pp_hints);
3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int err = resolver_iface->Resolve(resolver,
3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    node,
3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    0,
3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    &pp_hints,
3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    PP_BlockUntilComplete());
3515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (err) {
3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    switch (err) {
3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case PP_ERROR_NOACCESS:
3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return EAI_SYSTEM;
3555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case PP_ERROR_NAME_NOT_RESOLVED:
3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return EAI_NONAME;
3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      default:
3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return EAI_SYSTEM;
3595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  char* canon_name = NULL;
3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (hints->ai_flags & AI_CANONNAME) {
3645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    PP_Var name_var = resolver_iface->GetCanonicalName(resolver);
3655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (PP_VARTYPE_STRING == name_var.type) {
3665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      uint32_t len = 0;
367116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      const char* tmp = var_iface->VarToUtf8(name_var, &len);
3685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // For some reason GetCanonicalName alway returns an empty
3695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // string so this condition is never true.
3705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // TODO(sbc): investigate this issue with PPAPI team.
3715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (len > 0) {
3725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        // Copy and NULL-terminate the UTF8 string var.
37346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        canon_name = static_cast<char*>(malloc(len + 1));
3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        strncpy(canon_name, tmp, len);
3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        canon_name[len] = '\0';
3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
3785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!canon_name)
3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      canon_name = strdup(node);
380116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    var_iface->Release(name_var);
381bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
382bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
3835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int num_addresses = resolver_iface->GetNetAddressCount(resolver);
384bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (0 == num_addresses)
3855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return EAI_NODATA;
386bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
3875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Convert address to sockaddr struct.
3885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (int i = 0; i < num_addresses; i++) {
3895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ScopedResource addr(ppapi_, resolver_iface->GetNetAddress(resolver, i));
3905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    PP_Resource resource = addr.pp_resource();
3915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    assert(resource != 0);
3925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    assert(PP_ToBool(netaddr_iface->IsNetAddress(resource)));
3935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    struct sockaddr* sockaddr = NULL;
3945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    switch (netaddr_iface->GetFamily(resource)) {
3955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case PP_NETADDRESS_FAMILY_IPV4: {
3965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        struct PP_NetAddress_IPv4 pp_addr;
3975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (!netaddr_iface->DescribeAsIPv4Address(resource, &pp_addr)) {
3985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          assert(false);
3995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          break;
4005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        }
4015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        memcpy(&addr_in.sin_addr.s_addr, pp_addr.addr, sizeof(in_addr_t));
4025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        sockaddr = (struct sockaddr*)&addr_in;
4035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        break;
404bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      }
4055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case PP_NETADDRESS_FAMILY_IPV6: {
4065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        struct PP_NetAddress_IPv6 pp_addr;
4075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (!netaddr_iface->DescribeAsIPv6Address(resource, &pp_addr)) {
4085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          assert(false);
4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          break;
4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        }
41146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        memcpy(&addr_in6.sin6_addr.s6_addr, pp_addr.addr, sizeof(in6_addr));
4125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        sockaddr = (struct sockaddr*)&addr_in6;
4135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        break;
4145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
4155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      default:
4165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return EAI_SYSTEM;
4175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
4185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (sockaddr != NULL)
4205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      CreateAddrInfo(hints, sockaddr, canon_name, result, &end);
4215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (canon_name) {
4235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      free(canon_name);
4245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      canon_name = NULL;
425bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    }
426bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
4275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return 0;
429bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
430bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
431bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// Frees all of the deep pointers in a hostent struct. Called between uses of
432bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// gethostbyname, and when the kernel_proxy object is destroyed.
433bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochvoid HostResolver::hostent_cleanup() {
434bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (NULL != hostent_.h_name) {
435bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    free(hostent_.h_name);
436bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
437bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (NULL != hostent_.h_aliases) {
43846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    for (int i = 0; NULL != hostent_.h_aliases[i]; i++) {
439bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      free(hostent_.h_aliases[i]);
440bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    }
441bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    free(hostent_.h_aliases);
442bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
443bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (NULL != hostent_.h_addr_list) {
44446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    for (int i = 0; NULL != hostent_.h_addr_list[i]; i++) {
445bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      free(hostent_.h_addr_list[i]);
446bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    }
447bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    free(hostent_.h_addr_list);
448bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
449bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  hostent_.h_name = NULL;
450bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  hostent_.h_aliases = NULL;
451bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  hostent_.h_addr_list = NULL;
452cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#if !defined(h_addr)
453cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Initialize h_addr separately in the case where it is not a macro.
454cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  hostent_.h_addr = NULL;
455cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#endif
456bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
457bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
458bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}  // namespace nacl_io
459bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
460bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#endif  // PROVIDES_SOCKET_API
461