xref: /minix/external/bsd/bind/dist/lib/isc/inet_pton.c (revision 00b67f09)
1*00b67f09SDavid van Moolenbroek /*	$NetBSD: inet_pton.c,v 1.6 2014/12/10 04:37:59 christos Exp $	*/
2*00b67f09SDavid van Moolenbroek 
3*00b67f09SDavid van Moolenbroek /*
4*00b67f09SDavid van Moolenbroek  * Copyright (C) 2004, 2005, 2007, 2013, 2014  Internet Systems Consortium, Inc. ("ISC")
5*00b67f09SDavid van Moolenbroek  * Copyright (C) 1996-2003  Internet Software Consortium.
6*00b67f09SDavid van Moolenbroek  *
7*00b67f09SDavid van Moolenbroek  * Permission to use, copy, modify, and/or distribute this software for any
8*00b67f09SDavid van Moolenbroek  * purpose with or without fee is hereby granted, provided that the above
9*00b67f09SDavid van Moolenbroek  * copyright notice and this permission notice appear in all copies.
10*00b67f09SDavid van Moolenbroek  *
11*00b67f09SDavid van Moolenbroek  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12*00b67f09SDavid van Moolenbroek  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13*00b67f09SDavid van Moolenbroek  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14*00b67f09SDavid van Moolenbroek  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15*00b67f09SDavid van Moolenbroek  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16*00b67f09SDavid van Moolenbroek  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*00b67f09SDavid van Moolenbroek  * PERFORMANCE OF THIS SOFTWARE.
18*00b67f09SDavid van Moolenbroek  */
19*00b67f09SDavid van Moolenbroek 
20*00b67f09SDavid van Moolenbroek /*! \file */
21*00b67f09SDavid van Moolenbroek 
22*00b67f09SDavid van Moolenbroek #if defined(LIBC_SCCS) && !defined(lint)
23*00b67f09SDavid van Moolenbroek static char rcsid[] =
24*00b67f09SDavid van Moolenbroek 	"Id: inet_pton.c,v 1.19 2007/06/19 23:47:17 tbox Exp ";
25*00b67f09SDavid van Moolenbroek #endif /* LIBC_SCCS and not lint */
26*00b67f09SDavid van Moolenbroek 
27*00b67f09SDavid van Moolenbroek #include <config.h>
28*00b67f09SDavid van Moolenbroek 
29*00b67f09SDavid van Moolenbroek #include <errno.h>
30*00b67f09SDavid van Moolenbroek #include <string.h>
31*00b67f09SDavid van Moolenbroek 
32*00b67f09SDavid van Moolenbroek #include <isc/net.h>
33*00b67f09SDavid van Moolenbroek 
34*00b67f09SDavid van Moolenbroek /*% INT16 Size */
35*00b67f09SDavid van Moolenbroek #define NS_INT16SZ	 2
36*00b67f09SDavid van Moolenbroek /*% IPv4 Address Size */
37*00b67f09SDavid van Moolenbroek #define NS_INADDRSZ	 4
38*00b67f09SDavid van Moolenbroek /*% IPv6 Address Size */
39*00b67f09SDavid van Moolenbroek #define NS_IN6ADDRSZ	16
40*00b67f09SDavid van Moolenbroek 
41*00b67f09SDavid van Moolenbroek /*
42*00b67f09SDavid van Moolenbroek  * WARNING: Don't even consider trying to compile this on a system where
43*00b67f09SDavid van Moolenbroek  * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
44*00b67f09SDavid van Moolenbroek  */
45*00b67f09SDavid van Moolenbroek 
46*00b67f09SDavid van Moolenbroek static int inet_pton4(const char *src, unsigned char *dst);
47*00b67f09SDavid van Moolenbroek static int inet_pton6(const char *src, unsigned char *dst);
48*00b67f09SDavid van Moolenbroek 
49*00b67f09SDavid van Moolenbroek /*%
50*00b67f09SDavid van Moolenbroek  *	convert from presentation format (which usually means ASCII printable)
51*00b67f09SDavid van Moolenbroek  *	to network format (which is usually some kind of binary format).
52*00b67f09SDavid van Moolenbroek  * \return
53*00b67f09SDavid van Moolenbroek  *	1 if the address was valid for the specified address family
54*00b67f09SDavid van Moolenbroek  *	0 if the address wasn't valid (`dst' is untouched in this case)
55*00b67f09SDavid van Moolenbroek  *	-1 if some other error occurred (`dst' is untouched in this case, too)
56*00b67f09SDavid van Moolenbroek  * \author
57*00b67f09SDavid van Moolenbroek  *	Paul Vixie, 1996.
58*00b67f09SDavid van Moolenbroek  */
59*00b67f09SDavid van Moolenbroek int
isc_net_pton(int af,const char * src,void * dst)60*00b67f09SDavid van Moolenbroek isc_net_pton(int af, const char *src, void *dst) {
61*00b67f09SDavid van Moolenbroek 	switch (af) {
62*00b67f09SDavid van Moolenbroek 	case AF_INET:
63*00b67f09SDavid van Moolenbroek 		return (inet_pton4(src, dst));
64*00b67f09SDavid van Moolenbroek 	case AF_INET6:
65*00b67f09SDavid van Moolenbroek 		return (inet_pton6(src, dst));
66*00b67f09SDavid van Moolenbroek 	default:
67*00b67f09SDavid van Moolenbroek 		errno = EAFNOSUPPORT;
68*00b67f09SDavid van Moolenbroek 		return (-1);
69*00b67f09SDavid van Moolenbroek 	}
70*00b67f09SDavid van Moolenbroek 	/* NOTREACHED */
71*00b67f09SDavid van Moolenbroek }
72*00b67f09SDavid van Moolenbroek 
73*00b67f09SDavid van Moolenbroek /*!\fn static int inet_pton4(const char *src, unsigned char *dst)
74*00b67f09SDavid van Moolenbroek  * \brief
75*00b67f09SDavid van Moolenbroek  *	like inet_aton() but without all the hexadecimal and shorthand.
76*00b67f09SDavid van Moolenbroek  * \return
77*00b67f09SDavid van Moolenbroek  *	1 if `src' is a valid dotted quad, else 0.
78*00b67f09SDavid van Moolenbroek  * \note
79*00b67f09SDavid van Moolenbroek  *	does not touch `dst' unless it's returning 1.
80*00b67f09SDavid van Moolenbroek  * \author
81*00b67f09SDavid van Moolenbroek  *	Paul Vixie, 1996.
82*00b67f09SDavid van Moolenbroek  */
83*00b67f09SDavid van Moolenbroek static int
inet_pton4(const char * src,unsigned char * dst)84*00b67f09SDavid van Moolenbroek inet_pton4(const char *src, unsigned char *dst) {
85*00b67f09SDavid van Moolenbroek 	static const char digits[] = "0123456789";
86*00b67f09SDavid van Moolenbroek 	int saw_digit, octets, ch;
87*00b67f09SDavid van Moolenbroek 	unsigned char tmp[NS_INADDRSZ], *tp;
88*00b67f09SDavid van Moolenbroek 
89*00b67f09SDavid van Moolenbroek 	saw_digit = 0;
90*00b67f09SDavid van Moolenbroek 	octets = 0;
91*00b67f09SDavid van Moolenbroek 	*(tp = tmp) = 0;
92*00b67f09SDavid van Moolenbroek 	while ((ch = *src++) != '\0') {
93*00b67f09SDavid van Moolenbroek 		const char *pch;
94*00b67f09SDavid van Moolenbroek 
95*00b67f09SDavid van Moolenbroek 		if ((pch = strchr(digits, ch)) != NULL) {
96*00b67f09SDavid van Moolenbroek 			unsigned int new = *tp * 10;
97*00b67f09SDavid van Moolenbroek 
98*00b67f09SDavid van Moolenbroek 			new += (int)(pch - digits);
99*00b67f09SDavid van Moolenbroek 			if (saw_digit && *tp == 0)
100*00b67f09SDavid van Moolenbroek 				return (0);
101*00b67f09SDavid van Moolenbroek 			if (new > 255)
102*00b67f09SDavid van Moolenbroek 				return (0);
103*00b67f09SDavid van Moolenbroek 			*tp = new;
104*00b67f09SDavid van Moolenbroek 			if (!saw_digit) {
105*00b67f09SDavid van Moolenbroek 				if (++octets > 4)
106*00b67f09SDavid van Moolenbroek 					return (0);
107*00b67f09SDavid van Moolenbroek 				saw_digit = 1;
108*00b67f09SDavid van Moolenbroek 			}
109*00b67f09SDavid van Moolenbroek 		} else if (ch == '.' && saw_digit) {
110*00b67f09SDavid van Moolenbroek 			if (octets == 4)
111*00b67f09SDavid van Moolenbroek 				return (0);
112*00b67f09SDavid van Moolenbroek 			*++tp = 0;
113*00b67f09SDavid van Moolenbroek 			saw_digit = 0;
114*00b67f09SDavid van Moolenbroek 		} else
115*00b67f09SDavid van Moolenbroek 			return (0);
116*00b67f09SDavid van Moolenbroek 	}
117*00b67f09SDavid van Moolenbroek 	if (octets < 4)
118*00b67f09SDavid van Moolenbroek 		return (0);
119*00b67f09SDavid van Moolenbroek 	memmove(dst, tmp, NS_INADDRSZ);
120*00b67f09SDavid van Moolenbroek 	return (1);
121*00b67f09SDavid van Moolenbroek }
122*00b67f09SDavid van Moolenbroek 
123*00b67f09SDavid van Moolenbroek /*%
124*00b67f09SDavid van Moolenbroek  *	convert presentation level address to network order binary form.
125*00b67f09SDavid van Moolenbroek  * \return
126*00b67f09SDavid van Moolenbroek  *	1 if `src' is a valid [RFC1884 2.2] address, else 0.
127*00b67f09SDavid van Moolenbroek  * \note
128*00b67f09SDavid van Moolenbroek  *	(1) does not touch `dst' unless it's returning 1.
129*00b67f09SDavid van Moolenbroek  * \note
130*00b67f09SDavid van Moolenbroek  *	(2) :: in a full address is silently ignored.
131*00b67f09SDavid van Moolenbroek  * \author
132*00b67f09SDavid van Moolenbroek  *	inspired by Mark Andrews.
133*00b67f09SDavid van Moolenbroek  * \author
134*00b67f09SDavid van Moolenbroek  *	Paul Vixie, 1996.
135*00b67f09SDavid van Moolenbroek  */
136*00b67f09SDavid van Moolenbroek static int
inet_pton6(const char * src,unsigned char * dst)137*00b67f09SDavid van Moolenbroek inet_pton6(const char *src, unsigned char *dst) {
138*00b67f09SDavid van Moolenbroek 	static const char xdigits_l[] = "0123456789abcdef",
139*00b67f09SDavid van Moolenbroek 			  xdigits_u[] = "0123456789ABCDEF";
140*00b67f09SDavid van Moolenbroek 	unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
141*00b67f09SDavid van Moolenbroek 	const char *xdigits, *curtok;
142*00b67f09SDavid van Moolenbroek 	int ch, seen_xdigits;
143*00b67f09SDavid van Moolenbroek 	unsigned int val;
144*00b67f09SDavid van Moolenbroek 
145*00b67f09SDavid van Moolenbroek 	memset((tp = tmp), '\0', NS_IN6ADDRSZ);
146*00b67f09SDavid van Moolenbroek 	endp = tp + NS_IN6ADDRSZ;
147*00b67f09SDavid van Moolenbroek 	colonp = NULL;
148*00b67f09SDavid van Moolenbroek 	/* Leading :: requires some special handling. */
149*00b67f09SDavid van Moolenbroek 	if (*src == ':')
150*00b67f09SDavid van Moolenbroek 		if (*++src != ':')
151*00b67f09SDavid van Moolenbroek 			return (0);
152*00b67f09SDavid van Moolenbroek 	curtok = src;
153*00b67f09SDavid van Moolenbroek 	seen_xdigits = 0;
154*00b67f09SDavid van Moolenbroek 	val = 0;
155*00b67f09SDavid van Moolenbroek 	while ((ch = *src++) != '\0') {
156*00b67f09SDavid van Moolenbroek 		const char *pch;
157*00b67f09SDavid van Moolenbroek 
158*00b67f09SDavid van Moolenbroek 		if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
159*00b67f09SDavid van Moolenbroek 			pch = strchr((xdigits = xdigits_u), ch);
160*00b67f09SDavid van Moolenbroek 		if (pch != NULL) {
161*00b67f09SDavid van Moolenbroek 			val <<= 4;
162*00b67f09SDavid van Moolenbroek 			val |= (pch - xdigits);
163*00b67f09SDavid van Moolenbroek 			if (++seen_xdigits > 4)
164*00b67f09SDavid van Moolenbroek 				return (0);
165*00b67f09SDavid van Moolenbroek 			continue;
166*00b67f09SDavid van Moolenbroek 		}
167*00b67f09SDavid van Moolenbroek 		if (ch == ':') {
168*00b67f09SDavid van Moolenbroek 			curtok = src;
169*00b67f09SDavid van Moolenbroek 			if (!seen_xdigits) {
170*00b67f09SDavid van Moolenbroek 				if (colonp)
171*00b67f09SDavid van Moolenbroek 					return (0);
172*00b67f09SDavid van Moolenbroek 				colonp = tp;
173*00b67f09SDavid van Moolenbroek 				continue;
174*00b67f09SDavid van Moolenbroek 			}
175*00b67f09SDavid van Moolenbroek 			if (tp + NS_INT16SZ > endp)
176*00b67f09SDavid van Moolenbroek 				return (0);
177*00b67f09SDavid van Moolenbroek 			*tp++ = (unsigned char) (val >> 8) & 0xff;
178*00b67f09SDavid van Moolenbroek 			*tp++ = (unsigned char) val & 0xff;
179*00b67f09SDavid van Moolenbroek 			seen_xdigits = 0;
180*00b67f09SDavid van Moolenbroek 			val = 0;
181*00b67f09SDavid van Moolenbroek 			continue;
182*00b67f09SDavid van Moolenbroek 		}
183*00b67f09SDavid van Moolenbroek 		if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
184*00b67f09SDavid van Moolenbroek 		    inet_pton4(curtok, tp) > 0) {
185*00b67f09SDavid van Moolenbroek 			tp += NS_INADDRSZ;
186*00b67f09SDavid van Moolenbroek 			seen_xdigits = 0;
187*00b67f09SDavid van Moolenbroek 			break;	/* '\0' was seen by inet_pton4(). */
188*00b67f09SDavid van Moolenbroek 		}
189*00b67f09SDavid van Moolenbroek 		return (0);
190*00b67f09SDavid van Moolenbroek 	}
191*00b67f09SDavid van Moolenbroek 	if (seen_xdigits) {
192*00b67f09SDavid van Moolenbroek 		if (tp + NS_INT16SZ > endp)
193*00b67f09SDavid van Moolenbroek 			return (0);
194*00b67f09SDavid van Moolenbroek 		*tp++ = (unsigned char) (val >> 8) & 0xff;
195*00b67f09SDavid van Moolenbroek 		*tp++ = (unsigned char) val & 0xff;
196*00b67f09SDavid van Moolenbroek 	}
197*00b67f09SDavid van Moolenbroek 	if (colonp != NULL) {
198*00b67f09SDavid van Moolenbroek 		/*
199*00b67f09SDavid van Moolenbroek 		 * Since some memmove()'s erroneously fail to handle
200*00b67f09SDavid van Moolenbroek 		 * overlapping regions, we'll do the shift by hand.
201*00b67f09SDavid van Moolenbroek 		 */
202*00b67f09SDavid van Moolenbroek 		const int n = (int)(tp - colonp);
203*00b67f09SDavid van Moolenbroek 		int i;
204*00b67f09SDavid van Moolenbroek 
205*00b67f09SDavid van Moolenbroek 		if (tp == endp)
206*00b67f09SDavid van Moolenbroek 			return (0);
207*00b67f09SDavid van Moolenbroek 		for (i = 1; i <= n; i++) {
208*00b67f09SDavid van Moolenbroek 			endp[- i] = colonp[n - i];
209*00b67f09SDavid van Moolenbroek 			colonp[n - i] = 0;
210*00b67f09SDavid van Moolenbroek 		}
211*00b67f09SDavid van Moolenbroek 		tp = endp;
212*00b67f09SDavid van Moolenbroek 	}
213*00b67f09SDavid van Moolenbroek 	if (tp != endp)
214*00b67f09SDavid van Moolenbroek 		return (0);
215*00b67f09SDavid van Moolenbroek 	memmove(dst, tmp, NS_IN6ADDRSZ);
216*00b67f09SDavid van Moolenbroek 	return (1);
217*00b67f09SDavid van Moolenbroek }
218