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.
5 #include "ppapi/shared_impl/private/net_address_private_impl.h"
11 #elif defined(OS_POSIX) && !defined(OS_NACL)
12 #include <arpa/inet.h>
13 #include <sys/socket.h>
14 #include <sys/types.h>
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"
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
37 // The type of |sockaddr::sa_family|.
38 typedef ADDRESS_FAMILY sa_family_t
;
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)
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.
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
57 uint16
ConvertFromNetEndian16(uint16 x
) {
58 #if defined(ARCH_CPU_LITTLE_ENDIAN)
59 return (x
<< 8) | (x
>> 8);
65 uint16
ConvertToNetEndian16(uint16 x
) {
66 #if defined(ARCH_CPU_LITTLE_ENDIAN)
67 return (x
<< 8) | (x
>> 8);
73 static const size_t kIPv4AddressSize
= 4;
74 static const size_t kIPv6AddressSize
= 16;
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.
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
];
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 static_assert(sizeof(NetAddress
) == 28,
96 "NetAddress different for compiler");
98 // Make sure the storage in |PP_NetAddress_Private| is big enough. (Do it here
99 // since the data is opaque elsewhere.)
100 static_assert(sizeof(reinterpret_cast<PP_NetAddress_Private
*>(0)->data
) >=
102 "PP_NetAddress_Private data too small");
104 size_t GetAddressSize(const NetAddress
* net_addr
) {
105 return net_addr
->is_ipv6
? kIPv6AddressSize
: kIPv4AddressSize
;
108 // Convert to embedded struct if it has been initialized.
109 NetAddress
* ToNetAddress(PP_NetAddress_Private
* addr
) {
110 if (!addr
|| addr
->size
!= sizeof(NetAddress
))
112 return reinterpret_cast<NetAddress
*>(addr
->data
);
115 const NetAddress
* ToNetAddress(const PP_NetAddress_Private
* addr
) {
116 return ToNetAddress(const_cast<PP_NetAddress_Private
*>(addr
));
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
);
125 memset(net_addr
, 0, sizeof(NetAddress
));
129 bool IsValid(const NetAddress
* net_addr
) {
130 return net_addr
&& net_addr
->is_valid
;
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
;
141 uint16_t GetPort(const PP_NetAddress_Private
* addr
) {
142 const NetAddress
* net_addr
= ToNetAddress(addr
);
143 if (!IsValid(net_addr
))
145 return net_addr
->port
;
148 PP_Bool
GetAddress(const PP_NetAddress_Private
* addr
,
150 uint16_t address_size
) {
151 const NetAddress
* net_addr
= ToNetAddress(addr
);
152 if (!IsValid(net_addr
))
154 size_t net_addr_size
= GetAddressSize(net_addr
);
155 // address_size must be big enough.
156 if (net_addr_size
> address_size
)
158 memcpy(address
, net_addr
->address
, net_addr_size
);
162 uint32_t GetScopeID(const PP_NetAddress_Private
* addr
) {
163 const NetAddress
* net_addr
= ToNetAddress(addr
);
164 if (!IsValid(net_addr
))
166 return net_addr
->scope_id
;
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
))
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
))
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
])
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
))
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
);
203 std::string
ConvertIPv4AddressToString(const NetAddress
* net_addr
,
205 std::string description
= base::StringPrintf(
207 net_addr
->address
[0], net_addr
->address
[1],
208 net_addr
->address
[2], net_addr
->address
[3]);
210 base::StringAppendF(&description
, ":%u", net_addr
->port
);
214 // Format an IPv6 address for human consumption, basically according to RFC
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
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
,
227 std::string
description(include_port
? "[" : "");
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 &&
235 (address16
[5] == 0 || address16
[5] == 0xffff)) {
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]);
244 // "Real" IPv6 addresses.
246 // Find the first longest run of 0s (of length > 1), to collapse to "::".
247 int longest_start
= 0;
248 int longest_length
= 0;
251 for (int i
= 0; i
< 8; i
++) {
252 if (address16
[i
] != 0) {
258 if (curr_length
> longest_length
) {
259 longest_start
= curr_start
;
260 longest_length
= curr_length
;
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("::");
272 uint16_t v
= ConvertFromNetEndian16(address16
[i
]);
273 base::StringAppendF(&description
, need_sep
? ":%x" : "%x", v
);
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
);
285 base::StringAppendF(&description
, "]:%u", net_addr
->port
);
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
));
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.
300 return StringVar::StringToPPVar(str
);
303 PP_Bool
ReplacePort(const struct PP_NetAddress_Private
* src_addr
,
305 struct PP_NetAddress_Private
* dest_addr
) {
306 const NetAddress
* src_net_addr
= ToNetAddress(src_addr
);
307 if (!IsValid(src_net_addr
) || !dest_addr
)
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
;
316 void GetAnyAddress(PP_Bool is_ipv6
, PP_NetAddress_Private
* addr
) {
318 NetAddress
* net_addr
= InitNetAddress(addr
);
319 net_addr
->is_valid
= true;
320 net_addr
->is_ipv6
= (is_ipv6
== PP_TRUE
);
324 void CreateFromIPv4Address(const uint8_t ip
[4],
326 struct PP_NetAddress_Private
* 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
);
336 void CreateFromIPv6Address(const uint8_t ip
[16],
339 struct PP_NetAddress_Private
* 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
);
350 const PPB_NetAddress_Private_0_1 net_address_private_interface_0_1
= {
358 const PPB_NetAddress_Private_1_0 net_address_private_interface_1_0
= {
369 const PPB_NetAddress_Private_1_1 net_address_private_interface_1_1
= {
379 &CreateFromIPv4Address
,
380 &CreateFromIPv6Address
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
;
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
;
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
;
404 // For the NaCl target, all we need are the API functions and the thunk.
405 #if !defined(OS_NACL)
408 bool NetAddressPrivateImpl::ValidateNetAddress(
409 const PP_NetAddress_Private
& addr
) {
410 return IsValid(ToNetAddress(&addr
));
414 bool NetAddressPrivateImpl::SockaddrToNetAddress(
417 PP_NetAddress_Private
* addr
) {
418 if (!sa
|| sa_length
== 0 || !addr
)
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
) {
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
);
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
);
446 // InitNetAddress sets net_addr->is_valid to false.
452 bool NetAddressPrivateImpl::IPEndPointToNetAddress(
453 const std::vector
<unsigned char>& address
,
455 PP_NetAddress_Private
* addr
) {
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
= port
;
465 std::copy(address
.begin(), address
.end(), net_addr
->address
);
468 case kIPv6AddressSize
: {
469 net_addr
->is_valid
= true;
470 net_addr
->is_ipv6
= true;
471 net_addr
->port
= port
;
472 std::copy(address
.begin(), address
.end(), net_addr
->address
);
476 // InitNetAddress sets net_addr->is_valid to false.
484 bool NetAddressPrivateImpl::NetAddressToIPEndPoint(
485 const PP_NetAddress_Private
& addr
,
486 std::vector
<unsigned char>* address
,
488 if (!address
|| !port
)
491 const NetAddress
* net_addr
= ToNetAddress(&addr
);
492 if (!IsValid(net_addr
))
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
]);
501 #endif // !defined(OS_NACL)
504 std::string
NetAddressPrivateImpl::DescribeNetAddress(
505 const PP_NetAddress_Private
& addr
,
507 const NetAddress
* net_addr
= ToNetAddress(&addr
);
508 if (!IsValid(net_addr
))
509 return std::string();
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
);
521 void NetAddressPrivateImpl::GetAnyAddress(PP_Bool is_ipv6
,
522 PP_NetAddress_Private
* addr
) {
523 ppapi::GetAnyAddress(is_ipv6
, addr
);
527 void NetAddressPrivateImpl::CreateNetAddressPrivateFromIPv4Address(
528 const PP_NetAddress_IPv4
& ipv4_addr
,
529 PP_NetAddress_Private
* addr
) {
530 CreateFromIPv4Address(ipv4_addr
.addr
, ConvertFromNetEndian16(ipv4_addr
.port
),
535 void NetAddressPrivateImpl::CreateNetAddressPrivateFromIPv6Address(
536 const PP_NetAddress_IPv6
& ipv6_addr
,
537 PP_NetAddress_Private
* addr
) {
538 CreateFromIPv6Address(ipv6_addr
.addr
, 0,
539 ConvertFromNetEndian16(ipv6_addr
.port
), addr
);
543 PP_NetAddress_Family
NetAddressPrivateImpl::GetFamilyFromNetAddressPrivate(
544 const PP_NetAddress_Private
& addr
) {
545 const NetAddress
* net_addr
= ToNetAddress(&addr
);
546 if (!IsValid(net_addr
))
547 return PP_NETADDRESS_FAMILY_UNSPECIFIED
;
548 return net_addr
->is_ipv6
? PP_NETADDRESS_FAMILY_IPV6
:
549 PP_NETADDRESS_FAMILY_IPV4
;
553 bool NetAddressPrivateImpl::DescribeNetAddressPrivateAsIPv4Address(
554 const PP_NetAddress_Private
& addr
,
555 PP_NetAddress_IPv4
* ipv4_addr
) {
559 const NetAddress
* net_addr
= ToNetAddress(&addr
);
560 if (!IsValid(net_addr
) || net_addr
->is_ipv6
)
563 ipv4_addr
->port
= ConvertToNetEndian16(net_addr
->port
);
565 static_assert(sizeof(ipv4_addr
->addr
) == kIPv4AddressSize
,
566 "mismatched IPv4 address size");
567 memcpy(ipv4_addr
->addr
, net_addr
->address
, kIPv4AddressSize
);
573 bool NetAddressPrivateImpl::DescribeNetAddressPrivateAsIPv6Address(
574 const PP_NetAddress_Private
& addr
,
575 PP_NetAddress_IPv6
* ipv6_addr
) {
579 const NetAddress
* net_addr
= ToNetAddress(&addr
);
580 if (!IsValid(net_addr
) || !net_addr
->is_ipv6
)
583 ipv6_addr
->port
= ConvertToNetEndian16(net_addr
->port
);
585 static_assert(sizeof(ipv6_addr
->addr
) == kIPv6AddressSize
,
586 "mismatched IPv6 address size");
587 memcpy(ipv6_addr
->addr
, net_addr
->address
, kIPv6AddressSize
);