2 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (c) 1996,1999 by Internet Software Consortium.
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
15 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 #if !defined(LINT) && !defined(CODECENTER)
19 static const char rcsid[] = "$Id: getnetent.c,v 1.4.206.2 2004/03/17 01:49:40 marka Exp $";
24 #include "port_before.h"
26 #if !defined(__BIND_NOSTATIC)
28 #include <sys/types.h>
29 #include <sys/socket.h>
31 #include <netinet/in.h>
32 #include <arpa/nameser.h>
33 #include <arpa/inet.h>
44 #include "port_after.h"
54 char name[MAXDNAME + 1];
59 static struct net_data *init(void);
60 static struct netent *nw_to_net(struct nwent *, struct net_data *);
61 static void freepvt(struct net_data *);
62 static struct netent *fakeaddr(const char *, int af, struct net_data *);
67 # define INADDR_NONE 0xffffffff
74 struct net_data *net_data = init();
76 return (getnetent_p(net_data));
80 getnetbyname(const char *name) {
81 struct net_data *net_data = init();
83 return (getnetbyname_p(name, net_data));
87 getnetbyaddr(unsigned long net, int type) {
88 struct net_data *net_data = init();
90 return (getnetbyaddr_p(net, type, net_data));
94 setnetent(int stayopen) {
95 struct net_data *net_data = init();
97 setnetent_p(stayopen, net_data);
103 struct net_data *net_data = init();
105 endnetent_p(net_data);
108 /* Shared private. */
111 getnetent_p(struct net_data *net_data) {
114 if (!net_data || !(nw = net_data->nw))
116 net_data->nww_last = (*nw->next)(nw);
117 net_data->nw_last = nw_to_net(net_data->nww_last, net_data);
118 return (net_data->nw_last);
122 getnetbyname_p(const char *name, struct net_data *net_data) {
127 if (!net_data || !(nw = net_data->nw))
129 if (net_data->nw_stayopen && net_data->nw_last) {
130 if (!strcmp(net_data->nw_last->n_name, name))
131 return (net_data->nw_last);
132 for (nap = net_data->nw_last->n_aliases; nap && *nap; nap++)
133 if (!strcmp(name, *nap))
134 return (net_data->nw_last);
136 if ((np = fakeaddr(name, AF_INET, net_data)) != NULL)
138 net_data->nww_last = (*nw->byname)(nw, name, AF_INET);
139 net_data->nw_last = nw_to_net(net_data->nww_last, net_data);
140 if (!net_data->nw_stayopen)
142 return (net_data->nw_last);
146 getnetbyaddr_p(unsigned long net, int type, struct net_data *net_data) {
151 if (!net_data || !(nw = net_data->nw))
153 if (net_data->nw_stayopen && net_data->nw_last)
154 if (type == net_data->nw_last->n_addrtype &&
155 net == net_data->nw_last->n_net)
156 return (net_data->nw_last);
158 /* cannonize net(host order) */
162 } else if (net < 65536UL) {
165 } else if (net < 16777216UL) {
171 /* convert to net order */
172 addr[0] = (0xFF000000 & net) >> 24;
173 addr[1] = (0x00FF0000 & net) >> 16;
174 addr[2] = (0x0000FF00 & net) >> 8;
175 addr[3] = (0x000000FF & net);
177 /* reduce bits to as close to natural number as possible */
178 if ((bits == 32) && (addr[0] < 224) && (addr[3] == 0)) {
179 if ((addr[0] < 192) && (addr[2] == 0)) {
180 if ((addr[0] < 128) && (addr[1] == 0))
189 net_data->nww_last = (*nw->byaddr)(nw, addr, bits, AF_INET);
190 net_data->nw_last = nw_to_net(net_data->nww_last, net_data);
191 if (!net_data->nw_stayopen)
193 return (net_data->nw_last);
200 setnetent_p(int stayopen, struct net_data *net_data) {
203 if (!net_data || !(nw = net_data->nw))
207 net_data->nw_stayopen = (stayopen != 0);
209 net_data_minimize(net_data);
213 endnetent_p(struct net_data *net_data) {
216 if ((net_data != NULL) && ((nw = net_data->nw) != NULL))
222 static struct net_data *
224 struct net_data *net_data;
226 if (!(net_data = net_data_init(NULL)))
229 net_data->nw = (*net_data->irs->nw_map)(net_data->irs);
231 if (!net_data->nw || !net_data->res) {
236 (*net_data->nw->res_set)(net_data->nw, net_data->res, NULL);
243 freepvt(struct net_data *net_data) {
244 if (net_data->nw_data) {
245 free(net_data->nw_data);
246 net_data->nw_data = NULL;
250 static struct netent *
251 fakeaddr(const char *name, int af, struct net_data *net_data) {
257 /* XXX should support IPv6 some day */
258 errno = EAFNOSUPPORT;
259 RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL);
262 if (!isascii((unsigned char)(name[0])) ||
263 !isdigit((unsigned char)(name[0])))
265 for (cp = name; *cp; ++cp)
266 if (!isascii(*cp) || (!isdigit((unsigned char)*cp) && *cp != '.'))
271 /* All-numeric, no dot at the end. */
273 tmp = inet_network(name);
274 if (tmp == INADDR_NONE) {
275 RES_SET_H_ERRNO(net_data->res, HOST_NOT_FOUND);
279 /* Valid network number specified.
280 * Fake up a netent as if we'd actually
284 net_data->nw_data = malloc(sizeof (struct pvt));
285 if (!net_data->nw_data) {
287 RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL);
290 pvt = net_data->nw_data;
292 strncpy(pvt->name, name, MAXDNAME);
293 pvt->name[MAXDNAME] = '\0';
294 pvt->netent.n_name = pvt->name;
295 pvt->netent.n_addrtype = AF_INET;
296 pvt->netent.n_aliases = pvt->aliases;
297 pvt->aliases[0] = NULL;
298 pvt->netent.n_net = tmp;
300 return (&pvt->netent);
303 static struct netent *
304 nw_to_net(struct nwent *nwent, struct net_data *net_data) {
310 if (!nwent || nwent->n_addrtype != AF_INET)
313 net_data->nw_data = malloc(sizeof (struct pvt));
314 if (!net_data->nw_data) {
316 RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL);
319 pvt = net_data->nw_data;
320 pvt->netent.n_name = nwent->n_name;
321 pvt->netent.n_aliases = nwent->n_aliases;
322 pvt->netent.n_addrtype = nwent->n_addrtype;
325 * What this code does: Converts net addresses from network to host form.
327 * msbyte: the index of the most significant byte in the n_addr array.
329 * Shift bytes in significant order into addr. When all signicant
330 * bytes are in, zero out bits in the LSB that are not part of the network.
332 msbyte = nwent->n_length / 8 +
333 ((nwent->n_length % 8) != 0 ? 1 : 0) - 1;
334 for (i = 0; i <= msbyte; i++)
335 addr = (addr << 8) | ((unsigned char *)nwent->n_addr)[i];
336 i = (32 - nwent->n_length) % 8;
338 addr &= ~((1 << (i + 1)) - 1);
339 pvt->netent.n_net = addr;
340 return (&pvt->netent);
343 #endif /*__BIND_NOSTATIC*/