1 /* 2 * Copyright (c) 1985 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 */ 6 7 #if defined(LIBC_SCCS) && !defined(lint) 8 static char sccsid[] = "@(#)gethostnamadr.c 6.27 (Berkeley) 12/11/87"; 9 #endif LIBC_SCCS and not lint 10 11 #include <sys/param.h> 12 #include <sys/socket.h> 13 #include <netinet/in.h> 14 #include <ctype.h> 15 #include <netdb.h> 16 #include <stdio.h> 17 #include <errno.h> 18 #include <arpa/inet.h> 19 #include <arpa/nameser.h> 20 #include <resolv.h> 21 22 #define MAXALIASES 35 23 #define MAXADDRS 35 24 25 static char *h_addr_ptrs[MAXADDRS + 1]; 26 27 static struct hostent host; 28 static char *host_aliases[MAXALIASES]; 29 static char hostbuf[BUFSIZ+1]; 30 static struct in_addr host_addr; 31 static char HOSTDB[] = "/etc/hosts"; 32 static FILE *hostf = NULL; 33 static char line[BUFSIZ+1]; 34 static char hostaddr[MAXADDRS]; 35 static char *host_addrs[2]; 36 static int stayopen = 0; 37 static char *any(); 38 39 #if PACKETSZ > 1024 40 #define MAXPACKET PACKETSZ 41 #else 42 #define MAXPACKET 1024 43 #endif 44 45 typedef union { 46 HEADER qb1; 47 char qb2[MAXPACKET]; 48 } querybuf; 49 50 static union { 51 long al; 52 char ac; 53 } align; 54 55 56 int h_errno; 57 extern errno; 58 59 static struct hostent * 60 getanswer(msg, msglen, iquery) 61 char *msg; 62 int msglen, iquery; 63 { 64 register HEADER *hp; 65 register char *cp; 66 register int n; 67 querybuf answer; 68 char *eom, *bp, **ap; 69 int type, class, buflen, ancount, qdcount; 70 int haveanswer, getclass = C_ANY; 71 char **hap; 72 73 n = res_send(msg, msglen, (char *)&answer, sizeof(answer)); 74 if (n < 0) { 75 #ifdef DEBUG 76 int terrno; 77 terrno = errno; 78 if (_res.options & RES_DEBUG) 79 printf("res_send failed\n"); 80 errno = terrno; 81 #endif 82 h_errno = TRY_AGAIN; 83 return (NULL); 84 } 85 eom = (char *)&answer + n; 86 /* 87 * find first satisfactory answer 88 */ 89 hp = (HEADER *) &answer; 90 ancount = ntohs(hp->ancount); 91 qdcount = ntohs(hp->qdcount); 92 if (hp->rcode != NOERROR || ancount == 0) { 93 #ifdef DEBUG 94 if (_res.options & RES_DEBUG) 95 printf("rcode = %d, ancount=%d\n", hp->rcode, ancount); 96 #endif 97 switch (hp->rcode) { 98 case NXDOMAIN: 99 /* Check if it's an authoritive answer */ 100 if (hp->aa) 101 h_errno = HOST_NOT_FOUND; 102 else 103 h_errno = TRY_AGAIN; 104 break; 105 case SERVFAIL: 106 h_errno = TRY_AGAIN; 107 break; 108 case NOERROR: 109 if (hp->aa) 110 h_errno = NO_ADDRESS; 111 else 112 h_errno = TRY_AGAIN; 113 break; 114 case FORMERR: 115 case NOTIMP: 116 case REFUSED: 117 h_errno = NO_RECOVERY; 118 } 119 return (NULL); 120 } 121 bp = hostbuf; 122 buflen = sizeof(hostbuf); 123 cp = (char *)&answer + sizeof(HEADER); 124 if (qdcount) { 125 if (iquery) { 126 if ((n = dn_expand((char *)&answer, eom, 127 cp, bp, buflen)) < 0) { 128 h_errno = NO_RECOVERY; 129 return (NULL); 130 } 131 cp += n + QFIXEDSZ; 132 host.h_name = bp; 133 n = strlen(bp) + 1; 134 bp += n; 135 buflen -= n; 136 } else 137 cp += dn_skipname(cp, eom) + QFIXEDSZ; 138 while (--qdcount > 0) 139 cp += dn_skipname(cp, eom) + QFIXEDSZ; 140 } else if (iquery) { 141 if (hp->aa) 142 h_errno = HOST_NOT_FOUND; 143 else 144 h_errno = TRY_AGAIN; 145 return (NULL); 146 } 147 ap = host_aliases; 148 host.h_aliases = host_aliases; 149 hap = h_addr_ptrs; 150 #if BSD >= 43 151 host.h_addr_list = h_addr_ptrs; 152 #endif 153 haveanswer = 0; 154 while (--ancount >= 0 && cp < eom) { 155 if ((n = dn_expand((char *)&answer, eom, cp, bp, buflen)) < 0) 156 break; 157 cp += n; 158 type = _getshort(cp); 159 cp += sizeof(u_short); 160 class = _getshort(cp); 161 cp += sizeof(u_short) + sizeof(u_long); 162 n = _getshort(cp); 163 cp += sizeof(u_short); 164 if (type == T_CNAME) { 165 cp += n; 166 if (ap >= &host_aliases[MAXALIASES-1]) 167 continue; 168 *ap++ = bp; 169 n = strlen(bp) + 1; 170 bp += n; 171 buflen -= n; 172 continue; 173 } 174 if (type == T_PTR) { 175 if ((n = dn_expand((char *)&answer, eom, 176 cp, bp, buflen)) < 0) { 177 cp += n; 178 continue; 179 } 180 cp += n; 181 host.h_name = bp; 182 return(&host); 183 } 184 if (type != T_A) { 185 #ifdef DEBUG 186 if (_res.options & RES_DEBUG) 187 printf("unexpected answer type %d, size %d\n", 188 type, n); 189 #endif 190 cp += n; 191 continue; 192 } 193 if (haveanswer) { 194 if (n != host.h_length) { 195 cp += n; 196 continue; 197 } 198 if (class != getclass) { 199 cp += n; 200 continue; 201 } 202 } else { 203 host.h_length = n; 204 getclass = class; 205 host.h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC; 206 if (!iquery) { 207 host.h_name = bp; 208 bp += strlen(bp) + 1; 209 } 210 } 211 212 bp += sizeof(align) - ((u_long)bp % sizeof(align)); 213 214 if (bp + n >= &hostbuf[sizeof(hostbuf)]) { 215 #ifdef DEBUG 216 if (_res.options & RES_DEBUG) 217 printf("size (%d) too big\n", n); 218 #endif 219 break; 220 } 221 bcopy(cp, *hap++ = bp, n); 222 bp +=n; 223 cp += n; 224 haveanswer++; 225 } 226 if (haveanswer) { 227 *ap = NULL; 228 #if BSD >= 43 229 *hap = NULL; 230 #else 231 host.h_addr = h_addr_ptrs[0]; 232 #endif 233 return (&host); 234 } else { 235 h_errno = TRY_AGAIN; 236 return (NULL); 237 } 238 } 239 240 struct hostent * 241 gethostbyname(name) 242 char *name; 243 { 244 register char *cp, **domain; 245 int n; 246 struct hostent *hp, *gethostdomain(); 247 char *hostalias(); 248 extern struct hostent *_gethtbyname(); 249 250 if (!(_res.options & RES_INIT) && res_init() == -1) 251 return (NULL); 252 /* 253 * disallow names consisting only of digits/dots, unless 254 * they end in a dot. 255 */ 256 if (isdigit(name[0])) 257 for (cp = name;; ++cp) { 258 if (!*cp) { 259 if (*--cp == '.') 260 break; 261 h_errno = HOST_NOT_FOUND; 262 return (NULL); 263 } 264 if (!isdigit(*cp) && *cp != '.') 265 break; 266 } 267 errno = 0; 268 for (cp = name, n = 0; *cp; cp++) 269 if (*cp == '.') 270 n++; 271 if ((n && *--cp == '.') || (_res.options & RES_DEFNAMES) == 0) { 272 int defflag = _res.options & RES_DEFNAMES; 273 274 _res.options &= ~RES_DEFNAMES; /* XXX */ 275 if (n && *cp == '.') 276 *cp = '\0'; 277 hp = gethostdomain(name, (char *)NULL); 278 if (n && *cp == '\0') 279 *cp = '.'; 280 if (defflag) 281 _res.options |= RES_DEFNAMES; 282 return (hp); 283 } 284 if (n == 0 && (cp = hostalias(name))) 285 return (gethostdomain(cp, (char *)NULL)); 286 for (domain = _res.dnsrch; *domain; domain++) { 287 hp = gethostdomain(name, *domain); 288 if (hp) 289 return (hp); 290 /* 291 * If no server present, use host table. 292 * If host isn't found in this domain, 293 * keep trying higher domains in the search list 294 * (if that's enabled). 295 * On a NO_ADDRESS error, keep trying, 296 * or a wildcard MX entry could keep us from finding 297 * host entries higher in the domain. 298 */ 299 if (errno == ECONNREFUSED) 300 return (_gethtbyname(name)); 301 if ((h_errno != HOST_NOT_FOUND && 302 h_errno != NO_ADDRESS) || 303 (_res.options & RES_DNSRCH) == 0) 304 return (NULL); 305 h_errno = 0; 306 } 307 return (gethostdomain(name, (char *)NULL)); 308 } 309 310 static struct hostent * 311 gethostdomain(name, domain) 312 char *name, *domain; 313 { 314 querybuf buf; 315 char nbuf[2*MAXDNAME+2]; 316 int n; 317 318 if (domain == NULL) 319 (void)sprintf(nbuf, "%.*s", MAXDNAME, name); 320 else 321 (void)sprintf(nbuf, "%.*s.%.*s", 322 MAXDNAME, name, MAXDNAME, domain); 323 n = res_mkquery(QUERY, nbuf, C_IN, T_A, (char *)NULL, 0, NULL, 324 (char *)&buf, sizeof(buf)); 325 if (n < 0) { 326 #ifdef DEBUG 327 if (_res.options & RES_DEBUG) 328 printf("res_mkquery failed\n"); 329 #endif 330 return (NULL); 331 } 332 return (getanswer((char *)&buf, n, 0)); 333 } 334 335 struct hostent * 336 gethostbyaddr(addr, len, type) 337 char *addr; 338 int len, type; 339 { 340 int n; 341 querybuf buf; 342 register struct hostent *hp; 343 char qbuf[MAXDNAME]; 344 extern struct hostent *_gethtbyaddr(); 345 346 if (type != AF_INET) 347 return (NULL); 348 (void)sprintf(qbuf, "%d.%d.%d.%d.in-addr.arpa", 349 ((unsigned)addr[3] & 0xff), 350 ((unsigned)addr[2] & 0xff), 351 ((unsigned)addr[1] & 0xff), 352 ((unsigned)addr[0] & 0xff)); 353 n = res_mkquery(QUERY, qbuf, C_IN, T_PTR, (char *)NULL, 0, NULL, 354 (char *)&buf, sizeof(buf)); 355 if (n < 0) { 356 #ifdef DEBUG 357 if (_res.options & RES_DEBUG) 358 printf("res_mkquery failed\n"); 359 #endif 360 return (NULL); 361 } 362 hp = getanswer((char *)&buf, n, 1); 363 if (hp == NULL && errno == ECONNREFUSED) 364 hp = _gethtbyaddr(addr, len, type); 365 if (hp == NULL) 366 return(NULL); 367 hp->h_addrtype = type; 368 hp->h_length = len; 369 h_addr_ptrs[0] = (char *)&host_addr; 370 h_addr_ptrs[1] = (char *)0; 371 host_addr = *(struct in_addr *)addr; 372 return(hp); 373 } 374 375 char * 376 hostalias(name) 377 register char *name; 378 { 379 register char *C1, *C2; 380 FILE *fp; 381 char *file, *getenv(), *strcpy(), *strncpy(); 382 char buf[BUFSIZ]; 383 static char abuf[MAXDNAME]; 384 385 file = getenv("HOSTALIASES"); 386 if (file == NULL || (fp = fopen(file, "r")) == NULL) 387 return (NULL); 388 buf[sizeof(buf) - 1] = '\0'; 389 while (fgets(buf, sizeof(buf), fp)) { 390 for (C1 = buf; *C1 && !isspace(*C1); ++C1); 391 if (!*C1) 392 break; 393 *C1 = '\0'; 394 if (!strcasecmp(buf, name)) { 395 while (isspace(*++C1)); 396 if (!*C1) 397 break; 398 for (C2 = C1 + 1; *C2 && !isspace(*C2); ++C2); 399 abuf[sizeof(abuf) - 1] = *C2 = '\0'; 400 (void)strncpy(abuf, C1, sizeof(abuf) - 1); 401 fclose(fp); 402 return (abuf); 403 } 404 } 405 fclose(fp); 406 return (NULL); 407 } 408 409 _sethtent(f) 410 int f; 411 { 412 if (hostf == NULL) 413 hostf = fopen(HOSTDB, "r" ); 414 else 415 rewind(hostf); 416 stayopen |= f; 417 } 418 419 _endhtent() 420 { 421 if (hostf && !stayopen) { 422 (void) fclose(hostf); 423 hostf = NULL; 424 } 425 } 426 427 struct hostent * 428 _gethtent() 429 { 430 char *p; 431 register char *cp, **q; 432 433 if (hostf == NULL && (hostf = fopen(HOSTDB, "r" )) == NULL) 434 return (NULL); 435 again: 436 if ((p = fgets(line, BUFSIZ, hostf)) == NULL) 437 return (NULL); 438 if (*p == '#') 439 goto again; 440 cp = any(p, "#\n"); 441 if (cp == NULL) 442 goto again; 443 *cp = '\0'; 444 cp = any(p, " \t"); 445 if (cp == NULL) 446 goto again; 447 *cp++ = '\0'; 448 /* THIS STUFF IS INTERNET SPECIFIC */ 449 #if BSD >= 43 450 host.h_addr_list = host_addrs; 451 #endif 452 host.h_addr = hostaddr; 453 *((u_long *)host.h_addr) = inet_addr(p); 454 host.h_length = sizeof (u_long); 455 host.h_addrtype = AF_INET; 456 while (*cp == ' ' || *cp == '\t') 457 cp++; 458 host.h_name = cp; 459 q = host.h_aliases = host_aliases; 460 cp = any(cp, " \t"); 461 if (cp != NULL) 462 *cp++ = '\0'; 463 while (cp && *cp) { 464 if (*cp == ' ' || *cp == '\t') { 465 cp++; 466 continue; 467 } 468 if (q < &host_aliases[MAXALIASES - 1]) 469 *q++ = cp; 470 cp = any(cp, " \t"); 471 if (cp != NULL) 472 *cp++ = '\0'; 473 } 474 *q = NULL; 475 return (&host); 476 } 477 478 static char * 479 any(cp, match) 480 register char *cp; 481 char *match; 482 { 483 register char *mp, c; 484 485 while (c = *cp) { 486 for (mp = match; *mp; mp++) 487 if (*mp == c) 488 return (cp); 489 cp++; 490 } 491 return ((char *)0); 492 } 493 494 struct hostent * 495 _gethtbyname(name) 496 char *name; 497 { 498 register struct hostent *p; 499 register char **cp; 500 501 _sethtent(0); 502 while (p = _gethtent()) { 503 if (strcasecmp(p->h_name, name) == 0) 504 break; 505 for (cp = p->h_aliases; *cp != 0; cp++) 506 if (strcasecmp(*cp, name) == 0) 507 goto found; 508 } 509 found: 510 _endhtent(); 511 return (p); 512 } 513 514 struct hostent * 515 _gethtbyaddr(addr, len, type) 516 char *addr; 517 int len, type; 518 { 519 register struct hostent *p; 520 521 _sethtent(0); 522 while (p = _gethtent()) 523 if (p->h_addrtype == type && !bcmp(p->h_addr, addr, len)) 524 break; 525 _endhtent(); 526 return (p); 527 } 528