File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / ntp / lib / isc / inet_pton.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue May 29 12:08:38 2012 UTC (12 years, 1 month ago) by misho
Branches: ntp, MAIN
CVS tags: v4_2_6p5p0, v4_2_6p5, HEAD
ntp 4.2.6p5

    1: /*
    2:  * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
    3:  * Copyright (C) 1996-2003  Internet Software Consortium.
    4:  *
    5:  * Permission to use, copy, modify, and/or distribute this software for any
    6:  * purpose with or without fee is hereby granted, provided that the above
    7:  * copyright notice and this permission notice appear in all copies.
    8:  *
    9:  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
   10:  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
   11:  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
   12:  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
   13:  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
   14:  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
   15:  * PERFORMANCE OF THIS SOFTWARE.
   16:  */
   17: 
   18: /*! \file */
   19: 
   20: #if defined(LIBC_SCCS) && !defined(lint)
   21: static char rcsid[] =
   22: 	"$Id: inet_pton.c,v 1.1.1.1 2012/05/29 12:08:38 misho Exp $";
   23: #endif /* LIBC_SCCS and not lint */
   24: 
   25: #include <config.h>
   26: 
   27: #include <errno.h>
   28: #include <string.h>
   29: 
   30: #include <isc/net.h>
   31: 
   32: /*% INT16 Size */
   33: #define NS_INT16SZ	 2
   34: /*% IPv4 Address Size */
   35: #define NS_INADDRSZ	 4
   36: /*% IPv6 Address Size */
   37: #define NS_IN6ADDRSZ	16
   38: 
   39: /*
   40:  * WARNING: Don't even consider trying to compile this on a system where
   41:  * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
   42:  */
   43: 
   44: static int inet_pton4(const char *src, unsigned char *dst);
   45: static int inet_pton6(const char *src, unsigned char *dst);
   46: 
   47: /*% 
   48:  *	convert from presentation format (which usually means ASCII printable)
   49:  *	to network format (which is usually some kind of binary format).
   50:  * \return
   51:  *	1 if the address was valid for the specified address family
   52:  *	0 if the address wasn't valid (`dst' is untouched in this case)
   53:  *	-1 if some other error occurred (`dst' is untouched in this case, too)
   54:  * \author
   55:  *	Paul Vixie, 1996.
   56:  */
   57: int
   58: isc_net_pton(int af, const char *src, void *dst) {
   59: 	switch (af) {
   60: 	case AF_INET:
   61: 		return (inet_pton4(src, dst));
   62: 	case AF_INET6:
   63: 		return (inet_pton6(src, dst));
   64: 	default:
   65: 		errno = EAFNOSUPPORT;
   66: 		return (-1);
   67: 	}
   68: 	/* NOTREACHED */
   69: }
   70: 
   71: /*!\fn static int inet_pton4(const char *src, unsigned char *dst)
   72:  * \brief
   73:  *	like inet_aton() but without all the hexadecimal and shorthand.
   74:  * \return
   75:  *	1 if `src' is a valid dotted quad, else 0.
   76:  * \note
   77:  *	does not touch `dst' unless it's returning 1.
   78:  * \author
   79:  *	Paul Vixie, 1996.
   80:  */
   81: static int
   82: inet_pton4(const char *src, unsigned char *dst) {
   83: 	static const char digits[] = "0123456789";
   84: 	int saw_digit, octets, ch;
   85: 	unsigned char tmp[NS_INADDRSZ], *tp;
   86: 
   87: 	saw_digit = 0;
   88: 	octets = 0;
   89: 	*(tp = tmp) = 0;
   90: 	while ((ch = *src++) != '\0') {
   91: 		const char *pch;
   92: 
   93: 		if ((pch = strchr(digits, ch)) != NULL) {
   94: 			unsigned int newv = *tp * 10 + (pch - digits);
   95: 
   96: 			if (saw_digit && *tp == 0)
   97: 				return (0);
   98: 			if (newv > 255)
   99: 				return (0);
  100: 			*tp = (unsigned char)newv;
  101: 			if (!saw_digit) {
  102: 				if (++octets > 4)
  103: 					return (0);
  104: 				saw_digit = 1;
  105: 			}
  106: 		} else if (ch == '.' && saw_digit) {
  107: 			if (octets == 4)
  108: 				return (0);
  109: 			*++tp = 0;
  110: 			saw_digit = 0;
  111: 		} else
  112: 			return (0);
  113: 	}
  114: 	if (octets < 4)
  115: 		return (0);
  116: 	memcpy(dst, tmp, NS_INADDRSZ);
  117: 	return (1);
  118: }
  119: 
  120: /*%
  121:  *	convert presentation level address to network order binary form.
  122:  * \return
  123:  *	1 if `src' is a valid [RFC1884 2.2] address, else 0.
  124:  * \note
  125:  *	(1) does not touch `dst' unless it's returning 1.
  126:  * \note
  127:  *	(2) :: in a full address is silently ignored.
  128:  * \author
  129:  *	inspired by Mark Andrews.
  130:  * \author
  131:  *	Paul Vixie, 1996.
  132:  */
  133: static int
  134: inet_pton6(const char *src, unsigned char *dst) {
  135: 	static const char xdigits_l[] = "0123456789abcdef",
  136: 			  xdigits_u[] = "0123456789ABCDEF";
  137: 	unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
  138: 	const char *xdigits, *curtok;
  139: 	int ch, seen_xdigits;
  140: 	unsigned int val;
  141: 
  142: 	memset((tp = tmp), '\0', NS_IN6ADDRSZ);
  143: 	endp = tp + NS_IN6ADDRSZ;
  144: 	colonp = NULL;
  145: 	/* Leading :: requires some special handling. */
  146: 	if (*src == ':')
  147: 		if (*++src != ':')
  148: 			return (0);
  149: 	curtok = src;
  150: 	seen_xdigits = 0;
  151: 	val = 0;
  152: 	while ((ch = *src++) != '\0') {
  153: 		const char *pch;
  154: 
  155: 		if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
  156: 			pch = strchr((xdigits = xdigits_u), ch);
  157: 		if (pch != NULL) {
  158: 			val <<= 4;
  159: 			val |= (pch - xdigits);
  160: 			if (++seen_xdigits > 4)
  161: 				return (0);
  162: 			continue;
  163: 		}
  164: 		if (ch == ':') {
  165: 			curtok = src;
  166: 			if (!seen_xdigits) {
  167: 				if (colonp)
  168: 					return (0);
  169: 				colonp = tp;
  170: 				continue;
  171: 			}
  172: 			if (tp + NS_INT16SZ > endp)
  173: 				return (0);
  174: 			*tp++ = (unsigned char) (val >> 8) & 0xff;
  175: 			*tp++ = (unsigned char) val & 0xff;
  176: 			seen_xdigits = 0;
  177: 			val = 0;
  178: 			continue;
  179: 		}
  180: 		if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
  181: 		    inet_pton4(curtok, tp) > 0) {
  182: 			tp += NS_INADDRSZ;
  183: 			seen_xdigits = 0;
  184: 			break;	/* '\0' was seen by inet_pton4(). */
  185: 		}
  186: 		return (0);
  187: 	}
  188: 	if (seen_xdigits) {
  189: 		if (tp + NS_INT16SZ > endp)
  190: 			return (0);
  191: 		*tp++ = (unsigned char) (val >> 8) & 0xff;
  192: 		*tp++ = (unsigned char) val & 0xff;
  193: 	}
  194: 	if (colonp != NULL) {
  195: 		/*
  196: 		 * Since some memmove()'s erroneously fail to handle
  197: 		 * overlapping regions, we'll do the shift by hand.
  198: 		 */
  199: 		const int n = tp - colonp;
  200: 		int i;
  201: 
  202: 		if (tp == endp)
  203: 			return (0);
  204: 		for (i = 1; i <= n; i++) {
  205: 			endp[- i] = colonp[n - i];
  206: 			colonp[n - i] = 0;
  207: 		}
  208: 		tp = endp;
  209: 	}
  210: 	if (tp != endp)
  211: 		return (0);
  212: 	memcpy(dst, tmp, NS_IN6ADDRSZ);
  213: 	return (1);
  214: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>