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