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