1 /*- 2 * Copyright (c) 1985, 1988, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * - 33 * Portions Copyright (c) 1993 by Digital Equipment Corporation. 34 * 35 * Permission to use, copy, modify, and distribute this software for any 36 * purpose with or without fee is hereby granted, provided that the above 37 * copyright notice and this permission notice appear in all copies, and that 38 * the name of Digital Equipment Corporation not be used in advertising or 39 * publicity pertaining to distribution of the document or software without 40 * specific, written prior permission. 41 * 42 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL 43 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES 44 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT 45 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 46 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 47 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 48 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 49 * SOFTWARE. 50 * - 51 * --Copyright-- 52 */ 53 54 #if defined(LIBC_SCCS) && !defined(lint) 55 static char sccsid[] = "From: @(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93"; 56 /*static char rcsid[] = "From: Id: gethnamaddr.c,v 4.9.1.1 1993/05/02 22:43:03 vixie Rel ";*/ 57 static const char rcsid[] = 58 "$Id: gethostnamadr.c,v 1.2 1994/08/09 20:23:14 wollman Exp $"; 59 #endif /* LIBC_SCCS and not lint */ 60 61 #include <sys/param.h> 62 #include <sys/socket.h> 63 #include <netinet/in.h> 64 #include <arpa/inet.h> 65 #include <arpa/nameser.h> 66 #include <netdb.h> 67 #include <resolv.h> 68 #include <stdio.h> 69 #include <ctype.h> 70 #include <errno.h> 71 #include <string.h> 72 73 #define MAXALIASES 35 74 #define MAXADDRS 35 75 76 #define _PATH_HOSTCONF "/etc/host.conf" 77 78 enum service_type { 79 SERVICE_NONE = 0, 80 SERVICE_BIND, 81 SERVICE_HOSTS, 82 SERVICE_NIS }; 83 #define SERVICE_MAX SERVICE_NIS 84 85 static struct { 86 const char *name; 87 enum service_type type; 88 } service_names[] = { 89 { "hosts", SERVICE_HOSTS }, 90 { "/etc/hosts", SERVICE_HOSTS }, 91 { "hosttable", SERVICE_HOSTS }, 92 { "htable", SERVICE_HOSTS }, 93 { "bind", SERVICE_BIND }, 94 { "dns", SERVICE_BIND }, 95 { "domain", SERVICE_BIND }, 96 { "yp", SERVICE_NIS }, 97 { "yellowpages", SERVICE_NIS }, 98 { "nis", SERVICE_NIS }, 99 { 0, SERVICE_NONE } 100 }; 101 102 static enum service_type service_order[SERVICE_MAX + 1]; 103 static int service_done = 0; 104 105 static char *h_addr_ptrs[MAXADDRS + 1]; 106 107 static struct hostent host; 108 static char *host_aliases[MAXALIASES]; 109 static char hostbuf[BUFSIZ+1]; 110 static struct in_addr host_addr; 111 static FILE *hostf = NULL; 112 static char hostaddr[MAXADDRS]; 113 static char *host_addrs[2]; 114 static int stayopen = 0; 115 116 #if PACKETSZ > 1024 117 #define MAXPACKET PACKETSZ 118 #else 119 #define MAXPACKET 1024 120 #endif 121 122 typedef union { 123 HEADER hdr; 124 u_char buf[MAXPACKET]; 125 } querybuf; 126 127 typedef union { 128 int32_t al; 129 char ac; 130 } align; 131 132 extern int h_errno; 133 134 static enum service_type 135 get_service_name(const char *name) { 136 int i; 137 for(i = 0; service_names[i].type != SERVICE_NONE; i++) { 138 if(!strcasecmp(name, service_names[i].name)) { 139 return service_names[i].type; 140 } 141 } 142 return SERVICE_NONE; 143 } 144 145 static void 146 init_services() 147 { 148 char *cp, buf[BUFSIZ]; 149 register int cc = 0; 150 FILE *fd; 151 152 if ((fd = (FILE *)fopen(_PATH_HOSTCONF, "r")) == NULL) { 153 /* make some assumptions */ 154 service_order[0] = SERVICE_BIND; 155 service_order[1] = SERVICE_HOSTS; 156 service_order[2] = SERVICE_NONE; 157 } else { 158 while (fgets(buf, BUFSIZ, fd) != NULL && cc < SERVICE_MAX) { 159 if(buf[0] == '#') 160 continue; 161 162 cp = strtok(buf, "\n \t,:;"); 163 do { 164 if(!isalpha(cp[0])) continue; 165 service_order[cc] = get_service_name(buf); 166 if(service_order[cc] != SERVICE_NONE) 167 cc++; 168 } while((cp = strtok((char *)0, "\n \t,:;")) 169 && (cc < SERVICE_MAX)); 170 } 171 service_order[cc] = SERVICE_NONE; 172 fclose(fd); 173 } 174 service_done = 1; 175 } 176 177 static struct hostent * 178 getanswer(answer, anslen, iquery) 179 querybuf *answer; 180 int anslen; 181 int iquery; 182 { 183 register HEADER *hp; 184 register u_char *cp; 185 register int n; 186 u_char *eom; 187 char *bp, **ap; 188 int type, class, buflen, ancount, qdcount; 189 int haveanswer, getclass = C_ANY; 190 char **hap; 191 192 eom = answer->buf + anslen; 193 /* 194 * find first satisfactory answer 195 */ 196 hp = &answer->hdr; 197 ancount = ntohs(hp->ancount); 198 qdcount = ntohs(hp->qdcount); 199 bp = hostbuf; 200 buflen = sizeof(hostbuf); 201 cp = answer->buf + sizeof(HEADER); 202 if (qdcount) { 203 if (iquery) { 204 if ((n = dn_expand((u_char *)answer->buf, 205 (u_char *)eom, (u_char *)cp, (u_char *)bp, 206 buflen)) < 0) { 207 h_errno = NO_RECOVERY; 208 return ((struct hostent *) NULL); 209 } 210 cp += n + QFIXEDSZ; 211 host.h_name = bp; 212 n = strlen(bp) + 1; 213 bp += n; 214 buflen -= n; 215 } else 216 cp += __dn_skipname(cp, eom) + QFIXEDSZ; 217 while (--qdcount > 0) 218 cp += __dn_skipname(cp, eom) + QFIXEDSZ; 219 } else if (iquery) { 220 if (hp->aa) 221 h_errno = HOST_NOT_FOUND; 222 else 223 h_errno = TRY_AGAIN; 224 return ((struct hostent *) NULL); 225 } 226 ap = host_aliases; 227 *ap = NULL; 228 host.h_aliases = host_aliases; 229 hap = h_addr_ptrs; 230 *hap = NULL; 231 #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ 232 host.h_addr_list = h_addr_ptrs; 233 #endif 234 haveanswer = 0; 235 while (--ancount >= 0 && cp < eom) { 236 if ((n = dn_expand((u_char *)answer->buf, (u_char *)eom, 237 (u_char *)cp, (u_char *)bp, buflen)) < 0) 238 break; 239 cp += n; 240 type = _getshort(cp); 241 cp += sizeof(u_int16_t); 242 class = _getshort(cp); 243 cp += sizeof(u_int16_t) + sizeof(u_int32_t); 244 n = _getshort(cp); 245 cp += sizeof(u_int16_t); 246 if (type == T_CNAME) { 247 cp += n; 248 if (ap >= &host_aliases[MAXALIASES-1]) 249 continue; 250 *ap++ = bp; 251 n = strlen(bp) + 1; 252 bp += n; 253 buflen -= n; 254 continue; 255 } 256 if (iquery && type == T_PTR) { 257 if ((n = dn_expand((u_char *)answer->buf, 258 (u_char *)eom, (u_char *)cp, (u_char *)bp, 259 buflen)) < 0) 260 break; 261 cp += n; 262 host.h_name = bp; 263 return(&host); 264 } 265 if (iquery || type != T_A) { 266 #ifdef DEBUG 267 if (_res.options & RES_DEBUG) 268 printf("unexpected answer type %d, size %d\n", 269 type, n); 270 #endif 271 cp += n; 272 continue; 273 } 274 if (haveanswer) { 275 if (n != host.h_length) { 276 cp += n; 277 continue; 278 } 279 if (class != getclass) { 280 cp += n; 281 continue; 282 } 283 } else { 284 host.h_length = n; 285 getclass = class; 286 host.h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC; 287 if (!iquery) { 288 host.h_name = bp; 289 bp += strlen(bp) + 1; 290 } 291 } 292 293 bp += sizeof(align) - ((u_int32_t)bp % sizeof(align)); 294 295 if (bp + n >= &hostbuf[sizeof(hostbuf)]) { 296 #ifdef DEBUG 297 if (_res.options & RES_DEBUG) 298 printf("size (%d) too big\n", n); 299 #endif 300 break; 301 } 302 bcopy(cp, *hap++ = bp, n); 303 bp +=n; 304 cp += n; 305 haveanswer++; 306 } 307 if (haveanswer) { 308 *ap = NULL; 309 #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ 310 *hap = NULL; 311 #else 312 host.h_addr = h_addr_ptrs[0]; 313 #endif 314 return (&host); 315 } else { 316 h_errno = TRY_AGAIN; 317 return ((struct hostent *) NULL); 318 } 319 } 320 321 struct hostent * 322 _getdnsbyname(name) 323 const char *name; 324 { 325 querybuf buf; 326 register const char *cp; 327 int n; 328 extern struct hostent *_gethtbyname(); 329 330 /* 331 * disallow names consisting only of digits/dots, unless 332 * they end in a dot. 333 */ 334 if (isdigit(name[0])) 335 for (cp = name;; ++cp) { 336 if (!*cp) { 337 if (*--cp == '.') 338 break; 339 /* 340 * All-numeric, no dot at the end. 341 * Fake up a hostent as if we'd actually 342 * done a lookup. 343 */ 344 if (!inet_aton(name, &host_addr)) { 345 h_errno = HOST_NOT_FOUND; 346 return((struct hostent *) NULL); 347 } 348 host.h_name = (char *)name; 349 host.h_aliases = host_aliases; 350 host_aliases[0] = NULL; 351 host.h_addrtype = AF_INET; 352 host.h_length = sizeof(u_int32_t); 353 h_addr_ptrs[0] = (char *)&host_addr; 354 h_addr_ptrs[1] = (char *)0; 355 #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ 356 host.h_addr_list = h_addr_ptrs; 357 #else 358 host.h_addr = h_addr_ptrs[0]; 359 #endif 360 return (&host); 361 } 362 if (!isdigit(*cp) && *cp != '.') 363 break; 364 } 365 366 if ((n = res_search(name, C_IN, T_A, buf.buf, sizeof(buf))) < 0) { 367 #ifdef DEBUG 368 if (_res.options & RES_DEBUG) 369 printf("res_search failed\n"); 370 #endif 371 return ((struct hostent *) NULL); 372 } 373 return (getanswer(&buf, n, 0)); 374 } 375 376 struct hostent * 377 _getdnsbyaddr(addr, len, type) 378 const char *addr; 379 int len, type; 380 { 381 int n; 382 querybuf buf; 383 register struct hostent *hp; 384 char qbuf[MAXDNAME]; 385 extern struct hostent *_gethtbyaddr(); 386 387 if (type != AF_INET) 388 return ((struct hostent *) NULL); 389 (void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", 390 ((unsigned)addr[3] & 0xff), 391 ((unsigned)addr[2] & 0xff), 392 ((unsigned)addr[1] & 0xff), 393 ((unsigned)addr[0] & 0xff)); 394 n = res_query(qbuf, C_IN, T_PTR, (char *)&buf, sizeof(buf)); 395 if (n < 0) { 396 #ifdef DEBUG 397 if (_res.options & RES_DEBUG) 398 printf("res_query failed\n"); 399 #endif 400 return ((struct hostent *) NULL); 401 } 402 hp = getanswer(&buf, n, 1); 403 if (hp == NULL) 404 return ((struct hostent *) NULL); 405 hp->h_addrtype = type; 406 hp->h_length = len; 407 h_addr_ptrs[0] = (char *)&host_addr; 408 h_addr_ptrs[1] = (char *)0; 409 host_addr = *(struct in_addr *)addr; 410 #if BSD < 43 && !defined(h_addr) /* new-style hostent structure */ 411 hp->h_addr = h_addr_ptrs[0]; 412 #endif 413 return(hp); 414 } 415 416 void 417 _sethtent(f) 418 int f; 419 { 420 if (hostf == NULL) 421 hostf = fopen(_PATH_HOSTS, "r" ); 422 else 423 rewind(hostf); 424 stayopen |= f; 425 } 426 427 void 428 _endhtent() 429 { 430 if (hostf && !stayopen) { 431 (void) fclose(hostf); 432 hostf = NULL; 433 } 434 } 435 436 struct hostent * 437 _gethtent() 438 { 439 char *p; 440 register char *cp, **q; 441 442 if (hostf == NULL && (hostf = fopen(_PATH_HOSTS, "r" )) == NULL) 443 return (NULL); 444 again: 445 if ((p = fgets(hostbuf, BUFSIZ, hostf)) == NULL) 446 return (NULL); 447 if (*p == '#') 448 goto again; 449 cp = strpbrk(p, "#\n"); 450 if (cp == NULL) 451 goto again; 452 *cp = '\0'; 453 cp = strpbrk(p, " \t"); 454 if (cp == NULL) 455 goto again; 456 *cp++ = '\0'; 457 /* THIS STUFF IS INTERNET SPECIFIC */ 458 #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ 459 host.h_addr_list = host_addrs; 460 #endif 461 host.h_addr = hostaddr; 462 *((u_int32_t *)host.h_addr) = inet_addr(p); 463 host.h_length = sizeof (u_int32_t); 464 host.h_addrtype = AF_INET; 465 while (*cp == ' ' || *cp == '\t') 466 cp++; 467 host.h_name = cp; 468 q = host.h_aliases = host_aliases; 469 cp = strpbrk(cp, " \t"); 470 if (cp != NULL) 471 *cp++ = '\0'; 472 while (cp && *cp) { 473 if (*cp == ' ' || *cp == '\t') { 474 cp++; 475 continue; 476 } 477 if (q < &host_aliases[MAXALIASES - 1]) 478 *q++ = cp; 479 cp = strpbrk(cp, " \t"); 480 if (cp != NULL) 481 *cp++ = '\0'; 482 } 483 *q = NULL; 484 return (&host); 485 } 486 487 struct hostent * 488 _gethtbyname(name) 489 char *name; 490 { 491 register struct hostent *p; 492 register char **cp; 493 494 _sethtent(0); 495 while (p = _gethtent()) { 496 if (strcasecmp(p->h_name, name) == 0) 497 break; 498 for (cp = p->h_aliases; *cp != 0; cp++) 499 if (strcasecmp(*cp, name) == 0) 500 goto found; 501 } 502 found: 503 _endhtent(); 504 return (p); 505 } 506 507 struct hostent * 508 _gethtbyaddr(addr, len, type) 509 const char *addr; 510 int len, type; 511 { 512 register struct hostent *p; 513 514 _sethtent(0); 515 while (p = _gethtent()) 516 if (p->h_addrtype == type && !bcmp(p->h_addr, addr, len)) 517 break; 518 _endhtent(); 519 return (p); 520 } 521 522 523 #ifdef YP 524 struct hostent * 525 _getnishost(name, map) 526 char *name, *map; 527 { 528 register char *cp, *dp, **q; 529 char *result; 530 int resultlen; 531 static struct hostent h; 532 static char *domain = (char *)NULL; 533 534 if (domain == (char *)NULL) 535 if (yp_get_default_domain (&domain)) 536 return ((struct hostent *)NULL); 537 538 if (yp_match(domain, map, name, strlen(name), &result, &resultlen)) 539 return ((struct hostent *)NULL); 540 541 if (cp = index(result, '\n')) 542 *cp = '\0'; 543 544 cp = strpbrk(result, " \t"); 545 *cp++ = '\0'; 546 #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ 547 h.h_addr_list = host_addrs; 548 #endif 549 h.h_addr = hostaddr; 550 *((u_long *)h.h_addr) = inet_addr(result); 551 h.h_length = sizeof(u_long); 552 h.h_addrtype = AF_INET; 553 while (*cp == ' ' || *cp == '\t') 554 cp++; 555 h.h_name = cp; 556 q = h.h_aliases = host_aliases; 557 cp = strpbrk(cp, " \t"); 558 if (cp != NULL) 559 *cp++ = '\0'; 560 while (cp && *cp) { 561 if (*cp == ' ' || *cp == '\t') { 562 cp++; 563 continue; 564 } 565 if (q < &host_aliases[MAXALIASES - 1]) 566 *q++ = cp; 567 cp = strpbrk(cp, " \t"); 568 if (cp != NULL) 569 *cp++ = '\0'; 570 } 571 *q = NULL; 572 return (&h); 573 } 574 #endif /* YP */ 575 576 struct hostent * 577 gethostbyname(const char *name) 578 { 579 struct hostent *hp = 0; 580 int nserv = 0; 581 582 if(!service_done) { 583 init_services(); 584 } 585 586 while(!hp) { 587 switch(service_order[nserv]) { 588 case SERVICE_NONE: 589 return 0; 590 case SERVICE_HOSTS: 591 hp = _gethtbyname(name); 592 break; 593 case SERVICE_BIND: 594 hp = _getdnsbyname(name); 595 break; 596 case SERVICE_NIS: 597 #ifdef YP 598 hp = _getnishost(name, "hosts.byname"); 599 #endif 600 break; 601 } 602 nserv++; 603 } 604 return hp; 605 } 606 607 struct hostent * 608 gethostbyaddr(const char *addr, int len, int type) 609 { 610 struct hostent *hp = 0; 611 int nserv = 0; 612 613 if(!service_done) { 614 init_services(); 615 } 616 617 while(!hp) { 618 switch(service_order[nserv]) { 619 case SERVICE_NONE: 620 return 0; 621 case SERVICE_HOSTS: 622 hp = _gethtbyaddr(addr, len, type); 623 break; 624 case SERVICE_BIND: 625 hp = _getdnsbyname(addr, len, type); 626 break; 627 case SERVICE_NIS: 628 #ifdef YP 629 hp = _getnishost(addr, "hosts.byaddr"); 630 #endif 631 break; 632 } 633 nserv++; 634 } 635 return hp; 636 } 637 638