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. | |
|
Sam Clegg
2013/12/06 20:57:03
C style comments here and below.
Sergey Ulanov
2013/12/06 21:15:44
Done.
| |
| 4 | |
| 5 #include "nacl_io/ossocket.h" | |
| 6 #if defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) | |
| 7 | |
| 8 #include <ctype.h> | |
| 9 #include <errno.h> | |
| 10 #include <stdlib.h> | |
| 11 #include <string.h> | |
| 12 | |
| 13 #include "sdk_util/macros.h" | |
| 14 | |
| 15 enum { | |
| 16 kIpv4AddressSize = 4, | |
| 17 kIpv6AddressSize = 16, | |
| 18 }; | |
| 19 | |
| 20 // Helper function for inet_pton() for IPv4 addresses. | |
| 21 static int inet_pton_v4(const char* src, void* dst) { | |
| 22 const char* pos = src; | |
| 23 uint8_t result[kIpv4AddressSize] = {0}; | |
| 24 | |
| 25 for (int i = 0; i < kIpv4AddressSize; ++i) { | |
| 26 // strtol() won't treat whitespace characters in the beginning as an error, | |
| 27 // so check to ensure this is started with digit before passing to strtol(). | |
| 28 if (isspace((int)(*pos))) | |
| 29 return 0; | |
| 30 char* end_pos; | |
| 31 unsigned long value = strtoul(pos, &end_pos, 10); | |
| 32 if (value > 255 || pos == end_pos) | |
| 33 return 0; | |
| 34 result[i] = (unsigned char)value; | |
| 35 pos = end_pos; | |
| 36 | |
| 37 if (i < (kIpv4AddressSize - 1)) { | |
| 38 if (*pos != '.') | |
| 39 return 0; | |
| 40 ++pos; | |
| 41 } | |
| 42 } | |
| 43 if (*pos != '\0') | |
| 44 return 0; | |
| 45 memcpy(dst, result, sizeof(result)); | |
| 46 return 1; | |
| 47 } | |
| 48 | |
| 49 // Helper function for inet_pton() for IPv6 addresses. | |
| 50 int inet_pton_v6(const char* src, void* dst) { | |
| 51 // strtol() skips 0x in from of a number, while it's not allowed in IPv6 | |
| 52 // addresses. Check that there is no 'x' in the string. | |
| 53 const char* pos = src; | |
| 54 while (*pos != '\0') { | |
| 55 if (*pos == 'x') | |
| 56 return 0; | |
| 57 pos++; | |
| 58 } | |
| 59 pos = src; | |
| 60 | |
| 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((int)(*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 + kIpv4AddressSize > 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 int inet_pton(int af, const char *src, void *dst) { | |
| 132 if (!src || !dst) { | |
| 133 return 0; | |
| 134 } | |
| 135 if (af == AF_INET) { | |
| 136 return inet_pton_v4(src, dst); | |
| 137 } else if (af == AF_INET6) { | |
| 138 return inet_pton_v6(src, dst); | |
| 139 } | |
| 140 errno = EAFNOSUPPORT; | |
| 141 return -1; | |
| 142 } | |
| 143 | |
| 144 #endif // defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) | |
| 145 | |
|
Sam Clegg
2013/12/06 20:57:03
Remove trailing line
Sergey Ulanov
2013/12/06 21:15:44
Done.
| |
| OLD | NEW |