]>
Commit | Line | Data |
---|---|---|
974e3884 A |
1 | /* |
2 | * Copyright (c) 2003,2005,2006,2011,2012 Apple, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
6 | * This file contains Original Code and/or Modifications of Original Code | |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. Please obtain a copy of the License at | |
10 | * http://www.opensource.apple.com/apsl/ and read it before using this | |
11 | * file. | |
12 | * | |
13 | * The Original Code and all software distributed under the License are | |
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
18 | * Please see the License for the specific language governing rights and | |
19 | * limitations under the License. | |
20 | * | |
21 | * @APPLE_LICENSE_HEADER_END@ | |
22 | */ | |
6465356a A |
23 | |
24 | #include <sys/types.h> | |
25 | #include <netinet/in.h> | |
26 | #include <arpa/inet.h> | |
27 | #include <stdio.h> | |
28 | #include <stdint.h> | |
29 | #include <string.h> | |
30 | #include <errno.h> | |
31 | #include <sys/socket.h> | |
32 | ||
33 | #define MAX_V4_ADDR_LEN 16 | |
34 | #define MAX_V6_ADDR_LEN 64 | |
35 | ||
36 | static const char *hexchars = "0123456789abcdef"; | |
37 | ||
974e3884 A |
38 | const char * inet_ntop6(const struct in6_addr *addr, char *dst, socklen_t size); |
39 | const char * inet_ntop4(const struct in_addr *addr, char *dst, socklen_t size); | |
40 | ||
41 | const char * | |
42 | inet_ntop(int af, const void *addr, char *buf, socklen_t len) | |
43 | { | |
44 | if (af == AF_INET6) return inet_ntop6(addr, buf, len); | |
45 | if (af == AF_INET) return inet_ntop4(addr, buf, len); | |
46 | ||
47 | errno = EAFNOSUPPORT; | |
48 | return NULL; | |
49 | } | |
50 | ||
6465356a A |
51 | const char * |
52 | inet_ntop6(const struct in6_addr *addr, char *dst, socklen_t size) | |
53 | { | |
54 | char hexa[8][5], tmp[MAX_V6_ADDR_LEN]; | |
55 | int zr[8]; | |
56 | socklen_t len; | |
57 | int32_t i, j, k, skip; | |
58 | uint8_t x8, hx8; | |
59 | uint16_t x16; | |
60 | struct in_addr a4; | |
61 | ||
62 | if (addr == NULL) | |
63 | { | |
64 | errno = EAFNOSUPPORT; | |
65 | return NULL; | |
66 | } | |
67 | ||
68 | if (dst == NULL) | |
69 | { | |
70 | errno = ENOSPC; | |
71 | return NULL; | |
72 | } | |
73 | ||
74 | memset(tmp, 0, MAX_V6_ADDR_LEN); | |
75 | ||
76 | /* check for mapped or compat addresses */ | |
77 | i = IN6_IS_ADDR_V4MAPPED(addr); | |
78 | j = IN6_IS_ADDR_V4COMPAT(addr); | |
79 | if ((i != 0) || (j != 0)) | |
80 | { | |
974e3884 A |
81 | const char *prefix; |
82 | socklen_t prefix_len; | |
83 | if (i != 0) { | |
84 | prefix = "::ffff:"; | |
85 | prefix_len = 7; | |
86 | } else { | |
87 | prefix = "::"; | |
88 | prefix_len = 2; | |
89 | } | |
6465356a | 90 | a4.s_addr = addr->__u6_addr.__u6_addr32[3]; |
974e3884 | 91 | inet_ntop4(&a4, tmp, sizeof(tmp)); |
6465356a | 92 | len = strlen(tmp) + 1; |
974e3884 | 93 | if (prefix_len + len > size) |
6465356a A |
94 | { |
95 | errno = ENOSPC; | |
96 | return NULL; | |
97 | } | |
98 | ||
974e3884 A |
99 | memcpy(dst, prefix, prefix_len); |
100 | memcpy(dst + prefix_len, tmp, len); | |
6465356a A |
101 | return dst; |
102 | } | |
103 | ||
104 | k = 0; | |
105 | for (i = 0; i < 16; i += 2) | |
106 | { | |
107 | j = 0; | |
108 | skip = 1; | |
109 | ||
110 | memset(hexa[k], 0, 5); | |
111 | ||
112 | x8 = addr->__u6_addr.__u6_addr8[i]; | |
113 | ||
114 | hx8 = x8 >> 4; | |
115 | if (hx8 != 0) | |
116 | { | |
117 | skip = 0; | |
118 | hexa[k][j++] = hexchars[hx8]; | |
119 | } | |
120 | ||
121 | hx8 = x8 & 0x0f; | |
122 | if ((skip == 0) || ((skip == 1) && (hx8 != 0))) | |
123 | { | |
124 | skip = 0; | |
125 | hexa[k][j++] = hexchars[hx8]; | |
126 | } | |
127 | ||
128 | x8 = addr->__u6_addr.__u6_addr8[i + 1]; | |
129 | ||
130 | hx8 = x8 >> 4; | |
131 | if ((skip == 0) || ((skip == 1) && (hx8 != 0))) | |
132 | { | |
133 | hexa[k][j++] = hexchars[hx8]; | |
134 | } | |
135 | ||
136 | hx8 = x8 & 0x0f; | |
137 | hexa[k][j++] = hexchars[hx8]; | |
138 | ||
139 | k++; | |
140 | } | |
141 | ||
142 | /* find runs of zeros for :: convention */ | |
143 | j = 0; | |
144 | for (i = 7; i >= 0; i--) | |
145 | { | |
146 | zr[i] = j; | |
147 | x16 = addr->__u6_addr.__u6_addr16[i]; | |
148 | if (x16 == 0) j++; | |
149 | else j = 0; | |
150 | zr[i] = j; | |
151 | } | |
152 | ||
153 | /* find longest run of zeros */ | |
154 | k = -1; | |
155 | j = 0; | |
156 | for(i = 0; i < 8; i++) | |
157 | { | |
158 | if (zr[i] > j) | |
159 | { | |
160 | k = i; | |
161 | j = zr[i]; | |
162 | } | |
163 | } | |
164 | ||
165 | for(i = 0; i < 8; i++) | |
166 | { | |
167 | if (i != k) zr[i] = 0; | |
168 | } | |
169 | ||
170 | len = 0; | |
171 | for (i = 0; i < 8; i++) | |
172 | { | |
173 | if (zr[i] != 0) | |
174 | { | |
175 | /* check for leading zero */ | |
176 | if (i == 0) tmp[len++] = ':'; | |
177 | tmp[len++] = ':'; | |
178 | i += (zr[i] - 1); | |
179 | continue; | |
180 | } | |
181 | for (j = 0; hexa[i][j] != '\0'; j++) tmp[len++] = hexa[i][j]; | |
182 | if (i != 7) tmp[len++] = ':'; | |
183 | } | |
184 | ||
185 | /* trailing NULL */ | |
186 | len++; | |
187 | ||
188 | if (len > size) | |
189 | { | |
190 | errno = ENOSPC; | |
191 | return NULL; | |
192 | } | |
193 | ||
194 | memcpy(dst, tmp, len); | |
195 | return dst; | |
196 | } | |
197 | ||
198 | const char * | |
199 | inet_ntop4(const struct in_addr *addr, char *dst, socklen_t size) | |
200 | { | |
201 | char tmp[MAX_V4_ADDR_LEN], *p; | |
202 | const u_int8_t *ap = (u_int8_t *)&addr->s_addr; | |
203 | int i, ql, len; | |
204 | ||
205 | if (addr == NULL) | |
206 | { | |
207 | errno = EAFNOSUPPORT; | |
208 | return NULL; | |
209 | } | |
210 | ||
211 | if (dst == NULL) | |
212 | { | |
213 | errno = ENOSPC; | |
214 | return NULL; | |
215 | } | |
216 | ||
217 | memset(tmp, 0, MAX_V4_ADDR_LEN); | |
218 | ||
219 | /* 3 dots, trailing nul */ | |
220 | len = 4; | |
221 | ||
222 | p = tmp; | |
223 | ||
224 | for (i = 0; i < 4; i++, ap++) | |
225 | { | |
226 | snprintf(p, 4, "%d", *ap); | |
227 | ql = strlen(p); | |
228 | len += ql; | |
229 | p += ql; | |
230 | if (i < 3) *p++ = '.'; | |
231 | } | |
232 | ||
233 | if (len > size) | |
234 | { | |
235 | errno = ENOSPC; | |
236 | return NULL; | |
237 | } | |
238 | ||
239 | memcpy(dst, tmp, len); | |
240 | return dst; | |
241 | } |