Home | History | Annotate | Download | only in BsdSocketLib
      1 /* Copyright (c) 1996 by Internet Software Consortium.
      2  *
      3  * Permission to use, copy, modify, and distribute this software for any
      4  * purpose with or without fee is hereby granted, provided that the above
      5  * copyright notice and this permission notice appear in all copies.
      6  *
      7  * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
      8  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
      9  * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
     10  * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
     11  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
     12  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
     13  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
     14  * SOFTWARE.
     15  */
     16 
     17 /*
     18  * Portions copyright (c) 1999, 2000
     19  * Intel Corporation.
     20  * All rights reserved.
     21  *
     22  * Redistribution and use in source and binary forms, with or without
     23  * modification, are permitted provided that the following conditions
     24  * are met:
     25  *
     26  * 1. Redistributions of source code must retain the above copyright
     27  *    notice, this list of conditions and the following disclaimer.
     28  *
     29  * 2. Redistributions in binary form must reproduce the above copyright
     30  *    notice, this list of conditions and the following disclaimer in the
     31  *    documentation and/or other materials provided with the distribution.
     32  *
     33  * 3. All advertising materials mentioning features or use of this software
     34  *    must display the following acknowledgement:
     35  *
     36  *    This product includes software developed by Intel Corporation and
     37  *    its contributors.
     38  *
     39  * 4. Neither the name of Intel Corporation or its contributors may be
     40  *    used to endorse or promote products derived from this software
     41  *    without specific prior written permission.
     42  *
     43  * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION AND CONTRIBUTORS ``AS IS''
     44  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     45  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     46  * ARE DISCLAIMED.  IN NO EVENT SHALL INTEL CORPORATION OR CONTRIBUTORS BE
     47  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     48  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     49  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     50  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     51  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     52  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     53  * THE POSSIBILITY OF SUCH DAMAGE.
     54  *
     55  */
     56 
     57 #if defined(LIBC_SCCS) && !defined(lint)
     58 static char rcsid[] = "$Id: inet_pton.c,v 1.1.1.1 2003/11/19 01:51:30 kyu3 Exp $";
     59 #endif /* LIBC_SCCS and not lint */
     60 
     61 #include <sys/param.h>
     62 #include <sys/types.h>
     63 #include <sys/socket.h>
     64 #include <netinet/in.h>
     65 #include <arpa/inet.h>
     66 #include <arpa/nameser.h>
     67 #include <string.h>
     68 #include <errno.h>
     69 
     70 /*
     71  * WARNING: Don't even consider trying to compile this on a system where
     72  * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
     73  */
     74 
     75 static int	inet_pton4 (const char *src, u_char *dst);
     76 static int	inet_pton6 (const char *src, u_char *dst);
     77 
     78 /* int
     79  * inet_pton(af, src, dst)
     80  *	convert from presentation format (which usually means ASCII printable)
     81  *	to network format (which is usually some kind of binary format).
     82  * return:
     83  *	1 if the address was valid for the specified address family
     84  *	0 if the address wasn't valid (`dst' is untouched in this case)
     85  *	-1 if some other error occurred (`dst' is untouched in this case, too)
     86  * author:
     87  *	Paul Vixie, 1996.
     88  */
     89 int
     90 inet_pton(
     91 	int af,
     92 	const char *src,
     93 	void *dst
     94 	)
     95 {
     96 	switch (af) {
     97 	case AF_INET:
     98 		return (inet_pton4(src, dst));
     99 	case AF_INET6:
    100 		return (inet_pton6(src, dst));
    101 	default:
    102 		errno = EAFNOSUPPORT;
    103 		return (-1);
    104 	}
    105 	/* NOTREACHED */
    106 }
    107 
    108 /* int
    109  * inet_pton4(src, dst)
    110  *	like inet_aton() but without all the hexadecimal and shorthand.
    111  * return:
    112  *	1 if `src' is a valid dotted quad, else 0.
    113  * notice:
    114  *	does not touch `dst' unless it's returning 1.
    115  * author:
    116  *	Paul Vixie, 1996.
    117  */
    118 static int
    119 inet_pton4(
    120 	const char *src,
    121 	u_char *dst
    122 	)
    123 {
    124 	static const char digits[] = "0123456789";
    125 	int saw_digit, octets, ch;
    126 	u_char tmp[NS_INADDRSZ], *tp;
    127 
    128 	saw_digit = 0;
    129 	octets = 0;
    130 	*(tp = tmp) = 0;
    131 	while ((ch = *src++) != '\0') {
    132 		const char *pch;
    133 
    134 		if ((pch = strchr(digits, ch)) != NULL) {
    135 			u_int new = *tp * 10 + (u_int)(pch - digits);
    136 
    137 			if (new > 255)
    138 				return (0);
    139 			*tp = (u_char)new;
    140 			if (! saw_digit) {
    141 				if (++octets > 4)
    142 					return (0);
    143 				saw_digit = 1;
    144 			}
    145 		} else if (ch == '.' && saw_digit) {
    146 			if (octets == 4)
    147 				return (0);
    148 			*++tp = 0;
    149 			saw_digit = 0;
    150 		} else
    151 			return (0);
    152 	}
    153 	if (octets < 4)
    154 		return (0);
    155 
    156 	memcpy(dst, tmp, NS_INADDRSZ);
    157 	return (1);
    158 }
    159 
    160 /* int
    161  * inet_pton6(src, dst)
    162  *	convert presentation level address to network order binary form.
    163  * return:
    164  *	1 if `src' is a valid [RFC1884 2.2] address, else 0.
    165  * notice:
    166  *	(1) does not touch `dst' unless it's returning 1.
    167  *	(2) :: in a full address is silently ignored.
    168  * credit:
    169  *	inspired by Mark Andrews.
    170  * author:
    171  *	Paul Vixie, 1996.
    172  */
    173 static int
    174 inet_pton6(
    175 	const char *src,
    176 	u_char *dst
    177 	)
    178 {
    179 	static const char xdigits_l[] = "0123456789abcdef",
    180 			  xdigits_u[] = "0123456789ABCDEF";
    181 	u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
    182 	const char *xdigits, *curtok;
    183 	int ch, saw_xdigit;
    184 	u_int val;
    185 
    186 	memset((tp = tmp), '\0', NS_IN6ADDRSZ);
    187 	endp = tp + NS_IN6ADDRSZ;
    188 	colonp = NULL;
    189 	/* Leading :: requires some special handling. */
    190 	if (*src == ':')
    191 		if (*++src != ':')
    192 			return (0);
    193 	curtok = src;
    194 	saw_xdigit = 0;
    195 	val = 0;
    196 	while ((ch = *src++) != '\0') {
    197 		const char *pch;
    198 
    199 		if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
    200 			pch = strchr((xdigits = xdigits_u), ch);
    201 		if (pch != NULL) {
    202 			val <<= 4;
    203 			val |= (pch - xdigits);
    204 			if (val > 0xffff)
    205 				return (0);
    206 			saw_xdigit = 1;
    207 			continue;
    208 		}
    209 		if (ch == ':') {
    210 			curtok = src;
    211 			if (!saw_xdigit) {
    212 				if (colonp)
    213 					return (0);
    214 				colonp = tp;
    215 				continue;
    216 			}
    217 			if (tp + NS_INT16SZ > endp)
    218 				return (0);
    219 			*tp++ = (u_char) (val >> 8) & 0xff;
    220 			*tp++ = (u_char) val & 0xff;
    221 			saw_xdigit = 0;
    222 			val = 0;
    223 			continue;
    224 		}
    225 		if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
    226 		    inet_pton4(curtok, tp) > 0) {
    227 			tp += NS_INADDRSZ;
    228 			saw_xdigit = 0;
    229 			break;	/* '\0' was seen by inet_pton4(). */
    230 		}
    231 		return (0);
    232 	}
    233 	if (saw_xdigit) {
    234 		if (tp + NS_INT16SZ > endp)
    235 			return (0);
    236 		*tp++ = (u_char) (val >> 8) & 0xff;
    237 		*tp++ = (u_char) val & 0xff;
    238 	}
    239 	if (colonp != NULL) {
    240 		/*
    241 		 * Since some memmove()'s erroneously fail to handle
    242 		 * overlapping regions, we'll do the shift by hand.
    243 		 */
    244 		const int n = (int)(tp - colonp);
    245 		int i;
    246 
    247 		for (i = 1; i <= n; i++) {
    248 			endp[- i] = colonp[n - i];
    249 			colonp[n - i] = 0;
    250 		}
    251 		tp = endp;
    252 	}
    253 	if (tp != endp)
    254 		return (0);
    255 	memcpy(dst, tmp, NS_IN6ADDRSZ);
    256 	return (1);
    257 }
    258