1 /*- 2 * Copyright (c) 1985, 1988, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * - 7 * Portions Copyright (c) 1993 by Digital Equipment Corporation. 8 * 9 * Permission to use, copy, modify, and distribute this software for any 10 * purpose with or without fee is hereby granted, provided that the above 11 * copyright notice and this permission notice appear in all copies, and that 12 * the name of Digital Equipment Corporation not be used in advertising or 13 * publicity pertaining to distribution of the document or software without 14 * specific, written prior permission. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL 17 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT 19 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 20 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 21 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 22 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 23 * SOFTWARE. 24 * - 25 * --Copyright-- 26 */ 27 28 #if defined(LIBC_SCCS) && !defined(lint) 29 static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 06/04/93"; 30 static char rcsid[] = "$Id: gethnamaddr.c,v 4.9.1.1 1993/05/02 22:43:03 vixie Rel $"; 31 #endif /* LIBC_SCCS and not lint */ 32 33 #include <sys/param.h> 34 #include <sys/socket.h> 35 #include <netinet/in.h> 36 #include <arpa/inet.h> 37 #include <arpa/nameser.h> 38 #include <netdb.h> 39 #include <resolv.h> 40 #include <stdio.h> 41 #include <ctype.h> 42 #include <errno.h> 43 #include <string.h> 44 45 #define MAXALIASES 35 46 #define MAXADDRS 35 47 48 static char *h_addr_ptrs[MAXADDRS + 1]; 49 50 static struct hostent host; 51 static char *host_aliases[MAXALIASES]; 52 static char hostbuf[BUFSIZ+1]; 53 static struct in_addr host_addr; 54 static FILE *hostf = NULL; 55 static char hostaddr[MAXADDRS]; 56 static char *host_addrs[2]; 57 static int stayopen = 0; 58 char *strpbrk(); 59 60 #if PACKETSZ > 1024 61 #define MAXPACKET PACKETSZ 62 #else 63 #define MAXPACKET 1024 64 #endif 65 66 typedef union { 67 HEADER hdr; 68 u_char buf[MAXPACKET]; 69 } querybuf; 70 71 typedef union { 72 int32_t al; 73 char ac; 74 } align; 75 76 extern int h_errno; 77 78 static struct hostent * 79 getanswer(answer, anslen, iquery) 80 querybuf *answer; 81 int anslen; 82 int iquery; 83 { 84 register HEADER *hp; 85 register u_char *cp; 86 register int n; 87 u_char *eom; 88 char *bp, **ap; 89 int type, class, buflen, ancount, qdcount; 90 int haveanswer, getclass = C_ANY; 91 char **hap; 92 93 eom = answer->buf + anslen; 94 /* 95 * find first satisfactory answer 96 */ 97 hp = &answer->hdr; 98 ancount = ntohs(hp->ancount); 99 qdcount = ntohs(hp->qdcount); 100 bp = hostbuf; 101 buflen = sizeof(hostbuf); 102 cp = answer->buf + sizeof(HEADER); 103 if (qdcount) { 104 if (iquery) { 105 if ((n = dn_expand((u_char *)answer->buf, 106 (u_char *)eom, (u_char *)cp, (u_char *)bp, 107 buflen)) < 0) { 108 h_errno = NO_RECOVERY; 109 return ((struct hostent *) NULL); 110 } 111 cp += n + QFIXEDSZ; 112 host.h_name = bp; 113 n = strlen(bp) + 1; 114 bp += n; 115 buflen -= n; 116 } else 117 cp += __dn_skipname(cp, eom) + QFIXEDSZ; 118 while (--qdcount > 0) 119 cp += __dn_skipname(cp, eom) + QFIXEDSZ; 120 } else if (iquery) { 121 if (hp->aa) 122 h_errno = HOST_NOT_FOUND; 123 else 124 h_errno = TRY_AGAIN; 125 return ((struct hostent *) NULL); 126 } 127 ap = host_aliases; 128 *ap = NULL; 129 host.h_aliases = host_aliases; 130 hap = h_addr_ptrs; 131 *hap = NULL; 132 #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ 133 host.h_addr_list = h_addr_ptrs; 134 #endif 135 haveanswer = 0; 136 while (--ancount >= 0 && cp < eom) { 137 if ((n = dn_expand((u_char *)answer->buf, (u_char *)eom, 138 (u_char *)cp, (u_char *)bp, buflen)) < 0) 139 break; 140 cp += n; 141 type = _getshort(cp); 142 cp += sizeof(u_int16_t); 143 class = _getshort(cp); 144 cp += sizeof(u_int16_t) + sizeof(u_int32_t); 145 n = _getshort(cp); 146 cp += sizeof(u_int16_t); 147 if (type == T_CNAME) { 148 cp += n; 149 if (ap >= &host_aliases[MAXALIASES-1]) 150 continue; 151 *ap++ = bp; 152 n = strlen(bp) + 1; 153 bp += n; 154 buflen -= n; 155 continue; 156 } 157 if (iquery && type == T_PTR) { 158 if ((n = dn_expand((u_char *)answer->buf, 159 (u_char *)eom, (u_char *)cp, (u_char *)bp, 160 buflen)) < 0) 161 break; 162 cp += n; 163 host.h_name = bp; 164 return(&host); 165 } 166 if (iquery || type != T_A) { 167 #ifdef DEBUG 168 if (_res.options & RES_DEBUG) 169 printf("unexpected answer type %d, size %d\n", 170 type, n); 171 #endif 172 cp += n; 173 continue; 174 } 175 if (haveanswer) { 176 if (n != host.h_length) { 177 cp += n; 178 continue; 179 } 180 if (class != getclass) { 181 cp += n; 182 continue; 183 } 184 } else { 185 host.h_length = n; 186 getclass = class; 187 host.h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC; 188 if (!iquery) { 189 host.h_name = bp; 190 bp += strlen(bp) + 1; 191 } 192 } 193 194 bp += sizeof(align) - ((u_int32_t)bp % sizeof(align)); 195 196 if (bp + n >= &hostbuf[sizeof(hostbuf)]) { 197 #ifdef DEBUG 198 if (_res.options & RES_DEBUG) 199 printf("size (%d) too big\n", n); 200 #endif 201 break; 202 } 203 bcopy(cp, *hap++ = bp, n); 204 bp +=n; 205 cp += n; 206 haveanswer++; 207 } 208 if (haveanswer) { 209 *ap = NULL; 210 #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ 211 *hap = NULL; 212 #else 213 host.h_addr = h_addr_ptrs[0]; 214 #endif 215 return (&host); 216 } else { 217 h_errno = TRY_AGAIN; 218 return ((struct hostent *) NULL); 219 } 220 } 221 222 struct hostent * 223 gethostbyname(name) 224 const char *name; 225 { 226 querybuf buf; 227 register const char *cp; 228 int n; 229 extern struct hostent *_gethtbyname(); 230 231 /* 232 * disallow names consisting only of digits/dots, unless 233 * they end in a dot. 234 */ 235 if (isdigit(name[0])) 236 for (cp = name;; ++cp) { 237 if (!*cp) { 238 if (*--cp == '.') 239 break; 240 /* 241 * All-numeric, no dot at the end. 242 * Fake up a hostent as if we'd actually 243 * done a lookup. 244 */ 245 if (!inet_aton(name, &host_addr)) { 246 h_errno = HOST_NOT_FOUND; 247 return((struct hostent *) NULL); 248 } 249 host.h_name = (char *)name; 250 host.h_aliases = host_aliases; 251 host_aliases[0] = NULL; 252 host.h_addrtype = AF_INET; 253 host.h_length = sizeof(u_int32_t); 254 h_addr_ptrs[0] = (char *)&host_addr; 255 h_addr_ptrs[1] = (char *)0; 256 #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ 257 host.h_addr_list = h_addr_ptrs; 258 #else 259 host.h_addr = h_addr_ptrs[0]; 260 #endif 261 return (&host); 262 } 263 if (!isdigit(*cp) && *cp != '.') 264 break; 265 } 266 267 if ((n = res_search(name, C_IN, T_A, buf.buf, sizeof(buf))) < 0) { 268 #ifdef DEBUG 269 if (_res.options & RES_DEBUG) 270 printf("res_search failed\n"); 271 #endif 272 if (errno == ECONNREFUSED) 273 return (_gethtbyname(name)); 274 else 275 return ((struct hostent *) NULL); 276 } 277 return (getanswer(&buf, n, 0)); 278 } 279 280 struct hostent * 281 gethostbyaddr(addr, len, type) 282 const char *addr; 283 int len, type; 284 { 285 int n; 286 querybuf buf; 287 register struct hostent *hp; 288 char qbuf[MAXDNAME]; 289 extern struct hostent *_gethtbyaddr(); 290 291 if (type != AF_INET) 292 return ((struct hostent *) NULL); 293 (void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", 294 ((unsigned)addr[3] & 0xff), 295 ((unsigned)addr[2] & 0xff), 296 ((unsigned)addr[1] & 0xff), 297 ((unsigned)addr[0] & 0xff)); 298 n = res_query(qbuf, C_IN, T_PTR, (char *)&buf, sizeof(buf)); 299 if (n < 0) { 300 #ifdef DEBUG 301 if (_res.options & RES_DEBUG) 302 printf("res_query failed\n"); 303 #endif 304 if (errno == ECONNREFUSED) 305 return (_gethtbyaddr(addr, len, type)); 306 return ((struct hostent *) NULL); 307 } 308 hp = getanswer(&buf, n, 1); 309 if (hp == NULL) 310 return ((struct hostent *) NULL); 311 hp->h_addrtype = type; 312 hp->h_length = len; 313 h_addr_ptrs[0] = (char *)&host_addr; 314 h_addr_ptrs[1] = (char *)0; 315 host_addr = *(struct in_addr *)addr; 316 #if BSD < 43 && !defined(h_addr) /* new-style hostent structure */ 317 hp->h_addr = h_addr_ptrs[0]; 318 #endif 319 return(hp); 320 } 321 322 void 323 _sethtent(f) 324 int f; 325 { 326 if (hostf == NULL) 327 hostf = fopen(_PATH_HOSTS, "r" ); 328 else 329 rewind(hostf); 330 stayopen |= f; 331 } 332 333 void 334 _endhtent() 335 { 336 if (hostf && !stayopen) { 337 (void) fclose(hostf); 338 hostf = NULL; 339 } 340 } 341 342 struct hostent * 343 _gethtent() 344 { 345 char *p; 346 register char *cp, **q; 347 348 if (hostf == NULL && (hostf = fopen(_PATH_HOSTS, "r" )) == NULL) 349 return (NULL); 350 again: 351 if ((p = fgets(hostbuf, BUFSIZ, hostf)) == NULL) 352 return (NULL); 353 if (*p == '#') 354 goto again; 355 cp = strpbrk(p, "#\n"); 356 if (cp == NULL) 357 goto again; 358 *cp = '\0'; 359 cp = strpbrk(p, " \t"); 360 if (cp == NULL) 361 goto again; 362 *cp++ = '\0'; 363 /* THIS STUFF IS INTERNET SPECIFIC */ 364 #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ 365 host.h_addr_list = host_addrs; 366 #endif 367 host.h_addr = hostaddr; 368 *((u_int32_t *)host.h_addr) = inet_addr(p); 369 host.h_length = sizeof (u_int32_t); 370 host.h_addrtype = AF_INET; 371 while (*cp == ' ' || *cp == '\t') 372 cp++; 373 host.h_name = cp; 374 q = host.h_aliases = host_aliases; 375 cp = strpbrk(cp, " \t"); 376 if (cp != NULL) 377 *cp++ = '\0'; 378 while (cp && *cp) { 379 if (*cp == ' ' || *cp == '\t') { 380 cp++; 381 continue; 382 } 383 if (q < &host_aliases[MAXALIASES - 1]) 384 *q++ = cp; 385 cp = strpbrk(cp, " \t"); 386 if (cp != NULL) 387 *cp++ = '\0'; 388 } 389 *q = NULL; 390 return (&host); 391 } 392 393 struct hostent * 394 _gethtbyname(name) 395 char *name; 396 { 397 register struct hostent *p; 398 register char **cp; 399 400 _sethtent(0); 401 while (p = _gethtent()) { 402 if (strcasecmp(p->h_name, name) == 0) 403 break; 404 for (cp = p->h_aliases; *cp != 0; cp++) 405 if (strcasecmp(*cp, name) == 0) 406 goto found; 407 } 408 found: 409 _endhtent(); 410 return (p); 411 } 412 413 struct hostent * 414 _gethtbyaddr(addr, len, type) 415 const char *addr; 416 int len, type; 417 { 418 register struct hostent *p; 419 420 _sethtent(0); 421 while (p = _gethtent()) 422 if (p->h_addrtype == type && !bcmp(p->h_addr, addr, len)) 423 break; 424 _endhtent(); 425 return (p); 426 } 427