118099Spst/*
218099Spst * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
318099Spst * Copyright (c) 1996,1999 by Internet Software Consortium.
4151497Sru *
5151497Sru * Permission to use, copy, modify, and distribute this software for any
618099Spst * purpose with or without fee is hereby granted, provided that the above
718099Spst * copyright notice and this permission notice appear in all copies.
818099Spst *
918099Spst * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
1018099Spst * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1118099Spst * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
1218099Spst * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1318099Spst * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1418099Spst * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
1518099Spst * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1618099Spst */
1718099Spst
1818099Spst#include <sys/param.h>
1918099Spst#include <sys/socket.h>
2018099Spst#include <sys/systm.h>
2118099Spst
2218099Spst#include <netinet/in.h>
2318099Spst
2418099Spst/*%
2518099Spst * WARNING: Don't even consider trying to compile this on a system where
2618099Spst * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
2718099Spst */
2818099Spst
2918099Spststatic int	inet_pton4(const char *src, u_char *dst);
3018099Spststatic int	inet_pton6(const char *src, u_char *dst);
3118099Spst
3218099Spst/* int
3318099Spst * inet_pton(af, src, dst)
3418099Spst *	convert from presentation format (which usually means ASCII printable)
3518099Spst *	to network format (which is usually some kind of binary format).
3618099Spst * return:
3718099Spst *	1 if the address was valid for the specified address family
3818099Spst *	0 if the address wasn't valid (`dst' is untouched in this case)
3918099Spst *	-1 if some other error occurred (`dst' is untouched in this case, too)
4018099Spst * author:
4118099Spst *	Paul Vixie, 1996.
4218099Spst */
4318099Spstint
4418099Spstinet_pton(int af, const char *src, void *dst)
4518099Spst{
4618099Spst	switch (af) {
4718099Spst	case AF_INET:
4818099Spst		return (inet_pton4(src, dst));
4918099Spst	case AF_INET6:
5018099Spst		return (inet_pton6(src, dst));
5118099Spst	default:
5218099Spst		return (-1);
5318099Spst	}
5418099Spst	/* NOTREACHED */
5518099Spst}
5618099Spst
5718099Spst/* int
5818099Spst * inet_pton4(src, dst)
5918099Spst *	like inet_aton() but without all the hexadecimal and shorthand.
6018099Spst * return:
6118099Spst *	1 if `src' is a valid dotted quad, else 0.
6218099Spst * notice:
6318099Spst *	does not touch `dst' unless it's returning 1.
6418099Spst * author:
6518099Spst *	Paul Vixie, 1996.
6618099Spst */
6718099Spststatic int
6818099Spstinet_pton4(const char *src, u_char *dst)
6918099Spst{
7018099Spst	static const char digits[] = "0123456789";
7118099Spst	int saw_digit, octets, ch;
7218099Spst#define NS_INADDRSZ	4
7318099Spst	u_char tmp[NS_INADDRSZ], *tp;
7418099Spst
7518099Spst	saw_digit = 0;
7618099Spst	octets = 0;
7718099Spst	*(tp = tmp) = 0;
7818099Spst	while ((ch = *src++) != '\0') {
7918099Spst		const char *pch;
8018099Spst
8118099Spst		if ((pch = strchr(digits, ch)) != NULL) {
8218099Spst			u_int new = *tp * 10 + (pch - digits);
8318099Spst
8418099Spst			if (saw_digit && *tp == 0)
8518099Spst				return (0);
8618099Spst			if (new > 255)
8718099Spst				return (0);
8818099Spst			*tp = new;
8918099Spst			if (!saw_digit) {
9018099Spst				if (++octets > 4)
9118099Spst					return (0);
9218099Spst				saw_digit = 1;
9318099Spst			}
9418099Spst		} else if (ch == '.' && saw_digit) {
9518099Spst			if (octets == 4)
9618099Spst				return (0);
9718099Spst			*++tp = 0;
9818099Spst			saw_digit = 0;
9918099Spst		} else
10018099Spst			return (0);
10118099Spst	}
10218099Spst	if (octets < 4)
10318099Spst		return (0);
10418099Spst	memcpy(dst, tmp, NS_INADDRSZ);
10518099Spst	return (1);
10618099Spst}
10718099Spst
10818099Spst/* int
10918099Spst * inet_pton6(src, dst)
11018099Spst *	convert presentation level address to network order binary form.
11118099Spst * return:
11218099Spst *	1 if `src' is a valid [RFC1884 2.2] address, else 0.
11318099Spst * notice:
11418099Spst *	(1) does not touch `dst' unless it's returning 1.
11518099Spst *	(2) :: in a full address is silently ignored.
11618099Spst * credit:
11718099Spst *	inspired by Mark Andrews.
11818099Spst * author:
11918099Spst *	Paul Vixie, 1996.
12018099Spst */
12118099Spststatic int
12218099Spstinet_pton6(const char *src, u_char *dst)
12318099Spst{
12418099Spst	static const char xdigits_l[] = "0123456789abcdef",
12518099Spst			  xdigits_u[] = "0123456789ABCDEF";
12618099Spst#define NS_IN6ADDRSZ	16
12718099Spst#define NS_INT16SZ	2
12818099Spst	u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
12918099Spst	const char *xdigits, *curtok;
13018099Spst	int ch, seen_xdigits;
13118099Spst	u_int val;
13218099Spst
13318099Spst	memset((tp = tmp), '\0', NS_IN6ADDRSZ);
13418099Spst	endp = tp + NS_IN6ADDRSZ;
13518099Spst	colonp = NULL;
13618099Spst	/* Leading :: requires some special handling. */
13718099Spst	if (*src == ':')
13818099Spst		if (*++src != ':')
13918099Spst			return (0);
14018099Spst	curtok = src;
14118099Spst	seen_xdigits = 0;
14218099Spst	val = 0;
14318099Spst	while ((ch = *src++) != '\0') {
14418099Spst		const char *pch;
14518099Spst
14618099Spst		if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
14718099Spst			pch = strchr((xdigits = xdigits_u), ch);
14818099Spst		if (pch != NULL) {
14918099Spst			val <<= 4;
15018099Spst			val |= (pch - xdigits);
15118099Spst			if (++seen_xdigits > 4)
15218099Spst				return (0);
15318099Spst			continue;
15418099Spst		}
15518099Spst		if (ch == ':') {
15618099Spst			curtok = src;
15718099Spst			if (!seen_xdigits) {
15818099Spst				if (colonp)
15918099Spst					return (0);
16018099Spst				colonp = tp;
16118099Spst				continue;
16218099Spst			} else if (*src == '\0') {
16318099Spst				return (0);
16418099Spst			}
16518099Spst			if (tp + NS_INT16SZ > endp)
16618099Spst				return (0);
16718099Spst			*tp++ = (u_char) (val >> 8) & 0xff;
16818099Spst			*tp++ = (u_char) val & 0xff;
16918099Spst			seen_xdigits = 0;
17018099Spst			val = 0;
17118099Spst			continue;
17218099Spst		}
17318099Spst		if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
17418099Spst		    inet_pton4(curtok, tp) > 0) {
17518099Spst			tp += NS_INADDRSZ;
17618099Spst			seen_xdigits = 0;
17718099Spst			break;	/*%< '\\0' was seen by inet_pton4(). */
17818099Spst		}
17918099Spst		return (0);
18018099Spst	}
18118099Spst	if (seen_xdigits) {
18218099Spst		if (tp + NS_INT16SZ > endp)
18318099Spst			return (0);
18418099Spst		*tp++ = (u_char) (val >> 8) & 0xff;
18518099Spst		*tp++ = (u_char) val & 0xff;
18618099Spst	}
18718099Spst	if (colonp != NULL) {
18818099Spst		/*
18918099Spst		 * Since some memmove()'s erroneously fail to handle
19018099Spst		 * overlapping regions, we'll do the shift by hand.
19118099Spst		 */
19218099Spst		const int n = tp - colonp;
19318099Spst		int i;
19418099Spst
19518099Spst		if (tp == endp)
19618099Spst			return (0);
19718099Spst		for (i = 1; i <= n; i++) {
19818099Spst			endp[- i] = colonp[n - i];
19918099Spst			colonp[n - i] = 0;
20018099Spst		}
20118099Spst		tp = endp;
20218099Spst	}
20318099Spst	if (tp != endp)
20418099Spst		return (0);
20518099Spst	memcpy(dst, tmp, NS_IN6ADDRSZ);
20618099Spst	return (1);
20718099Spst}
20818099Spst
20918099Spst/*! \file */
21018099Spst