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.19 (Berkeley) 06/30/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 #else 144 host.h_addr = h_addr_ptrs[0]; 145 #endif 146 haveanswer = 0; 147 while (--ancount >= 0 && cp < eom) { 148 if ((n = dn_expand((char *)&answer, eom, cp, bp, buflen)) < 0) 149 break; 150 cp += n; 151 type = _getshort(cp); 152 cp += sizeof(u_short); 153 class = _getshort(cp); 154 cp += sizeof(u_short) + sizeof(u_long); 155 n = _getshort(cp); 156 cp += sizeof(u_short); 157 if (type == T_CNAME) { 158 cp += n; 159 if (ap >= &host_aliases[MAXALIASES-1]) 160 continue; 161 *ap++ = bp; 162 n = strlen(bp) + 1; 163 bp += n; 164 buflen -= n; 165 continue; 166 } 167 if (type == T_PTR) { 168 if ((n = dn_expand((char *)&answer, eom, 169 cp, bp, buflen)) < 0) { 170 cp += n; 171 continue; 172 } 173 cp += n; 174 host.h_name = bp; 175 return(&host); 176 } 177 if (type != T_A) { 178 #ifdef DEBUG 179 if (_res.options & RES_DEBUG) 180 printf("unexpected answer type %d, size %d\n", 181 type, n); 182 #endif 183 cp += n; 184 continue; 185 } 186 if (haveanswer) { 187 if (n != host.h_length) { 188 cp += n; 189 continue; 190 } 191 if (class != getclass) { 192 cp += n; 193 continue; 194 } 195 } else { 196 host.h_length = n; 197 getclass = class; 198 host.h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC; 199 if (!iquery) { 200 host.h_name = bp; 201 bp += strlen(bp) + 1; 202 } 203 } 204 205 bp += (sizeof(align) - ((u_long)bp % sizeof(align))) &~ 206 sizeof(align); 207 208 if (bp + n >= &hostbuf[sizeof(hostbuf)]) { 209 #ifdef DEBUG 210 if (_res.options & RES_DEBUG) 211 printf("size (%d) too big\n", n); 212 #endif 213 break; 214 } 215 bcopy(cp, *hap++ = bp, n); 216 bp +=n; 217 cp += n; 218 haveanswer++; 219 } 220 if (haveanswer) { 221 *ap = NULL; 222 *hap = NULL; 223 return (&host); 224 } else { 225 h_errno = TRY_AGAIN; 226 return (NULL); 227 } 228 } 229 230 struct hostent * 231 gethostbyname(name) 232 char *name; 233 { 234 register char *cp, **domain; 235 int n; 236 struct hostent *hp, *gethostdomain(); 237 char *hostalias(); 238 extern struct hostent *_gethtbyname(); 239 240 if (!(_res.options & RES_INIT) && res_init() == -1) 241 return (NULL); 242 errno = 0; 243 for (cp = name, n = 0; *cp; cp++) 244 if (*cp == '.') 245 n++; 246 if ((n && cp[-1] == '.') || (_res.options & RES_DEFNAMES) == 0) { 247 cp[-1] = 0; 248 hp = gethostdomain(name, (char *)NULL); 249 cp[-1] = '.'; 250 return (hp); 251 } 252 if (n == 0 && (cp = hostalias(name))) 253 return (gethostdomain(cp, (char *)NULL)); 254 for (domain = _res.dnsrch; *domain; domain++) { 255 hp = gethostdomain(name, *domain); 256 if (hp) 257 return (hp); 258 if (errno == ECONNREFUSED) 259 return (_gethtbyname(name)); 260 if (h_errno != HOST_NOT_FOUND || 261 (_res.options & RES_DNSRCH) == 0) 262 return (NULL); 263 h_errno = 0; 264 } 265 return (gethostdomain(name, (char *)NULL)); 266 } 267 268 static struct hostent * 269 gethostdomain(name, domain) 270 char *name, *domain; 271 { 272 querybuf buf; 273 char nbuf[2*MAXDNAME+2]; 274 int n; 275 276 sprintf(nbuf, "%.*s.%.*s", MAXDNAME, name, MAXDNAME, domain); 277 n = res_mkquery(QUERY, nbuf, C_IN, T_A, (char *)NULL, 0, NULL, 278 (char *)&buf, sizeof(buf)); 279 if (n < 0) { 280 #ifdef DEBUG 281 if (_res.options & RES_DEBUG) 282 printf("res_mkquery failed\n"); 283 #endif 284 return (NULL); 285 } 286 return (getanswer((char *)&buf, n, 0)); 287 } 288 289 struct hostent * 290 gethostbyaddr(addr, len, type) 291 char *addr; 292 int len, type; 293 { 294 int n; 295 querybuf buf; 296 register struct hostent *hp; 297 char qbuf[MAXDNAME]; 298 extern struct hostent *_gethtbyaddr(); 299 300 if (type != AF_INET) 301 return (NULL); 302 (void)sprintf(qbuf, "%d.%d.%d.%d.in-addr.arpa", 303 ((unsigned)addr[3] & 0xff), 304 ((unsigned)addr[2] & 0xff), 305 ((unsigned)addr[1] & 0xff), 306 ((unsigned)addr[0] & 0xff)); 307 n = res_mkquery(QUERY, qbuf, C_IN, T_PTR, (char *)NULL, 0, NULL, 308 (char *)&buf, sizeof(buf)); 309 if (n < 0) { 310 #ifdef DEBUG 311 if (_res.options & RES_DEBUG) 312 printf("res_mkquery failed\n"); 313 #endif 314 return (NULL); 315 } 316 hp = getanswer((char *)&buf, n, 1); 317 if (hp == NULL && errno == ECONNREFUSED) 318 hp = _gethtbyaddr(addr, len, type); 319 if (hp == NULL) 320 return(NULL); 321 hp->h_addrtype = type; 322 hp->h_length = len; 323 h_addr_ptrs[0] = (char *)&host_addr; 324 h_addr_ptrs[1] = (char *)0; 325 host_addr = *(struct in_addr *)addr; 326 return(hp); 327 } 328 329 char * 330 hostalias(name) 331 register char *name; 332 { 333 FILE *fp; 334 char *file, *getenv(); 335 static char abuf[MAXDNAME]; 336 char nbuf[MAXDNAME]; 337 int n; 338 339 file = getenv("HOSTALIASES"); 340 if (file == NULL || (fp = fopen(file, "r")) == NULL) 341 return (NULL); 342 while ((n = fscanf(fp, "%s %s\n", nbuf, abuf)) != EOF) 343 if (strcmp(nbuf, name) == 0) { 344 fclose(fp); 345 return (abuf); 346 } 347 fclose(fp); 348 return (NULL); 349 } 350 351 _sethtent(f) 352 int f; 353 { 354 if (hostf == NULL) 355 hostf = fopen(HOSTDB, "r" ); 356 else 357 rewind(hostf); 358 stayopen |= f; 359 } 360 361 _endhtent() 362 { 363 if (hostf && !stayopen) { 364 (void) fclose(hostf); 365 hostf = NULL; 366 } 367 } 368 369 struct hostent * 370 _gethtent() 371 { 372 char *p; 373 register char *cp, **q; 374 375 if (hostf == NULL && (hostf = fopen(HOSTDB, "r" )) == NULL) 376 return (NULL); 377 again: 378 if ((p = fgets(line, BUFSIZ, hostf)) == NULL) 379 return (NULL); 380 if (*p == '#') 381 goto again; 382 cp = any(p, "#\n"); 383 if (cp == NULL) 384 goto again; 385 *cp = '\0'; 386 cp = any(p, " \t"); 387 if (cp == NULL) 388 goto again; 389 *cp++ = '\0'; 390 /* THIS STUFF IS INTERNET SPECIFIC */ 391 #if BSD >= 43 392 host.h_addr_list = host_addrs; 393 #endif 394 host.h_addr = hostaddr; 395 *((u_long *)host.h_addr) = inet_addr(p); 396 host.h_length = sizeof (u_long); 397 host.h_addrtype = AF_INET; 398 while (*cp == ' ' || *cp == '\t') 399 cp++; 400 host.h_name = cp; 401 q = host.h_aliases = host_aliases; 402 cp = any(cp, " \t"); 403 if (cp != NULL) 404 *cp++ = '\0'; 405 while (cp && *cp) { 406 if (*cp == ' ' || *cp == '\t') { 407 cp++; 408 continue; 409 } 410 if (q < &host_aliases[MAXALIASES - 1]) 411 *q++ = cp; 412 cp = any(cp, " \t"); 413 if (cp != NULL) 414 *cp++ = '\0'; 415 } 416 *q = NULL; 417 return (&host); 418 } 419 420 static char * 421 any(cp, match) 422 register char *cp; 423 char *match; 424 { 425 register char *mp, c; 426 427 while (c = *cp) { 428 for (mp = match; *mp; mp++) 429 if (*mp == c) 430 return (cp); 431 cp++; 432 } 433 return ((char *)0); 434 } 435 436 struct hostent * 437 _gethtbyname(name) 438 char *name; 439 { 440 register struct hostent *p; 441 register char **cp; 442 char lowname[128]; 443 register char *lp = lowname; 444 445 while (*name) 446 if (isupper(*name)) 447 *lp++ = tolower(*name++); 448 else 449 *lp++ = *name++; 450 *lp = '\0'; 451 452 _sethtent(0); 453 while (p = _gethtent()) { 454 if (strcmp(p->h_name, lowname) == 0) 455 break; 456 for (cp = p->h_aliases; *cp != 0; cp++) 457 if (strcmp(*cp, lowname) == 0) 458 goto found; 459 } 460 found: 461 _endhtent(); 462 return (p); 463 } 464 465 struct hostent * 466 _gethtbyaddr(addr, len, type) 467 char *addr; 468 int len, type; 469 { 470 register struct hostent *p; 471 472 _sethtent(0); 473 while (p = _gethtent()) 474 if (p->h_addrtype == type && !bcmp(p->h_addr, addr, len)) 475 break; 476 _endhtent(); 477 return (p); 478 } 479