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