blob: fa733e0adc0f51cd39db882593ebc77e48cd7b8c [file] [log] [blame]
lh9ed821d2023-04-07 01:36:19 -07001/*
2 * Copyright (c) 1996-1999 by Internet Software Consortium.
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
9 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
10 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
11 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
12 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
13 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
14 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
15 * SOFTWARE.
16 */
17
18#define __FORCE_GLIBC
19#include <features.h>
20#include <sys/param.h>
21#include <sys/types.h>
22#include <sys/socket.h>
23
24#include <netinet/in.h>
25#include <arpa/inet.h>
26#include <arpa/nameser.h>
27
28#include <errno.h>
29#include <stdio.h>
30#include <string.h>
31#include <ctype.h>
32
33
34/*
35 * WARNING: Don't even consider trying to compile this on a system where
36 * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
37 */
38
39
40/* const char *
41 * inet_ntop4(src, dst, size)
42 * format an IPv4 address
43 * return:
44 * `dst' (as a const)
45 * notes:
46 * (1) uses no statics
47 * (2) takes a u_char* not an in_addr as input
48 * author:
49 * Paul Vixie, 1996.
50 */
51static const char *
52inet_ntop4(const u_char *src, char *dst, size_t size)
53{
54 char tmp[sizeof ("255.255.255.255") + 1];
55 int octet;
56 int i;
57
58 tmp[0] = '\0';
59
60 i = 0;
61 for (octet = 0; octet <= 3; octet++) {
62
63#if 0 /* since src is unsigned char, it will never be > 255 ... */
64 if (src[octet] > 255) {
65 __set_errno(ENOSPC);
66 return NULL;
67 }
68#endif
69 tmp[i++] = '0' + src[octet] / 100;
70 if (tmp[i - 1] == '0') {
71 tmp[i - 1] = '0' + (src[octet] / 10 % 10);
72 if (tmp[i - 1] == '0') i--;
73 } else {
74 tmp[i++] = '0' + (src[octet] / 10 % 10);
75 }
76 tmp[i++] = '0' + src[octet] % 10;
77 tmp[i++] = '.';
78 }
79 tmp[i - 1] = '\0';
80
81 if (strlen(tmp) > size) {
82 __set_errno(ENOSPC);
83 return NULL;
84 }
85
86 return strcpy(dst, tmp);
87}
88
89
90/* const char *
91 * inet_ntop6(src, dst, size)
92 * convert IPv6 binary address into presentation (printable) format
93 * author:
94 * Paul Vixie, 1996.
95 */
96
97#ifdef __UCLIBC_HAS_IPV6__
98
99static const char *
100inet_ntop6(const u_char *src, char *dst, size_t size)
101{
102 /*
103 * Note that int32_t and int16_t need only be "at least" large enough
104 * to contain a value of the specified size. On some systems, like
105 * Crays, there is no such thing as an integer variable with 16 bits.
106 * Keep this in mind if you think this function should have been coded
107 * to use pointer overlays. All the world's not a VAX.
108 */
109 char tmp[sizeof ("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")], *tp;
110 struct { int base, len; } best, cur;
111 u_int words[8];
112 int i;
113
114 /*
115 * Preprocess:
116 * Copy the input (bytewise) array into a wordwise array.
117 * Find the longest run of 0x00's in src[] for :: shorthanding.
118 */
119 memset(words, '\0', sizeof words);
120 for (i = 0; i < 16; i += 2)
121 words[i / 2] = (src[i] << 8) | src[i + 1];
122 best.base = -1;
123 cur.base = -1;
124 best.len = best.len; /* shutting up compiler warning */
125 cur.len = cur.len; /* shutting up compiler warning */
126 for (i = 0; i < 8; i++) {
127 if (words[i] == 0) {
128 if (cur.base == -1)
129 cur.base = i, cur.len = 1;
130 else
131 cur.len++;
132 } else {
133 if (cur.base != -1) {
134 if (best.base == -1 || cur.len > best.len)
135 best = cur;
136 cur.base = -1;
137 }
138 }
139 }
140 if (cur.base != -1) {
141 if (best.base == -1 || cur.len > best.len)
142 best = cur;
143 }
144 if (best.base != -1 && best.len < 2)
145 best.base = -1;
146
147 /*
148 * Format the result.
149 */
150 tp = tmp;
151 for (i = 0; i < 8; i++) {
152 /* Are we inside the best run of 0x00's? */
153 if (best.base != -1 && i >= best.base &&
154 i < (best.base + best.len)) {
155 if (i == best.base)
156 *tp++ = ':';
157 continue;
158 }
159 /* Are we following an initial run of 0x00s or any real hex? */
160 if (i != 0)
161 *tp++ = ':';
162 /* Is this address an encapsulated IPv4? */
163 if (i == 6 && best.base == 0 &&
164 (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
165 if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp)))
166 return NULL;
167 tp += strlen(tp);
168 break;
169 }
170 tp += sprintf(tp, "%x", words[i]);
171 }
172 /* Was it a trailing run of 0x00's? */
173 if (best.base != -1 && (best.base + best.len) == 8)
174 *tp++ = ':';
175 *tp++ = '\0';
176
177 /*
178 * Check for overflow, copy, and we're done.
179 */
180 if ((size_t)(tp - tmp) > size) {
181 __set_errno(ENOSPC);
182 return NULL;
183 }
184 return strcpy(dst, tmp);
185}
186#endif /* __UCLIBC_HAS_IPV6__ */
187
188
189/* int
190 * inet_pton4(src, dst)
191 * like inet_aton() but without all the hexadecimal and shorthand.
192 * return:
193 * 1 if `src' is a valid dotted quad, else 0.
194 * notice:
195 * does not touch `dst' unless it's returning 1.
196 * author:
197 * Paul Vixie, 1996.
198 */
199static int
200inet_pton4(const char *src, u_char *dst)
201{
202 int saw_digit, octets, ch;
203 u_char tmp[4], *tp;
204
205 saw_digit = 0;
206 octets = 0;
207 *(tp = tmp) = 0;
208 while ((ch = *src++) != '\0') {
209
210 if (ch >= '0' && ch <= '9') {
211 u_int new = *tp * 10 + (ch - '0');
212
213 if (new > 255)
214 return 0;
215 *tp = new;
216 if (! saw_digit) {
217 if (++octets > 4)
218 return 0;
219 saw_digit = 1;
220 }
221 } else if (ch == '.' && saw_digit) {
222 if (octets == 4)
223 return 0;
224 *++tp = 0;
225 saw_digit = 0;
226 } else
227 return 0;
228 }
229 if (octets < 4)
230 return 0;
231 memcpy(dst, tmp, 4);
232 return 1;
233}
234
235/* int
236 * inet_pton6(src, dst)
237 * convert presentation level address to network order binary form.
238 * return:
239 * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
240 * notice:
241 * (1) does not touch `dst' unless it's returning 1.
242 * (2) :: in a full address is silently ignored.
243 * credit:
244 * inspired by Mark Andrews.
245 * author:
246 * Paul Vixie, 1996.
247 */
248
249#ifdef __UCLIBC_HAS_IPV6__
250
251static int
252inet_pton6(const char *src, u_char *dst)
253{
254 static const char xdigits[] = "0123456789abcdef";
255 u_char tmp[16], *tp, *endp, *colonp;
256 const char *curtok;
257 int ch, saw_xdigit;
258 u_int val;
259
260
261 tp = memset(tmp, '\0', 16);
262 endp = tp + 16;
263 colonp = NULL;
264 /* Leading :: requires some special handling. */
265 if (*src == ':')
266 if (*++src != ':')
267 return 0;
268 curtok = src;
269 saw_xdigit = 0;
270 val = 0;
271 while ((ch = *src++) != '\0') {
272 const char *pch;
273
274 /* | 0x20 is cheap tolower(), valid for letters/numbers only */
275 pch = strchr(xdigits, (ch | 0x20));
276 if (pch != NULL) {
277 val <<= 4;
278 val |= (pch - xdigits);
279 if (val > 0xffff)
280 return 0;
281 saw_xdigit = 1;
282 continue;
283 }
284 if (ch == ':') {
285 curtok = src;
286 if (!saw_xdigit) {
287 if (colonp)
288 return 0;
289 colonp = tp;
290 continue;
291 }
292 if (*src == '\0')
293 return 0;
294 if (tp + 2 > endp)
295 return 0;
296 *tp++ = (u_char) (val >> 8);
297 *tp++ = (u_char) val;
298 saw_xdigit = 0;
299 val = 0;
300 continue;
301 }
302 if (ch == '.' && ((tp + 4) <= endp) &&
303 inet_pton4(curtok, tp) > 0) {
304 tp += 4;
305 saw_xdigit = 0;
306 break; /* '\0' was seen by inet_pton4(). */
307 }
308 return 0;
309 }
310 if (saw_xdigit) {
311 if (tp + 2 > endp)
312 return 0;
313 *tp++ = (u_char) (val >> 8);
314 *tp++ = (u_char) val;
315 }
316 if (colonp != NULL) {
317 /*
318 * Since some memmove()'s erroneously fail to handle
319 * overlapping regions, we'll do the shift by hand.
320 */
321 const int n = tp - colonp;
322 int i;
323
324 if (tp == endp)
325 return 0;
326 for (i = 1; i <= n; i++) {
327 endp[- i] = colonp[n - i];
328 colonp[n - i] = 0;
329 }
330 tp = endp;
331 }
332 if (tp != endp)
333 return 0;
334 memcpy(dst, tmp, 16);
335 return 1;
336}
337
338#endif /* __UCLIBC_HAS_IPV6__ */
339
340
341
342/* char *
343 * inet_ntop(af, src, dst, size)
344 * convert a network format address to presentation format.
345 * return:
346 * pointer to presentation format address (`dst'), or NULL (see errno).
347 * author:
348 * Paul Vixie, 1996.
349 */
350const char *
351inet_ntop(int af, const void *src, char *dst, socklen_t size)
352{
353 switch (af) {
354 case AF_INET:
355 return inet_ntop4(src, dst, size);
356#ifdef __UCLIBC_HAS_IPV6__
357 case AF_INET6:
358 return inet_ntop6(src, dst, size);
359#endif
360 default:
361 __set_errno(EAFNOSUPPORT);
362 return NULL;
363 }
364 /* NOTREACHED */
365}
366libc_hidden_def(inet_ntop)
367
368
369/* int
370 * inet_pton(af, src, dst)
371 * convert from presentation format (which usually means ASCII printable)
372 * to network format (which is usually some kind of binary format).
373 * return:
374 * 1 if the address was valid for the specified address family
375 * 0 if the address wasn't valid (`dst' is untouched in this case)
376 * -1 if some other error occurred (`dst' is untouched in this case, too)
377 * author:
378 * Paul Vixie, 1996.
379 */
380int
381inet_pton(int af, const char *src, void *dst)
382{
383 switch (af) {
384 case AF_INET:
385 return inet_pton4(src, dst);
386#ifdef __UCLIBC_HAS_IPV6__
387 case AF_INET6:
388 return inet_pton6(src, dst);
389#endif
390 default:
391 __set_errno(EAFNOSUPPORT);
392 return -1;
393 }
394 /* NOTREACHED */
395}
396libc_hidden_def(inet_pton)