Home | History | Annotate | Download | only in private
      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