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