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