xref: /illumos-gate/usr/src/lib/libc/port/inet/inet_ntoa.c (revision cb620785)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29 /*
30  * Portions of this source code were derived from Berkeley
31  * 4.3 BSD under license from the Regents of the University of
32  * California.
33  */
34 
35 #pragma ident	"%Z%%M%	%I%	%E% SMI"
36 
37 /*
38  * Convert network-format internet address
39  * to base 256 d.d.d.d representation.
40  *
41  * Reentrant interface
42  */
43 
44 #pragma weak inet_aton = _inet_aton
45 
46 #include "mt.h"
47 #include "rpc_mt.h"
48 #include <errno.h>
49 #include <sys/types.h>
50 #include <ctype.h>
51 #include <netinet/in.h>
52 #include <stdio.h>
53 #include <stdlib.h>
54 
55 
56 char *
57 inet_ntoa_r(in, b)
58 	struct in_addr in;
59 	char	b[];	/* Assumed >= 18 bytes */
60 {
61 	char	*p;
62 
63 	p = (char *)&in;
64 #define	UC(b)	(((int)b)&0xff)
65 	(void) sprintf(b, "%d.%d.%d.%d",
66 				UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3]));
67 	return (b);
68 }
69 
70 char *
71 inet_ntoa(in)
72 	struct in_addr in;
73 {
74 	char *b;
75 	static char b_main[18];
76 	static pthread_key_t ntoa_key = PTHREAD_ONCE_KEY_NP;
77 
78 	if (thr_main())
79 		b = b_main;
80 	else if ((b = thr_get_storage(&ntoa_key, 18, free)) == NULL)
81 		b = b_main;
82 
83 	return (inet_ntoa_r(in, b));
84 }
85 
86 /*
87  * Check whether "cp" is a valid ascii representation
88  * of an Internet address and convert to a binary address.
89  * Returns 1 if the address is valid, 0 if not.
90  * This replaces inet_addr, the return value from which
91  * cannot distinguish between failure and a local broadcast address.
92  */
93 int
94 inet_aton(const char *cp, struct in_addr *addr)
95 {
96 	uint32_t val;
97 	int base, n;
98 	char c;
99 	unsigned int parts[4];
100 	unsigned int *pp = parts;
101 
102 
103 	c = *cp;
104 	for (;;) {
105 		/*
106 		 * Collect number up to ``.''.
107 		 * Values are specified as for C:
108 		 * 0x=hex, 0=octal, isdigit=decimal.
109 		 */
110 		if (!isdigit(c))
111 			return (0);
112 		val = 0; base = 10;
113 		if (c == '0') {
114 			c = *++cp;
115 			if (c == 'x' || c == 'X')
116 				base = 16, c = *++cp;
117 			else
118 				base = 8;
119 		}
120 		for (;;) {
121 			if (isascii(c) && isdigit(c)) {
122 				val = (val * base) + (c - '0');
123 				c = *++cp;
124 			} else if (base == 16 && isascii(c) && isxdigit(c)) {
125 				val = (val << 4) |
126 					(c + 10 - (islower(c) ? 'a' : 'A'));
127 				c = *++cp;
128 			} else
129 				break;
130 		}
131 		if (c == '.') {
132 			/*
133 			 * Internet format:
134 			 *	a.b.c.d
135 			 *	a.b.c	(with c treated as 16 bits)
136 			 *	a.b	(with b treated as 24 bits)
137 			 */
138 			if (pp >= parts + 3)
139 				return (0);
140 			*pp++ = val;
141 			c = *++cp;
142 		} else
143 			break;
144 	}
145 	/*
146 	 * Check for trailing characters.
147 	 */
148 	if (c != '\0' && (!isascii(c) || !isspace(c)))
149 		return (0);
150 	/*
151 	 * Concoct the address according to
152 	 * the number of parts specified.
153 	 */
154 	n = pp - parts + 1;
155 	switch (n) {
156 
157 	case 0:
158 		return (0);		/* initial nondigit */
159 
160 	case 1:				/* a -- 32 bits */
161 		break;
162 
163 	case 2:				/* a.b -- 8.24 bits */
164 		if ((val > 0xffffff) || (parts[0] > 0xff))
165 			return (0);
166 		val |= parts[0] << 24;
167 		break;
168 
169 	case 3:				/* a.b.c -- 8.8.16 bits */
170 		if ((val > 0xffff) || (parts[0] > 0xff) || (parts[1] > 0xff))
171 			return (0);
172 		val |= (parts[0] << 24) | (parts[1] << 16);
173 		break;
174 
175 	case 4:				/* a.b.c.d -- 8.8.8.8 bits */
176 		if ((val > 0xff) || (parts[0] > 0xff) || (parts[1] > 0xff) ||
177 		    (parts[2] > 0xff))
178 			return (0);
179 		val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
180 		break;
181 	}
182 	if (addr)
183 		addr->s_addr = htonl(val);
184 	return (1);
185 }
186 
187 /*
188  * Internet address interpretation routine.
189  * All the network library routines call this
190  * routine to interpret entries in the data bases
191  * which are expected to be an address.
192  * The value returned is in network order.
193  */
194 in_addr_t
195 inet_addr(const char *cp)
196 {
197 	struct in_addr val;
198 
199 	if (inet_aton(cp, &val))
200 		return (val.s_addr);
201 	return (INADDR_NONE);
202 }
203 
204 /*
205  * Return the network number from an internet
206  * address; handles class a/b/c network #'s.
207  */
208 uint_t
209 inet_netof(struct in_addr in)
210 {
211 	uint32_t i = ntohl(in.s_addr);
212 
213 	if (IN_CLASSA(i))
214 		return ((i & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT);
215 	if (IN_CLASSB(i))
216 		return ((i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT);
217 	return ((i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT);
218 }
219