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