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