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