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