2 * Copyright (c) 1985, 1989
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
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
55 static char sccsid[] = "@(#)getinfo.c 5.26 (Berkeley) 3/21/91";
56 static char rcsid[] = "$Id: getinfo.c,v 8.11 1998/03/19 19:30:55 halley Exp $";
60 ******************************************************************************
64 * Routines to create requests to name servers
65 * and interpret the answers.
67 * Adapted from 4.3BSD BIND gethostnamadr.c
69 ******************************************************************************
72 #include "port_before.h"
74 #include <sys/param.h>
75 #include <sys/socket.h>
77 #include <netinet/in.h>
78 #include <arpa/nameser.h>
79 #include <arpa/inet.h>
86 #include "port_after.h"
90 extern char *_res_resultcodes[];
91 extern char *res_skip();
93 static char *addr_list[MAXADDRS + 1];
95 static char *host_aliases[MAXALIASES];
96 static int host_aliases_len[MAXALIASES];
97 static u_char hostbuf[MAXDNAME];
101 char *domain[MAXDOMAINS];
103 char *address[MAXADDRS];
107 ServerTable server[MAXSERVERS];
111 u_char qb2[PACKETSZ*2];
119 #define GetShort(cp) ns_get16(cp); cp += INT16SZ;
123 ******************************************************************************
127 * Interprets an answer packet and retrieves the following
131 * SUCCESS the info was retrieved.
132 * NO_INFO the packet did not contain an answer.
133 * NONAUTH non-authoritative information was found.
134 * ERROR the answer was malformed.
135 * Other errors returned in the packet header.
137 ******************************************************************************
141 GetAnswer(nsAddrPtr, queryType, msg, msglen, iquery, hostPtr, isServer)
142 struct in_addr *nsAddrPtr;
147 register HostInfo *hostPtr;
150 register HEADER *headerPtr;
159 int qdcount, ancount, arcount, nscount, buflen;
162 int numAddresses = 0;
169 Boolean printedAnswers = FALSE;
173 * If the hostPtr was used before, free up the calloc'd areas.
175 FreeHostInfoPtr(hostPtr);
177 status = SendRequest(nsAddrPtr, msg, msglen, (u_char *) &answer,
180 if (status != SUCCESS) {
181 if (_res.options & RES_DEBUG2)
182 printf("SendRequest failed\n");
185 eom = (u_char *) &answer + n;
187 headerPtr = (HEADER *) &answer;
189 if (headerPtr->rcode != NOERROR) {
190 return (headerPtr->rcode);
193 qdcount = ntohs(headerPtr->qdcount);
194 ancount = ntohs(headerPtr->ancount);
195 arcount = ntohs(headerPtr->arcount);
196 nscount = ntohs(headerPtr->nscount);
199 * If there are no answer, n.s. or additional records
200 * then return with an error.
202 if (ancount == 0 && nscount == 0 && arcount == 0) {
208 buflen = sizeof(hostbuf);
209 cp = (u_char *) &answer + HFIXEDSZ;
211 /* Skip over question section. */
212 while (qdcount-- > 0) {
213 n = dn_skipname(cp, eom);
221 aliasPtr = host_aliases;
226 * Scan through the answer resource records.
227 * Answers for address query types are saved.
228 * Other query type answers are just printed.
233 printf("Answer crypto-validated by server:\n");
235 if (!isServer && !headerPtr->aa) {
236 printf("Non-authoritative answer:\n");
239 if (queryType != T_A && !(iquery && queryType == T_PTR)) {
240 while (--ancount >= 0 && cp < eom) {
241 if ((cp = (u_char *)Print_rr(cp,
242 (u_char *)&answer, eom, stdout)) == NULL) {
246 printedAnswers = TRUE;
248 while (--ancount >= 0 && cp < eom) {
249 n = dn_expand(answer.qb2, eom, cp, (char *)bp, buflen);
253 if (cp + 3 * INT16SZ + INT32SZ > eom)
256 class = GetShort(cp);
257 cp += INT32SZ; /* skip TTL */
261 if (type == T_CNAME) {
266 if (aliasPtr >= &host_aliases[MAXALIASES-1]) {
269 *aliasPtr++ = (char *)bp;
270 n = strlen((char *)bp) + 1;
271 host_aliases_len[numAliases] = n;
276 } else if (type == T_PTR) {
278 * Found a "pointer" to the real name.
280 n = dn_expand(answer.qb2, eom, cp, (char *)bp, buflen);
286 len = strlen((char *)bp) + 1;
287 hostPtr->name = Calloc(1, len);
288 memcpy(hostPtr->name, bp, len);
291 } else if (type != T_A) {
295 if (dlen != INADDRSZ)
299 * If we've already got 1 address, we aren't interested
300 * in addresses with a different length or class.
302 if (dlen != hostPtr->addrLen) {
306 if (class != origClass) {
312 * First address: record its length and class so we
313 * only save additonal ones with the same attributes.
315 hostPtr->addrLen = dlen;
317 hostPtr->addrType = (class == C_IN) ? AF_INET : AF_UNSPEC;
318 len = strlen((char *)bp) + 1;
319 hostPtr->name = Calloc(1, len);
320 memcpy(hostPtr->name, bp, len);
322 bp += (((u_int32_t)bp) % sizeof(align));
324 if (bp + dlen >= &hostbuf[sizeof(hostbuf)]) {
325 if (_res.options & RES_DEBUG) {
326 printf("Size (%d) too big\n", dlen);
330 if (numAddresses >= MAXADDRS) {
331 printf("MAXADDRS exceeded: skipping address\n");
335 memcpy(*addrPtr++ = (char *)bp, cp, dlen);
344 if ((queryType == T_A || queryType == T_PTR) && haveAnswer) {
347 * Go through the alias and address lists and return them
348 * in the hostPtr variable.
351 if (numAliases > 0) {
353 (char **) Calloc(1 + numAliases, sizeof(char *));
354 for (i = 0; i < numAliases; i++) {
355 hostPtr->aliases[i] = Calloc(1, host_aliases_len[i]);
356 memcpy(hostPtr->aliases[i], host_aliases[i],
357 host_aliases_len[i]);
359 hostPtr->aliases[i] = NULL;
361 if (numAddresses > 0) {
363 (char **)Calloc(1+numAddresses, sizeof(char *));
364 for (i = 0; i < numAddresses; i++) {
365 hostPtr->addrList[i] = Calloc(1, hostPtr->addrLen);
366 memcpy(hostPtr->addrList[i], addr_list[i], hostPtr->addrLen);
368 hostPtr->addrList[i] = NULL;
371 if (headerPtr->aa || nscount == 0) {
372 hostPtr->servers = NULL;
376 hostPtr->servers = NULL;
382 * At this point, for the T_A query type, only empty answers remain.
383 * For other query types, additional information might be found
384 * in the additional resource records part.
387 if (!headerPtr->aa && (queryType != T_A) && (nscount > 0 || arcount > 0)) {
388 if (printedAnswers) {
391 printf("Authoritative answers can be found from:\n");
394 cp = (u_char *)res_skip((char *) &answer, 2, eom);
397 if (queryType != T_A) {
399 * If we don't need to save the record, just print it.
401 while (--nscount >= 0 && cp < eom) {
402 if ((cp = (u_char *)Print_rr(cp,
403 (u_char *) &answer, eom, stdout)) == NULL) {
408 while (--nscount >= 0 && cp < eom) {
410 * Go through the NS records and retrieve the names of hosts
411 * that serve the requested domain.
414 n = dn_expand(answer.qb2, eom, cp, (char *)bp, buflen);
419 len = strlen((char *)bp) + 1;
420 dnamePtr = Calloc(1, len); /* domain name */
421 memcpy(dnamePtr, bp, len);
423 if (cp + 3 * INT16SZ + INT32SZ > eom)
426 class = GetShort(cp);
427 cp += INT32SZ; /* skip TTL */
437 n = dn_expand(answer.qb2, eom, cp, (char *)bp, buflen);
442 len = strlen((char *)bp) + 1;
443 namePtr = Calloc(1, len); /* server host name */
444 memcpy(namePtr, bp, len);
447 * Store the information keyed by the server host name.
450 for (j = 0; j < numServers; j++) {
451 if (strcmp(namePtr, server[j].name) == 0) {
458 server[j].numDomains++;
459 if (server[j].numDomains <= MAXDOMAINS) {
460 server[j].domain[server[j].numDomains-1] = dnamePtr;
463 if (numServers >= MAXSERVERS) {
466 server[numServers].name = namePtr;
467 server[numServers].domain[0] = dnamePtr;
468 server[numServers].numDomains = 1;
469 server[numServers].numAddresses = 0;
477 * Additional resource records contain addresses of servers.
479 cp = (u_char *)res_skip((char *) &answer, 3, eom);
481 if (queryType != T_A) {
483 * If we don't need to save the record, just print it.
485 while (--arcount >= 0 && cp < eom) {
486 if ((cp = (u_char *)Print_rr(cp,
487 (u_char *) &answer, eom, stdout)) == NULL) {
492 while (--arcount >= 0 && cp < eom) {
493 n = dn_expand(answer.qb2, eom, cp, (char *)bp, buflen);
498 if (cp + 3 * INT16SZ + INT32SZ > eom)
501 class = GetShort(cp);
502 cp += INT32SZ; /* skip TTL */
511 if (dlen != INADDRSZ)
513 for (j = 0; j < numServers; j++) {
514 if (strcmp((char *)bp, server[j].name) == 0) {
515 server[j].numAddresses++;
516 if (server[j].numAddresses <= MAXADDRS) {
517 server[j].address[server[j].numAddresses-1] =
519 memcpy(server[j].address[server[j].numAddresses-1],
531 * If we are returning name server info, transfer it to the hostPtr.
533 if (numServers > 0) {
534 hostPtr->servers = (ServerInfo **)
535 Calloc(numServers+1, sizeof(ServerInfo *));
537 for (i = 0; i < numServers; i++) {
538 hostPtr->servers[i] = (ServerInfo *) Calloc(1, sizeof(ServerInfo));
539 hostPtr->servers[i]->name = server[i].name;
542 hostPtr->servers[i]->domains = (char **)
543 Calloc(server[i].numDomains+1,sizeof(char *));
544 for (j = 0; j < server[i].numDomains; j++) {
545 hostPtr->servers[i]->domains[j] = server[i].domain[j];
547 hostPtr->servers[i]->domains[j] = NULL;
550 hostPtr->servers[i]->addrList = (char **)
551 Calloc(server[i].numAddresses+1,sizeof(char *));
552 for (j = 0; j < server[i].numAddresses; j++) {
553 hostPtr->servers[i]->addrList[j] = server[i].address[j];
555 hostPtr->servers[i]->addrList[j] = NULL;
558 hostPtr->servers[i] = NULL;
574 *******************************************************************************
578 * Retrieves host name, address and alias information
581 * Algorithm from res_search().
584 * ERROR - res_mkquery failed.
585 * + return values from GetAnswer()
587 *******************************************************************************
591 GetHostInfoByName(nsAddrPtr, queryClass, queryType, name, hostPtr, isServer)
592 struct in_addr *nsAddrPtr;
601 register char **domain;
603 Boolean got_nodata = FALSE;
605 Boolean tried_as_is = FALSE;
607 /* Catch explicit addresses */
608 if ((queryType == T_A) && IsAddr(name, &ina)) {
609 hostPtr->name = Calloc(strlen(name)+3, 1);
610 (void)sprintf(hostPtr->name,"[%s]",name);
611 hostPtr->aliases = NULL;
612 hostPtr->servers = NULL;
613 hostPtr->addrType = AF_INET;
614 hostPtr->addrLen = INADDRSZ;
615 hostPtr->addrList = (char **)Calloc(2, sizeof(char *));
616 hostPtr->addrList[0] = Calloc(INT32SZ, sizeof(char));
617 memcpy(hostPtr->addrList[0], &ina, INADDRSZ);
618 hostPtr->addrList[1] = NULL;
623 for (cp = name, n = 0; *cp; cp++)
626 if (n == 0 && (cp = hostalias(name))) {
627 printf("Aliased to \"%s\"\n\n", cp);
628 return (GetHostDomain(nsAddrPtr, queryClass, queryType,
629 cp, (char *)NULL, hostPtr, isServer));
633 * If there are dots in the name already, let's just give it a try
634 * 'as is'. The threshold can be set with the "ndots" option.
636 if (n >= (int)_res.ndots) {
637 result = GetHostDomain(nsAddrPtr, queryClass, queryType,
638 name, (char *)NULL, hostPtr, isServer);
639 if (result == SUCCESS)
641 if (result == NO_INFO)
647 * We do at least one level of search if
648 * - there is no dot and RES_DEFNAME is set, or
649 * - there is at least one dot, there is no trailing dot,
650 * and RES_DNSRCH is set.
652 if ((n == 0 && _res.options & RES_DEFNAMES) ||
653 (n != 0 && *--cp != '.' && _res.options & RES_DNSRCH))
654 for (domain = _res.dnsrch; *domain; domain++) {
655 result = GetHostDomain(nsAddrPtr, queryClass, queryType,
656 name, *domain, hostPtr, isServer);
658 * If no server present, give up.
659 * If name isn't found in this domain,
660 * keep trying higher domains in the search list
661 * (if that's enabled).
662 * On a NO_INFO error, keep trying, otherwise
663 * a wildcard entry of another type could keep us
664 * from finding this entry higher in the domain.
665 * If we get some other error (negative answer or
666 * server failure), then stop searching up,
667 * but try the input name below in case it's fully-qualified.
669 if (result == SUCCESS || result == NO_RESPONSE)
671 if (result == NO_INFO)
673 if ((result != NXDOMAIN && result != NO_INFO) ||
674 (_res.options & RES_DNSRCH) == 0)
677 /* if we have not already tried the name "as is", do that now.
678 * note that we do this regardless of how many dots were in the
679 * name or whether it ends with a dot.
682 (result = GetHostDomain(nsAddrPtr, queryClass, queryType,
683 name, (char *)NULL, hostPtr, isServer)
692 * Perform a query on the concatenation of name and domain,
693 * removing a trailing dot from name if domain is NULL.
695 GetHostDomain(nsAddrPtr, queryClass, queryType, name, domain, hostPtr, isServer)
696 struct in_addr *nsAddrPtr;
704 char nbuf[2*MAXDNAME+2];
705 char *longname = nbuf;
708 if (domain == NULL) {
710 * Check for trailing '.';
711 * copy without '.' if present.
713 n = strlen(name) - 1;
714 if (name[n] == '.' && n < sizeof(nbuf) - 1) {
715 memcpy(nbuf, name, n);
720 (void)sprintf(nbuf, "%.*s.%.*s",
721 MAXDNAME, name, MAXDNAME, domain);
724 n = res_mkquery(QUERY, longname, queryClass, queryType,
725 NULL, 0, 0, buf.qb2, sizeof(buf));
727 if (_res.options & RES_DEBUG) {
728 printf("Res_mkquery failed\n");
733 n = GetAnswer(nsAddrPtr, queryType, (char *)&buf, n, 0, hostPtr, isServer);
736 * GetAnswer didn't find a name, so set it to the specified one.
739 if (hostPtr->name == NULL) {
740 int len = strlen(longname) + 1;
741 hostPtr->name = Calloc(len, sizeof(char));
742 memcpy(hostPtr->name, longname, len);
750 *******************************************************************************
752 * GetHostInfoByAddr --
754 * Performs a PTR lookup in in-addr.arpa to find the host name
755 * that corresponds to the given address.
758 * ERROR - res_mkquery failed.
759 * + return values from GetAnswer()
761 *******************************************************************************
765 GetHostInfoByAddr(nsAddrPtr, address, hostPtr)
766 struct in_addr *nsAddrPtr;
767 struct in_addr *address;
773 char *p = (char *) &address->s_addr;
775 (void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa",
776 ((unsigned)p[3] & 0xff),
777 ((unsigned)p[2] & 0xff),
778 ((unsigned)p[1] & 0xff),
779 ((unsigned)p[0] & 0xff));
780 n = res_mkquery(QUERY, qbuf, C_IN, T_PTR, NULL, 0, NULL,
781 buf.qb2, sizeof buf);
783 if (_res.options & RES_DEBUG) {
784 printf("res_mkquery() failed\n");
788 n = GetAnswer(nsAddrPtr, T_PTR, (char *) &buf, n, 1, hostPtr, 1);
790 hostPtr->addrType = AF_INET;
791 hostPtr->addrLen = 4;
792 hostPtr->addrList = (char **)Calloc(2, sizeof(char *));
793 hostPtr->addrList[0] = Calloc(INT32SZ, sizeof(char));
794 memcpy(hostPtr->addrList[0], p, INADDRSZ);
795 hostPtr->addrList[1] = NULL;
801 *******************************************************************************
805 * Deallocates all the calloc'd areas for a HostInfo variable.
807 *******************************************************************************
811 FreeHostInfoPtr(hostPtr)
812 register HostInfo *hostPtr;
816 if (hostPtr->name != NULL) {
818 hostPtr->name = NULL;
821 if (hostPtr->aliases != NULL) {
823 while (hostPtr->aliases[i] != NULL) {
824 free(hostPtr->aliases[i]);
827 free((char *)hostPtr->aliases);
828 hostPtr->aliases = NULL;
831 if (hostPtr->addrList != NULL) {
833 while (hostPtr->addrList[i] != NULL) {
834 free(hostPtr->addrList[i]);
837 free((char *)hostPtr->addrList);
838 hostPtr->addrList = NULL;
841 if (hostPtr->servers != NULL) {
843 while (hostPtr->servers[i] != NULL) {
845 if (hostPtr->servers[i]->name != NULL) {
846 free(hostPtr->servers[i]->name);
849 if (hostPtr->servers[i]->domains != NULL) {
851 while (hostPtr->servers[i]->domains[j] != NULL) {
852 free(hostPtr->servers[i]->domains[j]);
855 free((char *)hostPtr->servers[i]->domains);
858 if (hostPtr->servers[i]->addrList != NULL) {
860 while (hostPtr->servers[i]->addrList[j] != NULL) {
861 free(hostPtr->servers[i]->addrList[j]);
864 free((char *)hostPtr->servers[i]->addrList);
866 free((char *)hostPtr->servers[i]);
869 free((char *)hostPtr->servers);
870 hostPtr->servers = NULL;