home *** CD-ROM | disk | FTP | other *** search
/ PC-Online 1996 May / PCOnline_05_1996.bin / linux / source / n / bind / bind-4.001 / bind-4~ / bind-4.9.3-BETA9 / tools / host.c < prev    next >
C/C++ Source or Header  |  1994-07-19  |  34KB  |  1,459 lines

  1. /*
  2.  * ++Copyright++ 1986
  3.  * -
  4.  * Copyright (c) 1986
  5.  *    The Regents of the University of California.  All rights reserved.
  6.  * 
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions
  9.  * are met:
  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.
  22.  * 
  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
  33.  * SUCH DAMAGE.
  34.  * -
  35.  * Portions Copyright (c) 1993 by Digital Equipment Corporation.
  36.  * 
  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.
  43.  * 
  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
  51.  * SOFTWARE.
  52.  * -
  53.  * --Copyright--
  54.  */
  55.  
  56. #ifndef lint
  57. char copyright[] =
  58. "@(#) Copyright (c) 1986 Regents of the University of California.\n\
  59.  portions Copyright (c) 1993 Digital Equipment Corporation\n\
  60.  All rights reserved.\n";
  61. #endif /* not lint */
  62.  
  63. /*
  64.  * Actually, this program is from Rutgers University, however it is 
  65.  * based on nslookup and other pieces of named tools, so it needs
  66.  * that copyright notice.
  67.  */
  68.  
  69. #ifndef lint
  70. static char rcsid[] = "$Id: host.c,v 4.9.1.13 1994/07/19 22:51:24 vixie Exp $";
  71. #endif /* not lint */
  72.  
  73. #include <sys/types.h>
  74. #include <sys/param.h>
  75. #include <sys/socket.h>
  76.  
  77. #include <netinet/in.h>
  78. #include <arpa/inet.h>
  79. #include <arpa/nameser.h>
  80.  
  81. #include <stdio.h>
  82. #include <netdb.h>
  83. #include <resolv.h>
  84. #include <ctype.h>
  85.  
  86. #include "../conf/portability.h"
  87.  
  88. extern int h_errno;
  89.  
  90. #define NUMMX 50
  91.  
  92. #define  SUCCESS        0
  93. #define  TIME_OUT        -1
  94. #define  NO_INFO         -2
  95. #define  ERROR             -3
  96. #define  NONAUTH         -4
  97.  
  98. #define NAME_LEN 256
  99.  
  100. #ifndef T_TXT
  101. #define T_TXT 16
  102. #endif
  103. #ifndef NO_DATA
  104. #define NO_DATA NO_ADDRESS
  105. #endif
  106. #ifndef C_HS
  107. #define C_HS 4
  108. #endif
  109.  
  110. int sockFD;
  111. FILE *filePtr;
  112. char *DecodeError();
  113.  
  114. static struct __res_state orig;
  115. extern struct __res_state _res;
  116. static char *cname = NULL;
  117. int getclass = C_IN;
  118. int gettype;
  119. int verbose = 0;
  120. int list = 0;
  121. int server_specified = 0;
  122.  
  123. u_char *pr_cdname();
  124. char *pr_class(), *pr_rr(), *pr_type();
  125. extern char *hostalias();
  126.  
  127. main(c, v)
  128.     char **v;
  129. {
  130.     unsigned addr;
  131.     register struct hostent *hp;
  132.     register char *s;
  133.     register inverse = 0;
  134.     register waitmode = 0;
  135.     char *oldcname;
  136.     int ncnames;
  137.  
  138.     res_init();
  139.     _res.retrans = 5;
  140.  
  141.     if (c < 2) {
  142.         fprintf(stderr, "Usage: host [-w] [-v] [-r] [-d] [-t querytype] [-c class] [-a] host [server]\n  -w to wait forever until reply\n  -v for verbose output\n  -r to disable recursive processing\n  -d to turn on debugging output\n  -t querytype to look for a specific type of information\n  -c class to look for non-Internet data\n  -a is equivalent to '-v -t *'\n");
  143.         exit(1);
  144.     }
  145.     while (c > 2 && v[1][0] == '-') {
  146.         if (strcmp (v[1], "-w") == 0) {
  147.             _res.retry = 1;
  148.             _res.retrans = 15;
  149.             waitmode = 1;
  150.             v++;
  151.             c--;
  152.         }
  153.         else if (strcmp (v[1], "-r") == 0) {
  154.             _res.options &= ~RES_RECURSE;
  155.             v++;
  156.             c--;
  157.         }
  158.         else if (strcmp (v[1], "-d") == 0) {
  159.             _res.options |= RES_DEBUG;
  160.             v++;
  161.             c--;
  162.         }
  163.         else if (strcmp (v[1], "-v") == 0) {
  164.             verbose = 1;
  165.             v++;
  166.             c--;
  167.         }
  168.         else if (strcmp (v[1], "-l") == 0) {
  169.             list = 1;
  170.             v++;
  171.             c--;
  172.         }
  173.         else if (strncmp (v[1], "-t", 2) == 0) {
  174.             v++;
  175.             c--;
  176.             gettype = parsetype(v[1]);
  177.             v++;
  178.             c--;
  179.         }
  180.         else if (strncmp (v[1], "-c", 2) == 0) {
  181.             v++;
  182.             c--;
  183.             getclass = parseclass(v[1]);
  184.             v++;
  185.             c--;
  186.         }
  187.         else if (strcmp (v[1], "-a") == 0) {
  188.             verbose = 1;
  189.             gettype = T_ANY;
  190.             v++;
  191.             c--;
  192.         }        
  193.         }
  194.     if (c > 2) {
  195.         s = v[2];
  196.         server_specified++;
  197.         
  198.         if (!inet_aton(s, (struct in_addr *)&addr)) {
  199.           hp = gethostbyname(s);
  200.           if (hp == NULL) {
  201.             fprintf(stderr,"Error in looking up server name:\n");
  202.             hperror(h_errno);
  203.             exit(1);
  204.           }
  205.           _res.nsaddr.sin_addr = *(struct in_addr *)hp->h_addr;
  206.           printf("Using domain server:\n");
  207.           printanswer(hp);
  208.         }
  209.         else {
  210.           _res.nsaddr.sin_family = AF_INET;
  211.           _res.nsaddr.sin_addr.s_addr = addr;
  212.           _res.nsaddr.sin_port = htons(NAMESERVER_PORT);
  213.           printf("Using domain server %s:\n",
  214.              inet_ntoa(_res.nsaddr.sin_addr));
  215.         }
  216.         _res.nscount = 1;
  217.         _res.retry = 2;
  218.           }
  219.     if (strcmp (v[1], ".") == 0 ||
  220.         !inet_aton(v[1], (struct in_addr *)&addr))
  221.         addr = -1;
  222.     hp = NULL;
  223.     h_errno = TRY_AGAIN;
  224. /*
  225.  * we handle default domains ourselves, thank you
  226.  */
  227.     _res.options &= ~RES_DEFNAMES;
  228.  
  229.         if (list)
  230.       exit(ListHosts(v[1], gettype ? gettype : T_A));
  231.     oldcname = NULL;
  232.     ncnames = 5;
  233.     while (hp == NULL && h_errno == TRY_AGAIN) {
  234.       if (addr == -1) {
  235.           cname = NULL;
  236.           if (oldcname == NULL)
  237.         hp = (struct hostent *)gethostinfo(v[1]);
  238.           else
  239.         hp = (struct hostent *)gethostinfo(oldcname);
  240.           if (cname) {
  241.         if (ncnames-- == 0) {
  242.           printf("Too many cnames.  Possible loop.\n");
  243.           exit(1);
  244.         }
  245.         oldcname = cname;
  246.         hp = NULL;
  247.         h_errno = TRY_AGAIN;
  248.         continue;
  249.           }
  250.       }
  251.       else {
  252.         hp = gethostbyaddr((char*)&addr, 4, AF_INET);
  253.         if (hp)
  254.           printanswer(hp);
  255.       }
  256.       if (!waitmode)
  257.         break;
  258.     }
  259.  
  260.     if (hp == NULL) {
  261.       hperror(h_errno);
  262.       exit(1);
  263.     }
  264.  
  265.     exit(0);
  266.  
  267. }
  268.  
  269. parsetype(s)
  270.     char *s;
  271. {
  272. if (strcmp(s,"a") == 0)
  273.   return(T_A);
  274. if (strcmp(s,"ns") == 0)
  275.   return(T_NS);
  276. if (strcmp(s,"md") == 0)
  277.   return(T_MD);
  278. if (strcmp(s,"mf") == 0)
  279.   return(T_MF);
  280. if (strcmp(s,"cname") == 0)
  281.   return(T_CNAME);
  282. if (strcmp(s,"soa") == 0)
  283.   return(T_SOA);
  284. if (strcmp(s,"mb") == 0)
  285.   return(T_MB);
  286. if (strcmp(s,"mg") == 0)
  287.   return(T_MG);
  288. if (strcmp(s,"mr") == 0)
  289.   return(T_MR);
  290. if (strcmp(s,"null") == 0)
  291.   return(T_NULL);
  292. if (strcmp(s,"wks") == 0)
  293.   return(T_WKS);
  294. if (strcmp(s,"ptr") == 0)
  295.   return(T_PTR);
  296. if (strcmp(s,"hinfo") == 0)
  297.   return(T_HINFO);
  298. if (strcmp(s,"minfo") == 0)
  299.   return(T_MINFO);
  300. if (strcmp(s,"mx") == 0)
  301.   return(T_MX);
  302. if (strcmp(s,"txt") == 0)
  303.   return(T_TXT);
  304. if (strcmp(s,"rp") == 0)
  305.   return(T_RP);
  306. if (strcmp(s,"afsdb") == 0)
  307.   return(T_AFSDB);
  308. if (strcmp(s,"x25") == 0)
  309.   return(T_X25);
  310. if (strcmp(s,"isdn") == 0)
  311.   return(T_ISDN);
  312. if (strcmp(s,"rt") == 0)
  313.   return(T_RT);
  314. if (strcmp(s,"uinfo") == 0)
  315.   return(T_UINFO);
  316. if (strcmp(s,"uid") == 0)
  317.   return(T_UID);
  318. if (strcmp(s,"gid") == 0)
  319.   return(T_GID);
  320. if (strcmp(s,"unspec") == 0)
  321.   return(T_UNSPEC);
  322. if (strcmp(s,"any") == 0)
  323.   return(T_ANY);
  324. if (strcmp(s,"*") == 0)
  325.   return(T_ANY);
  326. if (atoi(s))
  327.   return(atoi(s));
  328. fprintf(stderr, "Invalid query type: %s\n", s);
  329. exit(2);
  330. }
  331.  
  332. parseclass(s)
  333.     char *s;
  334. {
  335. if (strcmp(s,"in") == 0)
  336.   return(C_IN);
  337. if (strcmp(s,"hs") == 0)
  338.   return(C_HS);
  339. if (strcmp(s,"any") == 0)
  340.   return(C_ANY);
  341. if (atoi(s))
  342.   return(atoi(s));
  343. fprintf(stderr, "Invalid query class: %s\n", s);
  344. exit(2);
  345. }
  346.  
  347. printanswer(hp)
  348.     register struct hostent *hp;
  349. {
  350.     register char **cp;
  351.     register long **hptr;
  352.  
  353.     printf("Name: %s\n", hp->h_name);
  354.     printf("Address:");
  355.     for (hptr = (long **)hp->h_addr_list; *hptr; hptr++)
  356.       printf(" %s", inet_ntoa(*(struct in_addr *)*hptr));
  357.     printf("\nAliases:");
  358.     for (cp = hp->h_aliases; cp && *cp && **cp; cp++)
  359.         printf(" %s", *cp);
  360.     printf("\n\n");
  361. }
  362.  
  363. hperror(errno) 
  364. int errno;
  365. {
  366. switch(errno) {
  367.     case HOST_NOT_FOUND:
  368.         fprintf(stderr,"Host not found.\n");
  369.         break;
  370.     case TRY_AGAIN:
  371.         fprintf(stderr,"Host not found, try again.\n");
  372.         break;
  373.     case NO_RECOVERY:
  374.         fprintf(stderr,"No recovery, Host not found.\n");
  375.         break;
  376.     case NO_ADDRESS:
  377.         fprintf(stderr,"There is an entry for this host, but it doesn't have ");
  378.         switch (gettype) {
  379.             case T_A:
  380.                 fprintf(stderr,"an Internet address.\n");
  381.                 break;
  382.             case T_NS:
  383.                 fprintf(stderr,"a Name Server.\n");
  384.                 break;
  385.             case T_MD:
  386.                 fprintf(stderr,"a Mail Destination.\n");
  387.                 break;
  388.             case T_MF:
  389.                 fprintf(stderr,"a Mail Forwarder.\n");
  390.                 break;
  391.             case T_CNAME:
  392.                 fprintf(stderr,"a Canonical Name.\n");
  393.                 break;
  394.             case T_SOA:
  395.                 fprintf(stderr,"a Start of Authority record.\n");
  396.                 break;
  397.             case T_MB:
  398.                 fprintf(stderr,"a Mailbox Domain Name.\n");
  399.                 break;
  400.             case T_MG:
  401.                 fprintf(stderr,"a Mail Group Member.\n");
  402.                 break;
  403.             case T_MR:
  404.                 fprintf(stderr,"a Mail Rename Name.\n");
  405.                 break;
  406.             case T_NULL:
  407.                 fprintf(stderr,"a Null Resource record.\n");
  408.                 break;
  409.             case T_WKS:
  410.                 fprintf(stderr,"any Well Known Service information.\n");
  411.                 break;
  412.             case T_PTR:
  413.                 fprintf(stderr,"a Pointer record.\n");
  414.                 break;
  415.             case T_HINFO:
  416.                 fprintf(stderr,"any Host Information.\n");
  417.                 break;
  418.             case T_MINFO:
  419.                 fprintf(stderr,"any Mailbox Information.\n");
  420.                 break;
  421.             case T_MX:
  422.                 fprintf(stderr,"a Mail Exchanger record.\n");
  423.                 break;
  424.             case T_TXT:
  425.                 fprintf(stderr,"a Text record.\n");
  426.                 break;
  427.             case T_RP:
  428.                 fprintf(stderr,"a Responsible Person.\n");
  429.                 break;
  430.             case T_UINFO:
  431.                 fprintf(stderr,"any User Information.\n");
  432.                 break;
  433.             case T_UID:
  434.                 fprintf(stderr,"a User ID.\n");
  435.                 break;
  436.             case T_GID:
  437.                 fprintf(stderr,"a Group ID.\n");
  438.                 break;
  439.             case T_UNSPEC:
  440.                 fprintf(stderr,"any Unspecified Format data.\n");
  441.                 break;
  442.             default:
  443.                 fprintf(stderr,"the information you requested.\n");
  444.                 break;
  445.             }
  446.         break;
  447.     }
  448. }
  449.  
  450.  
  451. typedef union {
  452.     HEADER qb1;
  453.     u_char qb2[PACKETSZ];
  454. } querybuf;
  455.  
  456. static u_char hostbuf[BUFSIZ+1];
  457.  
  458. gethostinfo(name)
  459.     char *name;
  460. {
  461.     register char *cp, **domain;
  462.     int n;
  463.     int hp;
  464.     int nDomain;
  465.     int asis = 0;
  466.  
  467.     if (strcmp(name, ".") == 0)
  468.         return(getdomaininfo(name, NULL));
  469.     for (cp = name, n = 0; *cp; cp++)
  470.         if (*cp == '.')
  471.             n++;
  472.     if (n && cp[-1] == '.') {
  473.         if (cp[-1] == '.')
  474.             cp[-1] = 0;
  475.         hp = getdomaininfo(name, (char *)NULL);
  476.         if (cp[-1] == 0)
  477.             cp[-1] = '.';
  478.         return (hp);
  479.     }
  480.     if (n == 0 && (cp = hostalias(name))) {
  481.             if (verbose)
  482.             printf("Aliased to \"%s\"\n", cp);
  483.         _res.options |= RES_DEFNAMES;      
  484.         return (getdomaininfo(cp, (char *)NULL));
  485.     }
  486.     if (n >= _res.ndots) {
  487.         asis = 1;
  488.         if (verbose)
  489.             printf("Trying null domain\n");
  490.         if(hp = getdomaininfo(name, (char*)NULL))
  491.             return(hp);
  492.     }
  493. #ifdef MAXDS
  494.     for (nDomain = 0;
  495.          _res.defdname_list[nDomain][0] != 0;
  496.          nDomain++) {
  497.         for (domain = _res.dnsrch_list[nDomain]; *domain; domain++) {
  498.             if (verbose)
  499.             printf("Trying domain \"%s\"\n", *domain);
  500.         hp = getdomaininfo(name, *domain);
  501.         if (hp)
  502.             return (hp);
  503.         }
  504.     }
  505. #else
  506.     for (domain = _res.dnsrch; *domain; domain++) {
  507.       if (verbose)
  508.         printf("Trying domain \"%s\"\n", *domain);
  509.       hp = getdomaininfo(name, *domain);
  510.       if (hp)
  511.         return (hp);
  512.     }
  513. #endif
  514.     if (h_errno != HOST_NOT_FOUND ||
  515.        (_res.options & RES_DNSRCH) == 0)
  516.         return (0);
  517.     if (!asis)
  518.         return (0);
  519.     if (verbose)
  520.         printf("Trying null domain\n");
  521.     return (getdomaininfo(name, (char *)NULL));
  522. }
  523.  
  524. getdomaininfo(name, domain)
  525.     char *name, *domain;
  526. {
  527.   int val1, val2;
  528.  
  529.   if (gettype)
  530.     return getinfo(name, domain, gettype);
  531.   else {
  532.     val1 = getinfo(name, domain, T_A);
  533.     if (cname || verbose)
  534.       return val1;
  535.     val2 = getinfo(name, domain, T_MX);
  536.     return val1 || val2;
  537.   }
  538. }
  539.  
  540. getinfo(name, domain, type)
  541.     char *name, *domain;
  542. {
  543.  
  544.     HEADER *hp;
  545.     char *eom, *bp, *cp;
  546.     querybuf buf, answer;
  547.     int n, n1, i, j, nmx, ancount, nscount, arcount, qdcount, buflen;
  548.     u_short pref, class;
  549.     char host[2*MAXDNAME+2];
  550.  
  551.     if (domain == NULL)
  552.         (void)sprintf(host, "%.*s", MAXDNAME, name);
  553.     else
  554.         (void)sprintf(host, "%.*s.%.*s", MAXDNAME, name, MAXDNAME, domain);
  555.  
  556.     n = res_mkquery(QUERY, host, getclass, type, NULL, 0, NULL,
  557.             buf.qb2, sizeof(buf));
  558.     if (n < 0) {
  559.         if (_res.options & RES_DEBUG)
  560.             printf("res_mkquery failed\n");
  561.         h_errno = NO_RECOVERY;
  562.         return(0);
  563.     }
  564.     n = res_send(buf.qb2, n, answer.qb2, sizeof answer);
  565.     if (n < 0) {
  566.         if (_res.options & RES_DEBUG)
  567.             printf("res_send failed\n");
  568.         h_errno = TRY_AGAIN;
  569.         return (0);
  570.     }
  571.     eom = (char *)&answer + n;
  572.     return(printinfo(&answer, eom, T_ANY, 0));
  573.       }
  574.  
  575. printinfo(answer, eom, filter, isls)
  576.     querybuf *answer;
  577.     u_char *eom;
  578.         int filter;
  579.         int isls;
  580. {
  581.     HEADER *hp;
  582.     u_char *bp, *cp;
  583.     int n, n1, i, j, nmx, ancount, nscount, arcount, qdcount, buflen;
  584.     u_short pref, class;
  585.  
  586.     /*
  587.      * find first satisfactory answer
  588.      */
  589.     hp = (HEADER *) answer;
  590.     ancount = ntohs(hp->ancount);
  591.     qdcount = ntohs(hp->qdcount);
  592.     nscount = ntohs(hp->nscount);
  593.     arcount = ntohs(hp->arcount);
  594.     if (_res.options & RES_DEBUG || (verbose && isls == 0))
  595.         printf("rcode = %d (%s), ancount=%d\n", 
  596.                hp->rcode, DecodeError(hp->rcode), ancount);
  597.     if (hp->rcode != NOERROR || (ancount+nscount+arcount) == 0) {
  598.         switch (hp->rcode) {
  599.             case NXDOMAIN:
  600.                 h_errno = HOST_NOT_FOUND;
  601.                 return(0);
  602.             case SERVFAIL:
  603.                 h_errno = TRY_AGAIN;
  604.                 return(0);
  605. #ifdef OLDJEEVES
  606.             /*
  607.              * Jeeves (TOPS-20 server) still does not
  608.              * support MX records.  For the time being,
  609.              * we must accept FORMERRs as the same as
  610.              * NOERROR.
  611.              */
  612.             case FORMERR:
  613. #endif /*OLDJEEVES*/
  614.             case NOERROR:
  615. /* TpB - set a return error for this case. NO_DATA */
  616.                 h_errno = NO_DATA;
  617.                 return(0); /* was 1,but now indicates exception */
  618. #ifndef OLDJEEVES
  619.             case FORMERR:
  620. #endif /*OLDJEEVES*/
  621.             case NOTIMP:
  622.             case REFUSED:
  623.                 h_errno = NO_RECOVERY;
  624.                 return(0);
  625.         }
  626.         return (0);
  627.     }
  628.     bp = hostbuf;
  629.     nmx = 0;
  630.     buflen = sizeof(hostbuf);
  631.     cp = (u_char *)answer + HFIXEDSZ;
  632.     if (qdcount) {
  633.         cp += dn_skipname(cp, eom) + QFIXEDSZ;
  634.         while (--qdcount > 0)
  635.             cp += dn_skipname(cp, eom) + QFIXEDSZ;
  636.     }
  637.     if (ancount) {
  638.       if (!hp->aa)
  639.         if (verbose && isls == 0)
  640.           printf("The following answer is not authoritative:\n");
  641.       while (--ancount >= 0 && cp && cp < eom) {
  642.         cp = (u_char *)pr_rr(cp, answer, stdout, filter);
  643. /*
  644.  * When we ask for address and there is a CNAME, it seems to return
  645.  * both the CNAME and the address.  Since we trace down the CNAME
  646.  * chain ourselves, we don't really want to print the address at
  647.  * this point.
  648.  */
  649.         if (cname && ! verbose)
  650.           return (1);
  651.       }
  652.     }
  653.     if (! verbose)
  654.       return (1);
  655.     if (nscount) {
  656.       printf("For authoritative answers, see:\n");
  657.       while (--nscount >= 0 && cp && cp < eom) {
  658.         cp = (u_char *)pr_rr(cp, answer, stdout, filter);
  659.       }
  660.     }
  661.     if (arcount) {
  662.       printf("Additional information:\n");
  663.       while (--arcount >= 0 && cp && cp < eom) {
  664.         cp = (u_char *)pr_rr(cp, answer, stdout, filter);
  665.       }
  666.     }
  667.     return(1);
  668.  }
  669.  
  670. static char cnamebuf[MAXDNAME];
  671.  
  672. /*
  673.  * Print resource record fields in human readable form.
  674.  */
  675. char *
  676. pr_rr(cp, msg, file, filter)
  677.     u_char *cp, *msg;
  678.     FILE *file;
  679.         int filter;
  680. {
  681.     int type, class, dlen, n, c, proto, ttl;
  682.     struct in_addr inaddr;
  683.     u_char *cp1;
  684.     struct protoent *protop;
  685.     struct servent *servp;
  686.     char punc;
  687.     int doprint;
  688.     char name[MAXDNAME];
  689.  
  690.     if ((cp = (u_char *)pr_cdname(cp, msg, name, sizeof(name))) == NULL)
  691.         return (NULL);            /* compression error */
  692.  
  693.     type = _getshort(cp);
  694.     cp += INT16SZ;
  695.  
  696.     class = _getshort(cp);
  697.     cp += INT16SZ;
  698.  
  699.     ttl = _getlong(cp);
  700.     cp += INT32SZ;
  701.  
  702.     if (filter == type || filter == T_ANY ||
  703.         (filter == T_A && (type == T_PTR || type == T_NS)))
  704.       doprint = 1;
  705.     else
  706.       doprint = 0;
  707.  
  708.     if (doprint)
  709.       if (verbose)
  710.         fprintf(file,"%s\t%d%s\t%s",
  711.             name, ttl, pr_class(class), pr_type(type));
  712.       else
  713.         fprintf(file,"%s%s %s",name, pr_class(class), pr_type(type));
  714.     if (verbose)
  715.       punc = '\t';
  716.     else
  717.       punc = ' ';
  718.  
  719.     dlen = _getshort(cp);
  720.     cp += INT16SZ;
  721.     cp1 = cp;
  722.     /*
  723.      * Print type specific data, if appropriate
  724.      */
  725.     switch (type) {
  726.     case T_A:
  727.         switch (class) {
  728.         case C_IN:
  729.             bcopy(cp, (char *)&inaddr, INADDRSZ);
  730.             if (dlen == 4) {
  731.                     if (doprint)
  732.                   fprintf(file,"%c%s", punc,
  733.                     inet_ntoa(inaddr));
  734.                 cp += dlen;
  735.             } else if (dlen == 7) {
  736.                     if (doprint) {
  737.                   fprintf(file,"%c%s", punc,
  738.                       inet_ntoa(inaddr));
  739.                   fprintf(file,", protocol = %d", cp[4]);
  740.                   fprintf(file,", port = %d",
  741.                       (cp[5] << 8) + cp[6]);
  742.                 }
  743.                 cp += dlen;
  744.             }
  745.             break;
  746.         }
  747.         break;
  748.     case T_CNAME:
  749.         if (dn_expand(msg, msg + 512, cp, cnamebuf, 
  750.                   sizeof(cnamebuf)) >= 0)
  751.             cname = cnamebuf;                
  752.     case T_MB:
  753. #ifdef OLDRR
  754.     case T_MD:
  755.     case T_MF:
  756. #endif /* OLDRR */
  757.     case T_MG:
  758.     case T_MR:
  759.     case T_NS:
  760.     case T_PTR:
  761.         cp = (u_char *)pr_cdname(cp, msg, name, sizeof(name));
  762.         if (doprint)
  763.           fprintf(file,"%c%s",punc, name);
  764.         break;
  765.  
  766.     case T_HINFO:
  767.     case T_ISDN:
  768.         if (n = *cp++) {
  769.             if (doprint)
  770.               fprintf(file,"%c%.*s", punc, n, cp);
  771.             cp += n;
  772.         }
  773.         if (n = *cp++) {
  774.             if (doprint)
  775.               fprintf(file,"%c%.*s", punc, n, cp);
  776.             cp += n;
  777.         }
  778.         break;
  779.  
  780.     case T_SOA:
  781.         cp = (u_char *)pr_cdname(cp, msg, name, sizeof(name));
  782.         if (doprint)
  783.           fprintf(file,"\t%s", name);
  784.         cp = (u_char *)pr_cdname(cp, msg, name, sizeof(name));
  785.         if (doprint)
  786.           fprintf(file," %s", name);
  787.         if (doprint)
  788.           fprintf(file,"(\n\t\t\t%ld\t;serial (version)", _getlong(cp));
  789.         cp += INT32SZ;
  790.         if (doprint)
  791.           fprintf(file,"\n\t\t\t%ld\t;refresh period", _getlong(cp));
  792.         cp += INT32SZ;
  793.         if (doprint)
  794.           fprintf(file,"\n\t\t\t%ld\t;retry refresh this often", _getlong(cp));
  795.         cp += INT32SZ;
  796.         if (doprint)
  797.           fprintf(file,"\n\t\t\t%ld\t;expiration period", _getlong(cp));
  798.         cp += INT32SZ;
  799.         if (doprint)
  800.           fprintf(file,"\n\t\t\t%ld\t;minimum TTL\n\t\t\t)", _getlong(cp));
  801.         cp += INT32SZ;
  802.         break;
  803.  
  804.     case T_MX:
  805.     case T_AFSDB:
  806.     case T_RT:
  807.         if (doprint)
  808.           if (verbose)
  809.             fprintf(file,"\t%ld ",_getshort(cp));
  810.           else
  811.             fprintf(file," ");
  812.         cp += sizeof(u_short);
  813.         cp = (u_char *)pr_cdname(cp, msg, name, sizeof(name));
  814.         if (doprint)
  815.           fprintf(file, "%s", name);
  816.         break;
  817.  
  818.     case T_MINFO:
  819.     case T_RP:
  820.         cp = (u_char *)pr_cdname(cp, msg, name, sizeof(name));
  821.         if (doprint){
  822.                   if (type == T_RP) {
  823.             char * p;
  824.             if (p = strchr(name, '.')) *p = '@';
  825.                   }
  826.  
  827.           fprintf(file, "%c%s", punc, name);
  828.         }
  829.         cp = (u_char *)pr_cdname(cp, msg, name, sizeof(name));
  830.         if (doprint)
  831.             fprintf(file, " %s", name);
  832.         break;
  833.  
  834.     case T_TXT:
  835.     case T_X25:
  836.         {
  837.           int n,j;
  838.           u_char * end = cp + dlen;
  839.          
  840.           if (doprint)
  841.             (void) fputs(" \"", file);
  842.           while (cp < end) {
  843.             if (n = *cp++) {
  844.               for (j = n; j > 0 && cp < end ; j --)
  845.             if (*cp == '\n') {
  846.               if (doprint){
  847.                 (void) putc('\\', file);
  848.                 (void) putc(*cp++, file);
  849.               }
  850.             } else
  851.               if (doprint)
  852.                 (void) putc(*cp++, file);
  853.             }
  854.           }
  855.           if (doprint)
  856.             (void) fputs("\"", file);
  857.           break;
  858.         }
  859.     case T_UINFO:
  860.         if (doprint)
  861.           fprintf(file,"%c%s", punc, cp);
  862.         cp += dlen;
  863.         break;
  864.  
  865.     case T_UID:
  866.     case T_GID:
  867.         if (dlen == 4) {
  868.             if (doprint)
  869.               fprintf(file,"%c%ld", punc, _getlong(cp));
  870.             cp += INT32SZ;
  871.         }
  872.         break;
  873.  
  874.     case T_WKS:
  875.         if (dlen < INT32SZ + 1)
  876.             break;
  877.         bcopy(cp, (char *)&inaddr, INADDRSZ);
  878.         cp += INT32SZ;
  879.         proto = *cp++;
  880.         protop = getprotobynumber(proto);
  881.         if (doprint)
  882.           if (protop)
  883.             fprintf(file,"%c%s %s", punc,
  884.                 inet_ntoa(inaddr), protop->p_name);
  885.           else
  886.             fprintf(file,"%c%s %d", punc,
  887.                 inet_ntoa(inaddr), proto);
  888.  
  889.         n = 0;
  890.         while (cp < cp1 + dlen) {
  891.             c = *cp++;
  892.             do {
  893.                  if (c & 0200) {
  894.                   servp = NULL;
  895.                   if (protop)
  896.                     servp = getservbyport (htons(n),
  897.                                protop->p_name);
  898.                   if (doprint)
  899.                     if (servp)
  900.                       fprintf(file, " %s", servp->s_name);
  901.                     else
  902.                       fprintf(file, " %d", n);
  903.                 }
  904.                  c <<= 1;
  905.             } while (++n & 07);
  906.         }
  907.         break;
  908.  
  909.     default:
  910.         if (doprint)
  911.           fprintf(file,"%c???", punc);
  912.         cp += dlen;
  913.     }
  914.     if (cp != cp1 + dlen)
  915.         fprintf(file,"packet size error (%#x != %#x)\n", cp, cp1+dlen);
  916.     if (doprint)
  917.       fprintf(file,"\n");
  918.     return (char *)cp;
  919. }
  920.  
  921. static    char nbuf[20];
  922.  
  923. /*
  924.  * Return a string for the type
  925.  */
  926. char *
  927. pr_type(type)
  928.     int type;
  929. {
  930.     switch (type) {
  931.     case T_A:
  932.         return(verbose? "A" : "has address");
  933.     case T_NS:        /* authoritative server */
  934.         return("NS");
  935. #ifdef OLDRR
  936.     case T_MD:        /* mail destination */
  937.         return("MD");
  938.     case T_MF:        /* mail forwarder */
  939.         return("MF");
  940. #endif /* OLDRR */
  941.     case T_CNAME:        /* connonical name */
  942.         return(verbose? "CNAME" : "is a nickname for");
  943.     case T_SOA:        /* start of authority zone */
  944.         return("SOA");
  945.     case T_MB:        /* mailbox domain name */
  946.         return("MB");
  947.     case T_MG:        /* mail group member */
  948.         return("MG");
  949.     case T_MX:        /* mail routing info */
  950.         return(verbose? "MX" : "mail is handled by");
  951.     case T_TXT:        /* TXT - descriptive info */
  952.         return(verbose? "TXT" : "descriptive text");
  953.     case T_AFSDB:        /* AFS/DCE info */
  954.         return(verbose? "AFSDB" : "DCE or AFS service from");
  955.     case T_X25:        /* X25 */
  956.         return(verbose? "X25" : "X25 address");
  957.     case T_ISDN:        /* ISDN */
  958.         return(verbose? "ISDN" : "ISDN address");
  959.     case T_RT:        /* Router */
  960.         return(verbose? "RT" : "router");
  961.     case T_MR:        /* mail rename name */
  962.         return("MR");
  963.     case T_NULL:        /* null resource record */
  964.         return("NULL");
  965.     case T_WKS:        /* well known service */
  966.         return("WKS");
  967.     case T_PTR:        /* domain name pointer */
  968.         return("PTR");
  969.     case T_HINFO:        /* host information */
  970.         return("HINFO");
  971.     case T_MINFO:        /* mailbox information */
  972.         return("MINFO");
  973.         case T_RP:              /* responsible person */
  974.         return(verbose?"RP":"responsible person");
  975.     case T_AXFR:        /* zone transfer */
  976.         return("AXFR");
  977.     case T_MAILB:        /* mail box */
  978.         return("MAILB");
  979.     case T_MAILA:        /* mail address */
  980.         return("MAILA");
  981.     case T_ANY:        /* matches any type */
  982.         return("ANY");
  983.     case T_UINFO:
  984.         return("UINFO");
  985.     case T_UID:
  986.         return("UID");
  987.     case T_GID:
  988.         return("GID");
  989.     default:
  990.         sprintf(nbuf, "%d", type);
  991.         return nbuf;
  992.     }
  993. }
  994.  
  995. /*
  996.  * Return a mnemonic for class
  997.  */
  998. char *
  999. pr_class(class)
  1000.     int class;
  1001. {
  1002.  
  1003.     switch (class) {
  1004.     case C_IN:        /* internet class */
  1005.         return(verbose? " IN" : "");
  1006.     case C_HS:        /* internet class */
  1007.         return(verbose? " HS" : "");
  1008.     case C_ANY:        /* matches any class */
  1009.         return(" ANY");
  1010.     default:
  1011.         (void) sprintf(nbuf," %d", class);
  1012.         return nbuf;
  1013.     }
  1014. }
  1015.  
  1016. u_char *
  1017. pr_cdname(cp, msg, name, namelen)
  1018.     u_char *cp, *msg;
  1019.     char *name;
  1020.         int namelen;
  1021. {
  1022.     int n;
  1023.  
  1024.     if ((n = dn_expand(msg, msg + 512, cp, name, namelen - 2)) < 0)
  1025.         return (NULL);
  1026.     if (name[0] == '\0') {
  1027.         name[0] = '.';
  1028.         name[1] = '\0';
  1029.     }
  1030.     return (cp + n);
  1031. }
  1032.  
  1033. char *resultcodes[] = {
  1034.     "NOERROR",
  1035.     "FORMERR",
  1036.     "SERVFAIL",
  1037.     "NXDOMAIN",
  1038.     "NOTIMP",
  1039.     "REFUSED",
  1040.     "6",
  1041.     "7",
  1042.     "8",
  1043.     "9",
  1044.     "10",
  1045.     "11",
  1046.     "12",
  1047.     "13",
  1048.     "14",
  1049.     "NOCHANGE",
  1050. };
  1051.  
  1052.  
  1053.  
  1054. /*
  1055.  ******************************************************************************
  1056.  *
  1057.  *  ListHosts --
  1058.  *
  1059.  *    Requests the name server to do a zone transfer so we
  1060.  *    find out what hosts it knows about.
  1061.  *
  1062.  *  Results:
  1063.  *    SUCCESS        the listing was successful.
  1064.  *    ERROR        the server could not be contacted because 
  1065.  *            a socket could not be obtained or an error
  1066.  *            occured while receiving, or the output file
  1067.  *            could not be opened.
  1068.  *
  1069.  ******************************************************************************
  1070.  */
  1071.  
  1072. int
  1073. ListHosts(namePtr, queryType)
  1074.     char *namePtr;
  1075.     int  queryType;  /* e.g. T_A */
  1076. {
  1077.     querybuf         buf, answer;
  1078.     struct sockaddr_in     sin;
  1079.     HEADER             *headerPtr;
  1080.  
  1081.     int             msglen;
  1082.     int             amtToRead;
  1083.     int             numRead;
  1084.     int             i;
  1085.     int             numAnswers = 0;
  1086.     int             result;
  1087.     int             soacnt = 0;
  1088.     u_short         len;
  1089.     int            dlen;
  1090.     int            type;
  1091.     int            nscount;
  1092.     u_char             *cp, *nmp;
  1093.     char             name[NAME_LEN];
  1094.     char             dname[2][NAME_LEN];
  1095.     char             domain[NAME_LEN];
  1096. /* names and addresses of name servers to try */
  1097. #define NUMNS 8
  1098.     char            nsname[NUMNS][NAME_LEN];
  1099.     int            nshaveaddr[NUMNS];
  1100. #define IPADDRSIZE 4
  1101. #define NUMNSADDR 16
  1102.     char             nsipaddr[NUMNSADDR][IPADDRSIZE];
  1103.     int            numns;
  1104.     int            numnsaddr;
  1105.     int            thisns;
  1106.     struct hostent        *hp;
  1107.     enum {
  1108.         NO_ERRORS, 
  1109.         ERR_READING_LEN, 
  1110.         ERR_READING_MSG,
  1111.         ERR_PRINTING
  1112.     } error = NO_ERRORS;
  1113.  
  1114. /*
  1115.  * normalize to not have trailing dot.  We do string compares below
  1116.  * of info from name server, and it won't have trailing dots.
  1117.  */
  1118.     i = strlen(namePtr);
  1119.     if (namePtr[i-1] == '.')
  1120.       namePtr[i-1] = 0;
  1121.  
  1122.     if (server_specified) {
  1123.       bcopy(&_res.nsaddr.sin_addr, nsipaddr[0], IPADDRSIZE);
  1124.       numnsaddr = 1;
  1125.     }
  1126.     else {
  1127.  
  1128. /*
  1129.  * First we have to find out where to look.  This needs a NS query,
  1130.  * possibly followed by looking up addresses for some of the names.
  1131.  */
  1132.  
  1133.     msglen = res_mkquery(QUERY, namePtr, C_IN, T_NS, NULL,
  1134.                  0, NULL, buf.qb2, sizeof buf);
  1135.  
  1136.     if (msglen < 0) {
  1137.         printf("res_mkquery failed\n");
  1138.         return (ERROR);
  1139.     }
  1140.  
  1141.     msglen = res_send(buf.qb2, msglen, answer.qb2, sizeof answer);
  1142.     
  1143.     if (msglen < 0) {
  1144.         printf("Unable to get to nameserver -- try again later\n");
  1145.         return (ERROR);
  1146.     }
  1147.     if (_res.options & RES_DEBUG || verbose)
  1148.         printf("rcode = %d (%s), ancount=%d\n", 
  1149.                answer.qb1.rcode, DecodeError(answer.qb1.rcode),
  1150.                ntohs(answer.qb1.ancount));
  1151.  
  1152. /*
  1153.  * Analyze response to our NS lookup
  1154.  */
  1155.  
  1156.     nscount = ntohs(answer.qb1.ancount) + ntohs(answer.qb1.nscount) +
  1157.           ntohs(answer.qb1.arcount);
  1158.  
  1159.     if (answer.qb1.rcode != NOERROR || nscount == 0) {
  1160.         switch (answer.qb1.rcode) {
  1161.             case NXDOMAIN:
  1162.                 /* Check if it's an authoritive answer */
  1163.                 if (answer.qb1.aa) {
  1164.                     printf("No such domain\n");
  1165.                 } else {
  1166.                     printf("Unable to get information about domain -- try again later.\n");
  1167.                 }
  1168.                 break;
  1169.             case SERVFAIL:
  1170.                 printf("Unable to get information about that domain -- try again later.\n");
  1171.                 break;
  1172.             case NOERROR:
  1173.                 printf("That domain exists, but seems to be a leaf node.\n");
  1174.                 break;
  1175.             case FORMERR:
  1176.             case NOTIMP:
  1177.             case REFUSED:
  1178.                 printf("Unrecoverable error looking up domain name.\n");
  1179.                 break;
  1180.         }
  1181.         return (0);
  1182.     }
  1183.  
  1184.     cp = (u_char *)answer.qb2 + HFIXEDSZ;
  1185.     if (ntohs(answer.qb1.qdcount) > 0)
  1186.       cp += dn_skipname(cp, answer.qb2 + msglen) + QFIXEDSZ;
  1187.  
  1188.     numns = 0;
  1189.     numnsaddr = 0;
  1190.  
  1191. /*
  1192.  * Look at response from NS lookup for NS and A records.
  1193.  */
  1194.  
  1195.     for (;nscount; nscount--) {
  1196.       cp += dn_expand(answer.qb2, answer.qb2 + msglen, cp,
  1197.               domain, sizeof(domain));
  1198.       type = _getshort(cp);
  1199.       cp += INT16SZ + INT16SZ + INT32SZ;
  1200.       dlen = _getshort(cp);
  1201.       cp += INT16SZ;
  1202.       if (type == T_NS) {
  1203.         if (dn_expand(answer.qb2, answer.qb2 + msglen, cp, 
  1204.               name, sizeof(name)) >= 0) {
  1205.           if (numns < NUMNS && strcasecmp((char *)domain, namePtr) == 0) {
  1206.         for (i = 0; i < numns; i++)
  1207.           if (strcasecmp(nsname[i], (char *)name) == 0)
  1208.             break;  /* duplicate */
  1209.         if (i >= numns) {
  1210.           strncpy(nsname[numns], (char *)name, sizeof(name));
  1211.           nshaveaddr[numns] = 0;
  1212.           numns++;
  1213.         }
  1214.           }
  1215.         }
  1216.       }
  1217.       else if (type == T_A) {
  1218.         if (numnsaddr < NUMNSADDR)
  1219.           for (i = 0; i < numns; i++) {
  1220.         if (strcasecmp(nsname[i], (char *)domain) == 0) {
  1221.           nshaveaddr[i]++;
  1222.           bcopy(cp, nsipaddr[numnsaddr],IPADDRSIZE);
  1223.           numnsaddr++;
  1224.           break;
  1225.         }
  1226.           }
  1227.       }
  1228.       cp += dlen;
  1229.     }
  1230.  
  1231. /*
  1232.  * Usually we'll get addresses for all the servers in the additional
  1233.  * info section.  But in case we don't, look up their addresses.
  1234.  */
  1235.  
  1236.     for (i = 0; i < numns; i++) {
  1237.       if (! nshaveaddr[i]) {
  1238.         register long **hptr;
  1239.         int numaddrs = 0;
  1240.  
  1241.         hp = gethostbyname(nsname[i]);
  1242.         if (hp) {
  1243.           for (hptr = (long **)hp->h_addr_list; *hptr; hptr++)
  1244.         if (numnsaddr < NUMNSADDR) {
  1245.           bcopy((char *)*hptr, nsipaddr[numnsaddr],IPADDRSIZE);
  1246.           numnsaddr++;
  1247.           numaddrs++;
  1248.         }
  1249.         }
  1250.         if (_res.options & RES_DEBUG || verbose)
  1251.           printf("Found %d addresses for %s by extra query\n",
  1252.              numaddrs, nsname[i]);
  1253.       }
  1254.       else
  1255.         if (_res.options & RES_DEBUG || verbose)
  1256.           printf("Found %d addresses for %s\n",
  1257.              nshaveaddr[i], nsname[i]);
  1258.     }
  1259.         }
  1260. /*
  1261.  * Now nsipaddr has numnsaddr addresses for name servers that
  1262.  * serve the requested domain.  Now try to find one that will
  1263.  * accept a zone transfer.
  1264.  */
  1265.  
  1266.     thisns = 0;
  1267.  
  1268. again:
  1269.  
  1270.     numAnswers = 0;
  1271.     soacnt = 0;
  1272.  
  1273.     /*
  1274.      *  Create a query packet for the requested domain name.
  1275.      *
  1276.      */
  1277.     msglen = res_mkquery(QUERY, namePtr, getclass, T_AXFR, NULL,
  1278.                  0, NULL, buf.qb2, sizeof buf);
  1279.     if (msglen < 0) {
  1280.         if (_res.options & RES_DEBUG) {
  1281.         fprintf(stderr, "ListHosts: Res_mkquery failed\n");
  1282.         }
  1283.         return (ERROR);
  1284.     }
  1285.  
  1286.     bzero((char *)&sin, sizeof(sin));
  1287.     sin.sin_family    = AF_INET;
  1288.     sin.sin_port    =  htons(NAMESERVER_PORT);
  1289.  
  1290.     /*
  1291.      *  Set up a virtual circuit to the server.
  1292.      */
  1293.  
  1294.     for (;thisns < numnsaddr; thisns++) {
  1295.       if ((sockFD = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  1296.         perror("ListHosts");
  1297.         return(ERROR);
  1298.       }
  1299.       bcopy(nsipaddr[thisns], &sin.sin_addr, IPADDRSIZE);
  1300.       if (_res.options & RES_DEBUG || verbose)
  1301.         printf("Trying %s\n", inet_ntoa(sin.sin_addr));
  1302.       if (connect(sockFD, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
  1303.         break;
  1304.       if (verbose)
  1305.         perror("Connection failed, trying next server");
  1306.       (void) close(sockFD);
  1307.       sockFD = -1;
  1308.     }    
  1309.     if (thisns >= numnsaddr) {
  1310.       printf("No server for that domain responded\n");
  1311.       if (!verbose)
  1312.         perror("Error from the last server was");
  1313.       return (ERROR);
  1314.     }
  1315.  
  1316.     /*
  1317.      * Send length & message for zone transfer 
  1318.      */
  1319.  
  1320.     __putshort(msglen, (u_char *)&len);
  1321.  
  1322.         if (write(sockFD, (char *)&len, INT16SZ) != INT16SZ ||
  1323.             write(sockFD, (char *) &buf, msglen) != msglen) {
  1324.         perror("ListHosts");
  1325.         (void) close(sockFD);
  1326.         sockFD = -1;
  1327.         return (ERROR);
  1328.     }
  1329.  
  1330.     filePtr = stdout;
  1331.  
  1332.     while (1) {
  1333.  
  1334.         /*
  1335.          * Read the length of the response.
  1336.          */
  1337.  
  1338.         cp = (u_char *) &buf;
  1339.         amtToRead = INT16SZ;
  1340.         while(amtToRead > 0 && (numRead = read(sockFD, cp, amtToRead)) > 0){
  1341.         cp       += numRead;
  1342.         amtToRead -= numRead;
  1343.         }
  1344.         if (numRead <= 0) {
  1345.         error = ERR_READING_LEN;
  1346.         break;
  1347.         }    
  1348.  
  1349.         if ((len = _getshort((u_char*)&buf)) == 0) {
  1350.         break;    /* nothing left to read */
  1351.         }
  1352.  
  1353.         /*
  1354.          * Read the response.
  1355.          */
  1356.  
  1357.         amtToRead = len;
  1358.         cp = (u_char *) &buf;
  1359.         while(amtToRead > 0 && (numRead = read(sockFD, cp, amtToRead)) > 0){
  1360.         cp += numRead;
  1361.         amtToRead -= numRead;
  1362.         }
  1363.         if (numRead <= 0) {
  1364.         error = ERR_READING_MSG;
  1365.         break;
  1366.         }
  1367.  
  1368.         i = buf.qb1.rcode;
  1369.         if (i != NOERROR || ntohs(buf.qb1.ancount) == 0) {
  1370.           if ((thisns+1) < numnsaddr &&
  1371.           (i == SERVFAIL || i == NOTIMP || i == REFUSED)) {
  1372.         if (_res.options & RES_DEBUG || verbose)
  1373.           printf("Server failed, trying next server: %s\n",
  1374.              i != NOERROR ? 
  1375.              DecodeError(i) : "Premature end of data");
  1376.         (void) close(sockFD);
  1377.         sockFD = -1;
  1378.         thisns++;
  1379.         goto again;
  1380.           }
  1381.           printf("Server failed: %s\n",
  1382.              i != NOERROR ? DecodeError(i) : "Premature end of data");
  1383.           break;
  1384.         }
  1385.  
  1386.  
  1387.         result = printinfo(&buf, cp, queryType, 1);
  1388.         if (! result) {
  1389.         error = ERR_PRINTING;
  1390.         break;
  1391.         }
  1392.         numAnswers++;
  1393.         cp = buf.qb2 + HFIXEDSZ;
  1394.         if (ntohs(buf.qb1.qdcount) > 0)
  1395.         cp += dn_skipname(cp, buf.qb2 + len) + QFIXEDSZ;
  1396.  
  1397.         nmp = cp;
  1398.         cp += dn_skipname(cp, (u_char *)&buf + len);
  1399.         if ((_getshort(cp) == T_SOA)) {
  1400.         (void) dn_expand(buf.qb2, buf.qb2 + len, nmp,
  1401.                  dname[soacnt], sizeof dname[0]);
  1402.             if (soacnt) {
  1403.             if (strcmp((char *)dname[0], (char *)dname[1]) == 0)
  1404.             break;
  1405.         } else
  1406.             soacnt++;
  1407.         }
  1408.         }
  1409.  
  1410.     (void) close(sockFD);
  1411.     sockFD = -1;
  1412.  
  1413.     switch (error) {
  1414.         case NO_ERRORS:
  1415.         return (SUCCESS);
  1416.  
  1417.         case ERR_READING_LEN:
  1418.         return(ERROR);
  1419.  
  1420.         case ERR_PRINTING:
  1421.         fprintf(stderr,"*** Error during listing of %s: %s\n", 
  1422.                 namePtr, DecodeError(result));
  1423.         return(result);
  1424.  
  1425.         case ERR_READING_MSG:
  1426.         headerPtr = (HEADER *) &buf;
  1427.         fprintf(stderr,"ListHosts: error receiving zone transfer:\n");
  1428.         fprintf(stderr,
  1429.            "  result: %s, answers = %d, authority = %d, additional = %d\n", 
  1430.                 resultcodes[headerPtr->rcode], 
  1431.                 ntohs(headerPtr->ancount), ntohs(headerPtr->nscount), 
  1432.             ntohs(headerPtr->arcount));
  1433.         return(ERROR);
  1434.         default:
  1435.         return(ERROR);
  1436.     }
  1437. }
  1438.  
  1439. char *
  1440. DecodeError(result)
  1441.     int result;
  1442. {
  1443.     switch(result) {
  1444.         case NOERROR:     return("Success"); break;
  1445.         case FORMERR:    return("Format error"); break;
  1446.         case SERVFAIL:    return("Server failed"); break;
  1447.         case NXDOMAIN:    return("Non-existent domain"); break;
  1448.         case NOTIMP:    return("Not implemented"); break;
  1449.         case REFUSED:    return("Query refused"); break;
  1450.         case NOCHANGE:    return("No change"); break;
  1451.         case NO_INFO:     return("No information"); break;
  1452.         case ERROR:     return("Unspecified error"); break;
  1453.         case TIME_OUT:     return("Timed out"); break;
  1454.         case NONAUTH:     return("Non-authoritative answer"); break;
  1455.         default:         break;
  1456.     }
  1457.     return("BAD ERROR VALUE"); 
  1458. }
  1459.