1/* Copyright (c) 1996 by Internet Software Consortium.
2 *
3 * Permission to use, copy, modify, and distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
6 *
7 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
8 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
9 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
10 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
11 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
12 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
13 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
14 * SOFTWARE.
15 */
16
17/*
18 * Portions copyright (c) 1999, 2000
19 * Intel Corporation.
20 * All rights reserved.
21 *
22 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions
24 * are met:
25 *
26 * 1. Redistributions of source code must retain the above copyright
27 *    notice, this list of conditions and the following disclaimer.
28 *
29 * 2. Redistributions in binary form must reproduce the above copyright
30 *    notice, this list of conditions and the following disclaimer in the
31 *    documentation and/or other materials provided with the distribution.
32 *
33 * 3. All advertising materials mentioning features or use of this software
34 *    must display the following acknowledgement:
35 *
36 *    This product includes software developed by Intel Corporation and
37 *    its contributors.
38 *
39 * 4. Neither the name of Intel Corporation or its contributors may be
40 *    used to endorse or promote products derived from this software
41 *    without specific prior written permission.
42 *
43 * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION AND CONTRIBUTORS ``AS IS''
44 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46 * ARE DISCLAIMED.  IN NO EVENT SHALL INTEL CORPORATION OR CONTRIBUTORS BE
47 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
48 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
49 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
50 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
51 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
52 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
53 * THE POSSIBILITY OF SUCH DAMAGE.
54 *
55 */
56
57#if defined(LIBC_SCCS) && !defined(lint)
58static char rcsid[] = "$Id: inet_pton.c,v 1.1.1.1 2003/11/19 01:51:30 kyu3 Exp $";
59#endif /* LIBC_SCCS and not lint */
60
61#include <sys/param.h>
62#include <sys/types.h>
63#include <sys/socket.h>
64#include <netinet/in.h>
65#include <arpa/inet.h>
66#include <arpa/nameser.h>
67#include <string.h>
68#include <errno.h>
69
70/*
71 * WARNING: Don't even consider trying to compile this on a system where
72 * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
73 */
74
75static int	inet_pton4 (const char *src, u_char *dst);
76static int	inet_pton6 (const char *src, u_char *dst);
77
78/* int
79 * inet_pton(af, src, dst)
80 *	convert from presentation format (which usually means ASCII printable)
81 *	to network format (which is usually some kind of binary format).
82 * return:
83 *	1 if the address was valid for the specified address family
84 *	0 if the address wasn't valid (`dst' is untouched in this case)
85 *	-1 if some other error occurred (`dst' is untouched in this case, too)
86 * author:
87 *	Paul Vixie, 1996.
88 */
89int
90inet_pton(
91	int af,
92	const char *src,
93	void *dst
94	)
95{
96	switch (af) {
97	case AF_INET:
98		return (inet_pton4(src, dst));
99	case AF_INET6:
100		return (inet_pton6(src, dst));
101	default:
102		errno = EAFNOSUPPORT;
103		return (-1);
104	}
105	/* NOTREACHED */
106}
107
108/* int
109 * inet_pton4(src, dst)
110 *	like inet_aton() but without all the hexadecimal and shorthand.
111 * return:
112 *	1 if `src' is a valid dotted quad, else 0.
113 * notice:
114 *	does not touch `dst' unless it's returning 1.
115 * author:
116 *	Paul Vixie, 1996.
117 */
118static int
119inet_pton4(
120	const char *src,
121	u_char *dst
122	)
123{
124	static const char digits[] = "0123456789";
125	int saw_digit, octets, ch;
126	u_char tmp[NS_INADDRSZ], *tp;
127
128	saw_digit = 0;
129	octets = 0;
130	*(tp = tmp) = 0;
131	while ((ch = *src++) != '\0') {
132		const char *pch;
133
134		if ((pch = strchr(digits, ch)) != NULL) {
135			u_int new = *tp * 10 + (u_int)(pch - digits);
136
137			if (new > 255)
138				return (0);
139			*tp = (u_char)new;
140			if (! saw_digit) {
141				if (++octets > 4)
142					return (0);
143				saw_digit = 1;
144			}
145		} else if (ch == '.' && saw_digit) {
146			if (octets == 4)
147				return (0);
148			*++tp = 0;
149			saw_digit = 0;
150		} else
151			return (0);
152	}
153	if (octets < 4)
154		return (0);
155
156	memcpy(dst, tmp, NS_INADDRSZ);
157	return (1);
158}
159
160/* int
161 * inet_pton6(src, dst)
162 *	convert presentation level address to network order binary form.
163 * return:
164 *	1 if `src' is a valid [RFC1884 2.2] address, else 0.
165 * notice:
166 *	(1) does not touch `dst' unless it's returning 1.
167 *	(2) :: in a full address is silently ignored.
168 * credit:
169 *	inspired by Mark Andrews.
170 * author:
171 *	Paul Vixie, 1996.
172 */
173static int
174inet_pton6(
175	const char *src,
176	u_char *dst
177	)
178{
179	static const char xdigits_l[] = "0123456789abcdef",
180			  xdigits_u[] = "0123456789ABCDEF";
181	u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
182	const char *xdigits, *curtok;
183	int ch, saw_xdigit;
184	u_int val;
185
186	memset((tp = tmp), '\0', NS_IN6ADDRSZ);
187	endp = tp + NS_IN6ADDRSZ;
188	colonp = NULL;
189	/* Leading :: requires some special handling. */
190	if (*src == ':')
191		if (*++src != ':')
192			return (0);
193	curtok = src;
194	saw_xdigit = 0;
195	val = 0;
196	while ((ch = *src++) != '\0') {
197		const char *pch;
198
199		if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
200			pch = strchr((xdigits = xdigits_u), ch);
201		if (pch != NULL) {
202			val <<= 4;
203			val |= (pch - xdigits);
204			if (val > 0xffff)
205				return (0);
206			saw_xdigit = 1;
207			continue;
208		}
209		if (ch == ':') {
210			curtok = src;
211			if (!saw_xdigit) {
212				if (colonp)
213					return (0);
214				colonp = tp;
215				continue;
216			}
217			if (tp + NS_INT16SZ > endp)
218				return (0);
219			*tp++ = (u_char) (val >> 8) & 0xff;
220			*tp++ = (u_char) val & 0xff;
221			saw_xdigit = 0;
222			val = 0;
223			continue;
224		}
225		if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
226		    inet_pton4(curtok, tp) > 0) {
227			tp += NS_INADDRSZ;
228			saw_xdigit = 0;
229			break;	/* '\0' was seen by inet_pton4(). */
230		}
231		return (0);
232	}
233	if (saw_xdigit) {
234		if (tp + NS_INT16SZ > endp)
235			return (0);
236		*tp++ = (u_char) (val >> 8) & 0xff;
237		*tp++ = (u_char) val & 0xff;
238	}
239	if (colonp != NULL) {
240		/*
241		 * Since some memmove()'s erroneously fail to handle
242		 * overlapping regions, we'll do the shift by hand.
243		 */
244		const int n = (int)(tp - colonp);
245		int i;
246
247		for (i = 1; i <= n; i++) {
248			endp[- i] = colonp[n - i];
249			colonp[n - i] = 0;
250		}
251		tp = endp;
252	}
253	if (tp != endp)
254		return (0);
255	memcpy(dst, tmp, NS_IN6ADDRSZ);
256	return (1);
257}
258