xref: /freebsd/sys/libkern/inet_aton.c (revision 60d717baf2144cf344ec9b47d715ce837b5d46d4)
1  /*-
2   * SPDX-License-Identifier: BSD-2-Clause
3   *
4   * Copyright (c) 2001 Charles Mott <cm@linktel.net>
5   * All rights reserved.
6   *
7   * Redistribution and use in source and binary forms, with or without
8   * modification, are permitted provided that the following conditions
9   * are met:
10   * 1. Redistributions of source code must retain the above copyright
11   *    notice, this list of conditions and the following disclaimer.
12   * 2. Redistributions in binary form must reproduce the above copyright
13   *    notice, this list of conditions and the following disclaimer in the
14   *    documentation and/or other materials provided with the distribution.
15   *
16   * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19   * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22   * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26   * SUCH DAMAGE.
27   */
28  
29  #include <sys/param.h>
30  #include <sys/ctype.h>
31  #include <sys/limits.h>
32  #include <sys/systm.h>
33  
34  #include <netinet/in.h>
35  
36  int
37  inet_aton(const char *cp, struct in_addr *addr)
38  {
39  	u_long parts[4];
40  	in_addr_t val;
41  	const char *c;
42  	char *endptr;
43  	int gotend, n;
44  
45  	c = (const char *)cp;
46  	n = 0;
47  
48  	/*
49  	 * Run through the string, grabbing numbers until
50  	 * the end of the string, or some error
51  	 */
52  	gotend = 0;
53  	while (!gotend) {
54  		unsigned long l;
55  
56  		l = strtoul(c, &endptr, 0);
57  
58  		if (l == ULONG_MAX || (l == 0 && endptr == c))
59  			return (0);
60  
61  		val = (in_addr_t)l;
62  
63  		/*
64  		 * If the whole string is invalid, endptr will equal
65  		 * c.. this way we can make sure someone hasn't
66  		 * gone '.12' or something which would get past
67  		 * the next check.
68  		 */
69  		if (endptr == c)
70  			return (0);
71  		parts[n] = val;
72  		c = endptr;
73  
74  		/* Check the next character past the previous number's end */
75  		switch (*c) {
76  		case '.' :
77  
78  			/* Make sure we only do 3 dots .. */
79  			if (n == 3)	/* Whoops. Quit. */
80  				return (0);
81  			n++;
82  			c++;
83  			break;
84  
85  		case '\0':
86  			gotend = 1;
87  			break;
88  
89  		default:
90  			if (isspace((unsigned char)*c)) {
91  				gotend = 1;
92  				break;
93  			} else {
94  				/* Invalid character, then fail. */
95  				return (0);
96  			}
97  		}
98  	}
99  
100  	/* Concoct the address according to the number of parts specified. */
101  	switch (n) {
102  	case 0:				/* a -- 32 bits */
103  
104  		/*
105  		 * Nothing is necessary here.  Overflow checking was
106  		 * already done in strtoul().
107  		 */
108  		break;
109  	case 1:				/* a.b -- 8.24 bits */
110  		if (val > 0xffffff || parts[0] > 0xff)
111  			return (0);
112  		val |= parts[0] << 24;
113  		break;
114  
115  	case 2:				/* a.b.c -- 8.8.16 bits */
116  		if (val > 0xffff || parts[0] > 0xff || parts[1] > 0xff)
117  			return (0);
118  		val |= (parts[0] << 24) | (parts[1] << 16);
119  		break;
120  
121  	case 3:				/* a.b.c.d -- 8.8.8.8 bits */
122  		if (val > 0xff || parts[0] > 0xff || parts[1] > 0xff ||
123  		    parts[2] > 0xff)
124  			return (0);
125  		val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
126  		break;
127  	}
128  
129  	if (addr != NULL)
130  		addr->s_addr = htonl(val);
131  	return (1);
132  }
133