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.7 2005/04/27 04:56:25 sra 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*/