inet_addr.c revision 1.3
1/*
2 * Copyright (c) 1983, 1990, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by the University of
16 *	California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#if defined(LIBC_SCCS) && !defined(lint)
35static char rcsid[] = "$OpenBSD: inet_addr.c,v 1.3 1996/08/19 08:29:08 tholo Exp $";
36#endif /* LIBC_SCCS and not lint */
37
38#include <sys/param.h>
39#include <netinet/in.h>
40#include <arpa/inet.h>
41#include <ctype.h>
42
43/*
44 * Ascii internet address interpretation routine.
45 * The value returned is in network order.
46 */
47u_long
48inet_addr(cp)
49	register const char *cp;
50{
51	struct in_addr val;
52
53	if (inet_aton(cp, &val))
54		return (val.s_addr);
55	return (INADDR_NONE);
56}
57
58/*
59 * Check whether "cp" is a valid ascii representation
60 * of an Internet address and convert to a binary address.
61 * Returns 1 if the address is valid, 0 if not.
62 * This replaces inet_addr, the return value from which
63 * cannot distinguish between failure and a local broadcast address.
64 */
65int
66inet_aton(cp, addr)
67	register const char *cp;
68	struct in_addr *addr;
69{
70	register u_long val;
71	register int base, n;
72	register char c;
73	u_int parts[4];
74	register u_int *pp = parts;
75
76	for (;;) {
77		/*
78		 * Collect number up to ``.''.
79		 * Values are specified as for C:
80		 * 0x=hex, 0=octal, other=decimal.
81		 */
82		val = 0; base = 10;
83		if (*cp == '0') {
84			if (*++cp == 'x' || *cp == 'X')
85				base = 16, cp++;
86			else
87				base = 8;
88		}
89		while ((c = *cp) != '\0') {
90			if (isascii(c) && isdigit(c)) {
91				val = (val * base) + (c - '0');
92				cp++;
93				continue;
94			}
95			if (base == 16 && isascii(c) && isxdigit(c)) {
96				val = (val << 4) +
97					(c + 10 - (islower(c) ? 'a' : 'A'));
98				cp++;
99				continue;
100			}
101			break;
102		}
103		if (*cp == '.') {
104			/*
105			 * Internet format:
106			 *	a.b.c.d
107			 *	a.b.c	(with c treated as 16-bits)
108			 *	a.b	(with b treated as 24 bits)
109			 */
110			if (pp >= parts + 3 || val > 0xff)
111				return (0);
112			*pp++ = val, cp++;
113		} else
114			break;
115	}
116	/*
117	 * Check for trailing characters.
118	 */
119	if (*cp && (!isascii(*cp) || !isspace(*cp)))
120		return (0);
121	/*
122	 * Concoct the address according to
123	 * the number of parts specified.
124	 */
125	n = pp - parts + 1;
126	switch (n) {
127
128	case 0:
129		return (0);		/* initial nondigit */
130
131	case 1:				/* a -- 32 bits */
132		break;
133
134	case 2:				/* a.b -- 8.24 bits */
135		if (val > 0xffffff)
136			return (0);
137		val |= parts[0] << 24;
138		break;
139
140	case 3:				/* a.b.c -- 8.8.16 bits */
141		if (val > 0xffff)
142			return (0);
143		val |= (parts[0] << 24) | (parts[1] << 16);
144		break;
145
146	case 4:				/* a.b.c.d -- 8.8.8.8 bits */
147		if (val > 0xff)
148			return (0);
149		val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
150		break;
151	}
152	if (addr)
153		addr->s_addr = htonl(val);
154	return (1);
155}
156