Home | History | Annotate | Download | only in BsdSocketLib
      1 /*
      2  * Copyright (c) 1996 by Internet Software Consortium.
      3  *
      4  * Permission to use, copy, modify, and distribute this software for any
      5  * purpose with or without fee is hereby granted, provided that the above
      6  * copyright notice and this permission notice appear in all copies.
      7  *
      8  * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
      9  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
     10  * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
     11  * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
     12  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
     13  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
     14  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
     15  * SOFTWARE.
     16  */
     17 
     18 /*
     19  * Portions copyright (c) 1999, 2000
     20  * Intel Corporation.
     21  * All rights reserved.
     22  *
     23  * Redistribution and use in source and binary forms, with or without
     24  * modification, are permitted provided that the following conditions
     25  * are met:
     26  *
     27  * 1. Redistributions of source code must retain the above copyright
     28  *    notice, this list of conditions and the following disclaimer.
     29  *
     30  * 2. Redistributions in binary form must reproduce the above copyright
     31  *    notice, this list of conditions and the following disclaimer in the
     32  *    documentation and/or other materials provided with the distribution.
     33  *
     34  * 3. All advertising materials mentioning features or use of this software
     35  *    must display the following acknowledgement:
     36  *
     37  *    This product includes software developed by Intel Corporation and
     38  *    its contributors.
     39  *
     40  * 4. Neither the name of Intel Corporation or its contributors may be
     41  *    used to endorse or promote products derived from this software
     42  *    without specific prior written permission.
     43  *
     44  * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION AND CONTRIBUTORS ``AS IS''
     45  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     46  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     47  * ARE DISCLAIMED.  IN NO EVENT SHALL INTEL CORPORATION OR CONTRIBUTORS BE
     48  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     49  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     50  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     51  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     52  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     53  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     54  * THE POSSIBILITY OF SUCH DAMAGE.
     55  *
     56  */
     57 
     58 #if defined(LIBC_SCCS) && !defined(lint)
     59 static const char orig_rcsid[] = "From Id: inet_net_pton.c,v 1.8 1996/11/21 10:28:12 vixie Exp $";
     60 static const char rcsid[] = "$Id: inet_net_pton.c,v 1.1.1.1 2003/11/19 01:51:29 kyu3 Exp $";
     61 #endif
     62 
     63 #include <sys/types.h>
     64 #include <sys/socket.h>
     65 #include <netinet/in.h>
     66 #include <arpa/inet.h>
     67 
     68 #include <assert.h>
     69 #include <ctype.h>
     70 #include <errno.h>
     71 #include <stdio.h>
     72 #include <string.h>
     73 #include <stdlib.h>
     74 
     75 #ifdef SPRINTF_CHAR
     76 # define SPRINTF(x) strlen(sprintf/**/x)
     77 #else
     78 # define SPRINTF(x) ((size_t)sprintf x)
     79 #endif
     80 
     81 static int	inet_net_pton_ipv4 (const char *src, u_char *dst,
     82 					size_t size);
     83 
     84 /*
     85  * static int
     86  * inet_net_pton(af, src, dst, size)
     87  *	convert network number from presentation to network format.
     88  *	accepts hex octets, hex strings, decimal octets, and /CIDR.
     89  *	"size" is in bytes and describes "dst".
     90  * return:
     91  *	number of bits, either imputed classfully or specified with /CIDR,
     92  *	or -1 if some failure occurred (check errno).  ENOENT means it was
     93  *	not a valid network specification.
     94  * author:
     95  *	Paul Vixie (ISC), June 1996
     96  */
     97 int
     98 inet_net_pton(
     99 	int af,
    100 	const char *src,
    101 	void *dst,
    102 	size_t size
    103 	)
    104 {
    105 	switch (af) {
    106 	case AF_INET:
    107 		return (inet_net_pton_ipv4(src, dst, size));
    108 	default:
    109 		errno = EAFNOSUPPORT;
    110 		return (-1);
    111 	}
    112 }
    113 
    114 /*
    115  * static int
    116  * inet_net_pton_ipv4(src, dst, size)
    117  *	convert IPv4 network number from presentation to network format.
    118  *	accepts hex octets, hex strings, decimal octets, and /CIDR.
    119  *	"size" is in bytes and describes "dst".
    120  * return:
    121  *	number of bits, either imputed classfully or specified with /CIDR,
    122  *	or -1 if some failure occurred (check errno).  ENOENT means it was
    123  *	not an IPv4 network specification.
    124  * note:
    125  *	network byte order assumed.  this means 192.5.5.240/28 has
    126  *	0x11110000 in its fourth octet.
    127  * author:
    128  *	Paul Vixie (ISC), June 1996
    129  */
    130 static int
    131 inet_net_pton_ipv4(
    132 	const char *src,
    133 	u_char *dst,
    134 	size_t size
    135 	)
    136 {
    137 	static const char xdigits[] = "0123456789abcdef";
    138 	static const char digits[] = "0123456789";
    139 	int n;
    140   int ch;
    141   int tmp;
    142   int dirty;
    143   int bits;
    144 	const u_char *odst = dst;
    145 
    146 	ch = *src++;
    147 	if (ch == '0' && (src[0] == 'x' || src[0] == 'X')
    148 	    && isascii(src[1]) && isxdigit(src[1])) {
    149 		/* Hexadecimal: Eat nybble string. */
    150 		if (size <= 0)
    151 			goto emsgsize;
    152 		*dst = 0, dirty = 0;
    153 		src++;	/* skip x or X. */
    154 		while ((ch = *src++) != '\0' &&
    155 		       isascii(ch) && isxdigit(ch)) {
    156 			if (isupper(ch))
    157 				ch = tolower(ch);
    158 			n = (int)(strchr(xdigits, ch) - xdigits);
    159 			assert(n >= 0 && n <= 15);
    160 			*dst |= n;
    161 			if (!dirty++)
    162 				*dst <<= 4;
    163 			else if (size-- > 0)
    164 				*++dst = 0, dirty = 0;
    165 			else
    166 				goto emsgsize;
    167 		}
    168 		if (dirty)
    169 			size--;
    170 	} else if (isascii(ch) && isdigit(ch)) {
    171 		/* Decimal: eat dotted digit string. */
    172 		for (;;) {
    173 			tmp = 0;
    174 			do {
    175 				n = (int)(strchr(digits, ch) - digits);
    176 				assert(n >= 0 && n <= 9);
    177 				tmp *= 10;
    178 				tmp += n;
    179 				if (tmp > 255)
    180 					goto enoent;
    181 			} while ((ch = *src++) != '\0' &&
    182 				 isascii(ch) && isdigit(ch));
    183 			if (size-- <= 0)
    184 				goto emsgsize;
    185 			*dst++ = (u_char) tmp;
    186 			if (ch == '\0' || ch == '/')
    187 				break;
    188 			if (ch != '.')
    189 				goto enoent;
    190 			ch = *src++;
    191 			if (!isascii(ch) || !isdigit(ch))
    192 				goto enoent;
    193 		}
    194 	} else
    195 		goto enoent;
    196 
    197 	bits = -1;
    198 	if (ch == '/' && isascii(src[0]) && isdigit(src[0]) && dst > odst) {
    199 		/* CIDR width specifier.  Nothing can follow it. */
    200 		ch = *src++;	/* Skip over the /. */
    201 		bits = 0;
    202 		do {
    203 			n = (int)(strchr(digits, ch) - digits);
    204 			assert(n >= 0 && n <= 9);
    205 			bits *= 10;
    206 			bits += n;
    207 		} while ((ch = *src++) != '\0' && isascii(ch) && isdigit(ch));
    208 		if (ch != '\0')
    209 			goto enoent;
    210 		if (bits > 32)
    211 			goto emsgsize;
    212 	}
    213 
    214 	/* Firey death and destruction unless we prefetched EOS. */
    215 	if (ch != '\0')
    216 		goto enoent;
    217 
    218 	/* If nothing was written to the destination, we found no address. */
    219 	if (dst == odst)
    220 		goto enoent;
    221 	/* If no CIDR spec was given, infer width from net class. */
    222 	if (bits == -1) {
    223 		if (*odst >= 240)	/* Class E */
    224 			bits = 32;
    225 		else if (*odst >= 224)	/* Class D */
    226 			bits = 4;
    227 		else if (*odst >= 192)	/* Class C */
    228 			bits = 24;
    229 		else if (*odst >= 128)	/* Class B */
    230 			bits = 16;
    231 		else			/* Class A */
    232 			bits = 8;
    233 		/* If imputed mask is narrower than specified octets, widen. */
    234 		if (bits >= 8 && bits < ((dst - odst) * 8))
    235 			bits = (int)(dst - odst) * 8;
    236 	}
    237 	/* Extend network to cover the actual mask. */
    238 	while (bits > ((dst - odst) * 8)) {
    239 		if (size-- <= 0)
    240 			goto emsgsize;
    241 		*dst++ = '\0';
    242 	}
    243 	return (bits);
    244 
    245  enoent:
    246 	errno = ENOENT;
    247 	return (-1);
    248 
    249  emsgsize:
    250 	errno = EMSGSIZE;
    251 	return (-1);
    252 }
    253