Index: native_client_sdk/src/libraries/nacl_io/syscalls/inet_ntop.cc |
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/inet_ntop.cc b/native_client_sdk/src/libraries/nacl_io/syscalls/inet_ntop.cc |
index ceabae5815f016286ab7049d9f58802f20072b98..e9bde2b13332c205b33646cecf69a4c0def1b378 100644 |
--- a/native_client_sdk/src/libraries/nacl_io/syscalls/inet_ntop.cc |
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/inet_ntop.cc |
@@ -14,7 +14,6 @@ |
#include "sdk_util/macros.h" |
- |
EXTERN_C_BEGIN |
const char* inet_ntop(int af, const void* src, char* dst, socklen_t size) { |
@@ -35,16 +34,58 @@ const char* inet_ntop(int af, const void* src, char* dst, socklen_t size) { |
errno = ENOSPC; |
return NULL; |
} |
- const uint8_t* tuples = static_cast<const uint8_t*>(src); |
- std::stringstream output; |
+ |
+ // Convert to an array of 8 host order shorts |
+ const uint16_t* tuples = static_cast<const uint16_t*>(src); |
+ uint16_t host_tuples[8]; |
+ int zero_run_start = -1; |
+ int zero_run_end = -1; |
for (int i = 0; i < 8; i++) { |
- uint16_t tuple = (tuples[2*i] << 8) + tuples[2*i+1]; |
- output << std::hex << tuple; |
- if (i < 7) { |
- output << ":"; |
+ host_tuples[i] = ntohs(tuples[i]); |
+ if (host_tuples[i] == 0) { |
+ if (zero_run_start == -1) |
+ zero_run_start = i; |
+ } else if (zero_run_start != -1 && zero_run_end == -1) { |
+ zero_run_end = i; |
+ } |
+ } |
+ |
+ if (zero_run_start != -1) { |
+ if (zero_run_end == -1) |
+ zero_run_end = 8; |
+ if (zero_run_end - zero_run_start < 2) { |
+ zero_run_start = -1; |
+ zero_run_end = -1; |
} |
} |
- memcpy(dst, output.str().c_str(), output.str().size() + 1); |
+ |
+ // Mimick glibc's behaviour here and allow ipv4 address to be specified |
+ // as either ::A.B.C.D or ::ffff:A.B.C.D. |
+ if (zero_run_start == 0 && |
+ (zero_run_end == 6 || |
+ (zero_run_end == 5 && host_tuples[zero_run_end] == 0xffff))) { |
+ |
+ if (zero_run_end == 5) { |
+ strcpy(dst, "::ffff:"); |
+ } else { |
+ strcpy(dst, "::"); |
+ } |
+ inet_ntop(AF_INET, host_tuples+6, dst+strlen(dst), INET_ADDRSTRLEN); |
+ } else { |
+ std::stringstream output; |
+ for (int i = 0; i < 8; i++) { |
+ if (i == zero_run_start) { |
+ output << "::"; |
+ continue; |
+ } |
+ if (i > zero_run_start && i < zero_run_end) |
+ continue; |
+ output << std::hex << host_tuples[i]; |
+ if (i < 7 && i + 1 != zero_run_start) |
+ output << ":"; |
+ } |
+ memcpy(dst, output.str().c_str(), output.str().size() + 1); |
+ } |
return dst; |
} |
@@ -55,4 +96,3 @@ const char* inet_ntop(int af, const void* src, char* dst, socklen_t size) { |
EXTERN_C_END |
#endif // defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) |
- |