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