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