xref: /onnv-gate/usr/src/stand/lib/wanboot/http_aux.c (revision 0:68f95e015346)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2002-2003 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <sys/salib.h>
30 #include <sys/types.h>
31 #include <sys/socket.h>
32 #include <sys/bootvfs.h>
33 #include <netinet/in.h>
34 
35 /*
36  * This structure defines the static area where gethostbyname()
37  * stores the hostent data that it returns to the caller.
38  */
39 static struct {
40 	struct hostent	he;
41 	in_addr_t	*ha_list[2];
42 	in_addr_t	ha_addr;
43 	char		ha_name[MAXHOSTNAMELEN+1];
44 } hostinfo;
45 
46 int h_errno;
47 
48 static in_addr_t inet_addr(const char *);
49 static in_addr_t nam2addr(const char *);
50 
51 /* Very stripped-down gethostbyname() */
52 struct hostent *
gethostbyname(const char * nam)53 gethostbyname(const char *nam)
54 {
55 	bzero(&hostinfo, sizeof (hostinfo));
56 
57 	hostinfo.ha_addr = inet_addr(nam);
58 	if ((int32_t)hostinfo.ha_addr == -1) {
59 		if (get_default_fs() == NULL) {
60 			h_errno = HOST_NOT_FOUND;
61 			return (NULL);
62 		}
63 		hostinfo.ha_addr = nam2addr(nam);
64 		if ((int32_t)hostinfo.ha_addr == -1) {
65 			h_errno = HOST_NOT_FOUND;
66 			return (NULL);
67 		}
68 	}
69 
70 	hostinfo.he.h_addrtype = AF_INET;
71 	(void) strlcpy(hostinfo.ha_name, nam, MAXHOSTNAMELEN);
72 	hostinfo.he.h_name = hostinfo.ha_name;
73 	hostinfo.he.h_length = sizeof (struct in_addr);
74 	hostinfo.ha_list[0] = &hostinfo.ha_addr;
75 	hostinfo.he.h_addr_list = (char **)&hostinfo.ha_list;
76 	return (&hostinfo.he);
77 }
78 
79 #define	SKIP_SPACE(_p)							\
80 	{								\
81 		char	_c;						\
82 		while ((_c = *(_p)) != '\0' && isspace(_c))		\
83 			p++;						\
84 		if (_c == '\0')						\
85 			goto next_line;					\
86 	}
87 
88 #define	SKIP_TOKEN(_p)							\
89 	{								\
90 		char	_c;						\
91 		while ((_c = *(_p)) != '\0' && !isspace(_c))		\
92 			p++;						\
93 		if (_c == '\0')						\
94 			goto next_line;					\
95 	}
96 
97 #define	TRIM_LINE(_l)							\
98 	{								\
99 		char	_c, *_p = (_l);					\
100 		while ((_c = *_p) != '#' && _c != '\n' && _c != '\0')	\
101 			_p++;						\
102 		*_p = '\0';						\
103 	}
104 
105 #define	BUFSZ	1024
106 #define	HOSTDB	"/etc/inet/hosts"
107 
108 static in_addr_t
nam2addr(const char * nam)109 nam2addr(const char *nam)
110 {
111 	FILE *h;
112 	char c, buf[BUFSZ];
113 	char *l, *p, *s;
114 	boolean_t first_token;
115 
116 	if ((h = fopen(HOSTDB, "r")) == NULL) {
117 		return ((in_addr_t)-1);
118 	}
119 
120 next_line:
121 	if ((l = fgets(buf, BUFSZ, h)) == NULL) {
122 		(void) fclose(h);
123 		return ((in_addr_t)-1);
124 	}
125 	TRIM_LINE(l);
126 
127 	p = l;
128 	first_token = B_TRUE;
129 next_token:
130 	SKIP_SPACE(p);
131 
132 	if (first_token) {
133 		first_token = B_FALSE;
134 		SKIP_TOKEN(p);
135 
136 		*p++ = '\0';
137 		goto next_token;
138 	}
139 
140 	s = (char *)nam;
141 	if (*p++ == *s++) {
142 		while ((c = *s++) == *p && c != '\0')
143 			p++;
144 		if (c == '\0' && (isspace(*p) || *p == '\0'))
145 			goto match;
146 	}
147 
148 	SKIP_TOKEN(p);
149 	goto next_token;
150 match:
151 	(void) fclose(h);
152 	return (inet_addr((const char *)l));
153 }
154 
155 static in_addr_t
inet_addr(const char * cp)156 inet_addr(const char *cp)
157 {
158 	in_addr_t val;
159 	uint_t base, n;
160 	char c;
161 	in_addr_t parts[4], *pp = parts;
162 
163 again:
164 	/*
165 	 * Collect number up to ``.''.
166 	 * Values are specified as for C:
167 	 * 0x=hex, 0=octal, other=decimal.
168 	 */
169 	val = 0; base = 10;
170 	if (*cp == '0') {
171 		if (*++cp == 'x' || *cp == 'X')
172 			base = 16, cp++;
173 		else
174 			base = 8;
175 	}
176 
177 	while ((c = *cp) != 0) {
178 		if (isdigit(c)) {
179 			if ((c - '0') >= base)
180 				break;
181 			val = (val * base) + (c - '0');
182 			cp++;
183 			continue;
184 		}
185 		if (base == 16 && isxdigit(c)) {
186 			val = (val << 4) + (c + 10 - (islower(c) ? 'a' : 'A'));
187 			cp++;
188 			continue;
189 		}
190 		break;
191 	}
192 	if (*cp == '.') {
193 		/*
194 		 * Internet format:
195 		 *	a.b.c.d
196 		 *	a.b.c	(with c treated as 16-bits)
197 		 *	a.b	(with b treated as 24 bits)
198 		 */
199 		if (pp >= parts + 4)
200 			return ((in_addr_t)-1);
201 		*pp++ = val, cp++;
202 		goto again;
203 	}
204 	/*
205 	 * Check for trailing characters.
206 	 */
207 	if (*cp && !isspace(*cp))
208 		return ((in_addr_t)-1);
209 	*pp++ = val;
210 	/*
211 	 * Concoct the address according to
212 	 * the number of parts specified.
213 	 */
214 	n = pp - parts;
215 	switch (n) {
216 
217 	case 1:			 /* a -- 32 bits */
218 		val = parts[0];
219 		break;
220 
221 	case 2:			 /* a.b -- 8.24 bits */
222 		val = (parts[0] << 24) | (parts[1] & 0xffffff);
223 		break;
224 
225 	case 3:			 /* a.b.c -- 8.8.16 bits */
226 		val = (parts[0] << 24) | ((parts[1] & 0xff) << 16) |
227 			(parts[2] & 0xffff);
228 		break;
229 
230 	case 4:			 /* a.b.c.d -- 8.8.8.8 bits */
231 		val = (parts[0] << 24) | ((parts[1] & 0xff) << 16) |
232 			((parts[2] & 0xff) << 8) | (parts[3] & 0xff);
233 		break;
234 
235 	default:
236 		return ((in_addr_t)-1);
237 	}
238 	val = htonl(val);
239 	return (val);
240 }
241