1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef __STDC_LIMIT_MACROS 6 #define __STDC_LIMIT_MACROS 7 #endif 8 9 #include "nacl_io/host_resolver.h" 10 11 #include <assert.h> 12 #include <stdint.h> 13 #include <stdlib.h> 14 #include <string.h> 15 16 #include "nacl_io/kernel_proxy.h" 17 #include "nacl_io/ossocket.h" 18 #include "nacl_io/pepper_interface.h" 19 20 #ifdef PROVIDES_SOCKET_API 21 22 namespace { 23 24 void HintsToPPHints(const addrinfo* hints, PP_HostResolver_Hint* pp_hints) { 25 memset(pp_hints, 0, sizeof(*pp_hints)); 26 27 if (hints->ai_family == AF_INET) 28 pp_hints->family = PP_NETADDRESS_FAMILY_IPV4; 29 else if (hints->ai_family == AF_INET6) 30 pp_hints->family = PP_NETADDRESS_FAMILY_IPV6; 31 32 if (hints->ai_flags & AI_CANONNAME) 33 pp_hints->flags = PP_HOSTRESOLVER_FLAG_CANONNAME; 34 } 35 36 void CreateAddrInfo(const addrinfo* hints, 37 struct sockaddr* addr, 38 const char* name, 39 addrinfo** list_start, 40 addrinfo** list_end) { 41 addrinfo* ai = static_cast<addrinfo*>(malloc(sizeof(addrinfo))); 42 memset(ai, 0, sizeof(*ai)); 43 44 if (hints && hints->ai_socktype) 45 ai->ai_socktype = hints->ai_socktype; 46 else 47 ai->ai_socktype = SOCK_STREAM; 48 49 if (hints && hints->ai_protocol) 50 ai->ai_protocol = hints->ai_protocol; 51 52 if (name) 53 ai->ai_canonname = strdup(name); 54 55 switch (addr->sa_family) { 56 case AF_INET6: { 57 sockaddr_in6* in = 58 static_cast<sockaddr_in6*>(malloc(sizeof(sockaddr_in6))); 59 *in = *(sockaddr_in6*)addr; 60 ai->ai_family = AF_INET6; 61 ai->ai_addr = reinterpret_cast<sockaddr*>(in); 62 ai->ai_addrlen = sizeof(*in); 63 break; 64 } 65 case AF_INET: { 66 sockaddr_in* in = static_cast<sockaddr_in*>(malloc(sizeof(sockaddr_in))); 67 *in = *(sockaddr_in*)addr; 68 ai->ai_family = AF_INET; 69 ai->ai_addr = reinterpret_cast<sockaddr*>(in); 70 ai->ai_addrlen = sizeof(*in); 71 break; 72 } 73 default: 74 assert(0); 75 return; 76 } 77 78 if (*list_start == NULL) { 79 *list_start = ai; 80 *list_end = ai; 81 return; 82 } 83 84 (*list_end)->ai_next = ai; 85 *list_end = ai; 86 } 87 88 } // namespace 89 90 namespace nacl_io { 91 92 HostResolver::HostResolver() : hostent_(), ppapi_(NULL) { 93 } 94 95 HostResolver::~HostResolver() { 96 hostent_cleanup(); 97 } 98 99 void HostResolver::Init(PepperInterface* ppapi) { 100 ppapi_ = ppapi; 101 } 102 103 struct hostent* HostResolver::gethostbyname(const char* name) { 104 h_errno = NETDB_INTERNAL; 105 106 struct addrinfo* ai; 107 struct addrinfo hints; 108 memset(&hints, 0, sizeof(hints)); 109 hints.ai_flags = AI_CANONNAME; 110 hints.ai_family = AF_INET; 111 int err = getaddrinfo(name, NULL, &hints, &ai); 112 if (err) { 113 switch (err) { 114 case EAI_SYSTEM: 115 h_errno = NO_RECOVERY; 116 break; 117 case EAI_NONAME: 118 h_errno = HOST_NOT_FOUND; 119 break; 120 default: 121 h_errno = NETDB_INTERNAL; 122 break; 123 } 124 return NULL; 125 } 126 127 // We use a single hostent struct for all calls to to gethostbyname 128 // (as explicitly permitted by the spec - gethostbyname is NOT supposed to 129 // be threadsafe!). However by using a lock around all the global data 130 // manipulation we can at least ensure that the call doesn't crash. 131 AUTO_LOCK(gethostbyname_lock_); 132 133 // The first thing we do is free any malloced data left over from 134 // the last call. 135 hostent_cleanup(); 136 137 switch (ai->ai_family) { 138 case AF_INET: 139 hostent_.h_addrtype = AF_INET; 140 hostent_.h_length = sizeof(in_addr); 141 break; 142 case AF_INET6: 143 hostent_.h_addrtype = AF_INET6; 144 hostent_.h_length = sizeof(in6_addr); 145 break; 146 default: 147 return NULL; 148 } 149 150 if (ai->ai_canonname != NULL) 151 hostent_.h_name = strdup(ai->ai_canonname); 152 else 153 hostent_.h_name = strdup(name); 154 155 // Aliases aren't supported at the moment, so we just make an empty list. 156 hostent_.h_aliases = static_cast<char**>(malloc(sizeof(char*))); 157 if (NULL == hostent_.h_aliases) 158 return NULL; 159 hostent_.h_aliases[0] = NULL; 160 161 // Count number of address in list 162 int num_addresses = 0; 163 struct addrinfo* current = ai; 164 while (current != NULL) { 165 // Only count address that have the same type as first address 166 if (current->ai_family == hostent_.h_addrtype) 167 num_addresses++; 168 current = current->ai_next; 169 } 170 171 // Allocate address list 172 hostent_.h_addr_list = static_cast<char**>(calloc(num_addresses + 1, 173 sizeof(char*))); 174 if (NULL == hostent_.h_addr_list) 175 return NULL; 176 177 // Copy all addresses of the relevant family. 178 current = ai; 179 char** hostent_addr = hostent_.h_addr_list; 180 while (current != NULL) { 181 if (current->ai_family != hostent_.h_addrtype) { 182 current = current->ai_next; 183 continue; 184 } 185 *hostent_addr = static_cast<char*>(malloc(hostent_.h_length)); 186 switch (current->ai_family) { 187 case AF_INET: { 188 sockaddr_in* in = reinterpret_cast<sockaddr_in*>(current->ai_addr); 189 memcpy(*hostent_addr, &in->sin_addr.s_addr, hostent_.h_length); 190 break; 191 } 192 case AF_INET6: { 193 sockaddr_in6* in6 = reinterpret_cast<sockaddr_in6*>(current->ai_addr); 194 memcpy(*hostent_addr, &in6->sin6_addr.s6_addr, hostent_.h_length); 195 break; 196 } 197 } 198 current = current->ai_next; 199 hostent_addr++; 200 } 201 202 freeaddrinfo(ai); 203 204 #if !defined(h_addr) 205 // Copy element zero of h_addr_list to h_addr when h_addr is not defined 206 // as in some libc's h_addr may be a separate member instead of a macro. 207 hostent_.h_addr = hostent_.h_addr_list[0]; 208 #endif 209 210 return &hostent_; 211 } 212 213 void HostResolver::freeaddrinfo(struct addrinfo* res) { 214 while (res) { 215 struct addrinfo* cur = res; 216 res = res->ai_next; 217 free(cur->ai_addr); 218 free(cur->ai_canonname); 219 free(cur); 220 } 221 } 222 223 int HostResolver::getaddrinfo(const char* node, 224 const char* service, 225 const struct addrinfo* hints_in, 226 struct addrinfo** result) { 227 *result = NULL; 228 struct addrinfo* end = NULL; 229 230 if (node == NULL && service == NULL) 231 return EAI_NONAME; 232 233 // Check the service name (port). Currently we only handle numeric 234 // services. 235 long port = 0; 236 if (service != NULL) { 237 char* cp; 238 port = strtol(service, &cp, 10); 239 if (port >= 0 && port <= UINT16_MAX && *cp == '\0') { 240 port = htons(port); 241 } else { 242 return EAI_SERVICE; 243 } 244 } 245 246 struct addrinfo default_hints; 247 memset(&default_hints, 0, sizeof(default_hints)); 248 const struct addrinfo* hints = hints_in ? hints_in : &default_hints; 249 250 // Verify values passed in hints structure 251 switch (hints->ai_family) { 252 case AF_INET6: 253 case AF_INET: 254 case AF_UNSPEC: 255 break; 256 default: 257 return EAI_FAMILY; 258 } 259 260 struct sockaddr_in addr_in; 261 memset(&addr_in, 0, sizeof(addr_in)); 262 addr_in.sin_family = AF_INET; 263 addr_in.sin_port = port; 264 265 struct sockaddr_in6 addr_in6; 266 memset(&addr_in6, 0, sizeof(addr_in6)); 267 addr_in6.sin6_family = AF_INET6; 268 addr_in6.sin6_port = port; 269 270 if (node) { 271 // Handle numeric node name. 272 if (hints->ai_family == AF_INET || hints->ai_family == AF_UNSPEC) { 273 in_addr in; 274 if (inet_pton(AF_INET, node, &in)) { 275 addr_in.sin_addr = in; 276 CreateAddrInfo(hints, (sockaddr*)&addr_in, node, result, &end); 277 return 0; 278 } 279 } 280 281 if (hints->ai_family == AF_INET6 || hints->ai_family == AF_UNSPEC) { 282 in6_addr in6; 283 if (inet_pton(AF_INET6, node, &in6)) { 284 addr_in6.sin6_addr = in6; 285 CreateAddrInfo(hints, (sockaddr*)&addr_in6, node, result, &end); 286 return 0; 287 } 288 } 289 } 290 291 // Handle AI_PASSIVE (used for listening sockets, e.g. INADDR_ANY) 292 if (node == NULL && (hints->ai_flags & AI_PASSIVE)) { 293 if (hints->ai_family == AF_INET6 || hints->ai_family == AF_UNSPEC) { 294 const in6_addr in6addr_any = IN6ADDR_ANY_INIT; 295 memcpy(&addr_in6.sin6_addr.s6_addr, &in6addr_any, sizeof(in6addr_any)); 296 CreateAddrInfo(hints, (sockaddr*)&addr_in6, NULL, result, &end); 297 } 298 299 if (hints->ai_family == AF_INET || hints->ai_family == AF_UNSPEC) { 300 addr_in.sin_addr.s_addr = INADDR_ANY; 301 CreateAddrInfo(hints, (sockaddr*)&addr_in, NULL, result, &end); 302 } 303 return 0; 304 } 305 306 if (NULL == ppapi_) 307 return EAI_SYSTEM; 308 309 // Use PPAPI interface to resolve nodename 310 HostResolverInterface* resolver_iface = ppapi_->GetHostResolverInterface(); 311 VarInterface* var_interface = ppapi_->GetVarInterface(); 312 NetAddressInterface* netaddr_iface = ppapi_->GetNetAddressInterface(); 313 314 if (NULL == resolver_iface || NULL == var_interface || NULL == netaddr_iface) 315 return EAI_SYSTEM; 316 317 ScopedResource scoped_resolver(ppapi_, 318 resolver_iface->Create(ppapi_->GetInstance())); 319 PP_Resource resolver = scoped_resolver.pp_resource(); 320 321 struct PP_HostResolver_Hint pp_hints; 322 HintsToPPHints(hints, &pp_hints); 323 324 int err = resolver_iface->Resolve(resolver, 325 node, 326 0, 327 &pp_hints, 328 PP_BlockUntilComplete()); 329 if (err) { 330 switch (err) { 331 case PP_ERROR_NOACCESS: 332 return EAI_SYSTEM; 333 case PP_ERROR_NAME_NOT_RESOLVED: 334 return EAI_NONAME; 335 default: 336 return EAI_SYSTEM; 337 } 338 } 339 340 char* canon_name = NULL; 341 if (hints->ai_flags & AI_CANONNAME) { 342 PP_Var name_var = resolver_iface->GetCanonicalName(resolver); 343 if (PP_VARTYPE_STRING == name_var.type) { 344 uint32_t len = 0; 345 const char* tmp = var_interface->VarToUtf8(name_var, &len); 346 // For some reason GetCanonicalName alway returns an empty 347 // string so this condition is never true. 348 // TODO(sbc): investigate this issue with PPAPI team. 349 if (len > 0) { 350 // Copy and NULL-terminate the UTF8 string var. 351 canon_name = static_cast<char*>(malloc(len + 1)); 352 strncpy(canon_name, tmp, len); 353 canon_name[len] = '\0'; 354 } 355 } 356 if (!canon_name) 357 canon_name = strdup(node); 358 var_interface->Release(name_var); 359 } 360 361 int num_addresses = resolver_iface->GetNetAddressCount(resolver); 362 if (0 == num_addresses) 363 return EAI_NODATA; 364 365 // Convert address to sockaddr struct. 366 for (int i = 0; i < num_addresses; i++) { 367 ScopedResource addr(ppapi_, resolver_iface->GetNetAddress(resolver, i)); 368 PP_Resource resource = addr.pp_resource(); 369 assert(resource != 0); 370 assert(PP_ToBool(netaddr_iface->IsNetAddress(resource))); 371 struct sockaddr* sockaddr = NULL; 372 switch (netaddr_iface->GetFamily(resource)) { 373 case PP_NETADDRESS_FAMILY_IPV4: { 374 struct PP_NetAddress_IPv4 pp_addr; 375 if (!netaddr_iface->DescribeAsIPv4Address(resource, &pp_addr)) { 376 assert(false); 377 break; 378 } 379 memcpy(&addr_in.sin_addr.s_addr, pp_addr.addr, sizeof(in_addr_t)); 380 sockaddr = (struct sockaddr*)&addr_in; 381 break; 382 } 383 case PP_NETADDRESS_FAMILY_IPV6: { 384 struct PP_NetAddress_IPv6 pp_addr; 385 if (!netaddr_iface->DescribeAsIPv6Address(resource, &pp_addr)) { 386 assert(false); 387 break; 388 } 389 memcpy(&addr_in6.sin6_addr.s6_addr, pp_addr.addr, sizeof(in6_addr)); 390 sockaddr = (struct sockaddr*)&addr_in6; 391 break; 392 } 393 default: 394 return EAI_SYSTEM; 395 } 396 397 if (sockaddr != NULL) 398 CreateAddrInfo(hints, sockaddr, canon_name, result, &end); 399 400 if (canon_name) { 401 free(canon_name); 402 canon_name = NULL; 403 } 404 } 405 406 return 0; 407 } 408 409 // Frees all of the deep pointers in a hostent struct. Called between uses of 410 // gethostbyname, and when the kernel_proxy object is destroyed. 411 void HostResolver::hostent_cleanup() { 412 if (NULL != hostent_.h_name) { 413 free(hostent_.h_name); 414 } 415 if (NULL != hostent_.h_aliases) { 416 for (int i = 0; NULL != hostent_.h_aliases[i]; i++) { 417 free(hostent_.h_aliases[i]); 418 } 419 free(hostent_.h_aliases); 420 } 421 if (NULL != hostent_.h_addr_list) { 422 for (int i = 0; NULL != hostent_.h_addr_list[i]; i++) { 423 free(hostent_.h_addr_list[i]); 424 } 425 free(hostent_.h_addr_list); 426 } 427 hostent_.h_name = NULL; 428 hostent_.h_aliases = NULL; 429 hostent_.h_addr_list = NULL; 430 #if !defined(h_addr) 431 // Initialize h_addr separately in the case where it is not a macro. 432 hostent_.h_addr = NULL; 433 #endif 434 } 435 436 } // namespace nacl_io 437 438 #endif // PROVIDES_SOCKET_API 439