10Sstevel@tonic-gate /*
2*11038SRao.Shoaib@Sun.COM * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
30Sstevel@tonic-gate * Copyright (c) 1996,1999 by Internet Software Consortium.
40Sstevel@tonic-gate *
50Sstevel@tonic-gate * Permission to use, copy, modify, and distribute this software for any
60Sstevel@tonic-gate * purpose with or without fee is hereby granted, provided that the above
70Sstevel@tonic-gate * copyright notice and this permission notice appear in all copies.
80Sstevel@tonic-gate *
9*11038SRao.Shoaib@Sun.COM * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
10*11038SRao.Shoaib@Sun.COM * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11*11038SRao.Shoaib@Sun.COM * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
12*11038SRao.Shoaib@Sun.COM * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13*11038SRao.Shoaib@Sun.COM * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14*11038SRao.Shoaib@Sun.COM * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
15*11038SRao.Shoaib@Sun.COM * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
160Sstevel@tonic-gate */
170Sstevel@tonic-gate
180Sstevel@tonic-gate #if !defined(LINT) && !defined(CODECENTER)
19*11038SRao.Shoaib@Sun.COM static const char rcsid[] = "$Id: getnetent.c,v 1.7 2005/04/27 04:56:25 sra Exp $";
200Sstevel@tonic-gate #endif
210Sstevel@tonic-gate
220Sstevel@tonic-gate /* Imports */
230Sstevel@tonic-gate
240Sstevel@tonic-gate #include "port_before.h"
250Sstevel@tonic-gate
260Sstevel@tonic-gate #if !defined(__BIND_NOSTATIC)
270Sstevel@tonic-gate
280Sstevel@tonic-gate #include <sys/types.h>
290Sstevel@tonic-gate #include <sys/socket.h>
300Sstevel@tonic-gate
310Sstevel@tonic-gate #include <netinet/in.h>
320Sstevel@tonic-gate #include <arpa/nameser.h>
330Sstevel@tonic-gate #include <arpa/inet.h>
340Sstevel@tonic-gate
350Sstevel@tonic-gate #include <ctype.h>
360Sstevel@tonic-gate #include <errno.h>
370Sstevel@tonic-gate #include <netdb.h>
380Sstevel@tonic-gate #include <resolv.h>
390Sstevel@tonic-gate #include <stdlib.h>
400Sstevel@tonic-gate #include <string.h>
410Sstevel@tonic-gate
420Sstevel@tonic-gate #include <irs.h>
430Sstevel@tonic-gate
440Sstevel@tonic-gate #include "port_after.h"
450Sstevel@tonic-gate
460Sstevel@tonic-gate #include "irs_p.h"
470Sstevel@tonic-gate #include "irs_data.h"
480Sstevel@tonic-gate
490Sstevel@tonic-gate /* Definitions */
500Sstevel@tonic-gate
510Sstevel@tonic-gate struct pvt {
520Sstevel@tonic-gate struct netent netent;
530Sstevel@tonic-gate char * aliases[1];
540Sstevel@tonic-gate char name[MAXDNAME + 1];
550Sstevel@tonic-gate };
560Sstevel@tonic-gate
570Sstevel@tonic-gate /* Forward */
580Sstevel@tonic-gate
590Sstevel@tonic-gate static struct net_data *init(void);
600Sstevel@tonic-gate static struct netent *nw_to_net(struct nwent *, struct net_data *);
610Sstevel@tonic-gate static void freepvt(struct net_data *);
620Sstevel@tonic-gate static struct netent *fakeaddr(const char *, int af, struct net_data *);
630Sstevel@tonic-gate
640Sstevel@tonic-gate /* Portability */
650Sstevel@tonic-gate
660Sstevel@tonic-gate #ifndef INADDR_NONE
670Sstevel@tonic-gate # define INADDR_NONE 0xffffffff
680Sstevel@tonic-gate #endif
690Sstevel@tonic-gate
700Sstevel@tonic-gate /* Public */
710Sstevel@tonic-gate
720Sstevel@tonic-gate struct netent *
getnetent()730Sstevel@tonic-gate getnetent() {
740Sstevel@tonic-gate struct net_data *net_data = init();
750Sstevel@tonic-gate
760Sstevel@tonic-gate return (getnetent_p(net_data));
770Sstevel@tonic-gate }
780Sstevel@tonic-gate
790Sstevel@tonic-gate struct netent *
getnetbyname(const char * name)800Sstevel@tonic-gate getnetbyname(const char *name) {
810Sstevel@tonic-gate struct net_data *net_data = init();
820Sstevel@tonic-gate
830Sstevel@tonic-gate return (getnetbyname_p(name, net_data));
840Sstevel@tonic-gate }
850Sstevel@tonic-gate
860Sstevel@tonic-gate struct netent *
getnetbyaddr(unsigned long net,int type)870Sstevel@tonic-gate getnetbyaddr(unsigned long net, int type) {
880Sstevel@tonic-gate struct net_data *net_data = init();
890Sstevel@tonic-gate
900Sstevel@tonic-gate return (getnetbyaddr_p(net, type, net_data));
910Sstevel@tonic-gate }
920Sstevel@tonic-gate
930Sstevel@tonic-gate void
setnetent(int stayopen)940Sstevel@tonic-gate setnetent(int stayopen) {
950Sstevel@tonic-gate struct net_data *net_data = init();
960Sstevel@tonic-gate
970Sstevel@tonic-gate setnetent_p(stayopen, net_data);
980Sstevel@tonic-gate }
990Sstevel@tonic-gate
1000Sstevel@tonic-gate
1010Sstevel@tonic-gate void
endnetent()1020Sstevel@tonic-gate endnetent() {
1030Sstevel@tonic-gate struct net_data *net_data = init();
1040Sstevel@tonic-gate
1050Sstevel@tonic-gate endnetent_p(net_data);
1060Sstevel@tonic-gate }
1070Sstevel@tonic-gate
1080Sstevel@tonic-gate /* Shared private. */
1090Sstevel@tonic-gate
1100Sstevel@tonic-gate struct netent *
getnetent_p(struct net_data * net_data)1110Sstevel@tonic-gate getnetent_p(struct net_data *net_data) {
1120Sstevel@tonic-gate struct irs_nw *nw;
1130Sstevel@tonic-gate
1140Sstevel@tonic-gate if (!net_data || !(nw = net_data->nw))
1150Sstevel@tonic-gate return (NULL);
1160Sstevel@tonic-gate net_data->nww_last = (*nw->next)(nw);
1170Sstevel@tonic-gate net_data->nw_last = nw_to_net(net_data->nww_last, net_data);
1180Sstevel@tonic-gate return (net_data->nw_last);
1190Sstevel@tonic-gate }
1200Sstevel@tonic-gate
1210Sstevel@tonic-gate struct netent *
getnetbyname_p(const char * name,struct net_data * net_data)1220Sstevel@tonic-gate getnetbyname_p(const char *name, struct net_data *net_data) {
1230Sstevel@tonic-gate struct irs_nw *nw;
1240Sstevel@tonic-gate struct netent *np;
1250Sstevel@tonic-gate char **nap;
1260Sstevel@tonic-gate
1270Sstevel@tonic-gate if (!net_data || !(nw = net_data->nw))
1280Sstevel@tonic-gate return (NULL);
1290Sstevel@tonic-gate if (net_data->nw_stayopen && net_data->nw_last) {
1300Sstevel@tonic-gate if (!strcmp(net_data->nw_last->n_name, name))
1310Sstevel@tonic-gate return (net_data->nw_last);
1320Sstevel@tonic-gate for (nap = net_data->nw_last->n_aliases; nap && *nap; nap++)
1330Sstevel@tonic-gate if (!strcmp(name, *nap))
1340Sstevel@tonic-gate return (net_data->nw_last);
1350Sstevel@tonic-gate }
1360Sstevel@tonic-gate if ((np = fakeaddr(name, AF_INET, net_data)) != NULL)
1370Sstevel@tonic-gate return (np);
1380Sstevel@tonic-gate net_data->nww_last = (*nw->byname)(nw, name, AF_INET);
1390Sstevel@tonic-gate net_data->nw_last = nw_to_net(net_data->nww_last, net_data);
1400Sstevel@tonic-gate if (!net_data->nw_stayopen)
1410Sstevel@tonic-gate endnetent();
1420Sstevel@tonic-gate return (net_data->nw_last);
1430Sstevel@tonic-gate }
1440Sstevel@tonic-gate
1450Sstevel@tonic-gate struct netent *
getnetbyaddr_p(unsigned long net,int type,struct net_data * net_data)1460Sstevel@tonic-gate getnetbyaddr_p(unsigned long net, int type, struct net_data *net_data) {
1470Sstevel@tonic-gate struct irs_nw *nw;
1480Sstevel@tonic-gate u_char addr[4];
1490Sstevel@tonic-gate int bits;
1500Sstevel@tonic-gate
1510Sstevel@tonic-gate if (!net_data || !(nw = net_data->nw))
1520Sstevel@tonic-gate return (NULL);
1530Sstevel@tonic-gate if (net_data->nw_stayopen && net_data->nw_last)
1540Sstevel@tonic-gate if (type == net_data->nw_last->n_addrtype &&
1550Sstevel@tonic-gate net == net_data->nw_last->n_net)
1560Sstevel@tonic-gate return (net_data->nw_last);
1570Sstevel@tonic-gate
1580Sstevel@tonic-gate /* cannonize net(host order) */
159*11038SRao.Shoaib@Sun.COM if (net < 256UL) {
1600Sstevel@tonic-gate net <<= 24;
1610Sstevel@tonic-gate bits = 8;
162*11038SRao.Shoaib@Sun.COM } else if (net < 65536UL) {
1630Sstevel@tonic-gate net <<= 16;
1640Sstevel@tonic-gate bits = 16;
165*11038SRao.Shoaib@Sun.COM } else if (net < 16777216UL) {
1660Sstevel@tonic-gate net <<= 8;
1670Sstevel@tonic-gate bits = 24;
1680Sstevel@tonic-gate } else
1690Sstevel@tonic-gate bits = 32;
1700Sstevel@tonic-gate
1710Sstevel@tonic-gate /* convert to net order */
1720Sstevel@tonic-gate addr[0] = (0xFF000000 & net) >> 24;
1730Sstevel@tonic-gate addr[1] = (0x00FF0000 & net) >> 16;
1740Sstevel@tonic-gate addr[2] = (0x0000FF00 & net) >> 8;
1750Sstevel@tonic-gate addr[3] = (0x000000FF & net);
1760Sstevel@tonic-gate
1770Sstevel@tonic-gate /* reduce bits to as close to natural number as possible */
1780Sstevel@tonic-gate if ((bits == 32) && (addr[0] < 224) && (addr[3] == 0)) {
1790Sstevel@tonic-gate if ((addr[0] < 192) && (addr[2] == 0)) {
1800Sstevel@tonic-gate if ((addr[0] < 128) && (addr[1] == 0))
1810Sstevel@tonic-gate bits = 8;
1820Sstevel@tonic-gate else
1830Sstevel@tonic-gate bits = 16;
1840Sstevel@tonic-gate } else {
1850Sstevel@tonic-gate bits = 24;
1860Sstevel@tonic-gate }
1870Sstevel@tonic-gate }
1880Sstevel@tonic-gate
1890Sstevel@tonic-gate net_data->nww_last = (*nw->byaddr)(nw, addr, bits, AF_INET);
1900Sstevel@tonic-gate net_data->nw_last = nw_to_net(net_data->nww_last, net_data);
1910Sstevel@tonic-gate if (!net_data->nw_stayopen)
1920Sstevel@tonic-gate endnetent();
1930Sstevel@tonic-gate return (net_data->nw_last);
1940Sstevel@tonic-gate }
1950Sstevel@tonic-gate
1960Sstevel@tonic-gate
1970Sstevel@tonic-gate
1980Sstevel@tonic-gate
1990Sstevel@tonic-gate void
setnetent_p(int stayopen,struct net_data * net_data)2000Sstevel@tonic-gate setnetent_p(int stayopen, struct net_data *net_data) {
2010Sstevel@tonic-gate struct irs_nw *nw;
2020Sstevel@tonic-gate
2030Sstevel@tonic-gate if (!net_data || !(nw = net_data->nw))
2040Sstevel@tonic-gate return;
2050Sstevel@tonic-gate freepvt(net_data);
2060Sstevel@tonic-gate (*nw->rewind)(nw);
2070Sstevel@tonic-gate net_data->nw_stayopen = (stayopen != 0);
2080Sstevel@tonic-gate if (stayopen == 0)
2090Sstevel@tonic-gate net_data_minimize(net_data);
2100Sstevel@tonic-gate }
2110Sstevel@tonic-gate
2120Sstevel@tonic-gate void
endnetent_p(struct net_data * net_data)2130Sstevel@tonic-gate endnetent_p(struct net_data *net_data) {
2140Sstevel@tonic-gate struct irs_nw *nw;
2150Sstevel@tonic-gate
2160Sstevel@tonic-gate if ((net_data != NULL) && ((nw = net_data->nw) != NULL))
2170Sstevel@tonic-gate (*nw->minimize)(nw);
2180Sstevel@tonic-gate }
2190Sstevel@tonic-gate
2200Sstevel@tonic-gate /* Private */
2210Sstevel@tonic-gate
2220Sstevel@tonic-gate static struct net_data *
init()2230Sstevel@tonic-gate init() {
2240Sstevel@tonic-gate struct net_data *net_data;
2250Sstevel@tonic-gate
2260Sstevel@tonic-gate if (!(net_data = net_data_init(NULL)))
2270Sstevel@tonic-gate goto error;
2280Sstevel@tonic-gate if (!net_data->nw) {
2290Sstevel@tonic-gate net_data->nw = (*net_data->irs->nw_map)(net_data->irs);
2300Sstevel@tonic-gate
2310Sstevel@tonic-gate if (!net_data->nw || !net_data->res) {
2320Sstevel@tonic-gate error:
2330Sstevel@tonic-gate errno = EIO;
2340Sstevel@tonic-gate return (NULL);
2350Sstevel@tonic-gate }
2360Sstevel@tonic-gate (*net_data->nw->res_set)(net_data->nw, net_data->res, NULL);
2370Sstevel@tonic-gate }
2380Sstevel@tonic-gate
2390Sstevel@tonic-gate return (net_data);
2400Sstevel@tonic-gate }
2410Sstevel@tonic-gate
2420Sstevel@tonic-gate static void
freepvt(struct net_data * net_data)2430Sstevel@tonic-gate freepvt(struct net_data *net_data) {
2440Sstevel@tonic-gate if (net_data->nw_data) {
2450Sstevel@tonic-gate free(net_data->nw_data);
2460Sstevel@tonic-gate net_data->nw_data = NULL;
2470Sstevel@tonic-gate }
2480Sstevel@tonic-gate }
2490Sstevel@tonic-gate
2500Sstevel@tonic-gate static struct netent *
fakeaddr(const char * name,int af,struct net_data * net_data)2510Sstevel@tonic-gate fakeaddr(const char *name, int af, struct net_data *net_data) {
2520Sstevel@tonic-gate struct pvt *pvt;
2530Sstevel@tonic-gate const char *cp;
2540Sstevel@tonic-gate u_long tmp;
2550Sstevel@tonic-gate
2560Sstevel@tonic-gate if (af != AF_INET) {
2570Sstevel@tonic-gate /* XXX should support IPv6 some day */
2580Sstevel@tonic-gate errno = EAFNOSUPPORT;
2590Sstevel@tonic-gate RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL);
2600Sstevel@tonic-gate return (NULL);
2610Sstevel@tonic-gate }
2620Sstevel@tonic-gate if (!isascii((unsigned char)(name[0])) ||
2630Sstevel@tonic-gate !isdigit((unsigned char)(name[0])))
2640Sstevel@tonic-gate return (NULL);
2650Sstevel@tonic-gate for (cp = name; *cp; ++cp)
2660Sstevel@tonic-gate if (!isascii(*cp) || (!isdigit((unsigned char)*cp) && *cp != '.'))
2670Sstevel@tonic-gate return (NULL);
2680Sstevel@tonic-gate if (*--cp == '.')
2690Sstevel@tonic-gate return (NULL);
2700Sstevel@tonic-gate
2710Sstevel@tonic-gate /* All-numeric, no dot at the end. */
2720Sstevel@tonic-gate
2730Sstevel@tonic-gate tmp = inet_network(name);
2740Sstevel@tonic-gate if (tmp == INADDR_NONE) {
2750Sstevel@tonic-gate RES_SET_H_ERRNO(net_data->res, HOST_NOT_FOUND);
2760Sstevel@tonic-gate return (NULL);
2770Sstevel@tonic-gate }
2780Sstevel@tonic-gate
2790Sstevel@tonic-gate /* Valid network number specified.
2800Sstevel@tonic-gate * Fake up a netent as if we'd actually
2810Sstevel@tonic-gate * done a lookup.
2820Sstevel@tonic-gate */
2830Sstevel@tonic-gate freepvt(net_data);
2840Sstevel@tonic-gate net_data->nw_data = malloc(sizeof (struct pvt));
2850Sstevel@tonic-gate if (!net_data->nw_data) {
2860Sstevel@tonic-gate errno = ENOMEM;
2870Sstevel@tonic-gate RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL);
2880Sstevel@tonic-gate return (NULL);
2890Sstevel@tonic-gate }
2900Sstevel@tonic-gate pvt = net_data->nw_data;
2910Sstevel@tonic-gate
2920Sstevel@tonic-gate strncpy(pvt->name, name, MAXDNAME);
2930Sstevel@tonic-gate pvt->name[MAXDNAME] = '\0';
2940Sstevel@tonic-gate pvt->netent.n_name = pvt->name;
2950Sstevel@tonic-gate pvt->netent.n_addrtype = AF_INET;
2960Sstevel@tonic-gate pvt->netent.n_aliases = pvt->aliases;
2970Sstevel@tonic-gate pvt->aliases[0] = NULL;
2980Sstevel@tonic-gate pvt->netent.n_net = tmp;
2990Sstevel@tonic-gate
3000Sstevel@tonic-gate return (&pvt->netent);
3010Sstevel@tonic-gate }
3020Sstevel@tonic-gate
3030Sstevel@tonic-gate static struct netent *
nw_to_net(struct nwent * nwent,struct net_data * net_data)3040Sstevel@tonic-gate nw_to_net(struct nwent *nwent, struct net_data *net_data) {
3050Sstevel@tonic-gate struct pvt *pvt;
3060Sstevel@tonic-gate u_long addr = 0;
3070Sstevel@tonic-gate int i;
3080Sstevel@tonic-gate int msbyte;
3090Sstevel@tonic-gate
3100Sstevel@tonic-gate if (!nwent || nwent->n_addrtype != AF_INET)
3110Sstevel@tonic-gate return (NULL);
3120Sstevel@tonic-gate freepvt(net_data);
3130Sstevel@tonic-gate net_data->nw_data = malloc(sizeof (struct pvt));
3140Sstevel@tonic-gate if (!net_data->nw_data) {
3150Sstevel@tonic-gate errno = ENOMEM;
3160Sstevel@tonic-gate RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL);
3170Sstevel@tonic-gate return (NULL);
3180Sstevel@tonic-gate }
3190Sstevel@tonic-gate pvt = net_data->nw_data;
3200Sstevel@tonic-gate pvt->netent.n_name = nwent->n_name;
3210Sstevel@tonic-gate pvt->netent.n_aliases = nwent->n_aliases;
3220Sstevel@tonic-gate pvt->netent.n_addrtype = nwent->n_addrtype;
3230Sstevel@tonic-gate
324*11038SRao.Shoaib@Sun.COM /*%
3250Sstevel@tonic-gate * What this code does: Converts net addresses from network to host form.
3260Sstevel@tonic-gate *
3270Sstevel@tonic-gate * msbyte: the index of the most significant byte in the n_addr array.
3280Sstevel@tonic-gate *
3290Sstevel@tonic-gate * Shift bytes in significant order into addr. When all signicant
3300Sstevel@tonic-gate * bytes are in, zero out bits in the LSB that are not part of the network.
3310Sstevel@tonic-gate */
3320Sstevel@tonic-gate msbyte = nwent->n_length / 8 +
3330Sstevel@tonic-gate ((nwent->n_length % 8) != 0 ? 1 : 0) - 1;
3340Sstevel@tonic-gate for (i = 0; i <= msbyte; i++)
3350Sstevel@tonic-gate addr = (addr << 8) | ((unsigned char *)nwent->n_addr)[i];
3360Sstevel@tonic-gate i = (32 - nwent->n_length) % 8;
3370Sstevel@tonic-gate if (i != 0)
3380Sstevel@tonic-gate addr &= ~((1 << (i + 1)) - 1);
3390Sstevel@tonic-gate pvt->netent.n_net = addr;
3400Sstevel@tonic-gate return (&pvt->netent);
3410Sstevel@tonic-gate }
3420Sstevel@tonic-gate
3430Sstevel@tonic-gate #endif /*__BIND_NOSTATIC*/
344*11038SRao.Shoaib@Sun.COM
345*11038SRao.Shoaib@Sun.COM /*! \file */
346