17c478bd9Sstevel@tonic-gate /*
2*9525b14bSRao Shoaib  * Copyright (C) 2004, 2005, 2008  Internet Systems Consortium, Inc. ("ISC")
3*9525b14bSRao Shoaib  * Copyright (C) 1996, 1998, 1999, 2001, 2003  Internet Software Consortium.
47c478bd9Sstevel@tonic-gate  *
5*9525b14bSRao Shoaib  * Permission to use, copy, modify, and/or distribute this software for any
67c478bd9Sstevel@tonic-gate  * purpose with or without fee is hereby granted, provided that the above
77c478bd9Sstevel@tonic-gate  * copyright notice and this permission notice appear in all copies.
87c478bd9Sstevel@tonic-gate  *
9*9525b14bSRao Shoaib  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10*9525b14bSRao Shoaib  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11*9525b14bSRao Shoaib  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12*9525b14bSRao Shoaib  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13*9525b14bSRao Shoaib  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14*9525b14bSRao Shoaib  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15*9525b14bSRao Shoaib  * PERFORMANCE OF THIS SOFTWARE.
167c478bd9Sstevel@tonic-gate  */
177c478bd9Sstevel@tonic-gate 
187c478bd9Sstevel@tonic-gate #if defined(LIBC_SCCS) && !defined(lint)
19*9525b14bSRao Shoaib static const char rcsid[] = "$Id: inet_net_pton.c,v 1.10 2008/11/14 02:36:51 marka Exp $";
207c478bd9Sstevel@tonic-gate #endif
217c478bd9Sstevel@tonic-gate 
227c478bd9Sstevel@tonic-gate #include "port_before.h"
237c478bd9Sstevel@tonic-gate 
247c478bd9Sstevel@tonic-gate #include <sys/types.h>
257c478bd9Sstevel@tonic-gate #include <sys/socket.h>
267c478bd9Sstevel@tonic-gate #include <netinet/in.h>
277c478bd9Sstevel@tonic-gate #include <arpa/nameser.h>
287c478bd9Sstevel@tonic-gate #include <arpa/inet.h>
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate #include <isc/assertions.h>
317c478bd9Sstevel@tonic-gate #include <ctype.h>
327c478bd9Sstevel@tonic-gate #include <errno.h>
337c478bd9Sstevel@tonic-gate #include <stdio.h>
347c478bd9Sstevel@tonic-gate #include <string.h>
357c478bd9Sstevel@tonic-gate #include <stdlib.h>
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate #include "port_after.h"
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate #ifdef SPRINTF_CHAR
407c478bd9Sstevel@tonic-gate # define SPRINTF(x) strlen(sprintf/**/x)
417c478bd9Sstevel@tonic-gate #else
427c478bd9Sstevel@tonic-gate # define SPRINTF(x) ((size_t)sprintf x)
437c478bd9Sstevel@tonic-gate #endif
447c478bd9Sstevel@tonic-gate 
45*9525b14bSRao Shoaib /*%
467c478bd9Sstevel@tonic-gate  * static int
477c478bd9Sstevel@tonic-gate  * inet_net_pton_ipv4(src, dst, size)
487c478bd9Sstevel@tonic-gate  *	convert IPv4 network number from presentation to network format.
497c478bd9Sstevel@tonic-gate  *	accepts hex octets, hex strings, decimal octets, and /CIDR.
507c478bd9Sstevel@tonic-gate  *	"size" is in bytes and describes "dst".
517c478bd9Sstevel@tonic-gate  * return:
527c478bd9Sstevel@tonic-gate  *	number of bits, either imputed classfully or specified with /CIDR,
537c478bd9Sstevel@tonic-gate  *	or -1 if some failure occurred (check errno).  ENOENT means it was
547c478bd9Sstevel@tonic-gate  *	not an IPv4 network specification.
557c478bd9Sstevel@tonic-gate  * note:
567c478bd9Sstevel@tonic-gate  *	network byte order assumed.  this means 192.5.5.240/28 has
577c478bd9Sstevel@tonic-gate  *	0b11110000 in its fourth octet.
587c478bd9Sstevel@tonic-gate  * author:
597c478bd9Sstevel@tonic-gate  *	Paul Vixie (ISC), June 1996
607c478bd9Sstevel@tonic-gate  */
617c478bd9Sstevel@tonic-gate static int
inet_net_pton_ipv4(const char * src,u_char * dst,size_t size)627c478bd9Sstevel@tonic-gate inet_net_pton_ipv4(const char *src, u_char *dst, size_t size) {
637c478bd9Sstevel@tonic-gate 	static const char xdigits[] = "0123456789abcdef";
647c478bd9Sstevel@tonic-gate 	static const char digits[] = "0123456789";
657c478bd9Sstevel@tonic-gate 	int n, ch, tmp = 0, dirty, bits;
667c478bd9Sstevel@tonic-gate 	const u_char *odst = dst;
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate 	ch = *src++;
697c478bd9Sstevel@tonic-gate 	if (ch == '0' && (src[0] == 'x' || src[0] == 'X')
707c478bd9Sstevel@tonic-gate 	    && isascii((unsigned char)(src[1]))
717c478bd9Sstevel@tonic-gate 	    && isxdigit((unsigned char)(src[1]))) {
727c478bd9Sstevel@tonic-gate 		/* Hexadecimal: Eat nybble string. */
73*9525b14bSRao Shoaib 		if (size <= 0U)
747c478bd9Sstevel@tonic-gate 			goto emsgsize;
757c478bd9Sstevel@tonic-gate 		dirty = 0;
76*9525b14bSRao Shoaib 		src++;	/*%< skip x or X. */
777c478bd9Sstevel@tonic-gate 		while ((ch = *src++) != '\0' && isascii(ch) && isxdigit(ch)) {
787c478bd9Sstevel@tonic-gate 			if (isupper(ch))
797c478bd9Sstevel@tonic-gate 				ch = tolower(ch);
807c478bd9Sstevel@tonic-gate 			n = strchr(xdigits, ch) - xdigits;
817c478bd9Sstevel@tonic-gate 			INSIST(n >= 0 && n <= 15);
827c478bd9Sstevel@tonic-gate 			if (dirty == 0)
837c478bd9Sstevel@tonic-gate 				tmp = n;
847c478bd9Sstevel@tonic-gate 			else
857c478bd9Sstevel@tonic-gate 				tmp = (tmp << 4) | n;
867c478bd9Sstevel@tonic-gate 			if (++dirty == 2) {
87*9525b14bSRao Shoaib 				if (size-- <= 0U)
887c478bd9Sstevel@tonic-gate 					goto emsgsize;
897c478bd9Sstevel@tonic-gate 				*dst++ = (u_char) tmp;
907c478bd9Sstevel@tonic-gate 				dirty = 0;
917c478bd9Sstevel@tonic-gate 			}
927c478bd9Sstevel@tonic-gate 		}
93*9525b14bSRao Shoaib 		if (dirty) {  /*%< Odd trailing nybble? */
94*9525b14bSRao Shoaib 			if (size-- <= 0U)
957c478bd9Sstevel@tonic-gate 				goto emsgsize;
967c478bd9Sstevel@tonic-gate 			*dst++ = (u_char) (tmp << 4);
977c478bd9Sstevel@tonic-gate 		}
987c478bd9Sstevel@tonic-gate 	} else if (isascii(ch) && isdigit(ch)) {
997c478bd9Sstevel@tonic-gate 		/* Decimal: eat dotted digit string. */
1007c478bd9Sstevel@tonic-gate 		for (;;) {
1017c478bd9Sstevel@tonic-gate 			tmp = 0;
1027c478bd9Sstevel@tonic-gate 			do {
1037c478bd9Sstevel@tonic-gate 				n = strchr(digits, ch) - digits;
1047c478bd9Sstevel@tonic-gate 				INSIST(n >= 0 && n <= 9);
1057c478bd9Sstevel@tonic-gate 				tmp *= 10;
1067c478bd9Sstevel@tonic-gate 				tmp += n;
1077c478bd9Sstevel@tonic-gate 				if (tmp > 255)
1087c478bd9Sstevel@tonic-gate 					goto enoent;
1097c478bd9Sstevel@tonic-gate 			} while ((ch = *src++) != '\0' &&
1107c478bd9Sstevel@tonic-gate 				 isascii(ch) && isdigit(ch));
111*9525b14bSRao Shoaib 			if (size-- <= 0U)
1127c478bd9Sstevel@tonic-gate 				goto emsgsize;
1137c478bd9Sstevel@tonic-gate 			*dst++ = (u_char) tmp;
1147c478bd9Sstevel@tonic-gate 			if (ch == '\0' || ch == '/')
1157c478bd9Sstevel@tonic-gate 				break;
1167c478bd9Sstevel@tonic-gate 			if (ch != '.')
1177c478bd9Sstevel@tonic-gate 				goto enoent;
1187c478bd9Sstevel@tonic-gate 			ch = *src++;
1197c478bd9Sstevel@tonic-gate 			if (!isascii(ch) || !isdigit(ch))
1207c478bd9Sstevel@tonic-gate 				goto enoent;
1217c478bd9Sstevel@tonic-gate 		}
1227c478bd9Sstevel@tonic-gate 	} else
1237c478bd9Sstevel@tonic-gate 		goto enoent;
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate 	bits = -1;
1267c478bd9Sstevel@tonic-gate 	if (ch == '/' && isascii((unsigned char)(src[0])) &&
1277c478bd9Sstevel@tonic-gate 	    isdigit((unsigned char)(src[0])) && dst > odst) {
1287c478bd9Sstevel@tonic-gate 		/* CIDR width specifier.  Nothing can follow it. */
129*9525b14bSRao Shoaib 		ch = *src++;	/*%< Skip over the /. */
1307c478bd9Sstevel@tonic-gate 		bits = 0;
1317c478bd9Sstevel@tonic-gate 		do {
1327c478bd9Sstevel@tonic-gate 			n = strchr(digits, ch) - digits;
1337c478bd9Sstevel@tonic-gate 			INSIST(n >= 0 && n <= 9);
1347c478bd9Sstevel@tonic-gate 			bits *= 10;
1357c478bd9Sstevel@tonic-gate 			bits += n;
136*9525b14bSRao Shoaib 			if (bits > 32)
137*9525b14bSRao Shoaib 				goto enoent;
1387c478bd9Sstevel@tonic-gate 		} while ((ch = *src++) != '\0' && isascii(ch) && isdigit(ch));
1397c478bd9Sstevel@tonic-gate 		if (ch != '\0')
1407c478bd9Sstevel@tonic-gate 			goto enoent;
1417c478bd9Sstevel@tonic-gate 	}
1427c478bd9Sstevel@tonic-gate 
1437c478bd9Sstevel@tonic-gate 	/* Firey death and destruction unless we prefetched EOS. */
1447c478bd9Sstevel@tonic-gate 	if (ch != '\0')
1457c478bd9Sstevel@tonic-gate 		goto enoent;
1467c478bd9Sstevel@tonic-gate 
1477c478bd9Sstevel@tonic-gate 	/* If nothing was written to the destination, we found no address. */
1487c478bd9Sstevel@tonic-gate 	if (dst == odst)
1497c478bd9Sstevel@tonic-gate 		goto enoent;
1507c478bd9Sstevel@tonic-gate 	/* If no CIDR spec was given, infer width from net class. */
1517c478bd9Sstevel@tonic-gate 	if (bits == -1) {
152*9525b14bSRao Shoaib 		if (*odst >= 240)	/*%< Class E */
1537c478bd9Sstevel@tonic-gate 			bits = 32;
154*9525b14bSRao Shoaib 		else if (*odst >= 224)	/*%< Class D */
155*9525b14bSRao Shoaib 			bits = 8;
156*9525b14bSRao Shoaib 		else if (*odst >= 192)	/*%< Class C */
1577c478bd9Sstevel@tonic-gate 			bits = 24;
158*9525b14bSRao Shoaib 		else if (*odst >= 128)	/*%< Class B */
1597c478bd9Sstevel@tonic-gate 			bits = 16;
160*9525b14bSRao Shoaib 		else			/*%< Class A */
1617c478bd9Sstevel@tonic-gate 			bits = 8;
1627c478bd9Sstevel@tonic-gate 		/* If imputed mask is narrower than specified octets, widen. */
163*9525b14bSRao Shoaib 		if (bits < ((dst - odst) * 8))
1647c478bd9Sstevel@tonic-gate 			bits = (dst - odst) * 8;
165*9525b14bSRao Shoaib 		/*
166*9525b14bSRao Shoaib 		 * If there are no additional bits specified for a class D
167*9525b14bSRao Shoaib 		 * address adjust bits to 4.
168*9525b14bSRao Shoaib 		 */
169*9525b14bSRao Shoaib 		if (bits == 8 && *odst == 224)
170*9525b14bSRao Shoaib 			bits = 4;
1717c478bd9Sstevel@tonic-gate 	}
1727c478bd9Sstevel@tonic-gate 	/* Extend network to cover the actual mask. */
1737c478bd9Sstevel@tonic-gate 	while (bits > ((dst - odst) * 8)) {
174*9525b14bSRao Shoaib 		if (size-- <= 0U)
1757c478bd9Sstevel@tonic-gate 			goto emsgsize;
1767c478bd9Sstevel@tonic-gate 		*dst++ = '\0';
1777c478bd9Sstevel@tonic-gate 	}
1787c478bd9Sstevel@tonic-gate 	return (bits);
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate  enoent:
1817c478bd9Sstevel@tonic-gate 	errno = ENOENT;
1827c478bd9Sstevel@tonic-gate 	return (-1);
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate  emsgsize:
1857c478bd9Sstevel@tonic-gate 	errno = EMSGSIZE;
1867c478bd9Sstevel@tonic-gate 	return (-1);
1877c478bd9Sstevel@tonic-gate }
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate static int
getbits(const char * src,int * bitsp)1907c478bd9Sstevel@tonic-gate getbits(const char *src, int *bitsp) {
1917c478bd9Sstevel@tonic-gate 	static const char digits[] = "0123456789";
1927c478bd9Sstevel@tonic-gate 	int n;
1937c478bd9Sstevel@tonic-gate 	int val;
1947c478bd9Sstevel@tonic-gate 	char ch;
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate 	val = 0;
1977c478bd9Sstevel@tonic-gate 	n = 0;
1987c478bd9Sstevel@tonic-gate 	while ((ch = *src++) != '\0') {
1997c478bd9Sstevel@tonic-gate 		const char *pch;
2007c478bd9Sstevel@tonic-gate 
2017c478bd9Sstevel@tonic-gate 		pch = strchr(digits, ch);
2027c478bd9Sstevel@tonic-gate 		if (pch != NULL) {
203*9525b14bSRao Shoaib 			if (n++ != 0 && val == 0)	/*%< no leading zeros */
2047c478bd9Sstevel@tonic-gate 				return (0);
2057c478bd9Sstevel@tonic-gate 			val *= 10;
2067c478bd9Sstevel@tonic-gate 			val += (pch - digits);
207*9525b14bSRao Shoaib 			if (val > 128)			/*%< range */
2087c478bd9Sstevel@tonic-gate 				return (0);
2097c478bd9Sstevel@tonic-gate 			continue;
2107c478bd9Sstevel@tonic-gate 		}
2117c478bd9Sstevel@tonic-gate 		return (0);
2127c478bd9Sstevel@tonic-gate 	}
2137c478bd9Sstevel@tonic-gate 	if (n == 0)
2147c478bd9Sstevel@tonic-gate 		return (0);
2157c478bd9Sstevel@tonic-gate 	*bitsp = val;
2167c478bd9Sstevel@tonic-gate 	return (1);
2177c478bd9Sstevel@tonic-gate }
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate static int
getv4(const char * src,u_char * dst,int * bitsp)2207c478bd9Sstevel@tonic-gate getv4(const char *src, u_char *dst, int *bitsp) {
2217c478bd9Sstevel@tonic-gate 	static const char digits[] = "0123456789";
2227c478bd9Sstevel@tonic-gate 	u_char *odst = dst;
2237c478bd9Sstevel@tonic-gate 	int n;
2247c478bd9Sstevel@tonic-gate 	u_int val;
2257c478bd9Sstevel@tonic-gate 	char ch;
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate 	val = 0;
2287c478bd9Sstevel@tonic-gate 	n = 0;
2297c478bd9Sstevel@tonic-gate 	while ((ch = *src++) != '\0') {
2307c478bd9Sstevel@tonic-gate 		const char *pch;
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate 		pch = strchr(digits, ch);
2337c478bd9Sstevel@tonic-gate 		if (pch != NULL) {
234*9525b14bSRao Shoaib 			if (n++ != 0 && val == 0)	/*%< no leading zeros */
2357c478bd9Sstevel@tonic-gate 				return (0);
2367c478bd9Sstevel@tonic-gate 			val *= 10;
2377c478bd9Sstevel@tonic-gate 			val += (pch - digits);
238*9525b14bSRao Shoaib 			if (val > 255)			/*%< range */
2397c478bd9Sstevel@tonic-gate 				return (0);
2407c478bd9Sstevel@tonic-gate 			continue;
2417c478bd9Sstevel@tonic-gate 		}
2427c478bd9Sstevel@tonic-gate 		if (ch == '.' || ch == '/') {
243*9525b14bSRao Shoaib 			if (dst - odst > 3)		/*%< too many octets? */
2447c478bd9Sstevel@tonic-gate 				return (0);
2457c478bd9Sstevel@tonic-gate 			*dst++ = val;
2467c478bd9Sstevel@tonic-gate 			if (ch == '/')
2477c478bd9Sstevel@tonic-gate 				return (getbits(src, bitsp));
2487c478bd9Sstevel@tonic-gate 			val = 0;
2497c478bd9Sstevel@tonic-gate 			n = 0;
2507c478bd9Sstevel@tonic-gate 			continue;
2517c478bd9Sstevel@tonic-gate 		}
2527c478bd9Sstevel@tonic-gate 		return (0);
2537c478bd9Sstevel@tonic-gate 	}
2547c478bd9Sstevel@tonic-gate 	if (n == 0)
2557c478bd9Sstevel@tonic-gate 		return (0);
256*9525b14bSRao Shoaib 	if (dst - odst > 3)		/*%< too many octets? */
2577c478bd9Sstevel@tonic-gate 		return (0);
2587c478bd9Sstevel@tonic-gate 	*dst++ = val;
2597c478bd9Sstevel@tonic-gate 	return (1);
2607c478bd9Sstevel@tonic-gate }
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate static int
inet_net_pton_ipv6(const char * src,u_char * dst,size_t size)2637c478bd9Sstevel@tonic-gate inet_net_pton_ipv6(const char *src, u_char *dst, size_t size) {
2647c478bd9Sstevel@tonic-gate 	static const char xdigits_l[] = "0123456789abcdef",
2657c478bd9Sstevel@tonic-gate 			  xdigits_u[] = "0123456789ABCDEF";
2667c478bd9Sstevel@tonic-gate 	u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
2677c478bd9Sstevel@tonic-gate 	const char *xdigits, *curtok;
2687c478bd9Sstevel@tonic-gate 	int ch, saw_xdigit;
2697c478bd9Sstevel@tonic-gate 	u_int val;
2707c478bd9Sstevel@tonic-gate 	int digits;
2717c478bd9Sstevel@tonic-gate 	int bits;
2727c478bd9Sstevel@tonic-gate 	size_t bytes;
2737c478bd9Sstevel@tonic-gate 	int words;
2747c478bd9Sstevel@tonic-gate 	int ipv4;
2757c478bd9Sstevel@tonic-gate 
2767c478bd9Sstevel@tonic-gate 	memset((tp = tmp), '\0', NS_IN6ADDRSZ);
2777c478bd9Sstevel@tonic-gate 	endp = tp + NS_IN6ADDRSZ;
2787c478bd9Sstevel@tonic-gate 	colonp = NULL;
2797c478bd9Sstevel@tonic-gate 	/* Leading :: requires some special handling. */
2807c478bd9Sstevel@tonic-gate 	if (*src == ':')
2817c478bd9Sstevel@tonic-gate 		if (*++src != ':')
2827c478bd9Sstevel@tonic-gate 			goto enoent;
2837c478bd9Sstevel@tonic-gate 	curtok = src;
2847c478bd9Sstevel@tonic-gate 	saw_xdigit = 0;
2857c478bd9Sstevel@tonic-gate 	val = 0;
2867c478bd9Sstevel@tonic-gate 	digits = 0;
2877c478bd9Sstevel@tonic-gate 	bits = -1;
2887c478bd9Sstevel@tonic-gate 	ipv4 = 0;
2897c478bd9Sstevel@tonic-gate 	while ((ch = *src++) != '\0') {
2907c478bd9Sstevel@tonic-gate 		const char *pch;
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate 		if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
2937c478bd9Sstevel@tonic-gate 			pch = strchr((xdigits = xdigits_u), ch);
2947c478bd9Sstevel@tonic-gate 		if (pch != NULL) {
2957c478bd9Sstevel@tonic-gate 			val <<= 4;
2967c478bd9Sstevel@tonic-gate 			val |= (pch - xdigits);
2977c478bd9Sstevel@tonic-gate 			if (++digits > 4)
2987c478bd9Sstevel@tonic-gate 				goto enoent;
2997c478bd9Sstevel@tonic-gate 			saw_xdigit = 1;
3007c478bd9Sstevel@tonic-gate 			continue;
3017c478bd9Sstevel@tonic-gate 		}
3027c478bd9Sstevel@tonic-gate 		if (ch == ':') {
3037c478bd9Sstevel@tonic-gate 			curtok = src;
3047c478bd9Sstevel@tonic-gate 			if (!saw_xdigit) {
3057c478bd9Sstevel@tonic-gate 				if (colonp)
3067c478bd9Sstevel@tonic-gate 					goto enoent;
3077c478bd9Sstevel@tonic-gate 				colonp = tp;
3087c478bd9Sstevel@tonic-gate 				continue;
3097c478bd9Sstevel@tonic-gate 			} else if (*src == '\0')
3107c478bd9Sstevel@tonic-gate 				goto enoent;
3117c478bd9Sstevel@tonic-gate 			if (tp + NS_INT16SZ > endp)
3127c478bd9Sstevel@tonic-gate 				return (0);
3137c478bd9Sstevel@tonic-gate 			*tp++ = (u_char) (val >> 8) & 0xff;
3147c478bd9Sstevel@tonic-gate 			*tp++ = (u_char) val & 0xff;
3157c478bd9Sstevel@tonic-gate 			saw_xdigit = 0;
3167c478bd9Sstevel@tonic-gate 			digits = 0;
3177c478bd9Sstevel@tonic-gate 			val = 0;
3187c478bd9Sstevel@tonic-gate 			continue;
3197c478bd9Sstevel@tonic-gate 		}
3207c478bd9Sstevel@tonic-gate 		if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
3217c478bd9Sstevel@tonic-gate 		     getv4(curtok, tp, &bits) > 0) {
3227c478bd9Sstevel@tonic-gate 			tp += NS_INADDRSZ;
3237c478bd9Sstevel@tonic-gate 			saw_xdigit = 0;
3247c478bd9Sstevel@tonic-gate 			ipv4 = 1;
325*9525b14bSRao Shoaib 			break;	/*%< '\\0' was seen by inet_pton4(). */
3267c478bd9Sstevel@tonic-gate 		}
3277c478bd9Sstevel@tonic-gate 		if (ch == '/' && getbits(src, &bits) > 0)
3287c478bd9Sstevel@tonic-gate 			break;
3297c478bd9Sstevel@tonic-gate 		goto enoent;
3307c478bd9Sstevel@tonic-gate 	}
3317c478bd9Sstevel@tonic-gate 	if (saw_xdigit) {
3327c478bd9Sstevel@tonic-gate 		if (tp + NS_INT16SZ > endp)
3337c478bd9Sstevel@tonic-gate 			goto enoent;
3347c478bd9Sstevel@tonic-gate 		*tp++ = (u_char) (val >> 8) & 0xff;
3357c478bd9Sstevel@tonic-gate 		*tp++ = (u_char) val & 0xff;
3367c478bd9Sstevel@tonic-gate 	}
3377c478bd9Sstevel@tonic-gate 	if (bits == -1)
3387c478bd9Sstevel@tonic-gate 		bits = 128;
3397c478bd9Sstevel@tonic-gate 
3407c478bd9Sstevel@tonic-gate 	words = (bits + 15) / 16;
3417c478bd9Sstevel@tonic-gate 	if (words < 2)
3427c478bd9Sstevel@tonic-gate 		words = 2;
3437c478bd9Sstevel@tonic-gate 	if (ipv4)
3447c478bd9Sstevel@tonic-gate 		words = 8;
3457c478bd9Sstevel@tonic-gate 	endp =  tmp + 2 * words;
3467c478bd9Sstevel@tonic-gate 
3477c478bd9Sstevel@tonic-gate 	if (colonp != NULL) {
3487c478bd9Sstevel@tonic-gate 		/*
3497c478bd9Sstevel@tonic-gate 		 * Since some memmove()'s erroneously fail to handle
3507c478bd9Sstevel@tonic-gate 		 * overlapping regions, we'll do the shift by hand.
3517c478bd9Sstevel@tonic-gate 		 */
3527c478bd9Sstevel@tonic-gate 		const int n = tp - colonp;
3537c478bd9Sstevel@tonic-gate 		int i;
3547c478bd9Sstevel@tonic-gate 
3557c478bd9Sstevel@tonic-gate 		if (tp == endp)
3567c478bd9Sstevel@tonic-gate 			goto enoent;
3577c478bd9Sstevel@tonic-gate 		for (i = 1; i <= n; i++) {
3587c478bd9Sstevel@tonic-gate 			endp[- i] = colonp[n - i];
3597c478bd9Sstevel@tonic-gate 			colonp[n - i] = 0;
3607c478bd9Sstevel@tonic-gate 		}
3617c478bd9Sstevel@tonic-gate 		tp = endp;
3627c478bd9Sstevel@tonic-gate 	}
3637c478bd9Sstevel@tonic-gate 	if (tp != endp)
3647c478bd9Sstevel@tonic-gate 		goto enoent;
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate 	bytes = (bits + 7) / 8;
3677c478bd9Sstevel@tonic-gate 	if (bytes > size)
3687c478bd9Sstevel@tonic-gate 		goto emsgsize;
3697c478bd9Sstevel@tonic-gate 	memcpy(dst, tmp, bytes);
3707c478bd9Sstevel@tonic-gate 	return (bits);
3717c478bd9Sstevel@tonic-gate 
3727c478bd9Sstevel@tonic-gate  enoent:
3737c478bd9Sstevel@tonic-gate 	errno = ENOENT;
3747c478bd9Sstevel@tonic-gate 	return (-1);
3757c478bd9Sstevel@tonic-gate 
3767c478bd9Sstevel@tonic-gate  emsgsize:
3777c478bd9Sstevel@tonic-gate 	errno = EMSGSIZE;
3787c478bd9Sstevel@tonic-gate 	return (-1);
3797c478bd9Sstevel@tonic-gate }
3807c478bd9Sstevel@tonic-gate 
381*9525b14bSRao Shoaib /*%
3827c478bd9Sstevel@tonic-gate  * int
3837c478bd9Sstevel@tonic-gate  * inet_net_pton(af, src, dst, size)
3847c478bd9Sstevel@tonic-gate  *	convert network number from presentation to network format.
3857c478bd9Sstevel@tonic-gate  *	accepts hex octets, hex strings, decimal octets, and /CIDR.
3867c478bd9Sstevel@tonic-gate  *	"size" is in bytes and describes "dst".
3877c478bd9Sstevel@tonic-gate  * return:
3887c478bd9Sstevel@tonic-gate  *	number of bits, either imputed classfully or specified with /CIDR,
3897c478bd9Sstevel@tonic-gate  *	or -1 if some failure occurred (check errno).  ENOENT means it was
3907c478bd9Sstevel@tonic-gate  *	not a valid network specification.
3917c478bd9Sstevel@tonic-gate  * author:
3927c478bd9Sstevel@tonic-gate  *	Paul Vixie (ISC), June 1996
3937c478bd9Sstevel@tonic-gate  */
3947c478bd9Sstevel@tonic-gate int
inet_net_pton(int af,const char * src,void * dst,size_t size)3957c478bd9Sstevel@tonic-gate inet_net_pton(int af, const char *src, void *dst, size_t size) {
3967c478bd9Sstevel@tonic-gate 	switch (af) {
3977c478bd9Sstevel@tonic-gate 	case AF_INET:
3987c478bd9Sstevel@tonic-gate 		return (inet_net_pton_ipv4(src, dst, size));
3997c478bd9Sstevel@tonic-gate 	case AF_INET6:
4007c478bd9Sstevel@tonic-gate 		return (inet_net_pton_ipv6(src, dst, size));
4017c478bd9Sstevel@tonic-gate 	default:
4027c478bd9Sstevel@tonic-gate 		errno = EAFNOSUPPORT;
4037c478bd9Sstevel@tonic-gate 		return (-1);
4047c478bd9Sstevel@tonic-gate 	}
4057c478bd9Sstevel@tonic-gate }
406*9525b14bSRao Shoaib 
407*9525b14bSRao Shoaib /*! \file */
408