Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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__) | |
| 7 | |
| 8 #include <errno.h> | |
| 9 #include <stdlib.h> | |
| 10 #include <string.h> | |
| 11 | |
| 12 #include <iostream> | |
| 13 #include <sstream> | |
| 14 #include <string> | |
|
Sam Clegg
2013/12/06 02:31:36
Are you using any of these C++ headers?
If not ca
Sergey Ulanov
2013/12/06 20:20:22
No, removed.
| |
| 15 | |
| 16 #include "sdk_util/macros.h" | |
| 17 | |
| 18 // Helper function for inet_pton() for IPv4 addresses. | |
| 19 static int inet_pton_v4(const char* src, void* dst) { | |
| 20 const int kIpv4AddressSize = 4; | |
| 21 const char* pos = src; | |
| 22 uint8_t result[kIpv4AddressSize] = {0}; | |
| 23 | |
| 24 for (int i = 0; i < kIpv4AddressSize; ++i) { | |
| 25 // strtol() won't treat whitespace characters in the beginning as an error, | |
| 26 // so check to ensure this is started with digit before passing to strtol(). | |
| 27 if (isspace(*pos)) | |
| 28 return 0; | |
| 29 char* end_pos; | |
| 30 unsigned long value = strtoul(pos, &end_pos, 10); | |
| 31 if (value > 255 || pos == end_pos) | |
| 32 return 0; | |
| 33 result[i] = static_cast<unsigned char>(value); | |
| 34 pos = end_pos; | |
| 35 | |
| 36 if (i < (kIpv4AddressSize - 1)) { | |
| 37 if (*pos != '.') | |
| 38 return 0; | |
| 39 ++pos; | |
| 40 } | |
| 41 } | |
| 42 if (*pos != '\0') | |
| 43 return 0; | |
| 44 memcpy(dst, result, sizeof(result)); | |
| 45 return 1; | |
| 46 } | |
| 47 | |
| 48 // Helper function for inet_pton() for IPv6 addresses. | |
| 49 int inet_pton_v6(const char* src, void* dst) { | |
| 50 // strtol() skips 0x in from of a number, while it's not allowed in IPv6 | |
| 51 // addresses. Check that there is no 'x' in the string. | |
| 52 const char* pos = src; | |
| 53 while (*pos != '\0') { | |
| 54 if (*pos == 'x') | |
| 55 return 0; | |
| 56 pos++; | |
| 57 } | |
| 58 pos = src; | |
| 59 | |
| 60 int kIpv6AddressSize = 16; | |
| 61 uint8_t result[kIpv6AddressSize]; | |
| 62 memset(&result, 0, sizeof(result)); | |
| 63 int double_colon_pos = -1; | |
| 64 int result_pos = 0; | |
| 65 | |
| 66 if (*pos == ':') { | |
| 67 if (*(pos + 1) != ':') | |
| 68 return 0; | |
| 69 pos += 2; | |
| 70 double_colon_pos = 0; | |
| 71 } | |
| 72 | |
| 73 while (*pos != '\0') { | |
| 74 // strtol() won't treat whitespace characters in the beginning as an error, | |
| 75 // so check to ensure this is started with digit before passing to strtol(). | |
| 76 if (isspace(*pos)) | |
| 77 return 0; | |
| 78 char* end_pos; | |
| 79 unsigned long word = strtoul(pos, &end_pos, 16); | |
| 80 if (word > 0xffff || pos == end_pos) | |
| 81 return 0; | |
| 82 | |
| 83 if (*end_pos == '.') { | |
| 84 if (result_pos + 4 > kIpv6AddressSize) | |
| 85 return 0; | |
| 86 // Parse rest of address as IPv4 address. | |
| 87 if (!inet_pton_v4(pos, result + result_pos)) | |
| 88 return 0; | |
| 89 result_pos += 4; | |
| 90 break; | |
| 91 } | |
| 92 | |
| 93 if (result_pos > kIpv6AddressSize - 2) | |
| 94 return 0; | |
| 95 result[result_pos] = (word & 0xFF00) >> 8; | |
| 96 result[result_pos + 1] = word & 0xFF; | |
| 97 result_pos += 2; | |
| 98 | |
| 99 if (*end_pos == '\0') | |
| 100 break; | |
| 101 | |
| 102 if (*end_pos != ':') | |
| 103 return 0; | |
| 104 | |
| 105 pos = end_pos + 1; | |
| 106 if (*pos == ':') { | |
| 107 if (double_colon_pos != -1) | |
| 108 return 0; | |
| 109 double_colon_pos = result_pos; | |
| 110 ++pos; | |
| 111 } | |
| 112 } | |
| 113 | |
| 114 // Finally move the data to the end in case the address contained '::'. | |
| 115 if (result_pos < kIpv6AddressSize) { | |
| 116 if (double_colon_pos == -1) | |
| 117 return 0; | |
| 118 int move_size = result_pos - double_colon_pos; | |
| 119 int gap_size = kIpv6AddressSize - result_pos; | |
| 120 memmove(result + kIpv6AddressSize - move_size, | |
| 121 result + double_colon_pos, move_size); | |
| 122 memset(result + double_colon_pos, 0, gap_size); | |
| 123 } | |
| 124 | |
| 125 // Finally copy the result to the output buffer. | |
| 126 memcpy(dst, result, sizeof(result)); | |
| 127 | |
| 128 return 1; | |
| 129 } | |
| 130 | |
| 131 EXTERN_C_BEGIN | |
| 132 | |
| 133 int inet_pton(int af, const char *src, void *dst) { | |
| 134 if (!src || !dst) { | |
| 135 return 0; | |
| 136 } | |
| 137 if (af == AF_INET) { | |
| 138 return inet_pton_v4(src, dst); | |
| 139 } else if (af == AF_INET6) { | |
| 140 return inet_pton_v6(src, dst); | |
| 141 } | |
| 142 errno = EAFNOSUPPORT; | |
| 143 return -1; | |
| 144 } | |
| 145 | |
| 146 EXTERN_C_END | |
| 147 | |
| 148 #endif // defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) | |
| 149 | |
| OLD | NEW |