Home | History | Annotate | Line # | Download | only in inet
inet_pton.c revision 1.5.12.1
      1  1.5.12.1  wrstuden /*	$NetBSD: inet_pton.c,v 1.5.12.1 2008/06/23 04:29:32 wrstuden Exp $	*/
      2       1.1  christos 
      3       1.1  christos /*
      4       1.1  christos  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
      5       1.1  christos  * Copyright (c) 1996,1999 by Internet Software Consortium.
      6       1.1  christos  *
      7       1.1  christos  * Permission to use, copy, modify, and distribute this software for any
      8       1.1  christos  * purpose with or without fee is hereby granted, provided that the above
      9       1.1  christos  * copyright notice and this permission notice appear in all copies.
     10       1.1  christos  *
     11       1.1  christos  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
     12       1.1  christos  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     13       1.1  christos  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
     14       1.1  christos  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     15       1.1  christos  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     16       1.1  christos  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
     17       1.1  christos  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     18       1.1  christos  */
     19       1.1  christos 
     20       1.2  christos #include <sys/cdefs.h>
     21       1.1  christos #if defined(LIBC_SCCS) && !defined(lint)
     22       1.2  christos #if 0
     23  1.5.12.1  wrstuden static const char rcsid[] = "Id: inet_pton.c,v 1.5 2005/07/28 06:51:47 marka Exp";
     24       1.2  christos #else
     25  1.5.12.1  wrstuden __RCSID("$NetBSD: inet_pton.c,v 1.5.12.1 2008/06/23 04:29:32 wrstuden Exp $");
     26       1.2  christos #endif
     27       1.1  christos #endif /* LIBC_SCCS and not lint */
     28       1.1  christos 
     29       1.1  christos #include "port_before.h"
     30       1.2  christos 
     31       1.2  christos #include "namespace.h"
     32       1.1  christos #include <sys/param.h>
     33       1.1  christos #include <sys/types.h>
     34       1.1  christos #include <sys/socket.h>
     35       1.1  christos #include <netinet/in.h>
     36       1.1  christos #include <arpa/inet.h>
     37       1.1  christos #include <arpa/nameser.h>
     38       1.1  christos #include <string.h>
     39       1.2  christos #include <assert.h>
     40       1.2  christos #include <ctype.h>
     41       1.1  christos #include <errno.h>
     42       1.2  christos 
     43       1.1  christos #include "port_after.h"
     44       1.1  christos 
     45       1.2  christos #ifdef __weak_alias
     46       1.2  christos __weak_alias(inet_pton,_inet_pton)
     47       1.2  christos #endif
     48       1.2  christos 
     49       1.4  christos /*%
     50       1.1  christos  * WARNING: Don't even consider trying to compile this on a system where
     51       1.1  christos  * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
     52       1.1  christos  */
     53       1.1  christos 
     54       1.2  christos static int	inet_pton4(const char *src, u_char *dst, int pton);
     55       1.2  christos static int	inet_pton6(const char *src, u_char *dst);
     56       1.1  christos 
     57       1.1  christos /* int
     58       1.1  christos  * inet_pton(af, src, dst)
     59       1.1  christos  *	convert from presentation format (which usually means ASCII printable)
     60       1.1  christos  *	to network format (which is usually some kind of binary format).
     61       1.1  christos  * return:
     62       1.1  christos  *	1 if the address was valid for the specified address family
     63       1.1  christos  *	0 if the address wasn't valid (`dst' is untouched in this case)
     64       1.1  christos  *	-1 if some other error occurred (`dst' is untouched in this case, too)
     65       1.1  christos  * author:
     66       1.1  christos  *	Paul Vixie, 1996.
     67       1.1  christos  */
     68       1.1  christos int
     69       1.2  christos inet_pton(int af, const char *src, void *dst)
     70       1.1  christos {
     71       1.2  christos 
     72       1.2  christos 	_DIAGASSERT(src != NULL);
     73       1.2  christos 	_DIAGASSERT(dst != NULL);
     74       1.2  christos 
     75       1.1  christos 	switch (af) {
     76       1.1  christos 	case AF_INET:
     77       1.2  christos 		return (inet_pton4(src, dst, 1));
     78       1.1  christos 	case AF_INET6:
     79       1.1  christos 		return (inet_pton6(src, dst));
     80       1.1  christos 	default:
     81       1.1  christos 		errno = EAFNOSUPPORT;
     82       1.1  christos 		return (-1);
     83       1.1  christos 	}
     84       1.1  christos 	/* NOTREACHED */
     85       1.1  christos }
     86       1.1  christos 
     87       1.1  christos /* int
     88       1.2  christos  * inet_pton4(src, dst, pton)
     89       1.2  christos  *	when last arg is 0: inet_aton(). with hexadecimal, octal and shorthand.
     90       1.2  christos  *	when last arg is 1: inet_pton(). decimal dotted-quad only.
     91       1.1  christos  * return:
     92       1.2  christos  *	1 if `src' is a valid input, else 0.
     93       1.1  christos  * notice:
     94       1.1  christos  *	does not touch `dst' unless it's returning 1.
     95       1.1  christos  * author:
     96       1.1  christos  *	Paul Vixie, 1996.
     97       1.1  christos  */
     98       1.1  christos static int
     99       1.2  christos inet_pton4(const char *src, u_char *dst, int pton)
    100       1.1  christos {
    101       1.2  christos 	u_int32_t val;
    102       1.2  christos 	u_int digit, base;
    103       1.2  christos 	int n;
    104       1.2  christos 	unsigned char c;
    105       1.2  christos 	u_int parts[4];
    106       1.2  christos 	register u_int *pp = parts;
    107       1.1  christos 
    108       1.2  christos 	_DIAGASSERT(src != NULL);
    109       1.2  christos 	_DIAGASSERT(dst != NULL);
    110       1.1  christos 
    111       1.2  christos 	c = *src;
    112       1.2  christos 	for (;;) {
    113       1.2  christos 		/*
    114       1.2  christos 		 * Collect number up to ``.''.
    115       1.2  christos 		 * Values are specified as for C:
    116       1.2  christos 		 * 0x=hex, 0=octal, isdigit=decimal.
    117       1.2  christos 		 */
    118       1.2  christos 		if (!isdigit(c))
    119       1.2  christos 			return (0);
    120       1.2  christos 		val = 0; base = 10;
    121       1.2  christos 		if (c == '0') {
    122       1.2  christos 			c = *++src;
    123       1.2  christos 			if (c == 'x' || c == 'X')
    124       1.2  christos 				base = 16, c = *++src;
    125       1.2  christos 			else if (isdigit(c) && c != '9')
    126       1.2  christos 				base = 8;
    127       1.2  christos 		}
    128       1.2  christos 		/* inet_pton() takes decimal only */
    129       1.2  christos 		if (pton && base != 10)
    130       1.2  christos 			return (0);
    131       1.2  christos 		for (;;) {
    132       1.2  christos 			if (isdigit(c)) {
    133       1.2  christos 				digit = c - '0';
    134       1.2  christos 				if (digit >= base)
    135       1.2  christos 					break;
    136       1.2  christos 				val = (val * base) + digit;
    137       1.2  christos 				c = *++src;
    138       1.2  christos 			} else if (base == 16 && isxdigit(c)) {
    139       1.2  christos 				digit = c + 10 - (islower(c) ? 'a' : 'A');
    140       1.2  christos 				if (digit >= 16)
    141       1.2  christos 					break;
    142       1.2  christos 				val = (val << 4) | digit;
    143       1.2  christos 				c = *++src;
    144       1.2  christos 			} else
    145       1.2  christos 				break;
    146       1.2  christos 		}
    147       1.2  christos 		if (c == '.') {
    148       1.2  christos 			/*
    149       1.2  christos 			 * Internet format:
    150       1.2  christos 			 *	a.b.c.d
    151       1.2  christos 			 *	a.b.c	(with c treated as 16 bits)
    152       1.2  christos 			 *	a.b	(with b treated as 24 bits)
    153       1.2  christos 			 *	a	(with a treated as 32 bits)
    154       1.2  christos 			 */
    155       1.2  christos 			if (pp >= parts + 3)
    156       1.1  christos 				return (0);
    157       1.2  christos 			*pp++ = val;
    158       1.2  christos 			c = *++src;
    159       1.1  christos 		} else
    160       1.2  christos 			break;
    161       1.2  christos 	}
    162       1.2  christos 	/*
    163       1.2  christos 	 * Check for trailing characters.
    164       1.2  christos 	 */
    165       1.2  christos 	if (c != '\0' && !isspace(c))
    166       1.2  christos 		return (0);
    167       1.2  christos 	/*
    168       1.2  christos 	 * Concoct the address according to
    169       1.2  christos 	 * the number of parts specified.
    170       1.2  christos 	 */
    171       1.2  christos 	n = pp - parts + 1;
    172       1.2  christos 	/* inet_pton() takes dotted-quad only.  it does not take shorthand. */
    173       1.2  christos 	if (pton && n != 4)
    174       1.2  christos 		return (0);
    175       1.2  christos 	switch (n) {
    176       1.2  christos 
    177       1.2  christos 	case 0:
    178       1.2  christos 		return (0);		/* initial nondigit */
    179       1.2  christos 
    180       1.2  christos 	case 1:				/* a -- 32 bits */
    181       1.2  christos 		break;
    182       1.2  christos 
    183       1.2  christos 	case 2:				/* a.b -- 8.24 bits */
    184       1.2  christos 		if (parts[0] > 0xff || val > 0xffffff)
    185       1.1  christos 			return (0);
    186       1.2  christos 		val |= parts[0] << 24;
    187       1.2  christos 		break;
    188       1.2  christos 
    189       1.2  christos 	case 3:				/* a.b.c -- 8.8.16 bits */
    190       1.2  christos 		if ((parts[0] | parts[1]) > 0xff || val > 0xffff)
    191       1.2  christos 			return (0);
    192       1.2  christos 		val |= (parts[0] << 24) | (parts[1] << 16);
    193       1.2  christos 		break;
    194       1.2  christos 
    195       1.2  christos 	case 4:				/* a.b.c.d -- 8.8.8.8 bits */
    196       1.2  christos 		if ((parts[0] | parts[1] | parts[2] | val) > 0xff)
    197       1.2  christos 			return (0);
    198       1.2  christos 		val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
    199       1.2  christos 		break;
    200       1.2  christos 	}
    201       1.2  christos 	if (dst) {
    202       1.2  christos 		val = htonl(val);
    203       1.2  christos 		memcpy(dst, &val, NS_INADDRSZ);
    204       1.1  christos 	}
    205       1.1  christos 	return (1);
    206       1.1  christos }
    207       1.1  christos 
    208       1.1  christos /* int
    209       1.1  christos  * inet_pton6(src, dst)
    210       1.1  christos  *	convert presentation level address to network order binary form.
    211       1.1  christos  * return:
    212       1.1  christos  *	1 if `src' is a valid [RFC1884 2.2] address, else 0.
    213       1.1  christos  * notice:
    214       1.1  christos  *	(1) does not touch `dst' unless it's returning 1.
    215       1.1  christos  *	(2) :: in a full address is silently ignored.
    216       1.1  christos  * credit:
    217       1.1  christos  *	inspired by Mark Andrews.
    218       1.1  christos  * author:
    219       1.1  christos  *	Paul Vixie, 1996.
    220       1.1  christos  */
    221       1.1  christos static int
    222       1.2  christos inet_pton6(const char *src, u_char *dst)
    223       1.1  christos {
    224       1.1  christos 	static const char xdigits_l[] = "0123456789abcdef",
    225       1.1  christos 			  xdigits_u[] = "0123456789ABCDEF";
    226       1.1  christos 	u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
    227       1.1  christos 	const char *xdigits, *curtok;
    228       1.4  christos 	int ch, seen_xdigits;
    229       1.1  christos 	u_int val;
    230       1.1  christos 
    231       1.2  christos 	_DIAGASSERT(src != NULL);
    232       1.2  christos 	_DIAGASSERT(dst != NULL);
    233       1.2  christos 
    234       1.1  christos 	memset((tp = tmp), '\0', NS_IN6ADDRSZ);
    235       1.1  christos 	endp = tp + NS_IN6ADDRSZ;
    236       1.1  christos 	colonp = NULL;
    237       1.1  christos 	/* Leading :: requires some special handling. */
    238       1.1  christos 	if (*src == ':')
    239       1.1  christos 		if (*++src != ':')
    240       1.1  christos 			return (0);
    241       1.1  christos 	curtok = src;
    242       1.4  christos 	seen_xdigits = 0;
    243       1.1  christos 	val = 0;
    244       1.1  christos 	while ((ch = *src++) != '\0') {
    245       1.1  christos 		const char *pch;
    246       1.1  christos 
    247       1.1  christos 		if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
    248       1.1  christos 			pch = strchr((xdigits = xdigits_u), ch);
    249       1.1  christos 		if (pch != NULL) {
    250       1.1  christos 			val <<= 4;
    251       1.1  christos 			val |= (pch - xdigits);
    252       1.4  christos 			if (++seen_xdigits > 4)
    253       1.1  christos 				return (0);
    254       1.1  christos 			continue;
    255       1.1  christos 		}
    256       1.1  christos 		if (ch == ':') {
    257       1.1  christos 			curtok = src;
    258       1.4  christos 			if (!seen_xdigits) {
    259       1.1  christos 				if (colonp)
    260       1.1  christos 					return (0);
    261       1.1  christos 				colonp = tp;
    262       1.1  christos 				continue;
    263       1.2  christos 			} else if (*src == '\0')
    264       1.1  christos 				return (0);
    265       1.3     lukem 			if (tp + NS_INT16SZ > endp)
    266       1.1  christos 				return (0);
    267       1.1  christos 			*tp++ = (u_char) (val >> 8) & 0xff;
    268       1.1  christos 			*tp++ = (u_char) val & 0xff;
    269       1.4  christos 			seen_xdigits = 0;
    270       1.1  christos 			val = 0;
    271       1.1  christos 			continue;
    272       1.1  christos 		}
    273       1.1  christos 		if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
    274       1.2  christos 		    inet_pton4(curtok, tp, 1) > 0) {
    275       1.1  christos 			tp += NS_INADDRSZ;
    276       1.4  christos 			seen_xdigits = 0;
    277       1.4  christos 			break;	/*%< '\\0' was seen by inet_pton4(). */
    278       1.1  christos 		}
    279       1.1  christos 		return (0);
    280       1.1  christos 	}
    281       1.4  christos 	if (seen_xdigits) {
    282       1.1  christos 		if (tp + NS_INT16SZ > endp)
    283       1.1  christos 			return (0);
    284       1.1  christos 		*tp++ = (u_char) (val >> 8) & 0xff;
    285       1.1  christos 		*tp++ = (u_char) val & 0xff;
    286       1.1  christos 	}
    287       1.1  christos 	if (colonp != NULL) {
    288       1.1  christos 		/*
    289       1.1  christos 		 * Since some memmove()'s erroneously fail to handle
    290       1.1  christos 		 * overlapping regions, we'll do the shift by hand.
    291       1.1  christos 		 */
    292       1.1  christos 		const int n = tp - colonp;
    293       1.1  christos 		int i;
    294       1.1  christos 
    295       1.1  christos 		if (tp == endp)
    296       1.1  christos 			return (0);
    297       1.1  christos 		for (i = 1; i <= n; i++) {
    298       1.1  christos 			endp[- i] = colonp[n - i];
    299       1.1  christos 			colonp[n - i] = 0;
    300       1.1  christos 		}
    301       1.1  christos 		tp = endp;
    302       1.1  christos 	}
    303       1.1  christos 	if (tp != endp)
    304       1.1  christos 		return (0);
    305       1.1  christos 	memcpy(dst, tmp, NS_IN6ADDRSZ);
    306       1.1  christos 	return (1);
    307       1.1  christos }
    308       1.4  christos 
    309       1.4  christos /*! \file */
    310