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 |