xref: /freebsd/sys/libkern/inet_aton.c (revision fdafd315ad0d0f28a11b9fb4476a9ab059c62b92)
175880123SAttilio Rao /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
38a36da99SPedro F. Giffuni  *
475880123SAttilio Rao  * Copyright (c) 2001 Charles Mott <cm@linktel.net>
575880123SAttilio Rao  * All rights reserved.
675880123SAttilio Rao  *
775880123SAttilio Rao  * Redistribution and use in source and binary forms, with or without
875880123SAttilio Rao  * modification, are permitted provided that the following conditions
975880123SAttilio Rao  * are met:
1075880123SAttilio Rao  * 1. Redistributions of source code must retain the above copyright
1175880123SAttilio Rao  *    notice, this list of conditions and the following disclaimer.
1275880123SAttilio Rao  * 2. Redistributions in binary form must reproduce the above copyright
1375880123SAttilio Rao  *    notice, this list of conditions and the following disclaimer in the
1475880123SAttilio Rao  *    documentation and/or other materials provided with the distribution.
1575880123SAttilio Rao  *
1675880123SAttilio Rao  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1775880123SAttilio Rao  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1875880123SAttilio Rao  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1975880123SAttilio Rao  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2075880123SAttilio Rao  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2175880123SAttilio Rao  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2275880123SAttilio Rao  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2375880123SAttilio Rao  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2475880123SAttilio Rao  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2575880123SAttilio Rao  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2675880123SAttilio Rao  * SUCH DAMAGE.
2775880123SAttilio Rao  */
2875880123SAttilio Rao 
2975880123SAttilio Rao #include <sys/param.h>
3075880123SAttilio Rao #include <sys/ctype.h>
3175880123SAttilio Rao #include <sys/limits.h>
3275880123SAttilio Rao #include <sys/systm.h>
3375880123SAttilio Rao 
3475880123SAttilio Rao #include <netinet/in.h>
3575880123SAttilio Rao 
3675880123SAttilio Rao int
inet_aton(const char * cp,struct in_addr * addr)3775880123SAttilio Rao inet_aton(const char *cp, struct in_addr *addr)
3875880123SAttilio Rao {
3975880123SAttilio Rao 	u_long parts[4];
4075880123SAttilio Rao 	in_addr_t val;
4175880123SAttilio Rao 	const char *c;
4275880123SAttilio Rao 	char *endptr;
4375880123SAttilio Rao 	int gotend, n;
4475880123SAttilio Rao 
4575880123SAttilio Rao 	c = (const char *)cp;
4675880123SAttilio Rao 	n = 0;
4775880123SAttilio Rao 
4875880123SAttilio Rao 	/*
4975880123SAttilio Rao 	 * Run through the string, grabbing numbers until
5075880123SAttilio Rao 	 * the end of the string, or some error
5175880123SAttilio Rao 	 */
5275880123SAttilio Rao 	gotend = 0;
5375880123SAttilio Rao 	while (!gotend) {
5475880123SAttilio Rao 		unsigned long l;
5575880123SAttilio Rao 
5675880123SAttilio Rao 		l = strtoul(c, &endptr, 0);
5775880123SAttilio Rao 
5875880123SAttilio Rao 		if (l == ULONG_MAX || (l == 0 && endptr == c))
5975880123SAttilio Rao 			return (0);
6075880123SAttilio Rao 
6175880123SAttilio Rao 		val = (in_addr_t)l;
6275880123SAttilio Rao 
6375880123SAttilio Rao 		/*
6475880123SAttilio Rao 		 * If the whole string is invalid, endptr will equal
6575880123SAttilio Rao 		 * c.. this way we can make sure someone hasn't
6675880123SAttilio Rao 		 * gone '.12' or something which would get past
6775880123SAttilio Rao 		 * the next check.
6875880123SAttilio Rao 		 */
6975880123SAttilio Rao 		if (endptr == c)
7075880123SAttilio Rao 			return (0);
7175880123SAttilio Rao 		parts[n] = val;
7275880123SAttilio Rao 		c = endptr;
7375880123SAttilio Rao 
7475880123SAttilio Rao 		/* Check the next character past the previous number's end */
7575880123SAttilio Rao 		switch (*c) {
7675880123SAttilio Rao 		case '.' :
7775880123SAttilio Rao 
7875880123SAttilio Rao 			/* Make sure we only do 3 dots .. */
7975880123SAttilio Rao 			if (n == 3)	/* Whoops. Quit. */
8075880123SAttilio Rao 				return (0);
8175880123SAttilio Rao 			n++;
8275880123SAttilio Rao 			c++;
8375880123SAttilio Rao 			break;
8475880123SAttilio Rao 
8575880123SAttilio Rao 		case '\0':
8675880123SAttilio Rao 			gotend = 1;
8775880123SAttilio Rao 			break;
8875880123SAttilio Rao 
8975880123SAttilio Rao 		default:
9075880123SAttilio Rao 			if (isspace((unsigned char)*c)) {
9175880123SAttilio Rao 				gotend = 1;
9275880123SAttilio Rao 				break;
9375880123SAttilio Rao 			} else {
9475880123SAttilio Rao 				/* Invalid character, then fail. */
9575880123SAttilio Rao 				return (0);
9675880123SAttilio Rao 			}
9775880123SAttilio Rao 		}
9875880123SAttilio Rao 	}
9975880123SAttilio Rao 
10075880123SAttilio Rao 	/* Concoct the address according to the number of parts specified. */
10175880123SAttilio Rao 	switch (n) {
10275880123SAttilio Rao 	case 0:				/* a -- 32 bits */
10375880123SAttilio Rao 
10475880123SAttilio Rao 		/*
10575880123SAttilio Rao 		 * Nothing is necessary here.  Overflow checking was
10675880123SAttilio Rao 		 * already done in strtoul().
10775880123SAttilio Rao 		 */
10875880123SAttilio Rao 		break;
10975880123SAttilio Rao 	case 1:				/* a.b -- 8.24 bits */
11075880123SAttilio Rao 		if (val > 0xffffff || parts[0] > 0xff)
11175880123SAttilio Rao 			return (0);
11275880123SAttilio Rao 		val |= parts[0] << 24;
11375880123SAttilio Rao 		break;
11475880123SAttilio Rao 
11575880123SAttilio Rao 	case 2:				/* a.b.c -- 8.8.16 bits */
11675880123SAttilio Rao 		if (val > 0xffff || parts[0] > 0xff || parts[1] > 0xff)
11775880123SAttilio Rao 			return (0);
11875880123SAttilio Rao 		val |= (parts[0] << 24) | (parts[1] << 16);
11975880123SAttilio Rao 		break;
12075880123SAttilio Rao 
12175880123SAttilio Rao 	case 3:				/* a.b.c.d -- 8.8.8.8 bits */
12275880123SAttilio Rao 		if (val > 0xff || parts[0] > 0xff || parts[1] > 0xff ||
12375880123SAttilio Rao 		    parts[2] > 0xff)
12475880123SAttilio Rao 			return (0);
12575880123SAttilio Rao 		val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
12675880123SAttilio Rao 		break;
12775880123SAttilio Rao 	}
12875880123SAttilio Rao 
12975880123SAttilio Rao 	if (addr != NULL)
13075880123SAttilio Rao 		addr->s_addr = htonl(val);
13175880123SAttilio Rao 	return (1);
13275880123SAttilio Rao }
133