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