1/* $NetBSD$ */ 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) 21static 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 53struct pvt { 54 struct netent netent; 55 char * aliases[1]; 56 char name[MAXDNAME + 1]; 57}; 58 59/* Forward */ 60 61static struct net_data *init(void); 62static struct netent *nw_to_net(struct nwent *, struct net_data *); 63static void freepvt(struct net_data *); 64static 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 74struct netent * 75getnetent() { 76 struct net_data *net_data = init(); 77 78 return (getnetent_p(net_data)); 79} 80 81struct netent * 82getnetbyname(const char *name) { 83 struct net_data *net_data = init(); 84 85 return (getnetbyname_p(name, net_data)); 86} 87 88struct netent * 89getnetbyaddr(unsigned long net, int type) { 90 struct net_data *net_data = init(); 91 92 return (getnetbyaddr_p(net, type, net_data)); 93} 94 95void 96setnetent(int stayopen) { 97 struct net_data *net_data = init(); 98 99 setnetent_p(stayopen, net_data); 100} 101 102 103void 104endnetent() { 105 struct net_data *net_data = init(); 106 107 endnetent_p(net_data); 108} 109 110/* Shared private. */ 111 112struct netent * 113getnetent_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 123struct netent * 124getnetbyname_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 147struct netent * 148getnetbyaddr_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 201void 202setnetent_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 214void 215endnetent_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 224static struct net_data * 225init() { 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 244static void 245freepvt(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 252static struct netent * 253fakeaddr(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 305static struct netent * 306nw_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