1199208Sattilio/*-
2199208Sattilio * Copyright (c) 2001 Charles Mott <cm@linktel.net>
3199208Sattilio * All rights reserved.
4199208Sattilio *
5199208Sattilio * Redistribution and use in source and binary forms, with or without
6199208Sattilio * modification, are permitted provided that the following conditions
7199208Sattilio * are met:
8199208Sattilio * 1. Redistributions of source code must retain the above copyright
9199208Sattilio *    notice, this list of conditions and the following disclaimer.
10199208Sattilio * 2. Redistributions in binary form must reproduce the above copyright
11199208Sattilio *    notice, this list of conditions and the following disclaimer in the
12199208Sattilio *    documentation and/or other materials provided with the distribution.
13199208Sattilio *
14199208Sattilio * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15199208Sattilio * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16199208Sattilio * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17199208Sattilio * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18199208Sattilio * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19199208Sattilio * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20199208Sattilio * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21199208Sattilio * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22199208Sattilio * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23199208Sattilio * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24199208Sattilio * SUCH DAMAGE.
25199208Sattilio */
26199208Sattilio
27199208Sattilio#include <sys/cdefs.h>
28199208Sattilio__FBSDID("$FreeBSD$");
29199208Sattilio
30199208Sattilio#include <sys/param.h>
31199208Sattilio#include <sys/ctype.h>
32199208Sattilio#include <sys/limits.h>
33199208Sattilio#include <sys/systm.h>
34199208Sattilio
35199208Sattilio#include <netinet/in.h>
36199208Sattilio
37199208Sattilioint
38199208Sattilioinet_aton(const char *cp, struct in_addr *addr)
39199208Sattilio{
40199208Sattilio	u_long parts[4];
41199208Sattilio	in_addr_t val;
42199208Sattilio	const char *c;
43199208Sattilio	char *endptr;
44199208Sattilio	int gotend, n;
45199208Sattilio
46199208Sattilio	c = (const char *)cp;
47199208Sattilio	n = 0;
48199208Sattilio
49199208Sattilio	/*
50199208Sattilio	 * Run through the string, grabbing numbers until
51199208Sattilio	 * the end of the string, or some error
52199208Sattilio	 */
53199208Sattilio	gotend = 0;
54199208Sattilio	while (!gotend) {
55199208Sattilio		unsigned long l;
56199208Sattilio
57199208Sattilio		l = strtoul(c, &endptr, 0);
58199208Sattilio
59199208Sattilio		if (l == ULONG_MAX || (l == 0 && endptr == c))
60199208Sattilio			return (0);
61199208Sattilio
62199208Sattilio		val = (in_addr_t)l;
63199208Sattilio
64199208Sattilio		/*
65199208Sattilio		 * If the whole string is invalid, endptr will equal
66199208Sattilio		 * c.. this way we can make sure someone hasn't
67199208Sattilio		 * gone '.12' or something which would get past
68199208Sattilio		 * the next check.
69199208Sattilio		 */
70199208Sattilio		if (endptr == c)
71199208Sattilio			return (0);
72199208Sattilio		parts[n] = val;
73199208Sattilio		c = endptr;
74199208Sattilio
75199208Sattilio		/* Check the next character past the previous number's end */
76199208Sattilio		switch (*c) {
77199208Sattilio		case '.' :
78199208Sattilio
79199208Sattilio			/* Make sure we only do 3 dots .. */
80199208Sattilio			if (n == 3)	/* Whoops. Quit. */
81199208Sattilio				return (0);
82199208Sattilio			n++;
83199208Sattilio			c++;
84199208Sattilio			break;
85199208Sattilio
86199208Sattilio		case '\0':
87199208Sattilio			gotend = 1;
88199208Sattilio			break;
89199208Sattilio
90199208Sattilio		default:
91199208Sattilio			if (isspace((unsigned char)*c)) {
92199208Sattilio				gotend = 1;
93199208Sattilio				break;
94199208Sattilio			} else {
95199208Sattilio
96199208Sattilio				/* Invalid character, then fail. */
97199208Sattilio				return (0);
98199208Sattilio			}
99199208Sattilio		}
100199208Sattilio
101199208Sattilio	}
102199208Sattilio
103199208Sattilio	/* Concoct the address according to the number of parts specified. */
104199208Sattilio	switch (n) {
105199208Sattilio	case 0:				/* a -- 32 bits */
106199208Sattilio
107199208Sattilio		/*
108199208Sattilio		 * Nothing is necessary here.  Overflow checking was
109199208Sattilio		 * already done in strtoul().
110199208Sattilio		 */
111199208Sattilio		break;
112199208Sattilio	case 1:				/* a.b -- 8.24 bits */
113199208Sattilio		if (val > 0xffffff || parts[0] > 0xff)
114199208Sattilio			return (0);
115199208Sattilio		val |= parts[0] << 24;
116199208Sattilio		break;
117199208Sattilio
118199208Sattilio	case 2:				/* a.b.c -- 8.8.16 bits */
119199208Sattilio		if (val > 0xffff || parts[0] > 0xff || parts[1] > 0xff)
120199208Sattilio			return (0);
121199208Sattilio		val |= (parts[0] << 24) | (parts[1] << 16);
122199208Sattilio		break;
123199208Sattilio
124199208Sattilio	case 3:				/* a.b.c.d -- 8.8.8.8 bits */
125199208Sattilio		if (val > 0xff || parts[0] > 0xff || parts[1] > 0xff ||
126199208Sattilio		    parts[2] > 0xff)
127199208Sattilio			return (0);
128199208Sattilio		val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
129199208Sattilio		break;
130199208Sattilio	}
131199208Sattilio
132199208Sattilio	if (addr != NULL)
133199208Sattilio		addr->s_addr = htonl(val);
134199208Sattilio	return (1);
135199208Sattilio}
136199208Sattilio
137