1b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes/*	$NetBSD: inet_pton.c,v 1.6.10.1 2011/01/10 00:42:17 riz Exp $	*/
21dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes/*
4b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
5b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes * Copyright (c) 1996,1999 by Internet Software Consortium.
61dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
71dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Permission to use, copy, modify, and distribute this software for any
81dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * purpose with or without fee is hereby granted, provided that the above
91dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * copyright notice and this permission notice appear in all copies.
101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
11b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
12b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
14b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
17b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
20b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes#include <sys/cdefs.h>
21b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes#if defined(LIBC_SCCS) && !defined(lint)
22b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes#if 0
23b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughesstatic const char rcsid[] = "Id: inet_pton.c,v 1.5 2005/07/28 06:51:47 marka Exp";
24b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes#else
25b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes__RCSID("$NetBSD: inet_pton.c,v 1.6.10.1 2011/01/10 00:42:17 riz Exp $");
26b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes#endif
27b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes#endif /* LIBC_SCCS and not lint */
28b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes
29b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes// BEGIN android-added
30b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes#define _DIAGASSERT(exp) assert(exp)
31b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes#include "../private/arpa_nameser.h"
32b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes// END android-added
33b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes
34b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes// android-removed: #include "port_before.h"
35b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes
36b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes// android-removed: #include "namespace.h"
371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/param.h>
381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/types.h>
391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/socket.h>
401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <netinet/in.h>
411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <arpa/inet.h>
42b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes#include <arpa/nameser.h>
431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <string.h>
44b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes#include <assert.h>
45b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes#include <ctype.h>
461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <errno.h>
471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
48b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes// android-removed: #include "port_after.h"
49b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes
503398ee9c15278b90bc2934afca6bdf83b6b605e6Elliott Hughes// BEGIN android-removed
513398ee9c15278b90bc2934afca6bdf83b6b605e6Elliott Hughes// #ifdef __weak_alias
523398ee9c15278b90bc2934afca6bdf83b6b605e6Elliott Hughes// __weak_alias(inet_pton,_inet_pton)
533398ee9c15278b90bc2934afca6bdf83b6b605e6Elliott Hughes// #endif
543398ee9c15278b90bc2934afca6bdf83b6b605e6Elliott Hughes// END android-removed
55b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes
56b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes/*%
571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * WARNING: Don't even consider trying to compile this on a system where
581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
61b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughesstatic int	inet_pton4(const char *src, u_char *dst, int pton);
621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int	inet_pton6(const char *src, u_char *dst);
631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* int
651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * inet_pton(af, src, dst)
661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	convert from presentation format (which usually means ASCII printable)
671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	to network format (which is usually some kind of binary format).
681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return:
691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	1 if the address was valid for the specified address family
701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	0 if the address wasn't valid (`dst' is untouched in this case)
711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	-1 if some other error occurred (`dst' is untouched in this case, too)
721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * author:
731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	Paul Vixie, 1996.
741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint
761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectinet_pton(int af, const char *src, void *dst)
771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
78b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes
79b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes	_DIAGASSERT(src != NULL);
80b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes	_DIAGASSERT(dst != NULL);
81b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes
821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	switch (af) {
831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	case AF_INET:
84b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes		return (inet_pton4(src, dst, 1));
851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	case AF_INET6:
861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (inet_pton6(src, dst));
871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	default:
881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		errno = EAFNOSUPPORT;
891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (-1);
901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/* NOTREACHED */
921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* int
95b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes * inet_pton4(src, dst, pton)
96b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes *	when last arg is 0: inet_aton(). with hexadecimal, octal and shorthand.
97b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes *	when last arg is 1: inet_pton(). decimal dotted-quad only.
981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return:
99b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes *	1 if `src' is a valid input, else 0.
1001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notice:
1011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	does not touch `dst' unless it's returning 1.
1021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * author:
1031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	Paul Vixie, 1996.
1041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
1051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int
106b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughesinet_pton4(const char *src, u_char *dst, int pton)
1071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
108b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes	u_int32_t val;
109b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes	u_int digit, base;
110b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes	int n;
111b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes	unsigned char c;
112b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes	u_int parts[4];
113b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes	register u_int *pp = parts;
1141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
115b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes	_DIAGASSERT(src != NULL);
116b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes	_DIAGASSERT(dst != NULL);
1171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
118b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes	c = *src;
119b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes	for (;;) {
120b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes		/*
121b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes		 * Collect number up to ``.''.
122b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes		 * Values are specified as for C:
123b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes		 * 0x=hex, 0=octal, isdigit=decimal.
124b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes		 */
125b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes		if (!isdigit(c))
126b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes			return (0);
127b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes		val = 0; base = 10;
128b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes		if (c == '0') {
129b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes			c = *++src;
130b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes			if (c == 'x' || c == 'X')
131b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes				base = 16, c = *++src;
132b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes			else if (isdigit(c) && c != '9')
133b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes				base = 8;
134b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes		}
135b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes		/* inet_pton() takes decimal only */
136b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes		if (pton && base != 10)
137b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes			return (0);
138b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes		for (;;) {
139b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes			if (isdigit(c)) {
140b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes				digit = c - '0';
141b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes				if (digit >= base)
142b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes					break;
143b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes				val = (val * base) + digit;
144b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes				c = *++src;
145b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes			} else if (base == 16 && isxdigit(c)) {
146b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes				digit = c + 10 - (islower(c) ? 'a' : 'A');
147b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes				if (digit >= 16)
148b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes					break;
149b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes				val = (val << 4) | digit;
150b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes				c = *++src;
151b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes			} else
152b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes				break;
153b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes		}
154b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes		if (c == '.') {
155b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes			/*
156b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes			 * Internet format:
157b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes			 *	a.b.c.d
158b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes			 *	a.b.c	(with c treated as 16 bits)
159b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes			 *	a.b	(with b treated as 24 bits)
160b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes			 *	a	(with a treated as 32 bits)
161b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes			 */
162b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes			if (pp >= parts + 3)
1631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return (0);
164b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes			*pp++ = val;
165b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes			c = *++src;
1661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		} else
167b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes			break;
1681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
169b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes	/*
170b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes	 * Check for trailing characters.
171b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes	 */
172b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes	if (c != '\0' && !isspace(c))
1731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (0);
174b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes	/*
175b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes	 * Concoct the address according to
176b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes	 * the number of parts specified.
177b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes	 */
178b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes	n = pp - parts + 1;
179b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes	/* inet_pton() takes dotted-quad only.  it does not take shorthand. */
180b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes	if (pton && n != 4)
181b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes		return (0);
182b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes	switch (n) {
183b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes
184b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes	case 0:
185b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes		return (0);		/* initial nondigit */
1861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
187b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes	case 1:				/* a -- 32 bits */
188b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes		break;
189b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes
190b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes	case 2:				/* a.b -- 8.24 bits */
191b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes		if (parts[0] > 0xff || val > 0xffffff)
192b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes			return (0);
193b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes		val |= parts[0] << 24;
194b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes		break;
195b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes
196b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes	case 3:				/* a.b.c -- 8.8.16 bits */
197b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes		if ((parts[0] | parts[1]) > 0xff || val > 0xffff)
198b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes			return (0);
199b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes		val |= (parts[0] << 24) | (parts[1] << 16);
200b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes		break;
201b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes
202b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes	case 4:				/* a.b.c.d -- 8.8.8.8 bits */
203b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes		if ((parts[0] | parts[1] | parts[2] | val) > 0xff)
204b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes			return (0);
205b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes		val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
206b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes		break;
207b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes	}
208b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes	if (dst) {
209b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes		val = htonl(val);
210b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes		memcpy(dst, &val, NS_INADDRSZ);
211b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes	}
2121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (1);
2131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
2141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* int
2161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * inet_pton6(src, dst)
2171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	convert presentation level address to network order binary form.
2181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return:
2191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	1 if `src' is a valid [RFC1884 2.2] address, else 0.
2201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notice:
2211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	(1) does not touch `dst' unless it's returning 1.
2221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	(2) :: in a full address is silently ignored.
2231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * credit:
2241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	inspired by Mark Andrews.
2251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * author:
2261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	Paul Vixie, 1996.
2271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
2281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int
2291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectinet_pton6(const char *src, u_char *dst)
2301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
2311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	static const char xdigits_l[] = "0123456789abcdef",
2321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			  xdigits_u[] = "0123456789ABCDEF";
233b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes	u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
2341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const char *xdigits, *curtok;
235b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes	int ch, seen_xdigits;
2361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	u_int val;
2371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
238b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes	_DIAGASSERT(src != NULL);
239b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes	_DIAGASSERT(dst != NULL);
240b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes
241b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes	memset((tp = tmp), '\0', NS_IN6ADDRSZ);
242b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes	endp = tp + NS_IN6ADDRSZ;
2431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	colonp = NULL;
2441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/* Leading :: requires some special handling. */
2451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (*src == ':')
2461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (*++src != ':')
2471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (0);
2481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	curtok = src;
249b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes	seen_xdigits = 0;
2501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	val = 0;
2511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	while ((ch = *src++) != '\0') {
2521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		const char *pch;
2531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
2551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			pch = strchr((xdigits = xdigits_u), ch);
2561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (pch != NULL) {
2571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			val <<= 4;
2581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			val |= (pch - xdigits);
259b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes			if (++seen_xdigits > 4)
2601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return (0);
2611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			continue;
2621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
2631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (ch == ':') {
2641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			curtok = src;
265b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes			if (!seen_xdigits) {
2661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (colonp)
2671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					return (0);
2681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				colonp = tp;
2691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				continue;
270b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes			} else if (*src == '\0')
2711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return (0);
272b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes			if (tp + NS_INT16SZ > endp)
2731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return (0);
2741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			*tp++ = (u_char) (val >> 8) & 0xff;
2751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			*tp++ = (u_char) val & 0xff;
276b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes			seen_xdigits = 0;
2771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			val = 0;
2781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			continue;
2791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
280b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes		if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
281b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes		    inet_pton4(curtok, tp, 1) > 0) {
282b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes			tp += NS_INADDRSZ;
283b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes			seen_xdigits = 0;
284b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes			break;	/*%< '\\0' was seen by inet_pton4(). */
2851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
2861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (0);
2871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
288b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes	if (seen_xdigits) {
289b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes		if (tp + NS_INT16SZ > endp)
2901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (0);
2911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		*tp++ = (u_char) (val >> 8) & 0xff;
2921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		*tp++ = (u_char) val & 0xff;
2931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
2941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (colonp != NULL) {
2951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/*
2961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * Since some memmove()'s erroneously fail to handle
2971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * overlapping regions, we'll do the shift by hand.
2981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 */
2991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		const int n = tp - colonp;
3001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		int i;
3011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
302b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes		if (tp == endp)
303b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes			return (0);
3041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		for (i = 1; i <= n; i++) {
3051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			endp[- i] = colonp[n - i];
3061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			colonp[n - i] = 0;
3071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
3081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		tp = endp;
3091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
3101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (tp != endp)
3111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (0);
312b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes	memcpy(dst, tmp, NS_IN6ADDRSZ);
3131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (1);
3141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
315b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes
316b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes/*! \file */
317