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#include "nacl_io/ossocket.h" 6#if defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) && !defined(__BIONIC__) 7 8#include <errno.h> 9#include <string.h> 10 11#include <iostream> 12#include <sstream> 13#include <string> 14 15#include "sdk_util/macros.h" 16 17EXTERN_C_BEGIN 18 19const char* inet_ntop(int af, const void* src, char* dst, socklen_t size) { 20 if (AF_INET == af) { 21 if (size < INET_ADDRSTRLEN) { 22 errno = ENOSPC; 23 return NULL; 24 } 25 struct in_addr in; 26 memcpy(&in, src, sizeof(in)); 27 char* result = inet_ntoa(in); 28 memcpy(dst, result, strlen(result) + 1); 29 return dst; 30 } 31 32 if (AF_INET6 == af) { 33 if (size < INET6_ADDRSTRLEN) { 34 errno = ENOSPC; 35 return NULL; 36 } 37 38 // Convert to an array of 8 host order shorts 39 const uint16_t* tuples = static_cast<const uint16_t*>(src); 40 uint16_t host_tuples[8]; 41 int zero_run_start = -1; 42 int zero_run_end = -1; 43 for (int i = 0; i < 8; i++) { 44 host_tuples[i] = ntohs(tuples[i]); 45 if (host_tuples[i] == 0) { 46 if (zero_run_start == -1) 47 zero_run_start = i; 48 } else if (zero_run_start != -1 && zero_run_end == -1) { 49 zero_run_end = i; 50 } 51 } 52 53 if (zero_run_start != -1) { 54 if (zero_run_end == -1) 55 zero_run_end = 8; 56 if (zero_run_end - zero_run_start < 2) { 57 zero_run_start = -1; 58 zero_run_end = -1; 59 } 60 } 61 62 // Mimick glibc's behaviour here and allow ipv4 address to be specified 63 // as either ::A.B.C.D or ::ffff:A.B.C.D. 64 if (zero_run_start == 0 && 65 (zero_run_end == 6 || 66 (zero_run_end == 5 && host_tuples[zero_run_end] == 0xffff))) { 67 if (zero_run_end == 5) { 68 strcpy(dst, "::ffff:"); 69 } else { 70 strcpy(dst, "::"); 71 } 72 inet_ntop(AF_INET, host_tuples + 6, dst + strlen(dst), INET_ADDRSTRLEN); 73 } else { 74 std::stringstream output; 75 for (int i = 0; i < 8; i++) { 76 if (i == zero_run_start) { 77 output << "::"; 78 continue; 79 } 80 if (i > zero_run_start && i < zero_run_end) 81 continue; 82 output << std::hex << host_tuples[i]; 83 if (i < 7 && i + 1 != zero_run_start) 84 output << ":"; 85 } 86 memcpy(dst, output.str().c_str(), output.str().size() + 1); 87 } 88 return dst; 89 } 90 91 errno = EAFNOSUPPORT; 92 return NULL; 93} 94 95EXTERN_C_END 96 97#endif // defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) ... 98