xref: /illumos-gate/usr/src/lib/libresolv2/common/irs/getnetent.c (revision 4eaa471005973e11a6110b69fe990530b3b95a38)
1 /*
2  * Copyright 1997-2002 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 /*
7  * Copyright (c) 1996,1999 by Internet Software Consortium.
8  *
9  * Permission to use, copy, modify, and distribute this software for any
10  * purpose with or without fee is hereby granted, provided that the above
11  * copyright notice and this permission notice appear in all copies.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
14  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
15  * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
16  * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
17  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
18  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
19  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20  * SOFTWARE.
21  */
22 
23 #pragma ident	"%Z%%M%	%I%	%E% SMI"
24 
25 #if !defined(LINT) && !defined(CODECENTER)
26 static const char rcsid[] = "$Id: getnetent.c,v 1.19 2001/05/29 05:48:47 marka Exp $";
27 #endif
28 
29 /* Imports */
30 
31 #include "port_before.h"
32 
33 #if !defined(__BIND_NOSTATIC)
34 
35 #include <sys/types.h>
36 #include <sys/socket.h>
37 
38 #include <netinet/in.h>
39 #include <arpa/nameser.h>
40 #include <arpa/inet.h>
41 
42 #include <ctype.h>
43 #include <errno.h>
44 #include <netdb.h>
45 #include <resolv.h>
46 #include <stdlib.h>
47 #include <string.h>
48 
49 #include <irs.h>
50 
51 #include "port_after.h"
52 
53 #include "irs_p.h"
54 #include "irs_data.h"
55 
56 /* Definitions */
57 
58 struct pvt {
59 	struct netent	netent;
60 	char *		aliases[1];
61 	char		name[MAXDNAME + 1];
62 };
63 
64 /* Forward */
65 
66 static struct net_data *init(void);
67 static struct netent   *nw_to_net(struct nwent *, struct net_data *);
68 static void		freepvt(struct net_data *);
69 static struct netent   *fakeaddr(const char *, int af, struct net_data *);
70 
71 /* Portability */
72 
73 #ifndef INADDR_NONE
74 # define INADDR_NONE 0xffffffff
75 #endif
76 
77 /* Public */
78 
79 struct netent *
80 getnetent() {
81 	struct net_data *net_data = init();
82 
83 	return (getnetent_p(net_data));
84 }
85 
86 struct netent *
87 getnetbyname(const char *name) {
88 	struct net_data *net_data = init();
89 
90 	return (getnetbyname_p(name, net_data));
91 }
92 
93 struct netent *
94 #ifdef	ORIGINAL_ISC_CODE
95 getnetbyaddr(unsigned long net, int type) {
96 #else
97 getnetbyaddr(in_addr_t net, int type) {
98 #endif
99 	struct net_data *net_data = init();
100 
101 	return (getnetbyaddr_p(net, type, net_data));
102 }
103 
104 #ifdef	ORIGINAL_ISC_CODE
105 void
106 #else
107 int
108 #endif
109 setnetent(int stayopen) {
110 	struct net_data *net_data = init();
111 
112 	setnetent_p(stayopen, net_data);
113 #ifdef	ORIGINAL_ISC_CODE
114 #else
115 	return (0);
116 #endif
117 }
118 
119 
120 #ifdef	ORIGINAL_ISC_CODE
121 void
122 #else
123 int
124 #endif
125 endnetent() {
126 	struct net_data *net_data = init();
127 
128 	endnetent_p(net_data);
129 #ifdef	ORIGINAL_ISC_CODE
130 #else
131 	return (0);
132 #endif
133 }
134 
135 /* Shared private. */
136 
137 struct netent *
138 getnetent_p(struct net_data *net_data) {
139 	struct irs_nw *nw;
140 
141 	if (!net_data || !(nw = net_data->nw))
142 		return (NULL);
143 	net_data->nww_last = (*nw->next)(nw);
144 	net_data->nw_last = nw_to_net(net_data->nww_last, net_data);
145 	return (net_data->nw_last);
146 }
147 
148 struct netent *
149 getnetbyname_p(const char *name, struct net_data *net_data) {
150 	struct irs_nw *nw;
151 	struct netent *np;
152 	char **nap;
153 
154 	if (!net_data || !(nw = net_data->nw))
155 		return (NULL);
156 	if (net_data->nw_stayopen && net_data->nw_last) {
157 		if (!strcmp(net_data->nw_last->n_name, name))
158 			return (net_data->nw_last);
159 		for (nap = net_data->nw_last->n_aliases; nap && *nap; nap++)
160 			if (!strcmp(name, *nap))
161 				return (net_data->nw_last);
162 	}
163 	if ((np = fakeaddr(name, AF_INET, net_data)) != NULL)
164 		return (np);
165 	net_data->nww_last = (*nw->byname)(nw, name, AF_INET);
166 	net_data->nw_last = nw_to_net(net_data->nww_last, net_data);
167 	if (!net_data->nw_stayopen)
168 		endnetent();
169 	return (net_data->nw_last);
170 }
171 
172 struct netent *
173 getnetbyaddr_p(unsigned long net, int type, struct net_data *net_data) {
174 	struct irs_nw *nw;
175 	u_char addr[4];
176 	int bits;
177 
178 	if (!net_data || !(nw = net_data->nw))
179 		return (NULL);
180 	if (net_data->nw_stayopen && net_data->nw_last)
181 		if (type == net_data->nw_last->n_addrtype &&
182 		    net == net_data->nw_last->n_net)
183 			return (net_data->nw_last);
184 
185 	/* cannonize net(host order) */
186 	if (net < 256) {
187 		net <<= 24;
188 		bits = 8;
189 	} else if (net < 65536) {
190 		net <<= 16;
191 		bits = 16;
192 	} else if (net < 16777216) {
193 		net <<= 8;
194 		bits = 24;
195 	} else
196 		bits = 32;
197 
198 	/* convert to net order */
199 	addr[0] = (0xFF000000 & net) >> 24;
200 	addr[1] = (0x00FF0000 & net) >> 16;
201 	addr[2] = (0x0000FF00 & net) >> 8;
202 	addr[3] = (0x000000FF & net);
203 
204 	/* reduce bits to as close to natural number as possible */
205 	if ((bits == 32) && (addr[0] < 224) && (addr[3] == 0)) {
206 		if ((addr[0] < 192) && (addr[2] == 0)) {
207 			if ((addr[0] < 128) && (addr[1] == 0))
208 				bits = 8;
209 			else
210 				bits = 16;
211 		} else {
212 			bits = 24;
213 		}
214 	}
215 
216 	net_data->nww_last = (*nw->byaddr)(nw, addr, bits, AF_INET);
217 	net_data->nw_last = nw_to_net(net_data->nww_last, net_data);
218 	if (!net_data->nw_stayopen)
219 		endnetent();
220 	return (net_data->nw_last);
221 }
222 
223 
224 
225 
226 void
227 setnetent_p(int stayopen, struct net_data *net_data) {
228 	struct irs_nw *nw;
229 
230 	if (!net_data || !(nw = net_data->nw))
231 		return;
232 	freepvt(net_data);
233 	(*nw->rewind)(nw);
234 	net_data->nw_stayopen = (stayopen != 0);
235 	if (stayopen == 0)
236 		net_data_minimize(net_data);
237 }
238 
239 void
240 endnetent_p(struct net_data *net_data) {
241 	struct irs_nw *nw;
242 
243 	if ((net_data != NULL) && ((nw	= net_data->nw) != NULL))
244 		(*nw->minimize)(nw);
245 }
246 
247 /* Private */
248 
249 static struct net_data *
250 init() {
251 	struct net_data *net_data;
252 
253 	if (!(net_data = net_data_init(NULL)))
254 		goto error;
255 	if (!net_data->nw) {
256 		net_data->nw = (*net_data->irs->nw_map)(net_data->irs);
257 
258 		if (!net_data->nw || !net_data->res) {
259  error:
260 			errno = EIO;
261 			return (NULL);
262 		}
263 		(*net_data->nw->res_set)(net_data->nw, net_data->res, NULL);
264 	}
265 
266 	return (net_data);
267 }
268 
269 static void
270 freepvt(struct net_data *net_data) {
271 	if (net_data->nw_data) {
272 		free(net_data->nw_data);
273 		net_data->nw_data = NULL;
274 	}
275 }
276 
277 static struct netent *
278 fakeaddr(const char *name, int af, struct net_data *net_data) {
279 	struct pvt *pvt;
280 	const char *cp;
281 	u_long tmp;
282 
283 	if (af != AF_INET) {
284 		/* XXX should support IPv6 some day */
285 		errno = EAFNOSUPPORT;
286 		RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL);
287 		return (NULL);
288 	}
289 	if (!isascii((unsigned char)(name[0])) ||
290 	    !isdigit((unsigned char)(name[0])))
291 		return (NULL);
292 	for (cp = name; *cp; ++cp)
293 		if (!isascii(*cp) || (!isdigit((unsigned char)*cp) && *cp != '.'))
294 			return (NULL);
295 	if (*--cp == '.')
296 		return (NULL);
297 
298 	/* All-numeric, no dot at the end. */
299 
300 	tmp = inet_network(name);
301 	if (tmp == INADDR_NONE) {
302 		RES_SET_H_ERRNO(net_data->res, HOST_NOT_FOUND);
303 		return (NULL);
304 	}
305 
306 	/* Valid network number specified.
307 	 * Fake up a netent as if we'd actually
308 	 * done a lookup.
309 	 */
310 	freepvt(net_data);
311 	net_data->nw_data = malloc(sizeof (struct pvt));
312 	if (!net_data->nw_data) {
313 		errno = ENOMEM;
314 		RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL);
315 		return (NULL);
316 	}
317 	pvt = net_data->nw_data;
318 
319 	strncpy(pvt->name, name, MAXDNAME);
320 	pvt->name[MAXDNAME] = '\0';
321 	pvt->netent.n_name = pvt->name;
322 	pvt->netent.n_addrtype = AF_INET;
323 	pvt->netent.n_aliases = pvt->aliases;
324 	pvt->aliases[0] = NULL;
325 	pvt->netent.n_net = tmp;
326 
327 	return (&pvt->netent);
328 }
329 
330 static struct netent *
331 nw_to_net(struct nwent *nwent, struct net_data *net_data) {
332 	struct pvt *pvt;
333 	u_long addr = 0;
334 	int i;
335 	int msbyte;
336 
337 	if (!nwent || nwent->n_addrtype != AF_INET)
338 		return (NULL);
339 	freepvt(net_data);
340 	net_data->nw_data = malloc(sizeof (struct pvt));
341 	if (!net_data->nw_data) {
342 		errno = ENOMEM;
343 		RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL);
344 		return (NULL);
345 	}
346 	pvt = net_data->nw_data;
347 	pvt->netent.n_name = nwent->n_name;
348 	pvt->netent.n_aliases = nwent->n_aliases;
349 	pvt->netent.n_addrtype = nwent->n_addrtype;
350 
351 /*
352  * What this code does: Converts net addresses from network to host form.
353  *
354  * msbyte: the index of the most significant byte in the n_addr array.
355  *
356  * Shift bytes in significant order into addr. When all signicant
357  * bytes are in, zero out bits in the LSB that are not part of the network.
358  */
359 	msbyte = nwent->n_length / 8 +
360 		((nwent->n_length % 8) != 0 ? 1 : 0) - 1;
361 	for (i = 0; i <= msbyte; i++)
362 		addr = (addr << 8) | ((unsigned char *)nwent->n_addr)[i];
363 	i = (32 - nwent->n_length) % 8;
364 	if (i != 0)
365 		addr &= ~((1 << (i + 1)) - 1);
366 	pvt->netent.n_net = addr;
367 	return (&pvt->netent);
368 }
369 
370 #endif /*__BIND_NOSTATIC*/
371