• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)
58 static 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 
75 static int	inet_pton4 (const char *src, u_char *dst);
76 static 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  */
89 int
inet_pton(int af,const char * src,void * dst)90 inet_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  */
118 static int
inet_pton4(const char * src,u_char * dst)119 inet_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  */
173 static int
inet_pton6(const char * src,u_char * dst)174 inet_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