home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.sbin / named / tools / nslookup / getinfo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-24  |  20.6 KB  |  799 lines

  1. /*
  2.  * Copyright (c) 1985,1989 Regents of the University of California.
  3.  * 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.  
  34. #ifndef lint
  35. static char sccsid[] = "@(#)getinfo.c    5.26 (Berkeley) 3/21/91";
  36. #endif /* not lint */
  37.  
  38. /*
  39.  *******************************************************************************
  40.  *
  41.  *  getinfo.c --
  42.  *
  43.  *    Routines to create requests to name servers
  44.  *    and interpret the answers.
  45.  *
  46.  *    Adapted from 4.3BSD BIND gethostnamadr.c
  47.  *
  48.  *******************************************************************************
  49.  */
  50.  
  51. #include <sys/param.h>
  52. #include <sys/socket.h>
  53. #include <netinet/in.h>
  54. #include <arpa/nameser.h>
  55. #include <arpa/inet.h>
  56. #include <resolv.h>
  57. #include <stdio.h>
  58. #include <ctype.h>
  59. #include "res.h"
  60.  
  61. extern char *_res_resultcodes[];
  62. extern char *res_skip();
  63.  
  64. #define    MAXALIASES    35
  65. #define MAXADDRS    35
  66. #define MAXDOMAINS    35
  67. #define MAXSERVERS    10
  68.  
  69. static char *addr_list[MAXADDRS + 1];
  70.  
  71. static char *host_aliases[MAXALIASES];
  72. static int   host_aliases_len[MAXALIASES];
  73. static u_char  hostbuf[BUFSIZ+1];
  74.  
  75. typedef struct {
  76.     char *name;
  77.     char *domain[MAXDOMAINS];
  78.     int   numDomains;
  79.     char *address[MAXADDRS];
  80.     int   numAddresses;
  81. } ServerTable;
  82.  
  83. ServerTable server[MAXSERVERS];
  84.  
  85. typedef union {
  86.     HEADER qb1;
  87.     char qb2[PACKETSZ];
  88. } querybuf;
  89.  
  90. typedef union {
  91.     long al;
  92.     char ac;
  93. } align;
  94.  
  95. #define GetShort(cp)    _getshort(cp); cp += sizeof(unsigned short);
  96.  
  97.  
  98. /*
  99.  *******************************************************************************
  100.  *
  101.  *  GetAnswer --
  102.  *
  103.  *    Interprets an answer packet and retrieves the following
  104.  *    information:
  105.  *
  106.  *  Results:
  107.  *      SUCCESS         the info was retrieved.
  108.  *      NO_INFO         the packet did not contain an answer.
  109.  *    NONAUTH        non-authoritative information was found.
  110.  *      ERROR           the answer was malformed.
  111.  *      Other errors    returned in the packet header.
  112.  *
  113.  *******************************************************************************
  114.  */
  115.  
  116. static int
  117. GetAnswer(nsAddrPtr, queryType, msg, msglen, iquery, hostPtr, isServer)
  118.     struct in_addr    *nsAddrPtr;
  119.     char        *msg;
  120.     int            queryType;
  121.     int            msglen;
  122.     Boolean        iquery;
  123.     register HostInfo    *hostPtr;
  124.     Boolean        isServer;
  125. {
  126.     register HEADER    *headerPtr;
  127.     register u_char    *cp;
  128.     querybuf        answer;
  129.     char        **aliasPtr;
  130.     u_char        *eom, *bp;
  131.     char        **addrPtr;
  132.     char        *namePtr;
  133.     char        *dnamePtr;
  134.     int            type, class;
  135.     int            qdcount, ancount, arcount, nscount, buflen;
  136.     int            origClass;
  137.     int            numAliases = 0;
  138.     int            numAddresses = 0;
  139.     int            n, i, j;
  140.     int            len;
  141.     int            dlen;
  142.     int            status;
  143.     int            numServers;
  144.     Boolean        haveAnswer;
  145.     Boolean        printedAnswers = FALSE;
  146.  
  147.  
  148.     /*
  149.      *  If the hostPtr was used before, free up the calloc'd areas.
  150.      */
  151.     FreeHostInfoPtr(hostPtr);
  152.  
  153.     status = SendRequest(nsAddrPtr, msg, msglen, (char *) &answer,
  154.                 sizeof(answer), &n);
  155.  
  156.     if (status != SUCCESS) {
  157.         if (_res.options & RES_DEBUG2)
  158.             printf("SendRequest failed\n");
  159.         return (status);
  160.     }
  161.     eom = (u_char *) &answer + n;
  162.  
  163.     headerPtr = (HEADER *) &answer;
  164.  
  165.     if (headerPtr->rcode != NOERROR) {
  166.     return (headerPtr->rcode);
  167.     }
  168.  
  169.     qdcount = ntohs(headerPtr->qdcount);
  170.     ancount = ntohs(headerPtr->ancount);
  171.     arcount = ntohs(headerPtr->arcount);
  172.     nscount = ntohs(headerPtr->nscount);
  173.  
  174.     /*
  175.      * If there are no answer, n.s. or additional records
  176.      * then return with an error.
  177.      */
  178.     if (ancount == 0 && nscount == 0 && arcount == 0) {
  179.     return (NO_INFO);
  180.     }
  181.  
  182.  
  183.     bp       = hostbuf;
  184.     buflen = sizeof(hostbuf);
  185.     cp       = (u_char *) &answer + sizeof(HEADER);
  186.  
  187.     /* Skip over question section. */
  188.     while (qdcount-- > 0) {
  189.     cp += dn_skipname(cp, eom) + QFIXEDSZ;
  190.     }
  191.  
  192.     aliasPtr    = host_aliases;
  193.     addrPtr    = addr_list;
  194.     haveAnswer    = FALSE;
  195.  
  196.     /*
  197.      * Scan through the answer resource records.
  198.      * Answers for address query types are saved.
  199.      * Other query type answers are just printed.
  200.      */
  201.     if (ancount != 0) {
  202.     if (!isServer && !headerPtr->aa) {
  203.         printf("Non-authoritative answer:\n");
  204.     }
  205.  
  206.     if (queryType != T_A && !(iquery && queryType == T_PTR)) {
  207.         while (--ancount >= 0 && cp < eom) {
  208.         if ((cp = (u_char *)Print_rr(cp,
  209.             (char *)&answer, eom, stdout)) == NULL) {
  210.             return(ERROR);
  211.         }
  212.         }
  213.         printedAnswers = TRUE;
  214.     } else {
  215.         while (--ancount >= 0 && cp < eom) {
  216.         if ((n =
  217.             dn_expand((u_char *)&answer, eom, cp, bp, buflen)) < 0) {
  218.             return(ERROR);
  219.         }
  220.         cp   += n;
  221.         type  = GetShort(cp);
  222.         class = GetShort(cp);
  223.         cp   += sizeof(u_long);    /* skip TTL */
  224.         dlen  = GetShort(cp);
  225.         if (type == T_CNAME) {
  226.             /*
  227.              * Found an alias.
  228.              */
  229.             cp += dlen;
  230.             if (aliasPtr >= &host_aliases[MAXALIASES-1]) {
  231.             continue;
  232.             }
  233.             *aliasPtr++ = (char *)bp;
  234.             n = strlen((char *)bp) + 1;
  235.             host_aliases_len[numAliases] = n;
  236.             numAliases++;
  237.             bp += n;
  238.             buflen -= n;
  239.             continue;
  240.         } else if (type == T_PTR) {
  241.             /*
  242.              *  Found a "pointer" to the real name.
  243.              */
  244.             if ((n =
  245.             dn_expand((u_char *)&answer, eom, cp, bp,buflen)) < 0) {
  246.             cp += n;
  247.             continue;
  248.             }
  249.             cp += n;
  250.             len = strlen(bp) + 1;
  251.             hostPtr->name = Calloc(1, len);
  252.             bcopy(bp, hostPtr->name, len);
  253.             haveAnswer = TRUE;
  254.             break;
  255.         } else if (type != T_A) {
  256.             cp += dlen;
  257.             continue;
  258.         }
  259.         if (haveAnswer) {
  260.             /*
  261.              * If we've already got 1 address, we aren't interested
  262.              * in addresses with a different length or class.
  263.              */
  264.             if (dlen != hostPtr->addrLen) {
  265.             cp += dlen;
  266.             continue;
  267.             }
  268.             if (class != origClass) {
  269.             cp += dlen;
  270.             continue;
  271.             }
  272.         } else {
  273.             /*
  274.              * First address: record its length and class so we
  275.              * only save additonal ones with the same attributes.
  276.              */
  277.             hostPtr->addrLen = dlen;
  278.             origClass = class;
  279.             hostPtr->addrType = (class == C_IN) ? AF_INET : AF_UNSPEC;
  280.             len = strlen(bp) + 1;
  281.             hostPtr->name = Calloc(1, len);
  282.             bcopy(bp, hostPtr->name, len);
  283.         }
  284.         bp += (((u_long)bp) % sizeof(align));
  285.  
  286.         if (bp + dlen >= &hostbuf[sizeof(hostbuf)]) {
  287.             if (_res.options & RES_DEBUG) {
  288.             printf("Size (%d) too big\n", dlen);
  289.             }
  290.             break;
  291.         }
  292.         bcopy(cp, *addrPtr++ = (char *)bp, dlen);
  293.         bp +=dlen;
  294.         cp += dlen;
  295.         numAddresses++;
  296.         haveAnswer = TRUE;
  297.         }
  298.     }
  299.     }
  300.  
  301.     if ((queryType == T_A || queryType == T_PTR) && haveAnswer) {
  302.  
  303.     /*
  304.      *  Go through the alias and address lists and return them
  305.      *  in the hostPtr variable.
  306.      */
  307.  
  308.     if (numAliases > 0) {
  309.         hostPtr->aliases = (char **) Calloc(1 + numAliases, sizeof(char *));
  310.         for (i = 0; i < numAliases; i++) {
  311.         hostPtr->aliases[i] = Calloc(1, host_aliases_len[i]);
  312.         bcopy(host_aliases[i], hostPtr->aliases[i],host_aliases_len[i]);
  313.         }
  314.         hostPtr->aliases[i] = NULL;
  315.     }
  316.     if (numAddresses > 0) {
  317.         hostPtr->addrList = (char **)Calloc(1+numAddresses, sizeof(char *));
  318.         for (i = 0; i < numAddresses; i++) {
  319.         hostPtr->addrList[i] = Calloc(1, hostPtr->addrLen);
  320.         bcopy(addr_list[i], hostPtr->addrList[i], hostPtr->addrLen);
  321.         }
  322.         hostPtr->addrList[i] = NULL;
  323.     }
  324. #ifdef verbose
  325.     if (headerPtr->aa || nscount == 0) {
  326.         hostPtr->servers = NULL;
  327.         return (SUCCESS);
  328.     }
  329. #else
  330.     hostPtr->servers = NULL;
  331.     return (SUCCESS);
  332. #endif
  333.     }
  334.  
  335.     /*
  336.      * At this point, for the T_A query type, only empty answers remain.
  337.      * For other query types, additional information might be found
  338.      * in the additional resource records part.
  339.      */
  340.  
  341.     if (!headerPtr->aa && (queryType != T_A) && (nscount > 0 || arcount > 0)) {
  342.     if (printedAnswers) {
  343.         putchar('\n');
  344.     }
  345.     printf("Authoritative answers can be found from:\n");
  346.     }
  347.  
  348.     cp = (u_char *)res_skip((char *) &answer, 2, eom);
  349.  
  350.     numServers = 0;
  351.     if (queryType != T_A) {
  352.     /*
  353.      * If we don't need to save the record, just print it.
  354.      */
  355.     while (--nscount >= 0 && cp < eom) {
  356.         if ((cp = (u_char *)Print_rr(cp,
  357.         (char *) &answer, eom, stdout)) == NULL) {
  358.         return(ERROR);
  359.         }
  360.     }
  361.     } else {
  362.     while (--nscount >= 0 && cp < eom) {
  363.         /*
  364.          *  Go through the NS records and retrieve the names of hosts
  365.          *  that serve the requested domain.
  366.          */
  367.  
  368.         if ((n = dn_expand((u_char *) &answer, eom, cp, bp, buflen)) < 0) {
  369.         return(ERROR);
  370.         }
  371.         cp += n;
  372.         len = strlen(bp) + 1;
  373.         dnamePtr = Calloc(1, len);   /* domain name */
  374.         bcopy(bp, dnamePtr, len);
  375.  
  376.         type  = GetShort(cp);
  377.         class = GetShort(cp);
  378.         cp   += sizeof(u_long);    /* skip TTL */
  379.         dlen  = GetShort(cp);
  380.  
  381.         if (type != T_NS) {
  382.         cp += dlen;
  383.         } else {
  384.         Boolean    found;
  385.  
  386.         if ((n =
  387.             dn_expand((u_char *) &answer, eom, cp, bp, buflen)) < 0) {
  388.             return(ERROR);
  389.         }
  390.         cp += n;
  391.         len = strlen(bp) + 1;
  392.         namePtr = Calloc(1, len); /* server host name */
  393.         bcopy(bp, namePtr, len);
  394.  
  395.         /*
  396.          * Store the information keyed by the server host name.
  397.          */
  398.         found = FALSE;
  399.         for (j = 0; j < numServers; j++) {
  400.             if (strcmp(namePtr, server[j].name) == 0) {
  401.             found = TRUE;
  402.             free(namePtr);
  403.             break;
  404.             }
  405.         }
  406.         if (found) {
  407.             server[j].numDomains++;
  408.             if (server[j].numDomains <= MAXDOMAINS) {
  409.             server[j].domain[server[j].numDomains-1] = dnamePtr;
  410.             }
  411.         } else {
  412.             if (numServers >= MAXSERVERS) {
  413.             break;
  414.             }
  415.             server[numServers].name = namePtr;
  416.             server[numServers].domain[0] = dnamePtr;
  417.             server[numServers].numDomains = 1;
  418.             server[numServers].numAddresses = 0;
  419.             numServers++;
  420.         }
  421.         }
  422.     }
  423.     }
  424.  
  425.     /*
  426.      * Additional resource records contain addresses of servers.
  427.      */
  428.     cp = (u_char *)res_skip((char *) &answer, 3, eom);
  429.  
  430.     if (queryType != T_A) {
  431.     /*
  432.      * If we don't need to save the record, just print it.
  433.      */
  434.     while (--arcount >= 0 && cp < eom) {
  435.         if ((cp = (u_char *)Print_rr(cp,
  436.         (char *) &answer, eom, stdout)) == NULL) {
  437.         return(ERROR);
  438.         }
  439.     }
  440.     } else {
  441.     while (--arcount >= 0 && cp < eom) {
  442.         if ((n = dn_expand((u_char *) &answer, eom, cp, bp, buflen)) < 0) {
  443.         break;
  444.         }
  445.         cp   += n;
  446.         type  = GetShort(cp);
  447.         class = GetShort(cp);
  448.         cp   += sizeof(u_long);    /* skip TTL */
  449.         dlen  = GetShort(cp);
  450.  
  451.         if (type != T_A)  {
  452.         cp += dlen;
  453.         continue;
  454.         } else {
  455.         for (j = 0; j < numServers; j++) {
  456.             if (strcmp(bp, server[j].name) == 0) {
  457.             server[j].numAddresses++;
  458.             if (server[j].numAddresses <= MAXADDRS) {
  459.                 server[j].address[server[j].numAddresses-1] = 
  460.                                     Calloc(1,dlen);
  461.                 bcopy(cp,
  462.                   server[j].address[server[j].numAddresses-1],dlen);
  463.                 break;
  464.             }
  465.             }
  466.         }
  467.         cp += dlen;
  468.         }
  469.     }
  470.     }
  471.  
  472.     /*
  473.      * If we are returning name server info, transfer it to the hostPtr.
  474.      */
  475.     if (numServers > 0) {
  476.     hostPtr->servers = (ServerInfo **)
  477.                 Calloc(numServers+1, sizeof(ServerInfo *));
  478.  
  479.     for (i = 0; i < numServers; i++) {
  480.         hostPtr->servers[i] = (ServerInfo *) Calloc(1, sizeof(ServerInfo));
  481.         hostPtr->servers[i]->name = server[i].name;
  482.  
  483.  
  484.         hostPtr->servers[i]->domains = (char **)
  485.                 Calloc(server[i].numDomains+1,sizeof(char *));
  486.         for (j = 0; j < server[i].numDomains; j++) {
  487.         hostPtr->servers[i]->domains[j] = server[i].domain[j];
  488.         }
  489.         hostPtr->servers[i]->domains[j] = NULL;
  490.  
  491.  
  492.         hostPtr->servers[i]->addrList = (char **)
  493.                 Calloc(server[i].numAddresses+1,sizeof(char *));
  494.         for (j = 0; j < server[i].numAddresses; j++) {
  495.         hostPtr->servers[i]->addrList[j] = server[i].address[j];
  496.         }
  497.         hostPtr->servers[i]->addrList[j] = NULL;
  498.  
  499.     }
  500.     hostPtr->servers[i] = NULL;
  501.     }
  502.  
  503.     switch (queryType) {
  504.     case T_A:
  505.         return NONAUTH;
  506.     case T_PTR:
  507.         if (iquery)
  508.             return NO_INFO;
  509.         /* fall through */
  510.     default:
  511.         return SUCCESS;
  512.     }
  513. }
  514.  
  515. /*
  516. *******************************************************************************
  517. *
  518. *  GetHostInfo --
  519. *
  520. *    Retrieves host name, address and alias information
  521. *    for a domain.
  522. *
  523. *    Algorithm from res_search().
  524. *
  525. *  Results:
  526. *    ERROR        - res_mkquery failed.
  527. *    + return values from GetAnswer()
  528. *
  529. *******************************************************************************
  530. */
  531.  
  532. int
  533. GetHostInfoByName(nsAddrPtr, queryClass, queryType, name, hostPtr, isServer)
  534.     struct in_addr    *nsAddrPtr;
  535.     int            queryClass;
  536.     int            queryType;
  537.     char        *name;
  538.     HostInfo        *hostPtr;
  539.     Boolean        isServer;
  540. {
  541.     int            n;
  542.     register int    result;
  543.     register char    *cp, **domain;
  544.     Boolean        got_nodata = FALSE;
  545.     unsigned long    ina;
  546.  
  547.     /* Catch explicit addresses */
  548.     if ((queryType == T_A) && IsAddr(name, &ina)) {
  549.     hostPtr->name = Calloc(strlen(name)+3, 1);
  550.     (void)sprintf(hostPtr->name,"[%s]",name);
  551.     hostPtr->aliases = NULL;
  552.     hostPtr->servers = NULL;
  553.     hostPtr->addrType = AF_INET;
  554.     hostPtr->addrLen = sizeof(struct in_addr);
  555.     hostPtr->addrList = (char **)Calloc(2, sizeof(char *));
  556.     hostPtr->addrList[0] = Calloc(sizeof(long), sizeof(char));
  557.     bcopy((char *)&ina, hostPtr->addrList[0], sizeof(ina));
  558.     hostPtr->addrList[1] = NULL;
  559.     return(SUCCESS);
  560.     }
  561.  
  562.     result = NXDOMAIN;
  563.     for (cp = name, n = 0; *cp; cp++)
  564.         if (*cp == '.')
  565.             n++;
  566.     if (n == 0 && (cp = hostalias(name))) {
  567.         printf("Aliased to \"%s\"\n\n", cp);
  568.         return (GetHostDomain(nsAddrPtr, queryClass, queryType,
  569.             cp, (char *)NULL, hostPtr, isServer));
  570.     }
  571.     /*
  572.      * We do at least one level of search if
  573.      *    - there is no dot and RES_DEFNAME is set, or
  574.      *    - there is at least one dot, there is no trailing dot,
  575.      *      and RES_DNSRCH is set.
  576.      */
  577.     if ((n == 0 && _res.options & RES_DEFNAMES) ||
  578.        (n != 0 && *--cp != '.' && _res.options & RES_DNSRCH))
  579.      for (domain = _res.dnsrch; *domain; domain++) {
  580.         result = GetHostDomain(nsAddrPtr, queryClass, queryType,
  581.             name, *domain, hostPtr, isServer);
  582.         /*
  583.          * If no server present, give up.
  584.          * If name isn't found in this domain,
  585.          * keep trying higher domains in the search list
  586.          * (if that's enabled).
  587.          * On a NO_INFO error, keep trying, otherwise
  588.          * a wildcard entry of another type could keep us
  589.          * from finding this entry higher in the domain.
  590.          * If we get some other error (negative answer or
  591.          * server failure), then stop searching up,
  592.          * but try the input name below in case it's fully-qualified.
  593.          */
  594.         if (result == SUCCESS || result == NO_RESPONSE)
  595.             return result;
  596.         if (result == NO_INFO)
  597.             got_nodata++;
  598.         if ((result != NXDOMAIN && result != NO_INFO) ||
  599.         (_res.options & RES_DNSRCH) == 0)
  600.             break;
  601.     }
  602.     /*
  603.      * If the search/default failed, try the name as fully-qualified,
  604.      * but only if it contained at least one dot (even trailing).
  605.      * This is purely a heuristic; we assume that any reasonable query
  606.      * about a top-level domain (for servers, SOA, etc) will not use
  607.      * res_search.
  608.      */
  609.     if (n && (result = GetHostDomain(nsAddrPtr, queryClass, queryType,
  610.             name, (char *)NULL, hostPtr, isServer)) == SUCCESS)
  611.         return result;
  612.     if (got_nodata)
  613.     result = NO_INFO;
  614.     return (result);
  615. }
  616.  
  617. /*
  618.  * Perform a query on the concatenation of name and domain,
  619.  * removing a trailing dot from name if domain is NULL.
  620.  */
  621. GetHostDomain(nsAddrPtr, queryClass, queryType, name, domain, hostPtr, isServer)
  622.     struct in_addr    *nsAddrPtr;
  623.     int            queryClass;
  624.     int            queryType;
  625.     char        *name, *domain;
  626.     HostInfo        *hostPtr;
  627.     Boolean        isServer;
  628. {
  629.     querybuf buf;
  630.     char nbuf[2*MAXDNAME+2];
  631.     char *longname = nbuf;
  632.     int n;
  633.  
  634.     if (domain == NULL) {
  635.         /*
  636.          * Check for trailing '.';
  637.          * copy without '.' if present.
  638.          */
  639.         n = strlen(name) - 1;
  640.         if (name[n] == '.' && n < sizeof(nbuf) - 1) {
  641.             bcopy(name, nbuf, n);
  642.             nbuf[n] = '\0';
  643.         } else
  644.             longname = name;
  645.     } else {
  646.         (void)sprintf(nbuf, "%.*s.%.*s",
  647.             MAXDNAME, name, MAXDNAME, domain);
  648.         longname = nbuf;
  649.     }
  650.     n = res_mkquery(QUERY, longname, queryClass, queryType,
  651.             (char *)0, 0, 0, (char *) &buf, sizeof(buf));
  652.     if (n < 0) {
  653.     if (_res.options & RES_DEBUG) {
  654.         printf("Res_mkquery failed\n");
  655.     }
  656.     return (ERROR);
  657.     }
  658.  
  659.     n = GetAnswer(nsAddrPtr, queryType, (char *)&buf, n, 0, hostPtr, isServer);
  660.  
  661.     /*
  662.      * GetAnswer didn't find a name, so set it to the specified one.
  663.      */
  664.     if (n == NONAUTH) {
  665.     if (hostPtr->name == NULL) {
  666.         int len = strlen(longname) + 1;
  667.         hostPtr->name = Calloc(len, sizeof(char));
  668.         bcopy(longname, hostPtr->name, len);
  669.     }
  670.     }
  671.     return(n);
  672. }
  673.  
  674.  
  675. /*
  676. *******************************************************************************
  677. *
  678. *  GetHostInfoByAddr --
  679. *
  680. *    Performs an inverse query to find the host name
  681. *    that corresponds to the given address.
  682. *
  683. *  Results:
  684. *    ERROR        - res_mkquery failed.
  685. *    + return values from GetAnswer()
  686. *
  687. *******************************************************************************
  688. */
  689.  
  690. int
  691. GetHostInfoByAddr(nsAddrPtr, address, hostPtr)
  692.     struct in_addr    *nsAddrPtr;
  693.     struct in_addr    *address;
  694.     HostInfo        *hostPtr;
  695. {
  696.     int        n;
  697.     querybuf    buf;
  698.     char    qbuf[MAXDNAME];
  699.     char    *p = (char *) &address->s_addr;
  700.  
  701.     (void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa",
  702.         ((unsigned)p[3] & 0xff),
  703.         ((unsigned)p[2] & 0xff),
  704.         ((unsigned)p[1] & 0xff),
  705.         ((unsigned)p[0] & 0xff));
  706.     n = res_mkquery(QUERY, qbuf, C_IN, T_PTR,
  707.         NULL,  0, NULL, (char *) &buf, sizeof(buf));
  708.     if (n < 0) {
  709.     if (_res.options & RES_DEBUG) {
  710.         printf("res_mkquery() failed\n");
  711.     }
  712.     return (ERROR);
  713.     }
  714.     n = GetAnswer(nsAddrPtr, T_PTR, (char *) &buf, n, 1, hostPtr, 1);
  715.     if (n == SUCCESS) {
  716.     hostPtr->addrType = AF_INET;
  717.     hostPtr->addrLen = 4;
  718.     hostPtr->addrList = (char **)Calloc(2, sizeof(char *));
  719.     hostPtr->addrList[0] = Calloc(sizeof(long), sizeof(char));
  720.     bcopy((char *)p, hostPtr->addrList[0], sizeof(struct in_addr));
  721.     hostPtr->addrList[1] = NULL;
  722.     }
  723.     return n;
  724. }
  725.  
  726. /*
  727. *******************************************************************************
  728. *
  729. *  FreeHostInfoPtr --
  730. *
  731. *    Deallocates all the calloc'd areas for a HostInfo variable.
  732. *
  733. *******************************************************************************
  734. */
  735.  
  736. void
  737. FreeHostInfoPtr(hostPtr)
  738.     register HostInfo *hostPtr;
  739. {
  740.     int i, j;
  741.  
  742.     if (hostPtr->name != NULL) {
  743.     free(hostPtr->name);
  744.     hostPtr->name = NULL;
  745.     }
  746.  
  747.     if (hostPtr->aliases != NULL) {
  748.     i = 0;
  749.     while (hostPtr->aliases[i] != NULL) {
  750.         free(hostPtr->aliases[i]);
  751.         i++;
  752.     }
  753.     free((char *)hostPtr->aliases);
  754.     hostPtr->aliases = NULL;
  755.     }
  756.  
  757.     if (hostPtr->addrList != NULL) {
  758.     i = 0;
  759.     while (hostPtr->addrList[i] != NULL) {
  760.         free(hostPtr->addrList[i]);
  761.         i++;
  762.     }
  763.     free((char *)hostPtr->addrList);
  764.     hostPtr->addrList = NULL;
  765.     }
  766.  
  767.     if (hostPtr->servers != NULL) {
  768.     i = 0;
  769.     while (hostPtr->servers[i] != NULL) {
  770.  
  771.         if (hostPtr->servers[i]->name != NULL) {
  772.         free(hostPtr->servers[i]->name);
  773.         }
  774.  
  775.         if (hostPtr->servers[i]->domains != NULL) {
  776.         j = 0;
  777.         while (hostPtr->servers[i]->domains[j] != NULL) {
  778.             free(hostPtr->servers[i]->domains[j]);
  779.             j++;
  780.         }
  781.         free((char *)hostPtr->servers[i]->domains);
  782.         }
  783.  
  784.         if (hostPtr->servers[i]->addrList != NULL) {
  785.         j = 0;
  786.         while (hostPtr->servers[i]->addrList[j] != NULL) {
  787.             free(hostPtr->servers[i]->addrList[j]);
  788.             j++;
  789.         }
  790.         free((char *)hostPtr->servers[i]->addrList);
  791.         }
  792.         free((char *)hostPtr->servers[i]);
  793.         i++;
  794.     }
  795.     free((char *)hostPtr->servers);
  796.     hostPtr->servers = NULL;
  797.     }
  798. }
  799.