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[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93"; 56 static char rcsid[] = "$Id: gethostbydns.c,v 1.3 1994/12/01 22:25:38 wollman Exp $"; 57 #endif /* LIBC_SCCS and not lint */ 58 59 #include <sys/param.h> 60 #include <sys/socket.h> 61 #include <netinet/in.h> 62 #include <arpa/inet.h> 63 #include <arpa/nameser.h> 64 #include <netdb.h> 65 #include <resolv.h> 66 #include <stdio.h> 67 #include <ctype.h> 68 #include <errno.h> 69 #include <string.h> 70 #include <syslog.h> 71 72 #define BYADDR 0 73 #define BYNAME 1 74 75 #define MAXALIASES 35 76 #define MAXADDRS 35 77 78 #define MULTI_PTRS_ARE_ALIASES 1 /* XXX - experimental */ 79 80 static const char AskedForGot[] = 81 "gethostby*.gethostanswer: asked for \"%s\", got \"%s\""; 82 83 static char *h_addr_ptrs[MAXADDRS + 1]; 84 85 static struct hostent host; 86 static char *host_aliases[MAXALIASES]; 87 static char hostbuf[8*1024]; 88 static struct in_addr host_addr; 89 static FILE *hostf = NULL; 90 static char hostaddr[MAXADDRS]; 91 static char *host_addrs[2]; 92 static int stayopen = 0; 93 94 #if PACKETSZ > 1024 95 #define MAXPACKET PACKETSZ 96 #else 97 #define MAXPACKET 1024 98 #endif 99 100 typedef union { 101 HEADER hdr; 102 u_char buf[MAXPACKET]; 103 } querybuf; 104 105 typedef union { 106 int32_t al; 107 char ac; 108 } align; 109 110 extern int h_errno; 111 112 #ifdef RESOLVSORT 113 static void 114 addrsort(ap, num) 115 char **ap; 116 int num; 117 { 118 int i, j; 119 char **p; 120 short aval[MAXADDRS]; 121 int needsort = 0; 122 123 p = ap; 124 for (i = 0; i < num; i++, p++) { 125 for (j = 0 ; j < _res.nsort; j++) 126 if (_res.sort_list[j].addr.s_addr == 127 (((struct in_addr *)(*p))->s_addr & _res.sort_list[j].mask)) 128 break; 129 aval[i] = j; 130 if (needsort == 0 && i > 0 && j < aval[i-1]) 131 needsort = i; 132 } 133 if (!needsort) 134 return; 135 136 while (needsort < num) { 137 for (j = needsort - 1; j >= 0; j--) { 138 if (aval[j] > aval[j+1]) { 139 char *hp; 140 141 i = aval[j]; 142 aval[j] = aval[j+1]; 143 aval[j+1] = i; 144 145 hp = ap[j]; 146 ap[j] = ap[j+1]; 147 ap[j+1] = hp; 148 149 } else 150 break; 151 } 152 needsort++; 153 } 154 } 155 #endif 156 157 static struct hostent * 158 gethostanswer(answer, anslen, qname, qclass, qtype) 159 const querybuf *answer; 160 int anslen; 161 const char *qname; 162 int qclass, qtype; 163 { 164 register const HEADER *hp; 165 register const u_char *cp; 166 register int n; 167 const u_char *eom; 168 char *bp, **ap, **hap; 169 int type, class, buflen, ancount, qdcount; 170 int haveanswer, had_error; 171 int toobig = 0; 172 char tbuf[MAXDNAME+1]; 173 174 host.h_name = NULL; 175 eom = answer->buf + anslen; 176 /* 177 * find first satisfactory answer 178 */ 179 hp = &answer->hdr; 180 ancount = ntohs(hp->ancount); 181 qdcount = ntohs(hp->qdcount); 182 bp = hostbuf; 183 buflen = sizeof hostbuf; 184 cp = answer->buf + HFIXEDSZ; 185 if (qdcount != 1) { 186 h_errno = NO_RECOVERY; 187 return (NULL); 188 } 189 if ((n = dn_expand(answer->buf, eom, cp, bp, buflen)) < 0) { 190 h_errno = NO_RECOVERY; 191 return (NULL); 192 } 193 cp += n + QFIXEDSZ; 194 if (qtype == T_A) { 195 /* res_send() has already verified that the query name is the 196 * same as the one we sent; this just gets the expanded name 197 * (i.e., with the succeeding search-domain tacked on). 198 */ 199 n = strlen(bp) + 1; /* for the \0 */ 200 host.h_name = bp; 201 bp += n; 202 buflen -= n; 203 /* The qname can be abbreviated, but h_name is now absolute. */ 204 qname = host.h_name; 205 } 206 ap = host_aliases; 207 *ap = NULL; 208 host.h_aliases = host_aliases; 209 hap = h_addr_ptrs; 210 *hap = NULL; 211 host.h_addr_list = h_addr_ptrs; 212 haveanswer = 0; 213 had_error = 0; 214 while (ancount-- > 0 && cp < eom && !had_error) { 215 n = dn_expand(answer->buf, eom, cp, bp, buflen); 216 if (n < 0) { 217 had_error++; 218 continue; 219 } 220 cp += n; /* name */ 221 type = _getshort(cp); 222 cp += INT16SZ; /* type */ 223 class = _getshort(cp); 224 cp += INT16SZ + INT32SZ; /* class, TTL */ 225 n = _getshort(cp); 226 cp += INT16SZ; /* len */ 227 if (class != qclass) { 228 /* XXX - debug? syslog? */ 229 cp += n; 230 continue; /* XXX - had_error++ ? */ 231 } 232 if (qtype == T_A && type == T_CNAME) { 233 if (ap >= &host_aliases[MAXALIASES-1]) 234 continue; 235 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); 236 if (n < 0) { 237 had_error++; 238 continue; 239 } 240 cp += n; 241 if (host.h_name && strcasecmp(host.h_name, bp) != 0) { 242 syslog(LOG_NOTICE|LOG_AUTH, 243 "gethostby*.getanswer: asked for \"%s\", got CNAME for \"%s\"", 244 host.h_name, bp); 245 continue; /* XXX - had_error++ ? */ 246 } 247 /* Store alias. */ 248 *ap++ = bp; 249 n = strlen(bp) + 1; /* for the \0 */ 250 bp += n; 251 buflen -= n; 252 /* Get canonical name. */ 253 n = strlen(tbuf) + 1; /* for the \0 */ 254 if (n > buflen) { 255 had_error++; 256 continue; 257 } 258 strcpy(bp, tbuf); 259 host.h_name = bp; 260 bp += n; 261 buflen -= n; 262 continue; 263 } 264 if (type != qtype) { 265 syslog(LOG_NOTICE|LOG_AUTH, 266 "gethostby*.getanswer: asked for type %d(%s), got %d(%s)", 267 qtype, qname, type, bp); 268 cp += n; 269 continue; /* XXX - had_error++ ? */ 270 } 271 switch (type) { 272 case T_PTR: 273 if (strcasecmp(qname, bp) != 0) { 274 syslog(LOG_NOTICE|LOG_AUTH, 275 AskedForGot, qname, bp); 276 cp += n; 277 continue; /* XXX - had_error++ ? */ 278 } 279 n = dn_expand(answer->buf, eom, cp, bp, buflen); 280 if (n < 0) { 281 had_error++; 282 break; 283 } 284 #if MULTI_PTRS_ARE_ALIASES 285 cp += n; 286 if (!haveanswer) 287 host.h_name = bp; 288 else if (ap < &host_aliases[MAXALIASES-1]) 289 *ap++ = bp; 290 else 291 n = -1; 292 if (n != -1) { 293 n = strlen(bp) + 1; /* for the \0 */ 294 bp += n; 295 buflen -= n; 296 } 297 break; 298 #else 299 host.h_name = bp; 300 return (&host); 301 #endif 302 case T_A: 303 if (strcasecmp(host.h_name, bp) != 0) { 304 syslog(LOG_NOTICE|LOG_AUTH, 305 AskedForGot, host.h_name, bp); 306 cp += n; 307 continue; /* XXX - had_error++ ? */ 308 } 309 if (haveanswer) { 310 if (n != host.h_length) { 311 cp += n; 312 continue; 313 } 314 } else { 315 register int nn; 316 317 host.h_length = n; 318 host.h_addrtype = (class == C_IN) 319 ? AF_INET 320 : AF_UNSPEC; 321 host.h_name = bp; 322 nn = strlen(bp) + 1; /* for the \0 */ 323 bp += nn; 324 buflen -= nn; 325 } 326 327 bp += sizeof(align) - ((u_long)bp % sizeof(align)); 328 329 if (bp + n >= &hostbuf[sizeof hostbuf]) { 330 if (_res.options & RES_DEBUG) 331 printf("size (%d) too big\n", n); 332 had_error++; 333 continue; 334 } 335 if (hap >= &h_addr_ptrs[MAXADDRS-1]) { 336 if (_res.options & RES_DEBUG && !toobig++) 337 printf("Too many addresses (%d)\n", 338 MAXADDRS); 339 cp += n; 340 continue; 341 } 342 bcopy(cp, *hap++ = bp, n); 343 bp += n; 344 cp += n; 345 break; 346 default: 347 abort(); 348 } /*switch*/ 349 if (!had_error) 350 haveanswer++; 351 } /*while*/ 352 if (haveanswer) { 353 *ap = NULL; 354 *hap = NULL; 355 # if defined(RESOLVSORT) 356 /* 357 * Note: we sort even if host can take only one address 358 * in its return structures - should give it the "best" 359 * address in that case, not some random one 360 */ 361 if (_res.nsort && haveanswer > 1 && 362 qclass == C_IN && qtype == T_A) 363 addrsort(h_addr_ptrs, haveanswer); 364 # endif /*RESOLVSORT*/ 365 if (!host.h_name) { 366 n = strlen(qname) + 1; /* for the \0 */ 367 strcpy(bp, qname); 368 host.h_name = bp; 369 } 370 return (&host); 371 } else { 372 h_errno = TRY_AGAIN; 373 return (NULL); 374 } 375 } 376 377 struct hostent * 378 _gethostbydnsname(name) 379 const char *name; 380 { 381 querybuf buf; 382 register const char *cp; 383 int n; 384 385 /* 386 * disallow names consisting only of digits/dots, unless 387 * they end in a dot. 388 */ 389 if (isdigit(name[0])) 390 for (cp = name;; ++cp) { 391 if (!*cp) { 392 if (*--cp == '.') 393 break; 394 /* 395 * All-numeric, no dot at the end. 396 * Fake up a hostent as if we'd actually 397 * done a lookup. 398 */ 399 if (!inet_aton(name, &host_addr)) { 400 h_errno = HOST_NOT_FOUND; 401 return (NULL); 402 } 403 host.h_name = (char *)name; 404 host.h_aliases = host_aliases; 405 host_aliases[0] = NULL; 406 host.h_addrtype = AF_INET; 407 host.h_length = INT32SZ; 408 h_addr_ptrs[0] = (char *)&host_addr; 409 h_addr_ptrs[1] = NULL; 410 host.h_addr_list = h_addr_ptrs; 411 return (&host); 412 } 413 if (!isdigit(*cp) && *cp != '.') 414 break; 415 } 416 417 if ((n = res_search(name, C_IN, T_A, buf.buf, sizeof(buf))) < 0) { 418 if (_res.options & RES_DEBUG) 419 printf("res_search failed\n"); 420 return (NULL); 421 } 422 return (gethostanswer(&buf, n, name, C_IN, T_A)); 423 } 424 425 struct hostent * 426 _gethostbydnsaddr(addr, len, type) 427 const char *addr; 428 int len, type; 429 { 430 int n; 431 querybuf buf; 432 register struct hostent *hp; 433 char qbuf[MAXDNAME+1]; 434 int o_res_options = _res.options; 435 436 if (type != AF_INET) 437 return (NULL); 438 (void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", 439 ((unsigned)addr[3] & 0xff), 440 ((unsigned)addr[2] & 0xff), 441 ((unsigned)addr[1] & 0xff), 442 ((unsigned)addr[0] & 0xff)); 443 _res.options |= RES_RECURSE; 444 n = res_query(qbuf, C_IN, T_PTR, (u_char *)buf.buf, sizeof buf.buf); 445 _res.options = o_res_options; 446 if (n < 0) { 447 if (_res.options & RES_DEBUG) 448 printf("res_query failed\n"); 449 return (NULL); 450 } 451 if (!(hp = gethostanswer(&buf, n, qbuf, C_IN, T_PTR))) 452 return (NULL); 453 hp->h_addrtype = type; 454 hp->h_length = len; 455 h_addr_ptrs[0] = (char *)&host_addr; 456 h_addr_ptrs[1] = NULL; 457 host_addr = *(struct in_addr *)addr; 458 #if BSD < 43 && !defined(h_addr) /* new-style hostent structure */ 459 hp->h_addr = h_addr_ptrs[0]; 460 #endif 461 return (hp); 462 } 463 464 void 465 _sethostdnsent(stayopen) 466 int stayopen; 467 { 468 if (stayopen) 469 _res.options |= RES_STAYOPEN | RES_USEVC; 470 } 471 472 void 473 _endhostdnsent() 474 { 475 _res.options &= ~(RES_STAYOPEN | RES_USEVC); 476 _res_close(); 477 } 478