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 |