2 * ++Copyright++ 1985, 1988, 1993
4 * Copyright (c) 1985, 1988, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
37 * Permission to use, copy, modify, and distribute this software for any
38 * purpose with or without fee is hereby granted, provided that the above
39 * copyright notice and this permission notice appear in all copies, and that
40 * the name of Digital Equipment Corporation not be used in advertising or
41 * publicity pertaining to distribution of the document or software without
42 * specific, written prior permission.
44 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
45 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
46 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
47 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
48 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
49 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
50 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
56 #if defined(LIBC_SCCS) && !defined(lint)
57 static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93";
58 static char rcsid[] = "$Id$";
59 #endif /* LIBC_SCCS and not lint */
61 #include <sys/param.h>
62 #include <sys/socket.h>
63 #include <netinet/in.h>
64 #include <arpa/inet.h>
65 #include <arpa/nameser.h>
78 #define MULTI_PTRS_ARE_ALIASES 1 /* XXX - experimental */
80 #if defined(BSD) && (BSD >= 199103)
83 # include "../conf/portability.h"
85 #if defined(USE_OPTIONS_H)
86 # include <../conf/options.h>
92 static const char AskedForGot[] =
93 "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
95 static char *h_addr_ptrs[MAXADDRS + 1];
97 static struct hostent host;
98 static char *host_aliases[MAXALIASES];
99 static char hostbuf[8*1024];
100 static struct in_addr host_addr;
101 static FILE *hostf = NULL;
102 static int stayopen = 0;
105 static void addrsort __P((char **, int));
109 #define MAXPACKET PACKETSZ
111 #define MAXPACKET 1024
116 u_char buf[MAXPACKET];
132 if (_res.options & RES_DEBUG) {
140 # define dprintf(msg, num) /*nada*/
143 static struct hostent *
144 getanswer(answer, anslen, qname, qclass, qtype)
145 const querybuf *answer;
150 register const HEADER *hp;
151 register const u_char *cp;
154 char *bp, **ap, **hap;
155 int type, class, buflen, ancount, qdcount;
156 int haveanswer, had_error;
158 char tbuf[MAXDNAME+1];
161 eom = answer->buf + anslen;
163 * find first satisfactory answer
166 ancount = ntohs(hp->ancount);
167 qdcount = ntohs(hp->qdcount);
169 buflen = sizeof hostbuf;
170 cp = answer->buf + HFIXEDSZ;
172 h_errno = NO_RECOVERY;
175 if ((n = dn_expand(answer->buf, eom, cp, bp, buflen)) < 0) {
176 h_errno = NO_RECOVERY;
181 /* res_send() has already verified that the query name is the
182 * same as the one we sent; this just gets the expanded name
183 * (i.e., with the succeeding search-domain tacked on).
185 n = strlen(bp) + 1; /* for the \0 */
189 /* The qname can be abbreviated, but h_name is now absolute. */
194 host.h_aliases = host_aliases;
197 #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */
198 host.h_addr_list = h_addr_ptrs;
202 while (ancount-- > 0 && cp < eom && !had_error) {
203 n = dn_expand(answer->buf, eom, cp, bp, buflen);
209 type = _getshort(cp);
210 cp += INT16SZ; /* type */
211 class = _getshort(cp);
212 cp += INT16SZ + INT32SZ; /* class, TTL */
214 cp += INT16SZ; /* len */
215 if (class != qclass) {
216 /* XXX - debug? syslog? */
218 continue; /* XXX - had_error++ ? */
220 if (qtype == T_A && type == T_CNAME) {
221 if (ap >= &host_aliases[MAXALIASES-1])
223 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
229 if (host.h_name && strcasecmp(host.h_name, bp) != 0) {
230 syslog(LOG_NOTICE|LOG_AUTH,
231 "gethostby*.getanswer: asked for \"%s\", got CNAME for \"%s\"",
233 continue; /* XXX - had_error++ ? */
237 n = strlen(bp) + 1; /* for the \0 */
240 /* Get canonical name. */
241 n = strlen(tbuf) + 1; /* for the \0 */
253 /* CNAME->PTR should not cause a log message. */
254 if (!(qtype == T_PTR && type == T_CNAME))
255 syslog(LOG_NOTICE|LOG_AUTH,
256 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
257 qname, p_class(qclass), p_type(qtype),
260 continue; /* XXX - had_error++ ? */
264 if (strcasecmp(qname, bp) != 0) {
265 syslog(LOG_NOTICE|LOG_AUTH,
266 AskedForGot, qname, bp);
268 continue; /* XXX - had_error++ ? */
270 n = dn_expand(answer->buf, eom, cp, bp, buflen);
275 #if MULTI_PTRS_ARE_ALIASES
279 else if (ap < &host_aliases[MAXALIASES-1])
284 n = strlen(bp) + 1; /* for the \0 */
291 h_errno = NETDB_SUCCESS;
295 if (strcasecmp(host.h_name, bp) != 0) {
296 syslog(LOG_NOTICE|LOG_AUTH,
297 AskedForGot, host.h_name, bp);
299 continue; /* XXX - had_error++ ? */
302 if (n != host.h_length) {
310 host.h_addrtype = (class == C_IN)
314 nn = strlen(bp) + 1; /* for the \0 */
319 bp += sizeof(align) - ((u_long)bp % sizeof(align));
321 if (bp + n >= &hostbuf[sizeof hostbuf]) {
322 dprintf("size (%d) too big\n", n);
326 if (hap >= &h_addr_ptrs[MAXADDRS-1]) {
328 dprintf("Too many addresses (%d)\n",
333 bcopy(cp, *hap++ = bp, n);
338 dprintf("Impossible condition (type=%d)\n", type);
339 h_errno = NO_RECOVERY;
348 # if defined(RESOLVSORT)
350 * Note: we sort even if host can take only one address
351 * in its return structures - should give it the "best"
352 * address in that case, not some random one
354 if (_res.nsort && haveanswer > 1 &&
355 qclass == C_IN && qtype == T_A)
356 addrsort(h_addr_ptrs, haveanswer);
357 # endif /*RESOLVSORT*/
358 #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */
361 host.h_addr = h_addr_ptrs[0];
364 n = strlen(qname) + 1; /* for the \0 */
368 h_errno = NETDB_SUCCESS;
381 register const char *cp;
383 extern struct hostent *_gethtbyname();
385 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
386 h_errno = NETDB_INTERNAL;
391 * if there aren't any dots, it could be a user-level alias.
392 * this is also done in res_query() since we are not the only
393 * function that looks up host names.
395 if (!strchr(name, '.') && (cp = __hostalias(name)))
399 * disallow names consisting only of digits/dots, unless
402 if (isdigit(name[0]))
403 for (cp = name;; ++cp) {
408 * All-numeric, no dot at the end.
409 * Fake up a hostent as if we'd actually
412 if (!inet_aton(name, &host_addr)) {
413 h_errno = HOST_NOT_FOUND;
416 strncpy(hostbuf, name, MAXDNAME);
417 hostbuf[MAXDNAME] = '\0';
418 host.h_name = hostbuf;
419 host.h_aliases = host_aliases;
420 host_aliases[0] = NULL;
421 host.h_addrtype = AF_INET;
422 host.h_length = INT32SZ;
423 h_addr_ptrs[0] = (char *)&host_addr;
424 h_addr_ptrs[1] = NULL;
425 #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */
426 host.h_addr_list = h_addr_ptrs;
428 host.h_addr = h_addr_ptrs[0];
430 h_errno = NETDB_SUCCESS;
433 if (!isdigit(*cp) && *cp != '.')
437 if ((n = res_search(name, C_IN, T_A, buf.buf, sizeof(buf))) < 0) {
438 dprintf("res_search failed (%d)\n", n);
439 if (errno == ECONNREFUSED)
440 return (_gethtbyname(name));
443 return (getanswer(&buf, n, name, C_IN, T_A));
447 gethostbyaddr(addr, len, type)
453 register struct hostent *hp;
454 char qbuf[MAXDNAME+1];
456 register struct hostent *rhp;
459 char hname2[MAXDNAME+1];
460 #endif /*SUNSECURITY*/
461 extern struct hostent *_gethtbyaddr();
463 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
464 h_errno = NETDB_INTERNAL;
467 if (type != AF_INET) {
468 errno = EAFNOSUPPORT;
469 h_errno = NETDB_INTERNAL;
472 (void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa",
473 ((unsigned)addr[3] & 0xff),
474 ((unsigned)addr[2] & 0xff),
475 ((unsigned)addr[1] & 0xff),
476 ((unsigned)addr[0] & 0xff));
477 n = res_query(qbuf, C_IN, T_PTR, (u_char *)buf.buf, sizeof buf.buf);
479 dprintf("res_query failed (%d)\n", n);
480 if (errno == ECONNREFUSED)
481 return (_gethtbyaddr(addr, len, type));
484 if (!(hp = getanswer(&buf, n, qbuf, C_IN, T_PTR)))
485 return (NULL); /* h_errno was set by getanswer() */
488 * turn off search as the name should be absolute,
489 * 'localhost' should be matched by defnames
491 strncpy(hname2, hp->h_name, MAXDNAME);
492 hname2[MAXDNAME] = '\0';
493 old_options = _res.options;
494 _res.options &= ~RES_DNSRCH;
495 _res.options |= RES_DEFNAMES;
496 if (!(rhp = gethostbyname(hname2))) {
497 syslog(LOG_NOTICE|LOG_AUTH,
498 "gethostbyaddr: No A record for %s (verifying [%s])",
499 hname2, inet_ntoa(*((struct in_addr *)addr)));
500 _res.options = old_options;
501 h_errno = HOST_NOT_FOUND;
504 _res.options = old_options;
505 for (haddr = rhp->h_addr_list; *haddr; haddr++)
506 if (!memcmp(*haddr, addr, INADDRSZ))
509 syslog(LOG_NOTICE|LOG_AUTH,
510 "gethostbyaddr: A record of %s != PTR record [%s]",
511 hname2, inet_ntoa(*((struct in_addr *)addr)));
512 h_errno = HOST_NOT_FOUND;
515 #endif /*SUNSECURITY*/
516 hp->h_addrtype = type;
518 h_addr_ptrs[0] = (char *)&host_addr;
519 h_addr_ptrs[1] = NULL;
520 host_addr = *(struct in_addr *)addr;
521 h_errno = NETDB_SUCCESS;
530 hostf = fopen(_PATH_HOSTS, "r" );
539 if (hostf && !stayopen) {
540 (void) fclose(hostf);
549 register char *cp, **q;
551 if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" ))) {
552 h_errno = NETDB_INTERNAL;
556 if (!(p = fgets(hostbuf, sizeof hostbuf, hostf))) {
557 h_errno = HOST_NOT_FOUND;
562 if (!(cp = strpbrk(p, "#\n")))
565 if (!(cp = strpbrk(p, " \t")))
568 /* THIS STUFF IS INTERNET SPECIFIC */
569 if (!inet_aton(p, &host_addr))
571 h_addr_ptrs[0] = (char *)&host_addr;
572 h_addr_ptrs[1] = NULL;
573 #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */
574 host.h_addr_list = h_addr_ptrs;
576 host.h_addr = h_addr_ptrs[0];
578 host.h_length = INT32SZ;
579 host.h_addrtype = AF_INET;
580 while (*cp == ' ' || *cp == '\t')
583 q = host.h_aliases = host_aliases;
584 if (cp = strpbrk(cp, " \t"))
587 if (*cp == ' ' || *cp == '\t') {
591 if (q < &host_aliases[MAXALIASES - 1])
593 if (cp = strpbrk(cp, " \t"))
597 h_errno = NETDB_SUCCESS;
605 register struct hostent *p;
609 while (p = _gethtent()) {
610 if (strcasecmp(p->h_name, name) == 0)
612 for (cp = p->h_aliases; *cp != 0; cp++)
613 if (strcasecmp(*cp, name) == 0)
622 _gethtbyaddr(addr, len, type)
626 register struct hostent *p;
629 while (p = _gethtent())
630 if (p->h_addrtype == type && !bcmp(p->h_addr, addr, len))
644 short aval[MAXADDRS];
648 for (i = 0; i < num; i++, p++) {
649 for (j = 0 ; (unsigned)j < _res.nsort; j++)
650 if (_res.sort_list[j].addr.s_addr ==
651 (((struct in_addr *)(*p))->s_addr & _res.sort_list[j].mask))
654 if (needsort == 0 && i > 0 && j < aval[i-1])
660 while (needsort < num) {
661 for (j = needsort - 1; j >= 0; j--) {
662 if (aval[j] > aval[j+1]) {
681 #if defined(BSD43_BSD43_NFS) || defined(sun)
682 /* some libc's out there are bound internally to these names (UMIPS) */
684 ht_sethostent(stayopen)
697 ht_gethostbyname(name)
700 return (_gethtbyname(name));
704 ht_gethostbyaddr(addr, len, type)
708 return (_gethtbyaddr(addr, len, type));
714 return (_gethtent());
724 dn_skipname(comp_dn, eom)
725 const u_char *comp_dn, *eom;
727 return (__dn_skipname(comp_dn, eom));
729 #endif /*old-style libc with yp junk in it*/
732 /* more icky libc packaging in ultrix */
734 local_hostname_length(hostname)
735 const char *hostname;
737 int len_host, len_domain;
741 len_host = strlen(hostname);
742 len_domain = strlen(_res.defdname);
743 if (len_host > len_domain &&
744 !strcasecmp(hostname + len_host - len_domain, _res.defdname) &&
745 hostname[len_host - len_domain - 1] == '.')
746 return (len_host - len_domain - 1);