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