1 // Copyright (c) 2012 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 #include "ppapi/shared_impl/private/net_address_private_impl.h" 6 7 #if defined(OS_WIN) 8 #include <windows.h> 9 #include <winsock2.h> 10 #include <ws2tcpip.h> 11 #elif defined(OS_POSIX) && !defined(OS_NACL) 12 #include <arpa/inet.h> 13 #include <sys/socket.h> 14 #include <sys/types.h> 15 #endif 16 17 #include <string.h> 18 19 #include <string> 20 21 #include "base/basictypes.h" 22 #include "base/logging.h" 23 #include "base/strings/stringprintf.h" 24 #include "build/build_config.h" 25 #include "ppapi/c/pp_var.h" 26 #include "ppapi/c/private/ppb_net_address_private.h" 27 #include "ppapi/shared_impl/proxy_lock.h" 28 #include "ppapi/shared_impl/var.h" 29 #include "ppapi/thunk/thunk.h" 30 31 #if defined(OS_MACOSX) 32 // This is a bit evil, but it's standard operating procedure for |s6_addr|.... 33 #define s6_addr16 __u6_addr.__u6_addr16 34 #endif 35 36 #if defined(OS_WIN) 37 // The type of |sockaddr::sa_family|. 38 typedef ADDRESS_FAMILY sa_family_t; 39 40 #define s6_addr16 u.Word 41 #define ntohs(x) _byteswap_ushort(x) 42 #define htons(x) _byteswap_ushort(x) 43 #endif // defined(OS_WIN) 44 45 // The net address interface doesn't have a normal C -> C++ thunk since it 46 // doesn't actually have any proxy wrapping or associated objects; it's just a 47 // call into base. So we implement the entire interface here, using the thunk 48 // namespace so it magically gets hooked up in the proper places. 49 50 namespace ppapi { 51 52 namespace { 53 54 // Define our own net-host-net conversion, rather than reuse the one in 55 // base/sys_byteorder.h, to simplify the NaCl port. NaCl has no byte swap 56 // primitives. 57 uint16 ConvertFromNetEndian16(uint16 x) { 58 #if defined(ARCH_CPU_LITTLE_ENDIAN) 59 return (x << 8) | (x >> 8); 60 #else 61 return x; 62 #endif 63 } 64 65 uint16 ConvertToNetEndian16(uint16 x) { 66 #if defined(ARCH_CPU_LITTLE_ENDIAN) 67 return (x << 8) | (x >> 8); 68 #else 69 return x; 70 #endif 71 } 72 73 static const size_t kIPv4AddressSize = 4; 74 static const size_t kIPv6AddressSize = 16; 75 76 // This structure is a platform-independent representation of a network address. 77 // It is a private format that we embed in PP_NetAddress_Private and is NOT part 78 // of the stable Pepper API. 79 struct NetAddress { 80 bool is_valid; 81 bool is_ipv6; // if true, IPv6, otherwise IPv4. 82 uint16_t port; // host order, not network order. 83 int32_t flow_info; // 0 for IPv4 84 int32_t scope_id; // 0 for IPv4 85 // IPv4 addresses are 4 bytes. IPv6 are 16 bytes. Addresses are stored in net 86 // order (big-endian), which only affects IPv6 addresses, which consist of 8 87 // 16-bit components. These will be byte-swapped on small-endian hosts. 88 uint8_t address[kIPv6AddressSize]; 89 }; 90 91 // Make sure that sizeof(NetAddress) is the same for all compilers. This ensures 92 // that the alignment is the same on both sides of the NaCl proxy, which is 93 // important because we serialize and deserialize PP_NetAddress_Private by 94 // simply copying the raw bytes. 95 COMPILE_ASSERT(sizeof(NetAddress) == 28, 96 NetAddress_different_for_compiler); 97 98 // Make sure the storage in |PP_NetAddress_Private| is big enough. (Do it here 99 // since the data is opaque elsewhere.) 100 COMPILE_ASSERT(sizeof(reinterpret_cast<PP_NetAddress_Private*>(0)->data) >= 101 sizeof(NetAddress), 102 PP_NetAddress_Private_data_too_small); 103 104 size_t GetAddressSize(const NetAddress* net_addr) { 105 return net_addr->is_ipv6 ? kIPv6AddressSize : kIPv4AddressSize; 106 } 107 108 // Convert to embedded struct if it has been initialized. 109 NetAddress* ToNetAddress(PP_NetAddress_Private* addr) { 110 if (!addr || addr->size != sizeof(NetAddress)) 111 return NULL; 112 return reinterpret_cast<NetAddress*>(addr->data); 113 } 114 115 const NetAddress* ToNetAddress(const PP_NetAddress_Private* addr) { 116 return ToNetAddress(const_cast<PP_NetAddress_Private*>(addr)); 117 } 118 119 // Initializes the NetAddress struct embedded in a PP_NetAddress_Private struct. 120 // Zeroes the memory, so net_addr->is_valid == false. 121 NetAddress* InitNetAddress(PP_NetAddress_Private* addr) { 122 addr->size = sizeof(NetAddress); 123 NetAddress* net_addr = ToNetAddress(addr); 124 DCHECK(net_addr); 125 memset(net_addr, 0, sizeof(NetAddress)); 126 return net_addr; 127 } 128 129 bool IsValid(const NetAddress* net_addr) { 130 return net_addr && net_addr->is_valid; 131 } 132 133 PP_NetAddressFamily_Private GetFamily(const PP_NetAddress_Private* addr) { 134 const NetAddress* net_addr = ToNetAddress(addr); 135 if (!IsValid(net_addr)) 136 return PP_NETADDRESSFAMILY_PRIVATE_UNSPECIFIED; 137 return net_addr->is_ipv6 ? 138 PP_NETADDRESSFAMILY_PRIVATE_IPV6 : PP_NETADDRESSFAMILY_PRIVATE_IPV4; 139 } 140 141 uint16_t GetPort(const PP_NetAddress_Private* addr) { 142 const NetAddress* net_addr = ToNetAddress(addr); 143 if (!IsValid(net_addr)) 144 return 0; 145 return net_addr->port; 146 } 147 148 PP_Bool GetAddress(const PP_NetAddress_Private* addr, 149 void* address, 150 uint16_t address_size) { 151 const NetAddress* net_addr = ToNetAddress(addr); 152 if (!IsValid(net_addr)) 153 return PP_FALSE; 154 size_t net_addr_size = GetAddressSize(net_addr); 155 // address_size must be big enough. 156 if (net_addr_size > address_size) 157 return PP_FALSE; 158 memcpy(address, net_addr->address, net_addr_size); 159 return PP_TRUE; 160 } 161 162 uint32_t GetScopeID(const PP_NetAddress_Private* addr) { 163 const NetAddress* net_addr = ToNetAddress(addr); 164 if (!IsValid(net_addr)) 165 return 0; 166 return net_addr->scope_id; 167 } 168 169 PP_Bool AreHostsEqual(const PP_NetAddress_Private* addr1, 170 const PP_NetAddress_Private* addr2) { 171 const NetAddress* net_addr1 = ToNetAddress(addr1); 172 const NetAddress* net_addr2 = ToNetAddress(addr2); 173 if (!IsValid(net_addr1) || !IsValid(net_addr2)) 174 return PP_FALSE; 175 176 if ((net_addr1->is_ipv6 != net_addr2->is_ipv6) || 177 (net_addr1->flow_info != net_addr2->flow_info) || 178 (net_addr1->scope_id != net_addr2->scope_id)) 179 return PP_FALSE; 180 181 size_t net_addr_size = GetAddressSize(net_addr1); 182 for (size_t i = 0; i < net_addr_size; i++) { 183 if (net_addr1->address[i] != net_addr2->address[i]) 184 return PP_FALSE; 185 } 186 187 return PP_TRUE; 188 } 189 190 PP_Bool AreEqual(const PP_NetAddress_Private* addr1, 191 const PP_NetAddress_Private* addr2) { 192 // |AreHostsEqual()| will also validate the addresses and return false if 193 // either is invalid. 194 if (!AreHostsEqual(addr1, addr2)) 195 return PP_FALSE; 196 197 // AreHostsEqual has validated these net addresses. 198 const NetAddress* net_addr1 = ToNetAddress(addr1); 199 const NetAddress* net_addr2 = ToNetAddress(addr2); 200 return PP_FromBool(net_addr1->port == net_addr2->port); 201 } 202 203 std::string ConvertIPv4AddressToString(const NetAddress* net_addr, 204 bool include_port) { 205 std::string description = base::StringPrintf( 206 "%u.%u.%u.%u", 207 net_addr->address[0], net_addr->address[1], 208 net_addr->address[2], net_addr->address[3]); 209 if (include_port) 210 base::StringAppendF(&description, ":%u", net_addr->port); 211 return description; 212 } 213 214 // Format an IPv6 address for human consumption, basically according to RFC 215 // 5952. 216 // - If the scope is nonzero, it is appended to the address as "%<scope>" (this 217 // is not in RFC 5952, but consistent with |getnameinfo()| on Linux and 218 // Windows). 219 // - If |include_port| is true, the address (possibly including the scope) is 220 // enclosed in square brackets and ":<port>" is appended, i.e., the overall 221 // format is "[<address>]:<port>". 222 // - If the address is an IPv4 address embedded IPv6 (per RFC 4291), then the 223 // mixed format is used, e.g., "::ffff:192.168.1.2". This is optional per RFC 224 // 5952, but consistent with |getnameinfo()|. 225 std::string ConvertIPv6AddressToString(const NetAddress* net_addr, 226 bool include_port) { 227 std::string description(include_port ? "[" : ""); 228 229 const uint16_t* address16 = 230 reinterpret_cast<const uint16_t*>(net_addr->address); 231 // IPv4 address embedded in IPv6. 232 if (address16[0] == 0 && address16[1] == 0 && 233 address16[2] == 0 && address16[3] == 0 && 234 address16[4] == 0 && 235 (address16[5] == 0 || address16[5] == 0xffff)) { 236 base::StringAppendF( 237 &description, 238 address16[5] == 0 ? "::%u.%u.%u.%u" : "::ffff:%u.%u.%u.%u", 239 net_addr->address[12], 240 net_addr->address[13], 241 net_addr->address[14], 242 net_addr->address[15]); 243 244 // "Real" IPv6 addresses. 245 } else { 246 // Find the first longest run of 0s (of length > 1), to collapse to "::". 247 int longest_start = 0; 248 int longest_length = 0; 249 int curr_start = 0; 250 int curr_length = 0; 251 for (int i = 0; i < 8; i++) { 252 if (address16[i] != 0) { 253 curr_length = 0; 254 } else { 255 if (!curr_length) 256 curr_start = i; 257 curr_length++; 258 if (curr_length > longest_length) { 259 longest_start = curr_start; 260 longest_length = curr_length; 261 } 262 } 263 } 264 265 bool need_sep = false; // Whether the next item needs a ':' to separate. 266 for (int i = 0; i < 8;) { 267 if (longest_length > 1 && i == longest_start) { 268 description.append("::"); 269 need_sep = false; 270 i += longest_length; 271 } else { 272 uint16_t v = ConvertFromNetEndian16(address16[i]); 273 base::StringAppendF(&description, need_sep ? ":%x" : "%x", v); 274 need_sep = true; 275 i++; 276 } 277 } 278 } 279 280 // Nonzero scopes, e.g., 123, are indicated by appending, e.g., "%123". 281 if (net_addr->scope_id != 0) 282 base::StringAppendF(&description, "%%%u", net_addr->scope_id); 283 284 if (include_port) 285 base::StringAppendF(&description, "]:%u", net_addr->port); 286 287 return description; 288 } 289 290 PP_Var Describe(PP_Module /*module*/, 291 const struct PP_NetAddress_Private* addr, 292 PP_Bool include_port) { 293 std::string str = NetAddressPrivateImpl::DescribeNetAddress( 294 *addr, PP_ToBool(include_port)); 295 if (str.empty()) 296 return PP_MakeUndefined(); 297 // We must acquire the lock while accessing the VarTracker, which is part of 298 // the critical section of the proxy which may be accessed by other threads. 299 ProxyAutoLock lock; 300 return StringVar::StringToPPVar(str); 301 } 302 303 PP_Bool ReplacePort(const struct PP_NetAddress_Private* src_addr, 304 uint16_t port, 305 struct PP_NetAddress_Private* dest_addr) { 306 const NetAddress* src_net_addr = ToNetAddress(src_addr); 307 if (!IsValid(src_net_addr) || !dest_addr) 308 return PP_FALSE; 309 dest_addr->size = sizeof(NetAddress); // make sure 'size' is valid. 310 NetAddress* dest_net_addr = ToNetAddress(dest_addr); 311 *dest_net_addr = *src_net_addr; 312 dest_net_addr->port = port; 313 return PP_TRUE; 314 } 315 316 void GetAnyAddress(PP_Bool is_ipv6, PP_NetAddress_Private* addr) { 317 if (addr) { 318 NetAddress* net_addr = InitNetAddress(addr); 319 net_addr->is_valid = true; 320 net_addr->is_ipv6 = (is_ipv6 == PP_TRUE); 321 } 322 } 323 324 void CreateFromIPv4Address(const uint8_t ip[4], 325 uint16_t port, 326 struct PP_NetAddress_Private* addr) { 327 if (addr) { 328 NetAddress* net_addr = InitNetAddress(addr); 329 net_addr->is_valid = true; 330 net_addr->is_ipv6 = false; 331 net_addr->port = port; 332 memcpy(net_addr->address, ip, kIPv4AddressSize); 333 } 334 } 335 336 void CreateFromIPv6Address(const uint8_t ip[16], 337 uint32_t scope_id, 338 uint16_t port, 339 struct PP_NetAddress_Private* addr) { 340 if (addr) { 341 NetAddress* net_addr = InitNetAddress(addr); 342 net_addr->is_valid = true; 343 net_addr->is_ipv6 = true; 344 net_addr->port = port; 345 net_addr->scope_id = scope_id; 346 memcpy(net_addr->address, ip, kIPv6AddressSize); 347 } 348 } 349 350 const PPB_NetAddress_Private_0_1 net_address_private_interface_0_1 = { 351 &AreEqual, 352 &AreHostsEqual, 353 &Describe, 354 &ReplacePort, 355 &GetAnyAddress 356 }; 357 358 const PPB_NetAddress_Private_1_0 net_address_private_interface_1_0 = { 359 &AreEqual, 360 &AreHostsEqual, 361 &Describe, 362 &ReplacePort, 363 &GetAnyAddress, 364 &GetFamily, 365 &GetPort, 366 &GetAddress 367 }; 368 369 const PPB_NetAddress_Private_1_1 net_address_private_interface_1_1 = { 370 &AreEqual, 371 &AreHostsEqual, 372 &Describe, 373 &ReplacePort, 374 &GetAnyAddress, 375 &GetFamily, 376 &GetPort, 377 &GetAddress, 378 &GetScopeID, 379 &CreateFromIPv4Address, 380 &CreateFromIPv6Address 381 }; 382 383 } // namespace 384 385 namespace thunk { 386 387 PPAPI_THUNK_EXPORT const PPB_NetAddress_Private_0_1* 388 GetPPB_NetAddress_Private_0_1_Thunk() { 389 return &net_address_private_interface_0_1; 390 } 391 392 PPAPI_THUNK_EXPORT const PPB_NetAddress_Private_1_0* 393 GetPPB_NetAddress_Private_1_0_Thunk() { 394 return &net_address_private_interface_1_0; 395 } 396 397 PPAPI_THUNK_EXPORT const PPB_NetAddress_Private_1_1* 398 GetPPB_NetAddress_Private_1_1_Thunk() { 399 return &net_address_private_interface_1_1; 400 } 401 402 } // namespace thunk 403 404 // For the NaCl target, all we need are the API functions and the thunk. 405 #if !defined(OS_NACL) 406 407 // static 408 bool NetAddressPrivateImpl::ValidateNetAddress( 409 const PP_NetAddress_Private& addr) { 410 return IsValid(ToNetAddress(&addr)); 411 } 412 413 // static 414 bool NetAddressPrivateImpl::SockaddrToNetAddress( 415 const sockaddr* sa, 416 uint32_t sa_length, 417 PP_NetAddress_Private* addr) { 418 if (!sa || sa_length == 0 || !addr) 419 return false; 420 421 // Our platform neutral format stores ports in host order, not net order, 422 // so convert them here. 423 NetAddress* net_addr = InitNetAddress(addr); 424 switch (sa->sa_family) { 425 case AF_INET: { 426 const struct sockaddr_in* addr4 = 427 reinterpret_cast<const struct sockaddr_in*>(sa); 428 net_addr->is_valid = true; 429 net_addr->is_ipv6 = false; 430 net_addr->port = ConvertFromNetEndian16(addr4->sin_port); 431 memcpy(net_addr->address, &addr4->sin_addr.s_addr, kIPv4AddressSize); 432 break; 433 } 434 case AF_INET6: { 435 const struct sockaddr_in6* addr6 = 436 reinterpret_cast<const struct sockaddr_in6*>(sa); 437 net_addr->is_valid = true; 438 net_addr->is_ipv6 = true; 439 net_addr->port = ConvertFromNetEndian16(addr6->sin6_port); 440 net_addr->flow_info = addr6->sin6_flowinfo; 441 net_addr->scope_id = addr6->sin6_scope_id; 442 memcpy(net_addr->address, addr6->sin6_addr.s6_addr, kIPv6AddressSize); 443 break; 444 } 445 default: 446 // InitNetAddress sets net_addr->is_valid to false. 447 return false; 448 } 449 return true;} 450 451 // static 452 bool NetAddressPrivateImpl::IPEndPointToNetAddress( 453 const std::vector<unsigned char>& address, 454 int port, 455 PP_NetAddress_Private* addr) { 456 if (!addr) 457 return false; 458 459 NetAddress* net_addr = InitNetAddress(addr); 460 switch (address.size()) { 461 case kIPv4AddressSize: { 462 net_addr->is_valid = true; 463 net_addr->is_ipv6 = false; 464 net_addr->port = static_cast<uint16_t>(port); 465 std::copy(address.begin(), address.end(), net_addr->address); 466 break; 467 } 468 case kIPv6AddressSize: { 469 net_addr->is_valid = true; 470 net_addr->is_ipv6 = true; 471 net_addr->port = static_cast<uint16_t>(port); 472 std::copy(address.begin(), address.end(), net_addr->address); 473 break; 474 } 475 default: 476 // InitNetAddress sets net_addr->is_valid to false. 477 return false; 478 } 479 480 return true; 481 } 482 483 // static 484 bool NetAddressPrivateImpl::NetAddressToIPEndPoint( 485 const PP_NetAddress_Private& addr, 486 std::vector<unsigned char>* address, 487 int* port) { 488 if (!address || !port) 489 return false; 490 491 const NetAddress* net_addr = ToNetAddress(&addr); 492 if (!IsValid(net_addr)) 493 return false; 494 495 *port = net_addr->port; 496 size_t address_size = GetAddressSize(net_addr); 497 address->assign(&net_addr->address[0], &net_addr->address[address_size]); 498 499 return true; 500 } 501 #endif // !defined(OS_NACL) 502 503 // static 504 std::string NetAddressPrivateImpl::DescribeNetAddress( 505 const PP_NetAddress_Private& addr, 506 bool include_port) { 507 const NetAddress* net_addr = ToNetAddress(&addr); 508 if (!IsValid(net_addr)) 509 return std::string(); 510 511 // On Windows, |NetAddressToString()| doesn't work in the sandbox. On Mac, 512 // the output isn't consistent with RFC 5952, at least on Mac OS 10.6: 513 // |getnameinfo()| collapses length-one runs of zeros (and also doesn't 514 // display the scope). 515 if (net_addr->is_ipv6) 516 return ConvertIPv6AddressToString(net_addr, include_port); 517 return ConvertIPv4AddressToString(net_addr, include_port); 518 } 519 520 // static 521 void NetAddressPrivateImpl::CreateNetAddressPrivateFromIPv4Address( 522 const PP_NetAddress_IPv4& ipv4_addr, 523 PP_NetAddress_Private* addr) { 524 CreateFromIPv4Address(ipv4_addr.addr, ConvertFromNetEndian16(ipv4_addr.port), 525 addr); 526 } 527 528 // static 529 void NetAddressPrivateImpl::CreateNetAddressPrivateFromIPv6Address( 530 const PP_NetAddress_IPv6& ipv6_addr, 531 PP_NetAddress_Private* addr) { 532 CreateFromIPv6Address(ipv6_addr.addr, 0, 533 ConvertFromNetEndian16(ipv6_addr.port), addr); 534 } 535 536 // static 537 PP_NetAddress_Family NetAddressPrivateImpl::GetFamilyFromNetAddressPrivate( 538 const PP_NetAddress_Private& addr) { 539 const NetAddress* net_addr = ToNetAddress(&addr); 540 if (!IsValid(net_addr)) 541 return PP_NETADDRESS_FAMILY_UNSPECIFIED; 542 return net_addr->is_ipv6 ? PP_NETADDRESS_FAMILY_IPV6 : 543 PP_NETADDRESS_FAMILY_IPV4; 544 } 545 546 // static 547 bool NetAddressPrivateImpl::DescribeNetAddressPrivateAsIPv4Address( 548 const PP_NetAddress_Private& addr, 549 PP_NetAddress_IPv4* ipv4_addr) { 550 if (!ipv4_addr) 551 return false; 552 553 const NetAddress* net_addr = ToNetAddress(&addr); 554 if (!IsValid(net_addr) || net_addr->is_ipv6) 555 return false; 556 557 ipv4_addr->port = ConvertToNetEndian16(net_addr->port); 558 559 COMPILE_ASSERT(sizeof(ipv4_addr->addr) == kIPv4AddressSize, 560 mismatched_IPv4_address_size); 561 memcpy(ipv4_addr->addr, net_addr->address, kIPv4AddressSize); 562 563 return true; 564 } 565 566 // static 567 bool NetAddressPrivateImpl::DescribeNetAddressPrivateAsIPv6Address( 568 const PP_NetAddress_Private& addr, 569 PP_NetAddress_IPv6* ipv6_addr) { 570 if (!ipv6_addr) 571 return false; 572 573 const NetAddress* net_addr = ToNetAddress(&addr); 574 if (!IsValid(net_addr) || !net_addr->is_ipv6) 575 return false; 576 577 ipv6_addr->port = ConvertToNetEndian16(net_addr->port); 578 579 COMPILE_ASSERT(sizeof(ipv6_addr->addr) == kIPv6AddressSize, 580 mismatched_IPv6_address_size); 581 memcpy(ipv6_addr->addr, net_addr->address, kIPv6AddressSize); 582 583 return true; 584 } 585 586 } // namespace ppapi 587