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