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