2003-06-03 11:33:24 +04:00
|
|
|
|
/* $NetBSD: getinfo.c,v 1.6 2003/06/03 07:33:43 itojun Exp $ */
|
1999-11-20 21:53:57 +03:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Copyright (c) 1985, 1989
|
|
|
|
|
* The Regents of the University of California. All rights reserved.
|
|
|
|
|
*
|
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
|
* are met:
|
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
|
* 3. All advertising materials mentioning features or use of this software
|
|
|
|
|
* must display the following acknowledgement:
|
|
|
|
|
* This product includes software developed by the University of
|
|
|
|
|
* California, Berkeley and its contributors.
|
|
|
|
|
* 4. Neither the name of the University nor the names of its contributors
|
|
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
|
* without specific prior written permission.
|
|
|
|
|
*
|
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Portions Copyright (c) 1993 by Digital Equipment Corporation.
|
|
|
|
|
*
|
|
|
|
|
* Permission to use, copy, modify, and distribute this software for any
|
|
|
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
|
|
|
* copyright notice and this permission notice appear in all copies, and that
|
|
|
|
|
* the name of Digital Equipment Corporation not be used in advertising or
|
|
|
|
|
* publicity pertaining to distribution of the document or software without
|
|
|
|
|
* specific, written prior permission.
|
|
|
|
|
*
|
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
|
|
|
|
|
* WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
|
|
|
|
|
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
|
|
|
|
|
* CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
|
|
|
|
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
|
|
|
|
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
|
|
|
|
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
|
|
|
|
* SOFTWARE.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#ifndef lint
|
|
|
|
|
static const char sccsid[] = "@(#)getinfo.c 5.26 (Berkeley) 3/21/91";
|
2003-06-03 11:33:24 +04:00
|
|
|
|
static const char rcsid[] = "Id: getinfo.c,v 8.29.8.2 2003/06/02 09:24:39 marka Exp";
|
1999-11-20 21:53:57 +03:00
|
|
|
|
#endif /* not lint */
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
******************************************************************************
|
|
|
|
|
*
|
|
|
|
|
* getinfo.c --
|
|
|
|
|
*
|
|
|
|
|
* Routines to create requests to name servers
|
|
|
|
|
* and interpret the answers.
|
|
|
|
|
*
|
|
|
|
|
* Adapted from 4.3BSD BIND gethostnamadr.c
|
|
|
|
|
*
|
|
|
|
|
******************************************************************************
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "port_before.h"
|
|
|
|
|
|
|
|
|
|
#include <sys/param.h>
|
|
|
|
|
#include <sys/socket.h>
|
|
|
|
|
|
|
|
|
|
#include <netinet/in.h>
|
|
|
|
|
#include <arpa/nameser.h>
|
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
|
|
|
|
|
|
#include <ctype.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
#include "port_after.h"
|
|
|
|
|
|
2002-06-20 15:42:53 +04:00
|
|
|
|
#include <resolv.h>
|
1999-11-20 21:53:57 +03:00
|
|
|
|
|
2002-06-20 15:42:53 +04:00
|
|
|
|
#include "res.h"
|
1999-11-20 21:53:57 +03:00
|
|
|
|
|
|
|
|
|
static char *addr_list[MAXADDRS + 1];
|
2002-06-20 15:42:53 +04:00
|
|
|
|
static int addr_len[MAXADDRS + 1];
|
|
|
|
|
static int addr_type[MAXADDRS + 1];
|
1999-11-20 21:53:57 +03:00
|
|
|
|
|
|
|
|
|
static char *host_aliases[MAXALIASES];
|
|
|
|
|
static int host_aliases_len[MAXALIASES];
|
|
|
|
|
static u_char hostbuf[MAXDNAME];
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
char *name;
|
|
|
|
|
char *domain[MAXDOMAINS];
|
|
|
|
|
int numDomains;
|
|
|
|
|
char *address[MAXADDRS];
|
2002-06-20 15:42:53 +04:00
|
|
|
|
char len[MAXADDRS];
|
|
|
|
|
char type[MAXADDRS];
|
1999-11-20 21:53:57 +03:00
|
|
|
|
int numAddresses;
|
|
|
|
|
} ServerTable;
|
|
|
|
|
|
|
|
|
|
ServerTable server[MAXSERVERS];
|
|
|
|
|
|
|
|
|
|
typedef union {
|
|
|
|
|
HEADER qb1;
|
2003-06-03 11:33:24 +04:00
|
|
|
|
u_char qb2[NS_MAXMSG];
|
1999-11-20 21:53:57 +03:00
|
|
|
|
} querybuf;
|
|
|
|
|
|
|
|
|
|
typedef union {
|
|
|
|
|
int32_t al;
|
|
|
|
|
char ac;
|
|
|
|
|
} align;
|
|
|
|
|
|
|
|
|
|
#define GetShort(cp) ns_get16(cp); cp += INT16SZ;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
******************************************************************************
|
|
|
|
|
*
|
|
|
|
|
* GetAnswer --
|
|
|
|
|
*
|
|
|
|
|
* Interprets an answer packet and retrieves the following
|
|
|
|
|
* information:
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* SUCCESS the info was retrieved.
|
|
|
|
|
* NO_INFO the packet did not contain an answer.
|
|
|
|
|
* NONAUTH non-authoritative information was found.
|
|
|
|
|
* ERROR the answer was malformed.
|
|
|
|
|
* Other errors returned in the packet header.
|
|
|
|
|
*
|
|
|
|
|
******************************************************************************
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static int
|
2002-06-20 15:42:53 +04:00
|
|
|
|
GetAnswer(union res_sockaddr_union *nsAddrPtr, int queryType,
|
|
|
|
|
char *msg, int msglen, Boolean iquery, HostInfo *hostPtr,
|
|
|
|
|
Boolean isServer, Boolean merge)
|
1999-11-20 21:53:57 +03:00
|
|
|
|
{
|
|
|
|
|
register HEADER *headerPtr;
|
2002-06-20 15:42:53 +04:00
|
|
|
|
register const u_char *cp;
|
1999-11-20 21:53:57 +03:00
|
|
|
|
querybuf answer;
|
|
|
|
|
char **aliasPtr;
|
2003-06-03 11:33:24 +04:00
|
|
|
|
u_char *eom, *bp, *ep;
|
1999-11-20 21:53:57 +03:00
|
|
|
|
char **addrPtr;
|
2002-06-20 15:42:53 +04:00
|
|
|
|
int *lenPtr;
|
|
|
|
|
int *typePtr;
|
1999-11-20 21:53:57 +03:00
|
|
|
|
char *namePtr;
|
|
|
|
|
char *dnamePtr;
|
|
|
|
|
int type, class;
|
2003-06-03 11:33:24 +04:00
|
|
|
|
int qdcount, ancount, arcount, nscount;
|
2002-06-20 15:42:53 +04:00
|
|
|
|
int origClass = 0;
|
1999-11-20 21:53:57 +03:00
|
|
|
|
int numAliases = 0;
|
|
|
|
|
int numAddresses = 0;
|
2002-06-20 15:42:53 +04:00
|
|
|
|
int n, i, j, k, l, m;
|
1999-11-20 21:53:57 +03:00
|
|
|
|
int dlen;
|
|
|
|
|
int status;
|
|
|
|
|
int numServers;
|
|
|
|
|
size_t s;
|
|
|
|
|
Boolean haveAnswer;
|
|
|
|
|
Boolean printedAnswers = FALSE;
|
2002-06-20 15:42:53 +04:00
|
|
|
|
int oldAliases;
|
|
|
|
|
char **newAliases;
|
|
|
|
|
int oldServers;
|
|
|
|
|
ServerInfo **newServers;
|
|
|
|
|
int oldAddresses;
|
|
|
|
|
AddrInfo **newAddresses;
|
1999-11-20 21:53:57 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If the hostPtr was used before, free up the calloc'd areas.
|
|
|
|
|
*/
|
2002-06-20 15:42:53 +04:00
|
|
|
|
if (!merge)
|
|
|
|
|
FreeHostInfoPtr(hostPtr);
|
1999-11-20 21:53:57 +03:00
|
|
|
|
|
2001-05-18 02:59:37 +04:00
|
|
|
|
status = SendRequest(nsAddrPtr, (u_char *)msg, msglen, (u_char *) &answer,
|
1999-11-20 21:53:57 +03:00
|
|
|
|
sizeof(answer), &n);
|
|
|
|
|
|
|
|
|
|
if (status != SUCCESS) {
|
|
|
|
|
if (res.options & RES_DEBUG2)
|
|
|
|
|
printf("SendRequest failed\n");
|
|
|
|
|
return (status);
|
|
|
|
|
}
|
|
|
|
|
eom = (u_char *) &answer + n;
|
|
|
|
|
|
|
|
|
|
headerPtr = (HEADER *) &answer;
|
|
|
|
|
|
|
|
|
|
if (headerPtr->rcode != NOERROR) {
|
|
|
|
|
return (headerPtr->rcode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
qdcount = ntohs(headerPtr->qdcount);
|
|
|
|
|
ancount = ntohs(headerPtr->ancount);
|
|
|
|
|
arcount = ntohs(headerPtr->arcount);
|
|
|
|
|
nscount = ntohs(headerPtr->nscount);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If there are no answer, n.s. or additional records
|
|
|
|
|
* then return with an error.
|
|
|
|
|
*/
|
|
|
|
|
if (ancount == 0 && nscount == 0 && arcount == 0) {
|
|
|
|
|
return (NO_INFO);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2003-06-03 11:33:24 +04:00
|
|
|
|
bp = hostbuf;
|
|
|
|
|
ep = hostbuf + sizeof(hostbuf);
|
|
|
|
|
cp = (u_char *) &answer + HFIXEDSZ;
|
1999-11-20 21:53:57 +03:00
|
|
|
|
|
|
|
|
|
/* Skip over question section. */
|
|
|
|
|
while (qdcount-- > 0) {
|
|
|
|
|
n = dn_skipname(cp, eom);
|
|
|
|
|
if (n < 0)
|
|
|
|
|
return (ERROR);
|
|
|
|
|
cp += n + QFIXEDSZ;
|
|
|
|
|
if (cp > eom)
|
|
|
|
|
return (ERROR);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
aliasPtr = host_aliases;
|
|
|
|
|
addrPtr = addr_list;
|
2002-06-20 15:42:53 +04:00
|
|
|
|
lenPtr = addr_len;
|
|
|
|
|
typePtr = addr_type;
|
1999-11-20 21:53:57 +03:00
|
|
|
|
haveAnswer = FALSE;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Scan through the answer resource records.
|
|
|
|
|
* Answers for address query types are saved.
|
|
|
|
|
* Other query type answers are just printed.
|
|
|
|
|
*/
|
|
|
|
|
if (ancount != 0) {
|
|
|
|
|
|
|
|
|
|
if (headerPtr->ad)
|
|
|
|
|
printf("Answer crypto-validated by server:\n");
|
|
|
|
|
|
|
|
|
|
if (!isServer && !headerPtr->aa) {
|
|
|
|
|
printf("Non-authoritative answer:\n");
|
|
|
|
|
}
|
|
|
|
|
|
2002-06-20 15:42:53 +04:00
|
|
|
|
if (queryType != T_A && queryType != T_AAAA && /* A6? */
|
|
|
|
|
!(iquery && queryType == T_PTR)) {
|
1999-11-20 21:53:57 +03:00
|
|
|
|
while (--ancount >= 0 && cp < eom) {
|
2002-06-20 15:42:53 +04:00
|
|
|
|
if ((cp = Print_rr(cp, (u_char *)&answer,
|
|
|
|
|
eom, stdout)) == NULL) {
|
1999-11-20 21:53:57 +03:00
|
|
|
|
return(ERROR);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
printedAnswers = TRUE;
|
|
|
|
|
} else {
|
|
|
|
|
while (--ancount >= 0 && cp < eom) {
|
2003-06-03 11:33:24 +04:00
|
|
|
|
n = dn_expand(answer.qb2, eom, cp, (char *)bp, ep - bp);
|
1999-11-20 21:53:57 +03:00
|
|
|
|
if (n < 0)
|
|
|
|
|
return(ERROR);
|
|
|
|
|
cp += n;
|
|
|
|
|
if (cp + 3 * INT16SZ + INT32SZ > eom)
|
|
|
|
|
return (ERROR);
|
|
|
|
|
type = GetShort(cp);
|
|
|
|
|
class = GetShort(cp);
|
|
|
|
|
cp += INT32SZ; /* skip TTL */
|
|
|
|
|
dlen = GetShort(cp);
|
|
|
|
|
if (cp + dlen > eom)
|
|
|
|
|
return (ERROR);
|
|
|
|
|
if (type == T_CNAME) {
|
|
|
|
|
/*
|
|
|
|
|
* Found an alias.
|
|
|
|
|
*/
|
|
|
|
|
cp += dlen;
|
|
|
|
|
if (aliasPtr >= &host_aliases[MAXALIASES-1]) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
*aliasPtr++ = (char *)bp;
|
|
|
|
|
s = strlen((char *)bp) + 1;
|
|
|
|
|
host_aliases_len[numAliases] = s;
|
|
|
|
|
numAliases++;
|
|
|
|
|
bp += s;
|
|
|
|
|
continue;
|
|
|
|
|
} else if (type == T_PTR) {
|
|
|
|
|
/*
|
|
|
|
|
* Found a "pointer" to the real name.
|
|
|
|
|
*/
|
2003-06-03 11:33:24 +04:00
|
|
|
|
n = dn_expand(answer.qb2, eom, cp, (char *)bp, ep - bp);
|
1999-11-20 21:53:57 +03:00
|
|
|
|
if (n < 0) {
|
|
|
|
|
cp += n;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
cp += n;
|
|
|
|
|
s = strlen((char *)bp) + 1;
|
|
|
|
|
hostPtr->name = Calloc(1, s);
|
|
|
|
|
memcpy(hostPtr->name, bp, s);
|
|
|
|
|
haveAnswer = TRUE;
|
|
|
|
|
break;
|
2002-06-20 15:42:53 +04:00
|
|
|
|
} else if (type != T_A && type != T_AAAA) {
|
1999-11-20 21:53:57 +03:00
|
|
|
|
cp += dlen;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2002-06-20 15:42:53 +04:00
|
|
|
|
if (type == T_A && dlen != INADDRSZ)
|
|
|
|
|
return (ERROR);
|
|
|
|
|
if (type == T_AAAA && dlen != 16)
|
1999-11-20 21:53:57 +03:00
|
|
|
|
return (ERROR);
|
|
|
|
|
if (haveAnswer) {
|
|
|
|
|
/*
|
|
|
|
|
* If we've already got 1 address, we aren't interested
|
2002-06-20 15:42:53 +04:00
|
|
|
|
* in addresses with a different class.
|
1999-11-20 21:53:57 +03:00
|
|
|
|
*/
|
|
|
|
|
if (class != origClass) {
|
|
|
|
|
cp += dlen;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
/*
|
2002-06-20 15:42:53 +04:00
|
|
|
|
* First address: record its class so we only save
|
|
|
|
|
* additonal ones with the same attributes.
|
1999-11-20 21:53:57 +03:00
|
|
|
|
*/
|
|
|
|
|
origClass = class;
|
2002-06-20 15:42:53 +04:00
|
|
|
|
if (hostPtr->name == NULL) {
|
|
|
|
|
s = strlen((char *)bp) + 1;
|
|
|
|
|
hostPtr->name = Calloc(1, s);
|
|
|
|
|
memcpy(hostPtr->name, bp, s);
|
|
|
|
|
}
|
1999-11-20 21:53:57 +03:00
|
|
|
|
}
|
1999-11-20 23:03:47 +03:00
|
|
|
|
bp += (((size_t)bp) % sizeof(align));
|
1999-11-20 21:53:57 +03:00
|
|
|
|
|
|
|
|
|
if (bp + dlen >= &hostbuf[sizeof(hostbuf)]) {
|
|
|
|
|
if (res.options & RES_DEBUG) {
|
|
|
|
|
printf("Size (%d) too big\n", dlen);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (numAddresses >= MAXADDRS) {
|
|
|
|
|
printf("MAXADDRS exceeded: skipping address\n");
|
|
|
|
|
cp += dlen;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
memcpy(*addrPtr++ = (char *)bp, cp, dlen);
|
2002-06-20 15:42:53 +04:00
|
|
|
|
*lenPtr++ = dlen;
|
|
|
|
|
*typePtr++ = (class == C_IN) ?
|
|
|
|
|
((type == T_A) ? AF_INET : AF_INET6) :
|
|
|
|
|
AF_UNSPEC;
|
1999-11-20 21:53:57 +03:00
|
|
|
|
bp += dlen;
|
|
|
|
|
cp += dlen;
|
|
|
|
|
numAddresses++;
|
|
|
|
|
haveAnswer = TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2002-06-20 15:42:53 +04:00
|
|
|
|
if ((queryType == T_A || queryType == T_AAAA || queryType == T_PTR) &&
|
|
|
|
|
haveAnswer) {
|
1999-11-20 21:53:57 +03:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Go through the alias and address lists and return them
|
|
|
|
|
* in the hostPtr variable.
|
|
|
|
|
*/
|
|
|
|
|
|
2002-06-20 15:42:53 +04:00
|
|
|
|
oldAliases = 0;
|
|
|
|
|
if (merge && hostPtr->aliases != NULL) {
|
|
|
|
|
while (hostPtr->aliases[oldAliases] != NULL)
|
|
|
|
|
oldAliases++;
|
|
|
|
|
}
|
1999-11-20 21:53:57 +03:00
|
|
|
|
if (numAliases > 0) {
|
2002-06-20 15:42:53 +04:00
|
|
|
|
newAliases =
|
|
|
|
|
(char **) Calloc(1 + numAliases + oldAliases, sizeof(char *));
|
|
|
|
|
if (merge && hostPtr->aliases != NULL) {
|
|
|
|
|
memcpy(newAliases, hostPtr->aliases,
|
|
|
|
|
oldAliases * sizeof(char *));
|
|
|
|
|
free(hostPtr->aliases);
|
|
|
|
|
}
|
|
|
|
|
hostPtr->aliases = newAliases;
|
|
|
|
|
k = oldAliases;
|
1999-11-20 21:53:57 +03:00
|
|
|
|
for (i = 0; i < numAliases; i++) {
|
2002-06-20 15:42:53 +04:00
|
|
|
|
for (l = 0; l < k; l++)
|
|
|
|
|
if (!strcasecmp(hostPtr->aliases[l], host_aliases[i]))
|
|
|
|
|
break;
|
|
|
|
|
if (l < k)
|
|
|
|
|
continue;
|
|
|
|
|
hostPtr->aliases[k] = Calloc(1, host_aliases_len[i]);
|
|
|
|
|
memcpy(hostPtr->aliases[k], host_aliases[i],
|
1999-11-20 21:53:57 +03:00
|
|
|
|
host_aliases_len[i]);
|
2002-06-20 15:42:53 +04:00
|
|
|
|
k++;
|
1999-11-20 21:53:57 +03:00
|
|
|
|
}
|
2002-06-20 15:42:53 +04:00
|
|
|
|
hostPtr->aliases[k] = NULL;
|
|
|
|
|
}
|
|
|
|
|
oldAddresses = 0;
|
|
|
|
|
if (merge && hostPtr->addrList != NULL) {
|
|
|
|
|
while (hostPtr->addrList[oldAddresses] != NULL)
|
|
|
|
|
oldAddresses++;
|
1999-11-20 21:53:57 +03:00
|
|
|
|
}
|
|
|
|
|
if (numAddresses > 0) {
|
2002-06-20 15:42:53 +04:00
|
|
|
|
newAddresses =
|
|
|
|
|
(AddrInfo **)Calloc(1+numAddresses, sizeof(AddrInfo *));
|
|
|
|
|
if (merge && hostPtr->addrList != NULL) {
|
|
|
|
|
memcpy(newAddresses, hostPtr->addrList,
|
|
|
|
|
oldAddresses * sizeof(char *));
|
|
|
|
|
free(hostPtr->addrList);
|
|
|
|
|
}
|
|
|
|
|
hostPtr->addrList = newAddresses;
|
|
|
|
|
k = oldAddresses;
|
1999-11-20 21:53:57 +03:00
|
|
|
|
for (i = 0; i < numAddresses; i++) {
|
2002-06-20 15:42:53 +04:00
|
|
|
|
for (l = 0; l < k; l++)
|
|
|
|
|
if (hostPtr->addrList[l]->addrType == addr_type[i] &&
|
|
|
|
|
hostPtr->addrList[l]->addrLen == addr_len[i] &&
|
|
|
|
|
!memcmp(hostPtr->addrList[l]->addr, addr_list[i],
|
|
|
|
|
addr_len[i]))
|
|
|
|
|
break;
|
|
|
|
|
if (l < k)
|
|
|
|
|
continue;
|
|
|
|
|
hostPtr->addrList[k] = (AddrInfo*)Calloc(1, sizeof(AddrInfo));
|
|
|
|
|
hostPtr->addrList[k]->addr = Calloc(1, addr_len[i]);
|
|
|
|
|
hostPtr->addrList[k]->addrType = addr_type[i];
|
|
|
|
|
hostPtr->addrList[k]->addrLen = addr_len[i];
|
|
|
|
|
memcpy(hostPtr->addrList[k]->addr, addr_list[i], addr_len[i]);
|
|
|
|
|
k++;
|
1999-11-20 21:53:57 +03:00
|
|
|
|
}
|
2002-06-20 15:42:53 +04:00
|
|
|
|
hostPtr->addrList[k] = NULL;
|
1999-11-20 21:53:57 +03:00
|
|
|
|
}
|
|
|
|
|
#ifdef verbose
|
|
|
|
|
if (headerPtr->aa || nscount == 0) {
|
|
|
|
|
hostPtr->servers = NULL;
|
|
|
|
|
return (SUCCESS);
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
hostPtr->servers = NULL;
|
|
|
|
|
return (SUCCESS);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* At this point, for the T_A query type, only empty answers remain.
|
|
|
|
|
* For other query types, additional information might be found
|
|
|
|
|
* in the additional resource records part.
|
|
|
|
|
*/
|
|
|
|
|
|
2002-06-20 15:42:53 +04:00
|
|
|
|
if (!headerPtr->aa && (queryType != T_A) && (queryType != T_AAAA) &&
|
|
|
|
|
(nscount > 0 || arcount > 0)) {
|
1999-11-20 21:53:57 +03:00
|
|
|
|
if (printedAnswers) {
|
|
|
|
|
putchar('\n');
|
|
|
|
|
}
|
|
|
|
|
printf("Authoritative answers can be found from:\n");
|
|
|
|
|
}
|
|
|
|
|
|
2002-06-20 15:42:53 +04:00
|
|
|
|
cp = res_skip((u_char *)&answer, 2, eom);
|
1999-11-20 21:53:57 +03:00
|
|
|
|
|
|
|
|
|
numServers = 0;
|
2002-06-20 15:42:53 +04:00
|
|
|
|
if (queryType != T_A && queryType != T_AAAA) {
|
1999-11-20 21:53:57 +03:00
|
|
|
|
/*
|
|
|
|
|
* If we don't need to save the record, just print it.
|
|
|
|
|
*/
|
|
|
|
|
while (--nscount >= 0 && cp < eom) {
|
2002-06-20 15:42:53 +04:00
|
|
|
|
if ((cp = Print_rr(cp, (u_char *) &answer,
|
|
|
|
|
eom, stdout)) == NULL) {
|
1999-11-20 21:53:57 +03:00
|
|
|
|
return(ERROR);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
while (--nscount >= 0 && cp < eom) {
|
|
|
|
|
/*
|
|
|
|
|
* Go through the NS records and retrieve the names of hosts
|
|
|
|
|
* that serve the requested domain.
|
|
|
|
|
*/
|
|
|
|
|
|
2003-06-03 11:33:24 +04:00
|
|
|
|
n = dn_expand(answer.qb2, eom, cp, (char *)bp, ep - bp);
|
1999-11-20 21:53:57 +03:00
|
|
|
|
if (n < 0) {
|
|
|
|
|
return(ERROR);
|
|
|
|
|
}
|
|
|
|
|
cp += n;
|
|
|
|
|
s = strlen((char *)bp) + 1;
|
|
|
|
|
dnamePtr = Calloc(1, s); /* domain name */
|
|
|
|
|
memcpy(dnamePtr, bp, s);
|
|
|
|
|
|
|
|
|
|
if (cp + 3 * INT16SZ + INT32SZ > eom)
|
|
|
|
|
return (ERROR);
|
|
|
|
|
type = GetShort(cp);
|
|
|
|
|
class = GetShort(cp);
|
|
|
|
|
cp += INT32SZ; /* skip TTL */
|
|
|
|
|
dlen = GetShort(cp);
|
|
|
|
|
if (cp + dlen > eom)
|
|
|
|
|
return (ERROR);
|
|
|
|
|
|
|
|
|
|
if (type != T_NS) {
|
|
|
|
|
cp += dlen;
|
|
|
|
|
} else {
|
|
|
|
|
Boolean found;
|
|
|
|
|
|
2003-06-03 11:33:24 +04:00
|
|
|
|
n = dn_expand(answer.qb2, eom, cp, (char *)bp, ep - bp);
|
1999-11-20 21:53:57 +03:00
|
|
|
|
if (n < 0) {
|
|
|
|
|
return(ERROR);
|
|
|
|
|
}
|
|
|
|
|
cp += n;
|
|
|
|
|
s = strlen((char *)bp) + 1;
|
|
|
|
|
namePtr = Calloc(1, s); /* server host name */
|
|
|
|
|
memcpy(namePtr, bp, s);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Store the information keyed by the server host name.
|
|
|
|
|
*/
|
|
|
|
|
found = FALSE;
|
|
|
|
|
for (j = 0; j < numServers; j++) {
|
2002-06-20 15:42:53 +04:00
|
|
|
|
if (strcasecmp(namePtr, server[j].name) == 0) {
|
1999-11-20 21:53:57 +03:00
|
|
|
|
found = TRUE;
|
|
|
|
|
free(namePtr);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (found) {
|
|
|
|
|
server[j].numDomains++;
|
|
|
|
|
if (server[j].numDomains <= MAXDOMAINS) {
|
|
|
|
|
server[j].domain[server[j].numDomains-1] = dnamePtr;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (numServers >= MAXSERVERS) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
server[numServers].name = namePtr;
|
|
|
|
|
server[numServers].domain[0] = dnamePtr;
|
|
|
|
|
server[numServers].numDomains = 1;
|
|
|
|
|
server[numServers].numAddresses = 0;
|
|
|
|
|
numServers++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Additional resource records contain addresses of servers.
|
|
|
|
|
*/
|
2002-06-20 15:42:53 +04:00
|
|
|
|
cp = res_skip((u_char*)&answer, 3, eom);
|
1999-11-20 21:53:57 +03:00
|
|
|
|
|
2002-06-20 15:42:53 +04:00
|
|
|
|
if (queryType != T_A && queryType != T_AAAA) {
|
1999-11-20 21:53:57 +03:00
|
|
|
|
/*
|
|
|
|
|
* If we don't need to save the record, just print it.
|
|
|
|
|
*/
|
|
|
|
|
while (--arcount >= 0 && cp < eom) {
|
2002-06-20 15:42:53 +04:00
|
|
|
|
if ((cp = Print_rr(cp, (u_char *) &answer,
|
|
|
|
|
eom, stdout)) == NULL) {
|
1999-11-20 21:53:57 +03:00
|
|
|
|
return(ERROR);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
while (--arcount >= 0 && cp < eom) {
|
2003-06-03 11:33:24 +04:00
|
|
|
|
n = dn_expand(answer.qb2, eom, cp, (char *)bp, ep - bp);
|
1999-11-20 21:53:57 +03:00
|
|
|
|
if (n < 0) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
cp += n;
|
|
|
|
|
if (cp + 3 * INT16SZ + INT32SZ > eom)
|
|
|
|
|
return (ERROR);
|
|
|
|
|
type = GetShort(cp);
|
|
|
|
|
class = GetShort(cp);
|
|
|
|
|
cp += INT32SZ; /* skip TTL */
|
|
|
|
|
dlen = GetShort(cp);
|
|
|
|
|
if (cp + dlen > eom)
|
|
|
|
|
return (ERROR);
|
|
|
|
|
|
2002-06-20 15:42:53 +04:00
|
|
|
|
if (type != T_A && type != T_AAAA) {
|
1999-11-20 21:53:57 +03:00
|
|
|
|
cp += dlen;
|
|
|
|
|
continue;
|
|
|
|
|
} else {
|
2002-06-20 15:42:53 +04:00
|
|
|
|
if (type == T_A && dlen != INADDRSZ)
|
|
|
|
|
return (ERROR);
|
|
|
|
|
if (type == T_AAAA && dlen != 16)
|
1999-11-20 21:53:57 +03:00
|
|
|
|
return (ERROR);
|
|
|
|
|
for (j = 0; j < numServers; j++) {
|
2002-06-20 15:42:53 +04:00
|
|
|
|
if (strcasecmp((char *)bp, server[j].name) == 0) {
|
1999-11-20 21:53:57 +03:00
|
|
|
|
server[j].numAddresses++;
|
|
|
|
|
if (server[j].numAddresses <= MAXADDRS) {
|
|
|
|
|
server[j].address[server[j].numAddresses-1] =
|
|
|
|
|
Calloc(1,dlen);
|
|
|
|
|
memcpy(server[j].address[server[j].numAddresses-1],
|
|
|
|
|
cp, dlen);
|
2002-06-20 15:42:53 +04:00
|
|
|
|
server[j].len[server[j].numAddresses-1] = dlen;
|
|
|
|
|
server[j].type[server[j].numAddresses-1] =
|
|
|
|
|
(type == T_A) ? AF_INET : AF_INET6;
|
1999-11-20 21:53:57 +03:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
cp += dlen;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If we are returning name server info, transfer it to the hostPtr.
|
|
|
|
|
*/
|
2002-06-20 15:42:53 +04:00
|
|
|
|
oldServers = 0;
|
|
|
|
|
if (merge && hostPtr->servers != NULL) {
|
|
|
|
|
while (hostPtr->servers[oldServers] != NULL)
|
|
|
|
|
oldServers++;
|
|
|
|
|
}
|
1999-11-20 21:53:57 +03:00
|
|
|
|
if (numServers > 0) {
|
2002-06-20 15:42:53 +04:00
|
|
|
|
newServers = (ServerInfo **) Calloc(numServers+oldServers+1,
|
|
|
|
|
sizeof(ServerInfo *));
|
|
|
|
|
if (merge && hostPtr->servers != NULL) {
|
|
|
|
|
memcpy(newServers, hostPtr->servers,
|
|
|
|
|
oldServers * sizeof(ServerInfo *));
|
|
|
|
|
free(hostPtr->servers);
|
|
|
|
|
}
|
|
|
|
|
hostPtr->servers = newServers;
|
|
|
|
|
k = oldServers;
|
1999-11-20 21:53:57 +03:00
|
|
|
|
for (i = 0; i < numServers; i++) {
|
2002-06-20 15:42:53 +04:00
|
|
|
|
for (l = 0; l < k; l++)
|
|
|
|
|
if (!strcasecmp(hostPtr->servers[l]->name, server[i].name))
|
|
|
|
|
break;
|
|
|
|
|
if (l < k) {
|
|
|
|
|
free(server[i].name);
|
|
|
|
|
for (j = 0; j < server[i].numDomains; j++)
|
|
|
|
|
free(server[i].domain[j]);
|
|
|
|
|
} else {
|
|
|
|
|
hostPtr->servers[l] = (ServerInfo *)
|
|
|
|
|
Calloc(1, sizeof(ServerInfo));
|
|
|
|
|
hostPtr->servers[l]->name = server[i].name;
|
|
|
|
|
k++;
|
1999-11-20 21:53:57 +03:00
|
|
|
|
|
2002-06-20 15:42:53 +04:00
|
|
|
|
hostPtr->servers[l]->domains = (char **)
|
1999-11-20 21:53:57 +03:00
|
|
|
|
Calloc(server[i].numDomains+1,sizeof(char *));
|
2002-06-20 15:42:53 +04:00
|
|
|
|
for (j = 0; j < server[i].numDomains; j++) {
|
|
|
|
|
hostPtr->servers[l]->domains[j] = server[i].domain[j];
|
|
|
|
|
}
|
|
|
|
|
hostPtr->servers[l]->domains[j] = NULL;
|
1999-11-20 21:53:57 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2002-06-20 15:42:53 +04:00
|
|
|
|
oldAddresses = 0;
|
|
|
|
|
if (merge && hostPtr->servers[l]->addrList != NULL)
|
|
|
|
|
while (hostPtr->servers[l]->addrList[oldAddresses] != NULL)
|
|
|
|
|
oldAddresses++;
|
|
|
|
|
newAddresses = (AddrInfo **)
|
|
|
|
|
Calloc(server[i].numAddresses+oldAddresses+1,
|
|
|
|
|
sizeof(AddrInfo *));
|
|
|
|
|
if (merge && hostPtr->servers[l]->addrList != NULL) {
|
|
|
|
|
memcpy(newAddresses, hostPtr->servers[l]->addrList,
|
|
|
|
|
sizeof(AddrInfo *) * oldAddresses);
|
|
|
|
|
free(hostPtr->servers[l]->addrList);
|
1999-11-20 21:53:57 +03:00
|
|
|
|
}
|
2002-06-20 15:42:53 +04:00
|
|
|
|
hostPtr->servers[l]->addrList = newAddresses;
|
|
|
|
|
m = oldAddresses;
|
|
|
|
|
for (j = 0; j < server[l].numAddresses; j++) {
|
|
|
|
|
for (n = 0; n < m; n++)
|
|
|
|
|
if (hostPtr->servers[l]->addrList[n]->addrType ==
|
|
|
|
|
server[i].type[j] &&
|
|
|
|
|
hostPtr->servers[l]->addrList[n]->addrLen ==
|
|
|
|
|
server[i].len[j] &&
|
|
|
|
|
!memcmp(hostPtr->servers[l]->addrList[n]->addr,
|
|
|
|
|
server[i].address[j], server[i].len[j]))
|
|
|
|
|
break;
|
|
|
|
|
if (n < m) {
|
|
|
|
|
free(server[i].address[j]);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
hostPtr->servers[l]->addrList[m] =
|
|
|
|
|
(AddrInfo*)Calloc(1, sizeof(AddrInfo));
|
|
|
|
|
hostPtr->servers[l]->addrList[m]->addr =
|
|
|
|
|
server[i].address[j];
|
|
|
|
|
hostPtr->servers[l]->addrList[m]->addrType =
|
|
|
|
|
server[i].type[j];
|
|
|
|
|
hostPtr->servers[l]->addrList[m]->addrLen =
|
|
|
|
|
server[i].len[j];
|
|
|
|
|
m++;
|
|
|
|
|
}
|
|
|
|
|
hostPtr->servers[l]->addrList[m] = NULL;
|
1999-11-20 21:53:57 +03:00
|
|
|
|
}
|
2002-06-20 15:42:53 +04:00
|
|
|
|
hostPtr->servers[k] = NULL;
|
1999-11-20 21:53:57 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (queryType) {
|
2002-06-20 15:42:53 +04:00
|
|
|
|
case T_AAAA:
|
1999-11-20 21:53:57 +03:00
|
|
|
|
case T_A:
|
|
|
|
|
return NONAUTH;
|
|
|
|
|
case T_PTR:
|
|
|
|
|
if (iquery)
|
|
|
|
|
return NO_INFO;
|
|
|
|
|
/* fall through */
|
|
|
|
|
default:
|
|
|
|
|
return SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*******************************************************************************
|
|
|
|
|
*
|
|
|
|
|
* GetHostInfo --
|
|
|
|
|
*
|
|
|
|
|
* Retrieves host name, address and alias information
|
|
|
|
|
* for a domain.
|
|
|
|
|
*
|
|
|
|
|
* Algorithm from res_nsearch().
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* ERROR - res_nmkquery failed.
|
|
|
|
|
* + return values from GetAnswer()
|
|
|
|
|
*
|
|
|
|
|
*******************************************************************************
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
int
|
2002-06-20 15:42:53 +04:00
|
|
|
|
GetHostInfoByName(nsAddrPtr, queryClass, queryType, name, hostPtr, isServer,
|
|
|
|
|
merge)
|
|
|
|
|
union res_sockaddr_union *nsAddrPtr;
|
1999-11-20 21:53:57 +03:00
|
|
|
|
int queryClass;
|
|
|
|
|
int queryType;
|
2002-06-20 15:42:53 +04:00
|
|
|
|
const char *name;
|
1999-11-20 21:53:57 +03:00
|
|
|
|
HostInfo *hostPtr;
|
|
|
|
|
Boolean isServer;
|
2002-06-20 15:42:53 +04:00
|
|
|
|
Boolean merge;
|
1999-11-20 21:53:57 +03:00
|
|
|
|
{
|
|
|
|
|
int n;
|
|
|
|
|
register int result;
|
|
|
|
|
register char **domain;
|
|
|
|
|
const char *cp;
|
|
|
|
|
Boolean got_nodata = FALSE;
|
2002-06-20 15:42:53 +04:00
|
|
|
|
union res_sockaddr_union ina;
|
1999-11-20 21:53:57 +03:00
|
|
|
|
Boolean tried_as_is = FALSE;
|
|
|
|
|
char tmp[NS_MAXDNAME];
|
|
|
|
|
|
|
|
|
|
/* Catch explicit addresses */
|
|
|
|
|
if ((queryType == T_A) && IsAddr(name, &ina)) {
|
|
|
|
|
hostPtr->name = Calloc(strlen(name)+3, 1);
|
|
|
|
|
(void)sprintf(hostPtr->name,"[%s]",name);
|
2002-06-20 15:42:53 +04:00
|
|
|
|
switch (ina.sin.sin_family) {
|
|
|
|
|
case AF_INET:
|
|
|
|
|
hostPtr->aliases = NULL;
|
|
|
|
|
hostPtr->servers = NULL;
|
|
|
|
|
hostPtr->addrList = (AddrInfo **)Calloc(2, sizeof(AddrInfo *));
|
|
|
|
|
hostPtr->addrList[0] = (AddrInfo *)Calloc(1, sizeof(AddrInfo));
|
|
|
|
|
hostPtr->addrList[0]->addr = Calloc(INT32SZ, sizeof(char));
|
|
|
|
|
memcpy(hostPtr->addrList[0]->addr, &ina.sin.sin_addr, INADDRSZ);
|
|
|
|
|
hostPtr->addrList[0]->addrType = AF_INET;
|
|
|
|
|
hostPtr->addrList[0]->addrLen = INADDRSZ;
|
|
|
|
|
hostPtr->addrList[1] = NULL;
|
|
|
|
|
break;
|
|
|
|
|
case AF_INET6:
|
|
|
|
|
hostPtr->aliases = NULL;
|
|
|
|
|
hostPtr->servers = NULL;
|
|
|
|
|
hostPtr->addrList = (AddrInfo **)Calloc(2, sizeof(AddrInfo *));
|
|
|
|
|
hostPtr->addrList[0] = (AddrInfo *)Calloc(1, sizeof(AddrInfo));
|
|
|
|
|
hostPtr->addrList[0]->addr = Calloc(1, 16);
|
|
|
|
|
memcpy(hostPtr->addrList[0]->addr, &ina.sin6.sin6_addr, 16);
|
|
|
|
|
hostPtr->addrList[0]->addrType = AF_INET6;
|
|
|
|
|
hostPtr->addrList[0]->addrLen = 16;
|
|
|
|
|
hostPtr->addrList[1] = NULL;
|
|
|
|
|
break;
|
|
|
|
|
}
|
1999-11-20 21:53:57 +03:00
|
|
|
|
return(SUCCESS);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result = NXDOMAIN;
|
|
|
|
|
for (cp = name, n = 0; *cp; cp++)
|
|
|
|
|
if (*cp == '.')
|
|
|
|
|
n++;
|
|
|
|
|
if (n == 0 && (cp = res_hostalias(&res, name, tmp, sizeof tmp))) {
|
|
|
|
|
printf("Aliased to \"%s\"\n\n", cp);
|
|
|
|
|
return (GetHostDomain(nsAddrPtr, queryClass, queryType,
|
2002-06-20 15:42:53 +04:00
|
|
|
|
cp, (char *)NULL, hostPtr, isServer, merge));
|
1999-11-20 21:53:57 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If there are dots in the name already, let's just give it a try
|
|
|
|
|
* 'as is'. The threshold can be set with the "ndots" option.
|
|
|
|
|
*/
|
|
|
|
|
if (n >= (int)res.ndots) {
|
|
|
|
|
result = GetHostDomain(nsAddrPtr, queryClass, queryType,
|
2002-06-20 15:42:53 +04:00
|
|
|
|
name, (char *)NULL, hostPtr, isServer,
|
|
|
|
|
merge);
|
1999-11-20 21:53:57 +03:00
|
|
|
|
if (result == SUCCESS)
|
|
|
|
|
return (result);
|
|
|
|
|
if (result == NO_INFO)
|
|
|
|
|
got_nodata++;
|
|
|
|
|
tried_as_is++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* We do at least one level of search if
|
|
|
|
|
* - there is no dot and RES_DEFNAME is set, or
|
|
|
|
|
* - there is at least one dot, there is no trailing dot,
|
|
|
|
|
* and RES_DNSRCH is set.
|
|
|
|
|
*/
|
2001-01-27 10:21:56 +03:00
|
|
|
|
if ((n == 0 && (res.options & RES_DEFNAMES) != 0) ||
|
|
|
|
|
(n != 0 && *--cp != '.' && (res.options & RES_DNSRCH) != 0))
|
|
|
|
|
for (domain = res.dnsrch; *domain != NULL; domain++) {
|
1999-11-20 21:53:57 +03:00
|
|
|
|
result = GetHostDomain(nsAddrPtr, queryClass, queryType,
|
2002-06-20 15:42:53 +04:00
|
|
|
|
name, *domain, hostPtr, isServer,
|
|
|
|
|
merge);
|
1999-11-20 21:53:57 +03:00
|
|
|
|
/*
|
|
|
|
|
* If no server present, give up.
|
|
|
|
|
* If name isn't found in this domain,
|
|
|
|
|
* keep trying higher domains in the search list
|
|
|
|
|
* (if that's enabled).
|
|
|
|
|
* On a NO_INFO error, keep trying, otherwise
|
|
|
|
|
* a wildcard entry of another type could keep us
|
|
|
|
|
* from finding this entry higher in the domain.
|
|
|
|
|
* If we get some other error (negative answer or
|
|
|
|
|
* server failure), then stop searching up,
|
|
|
|
|
* but try the input name below in case it's fully-qualified.
|
|
|
|
|
*/
|
|
|
|
|
if (result == SUCCESS || result == NO_RESPONSE)
|
|
|
|
|
return result;
|
|
|
|
|
if (result == NO_INFO)
|
|
|
|
|
got_nodata++;
|
|
|
|
|
if ((result != NXDOMAIN && result != NO_INFO) ||
|
|
|
|
|
(res.options & RES_DNSRCH) == 0)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
/* if we have not already tried the name "as is", do that now.
|
|
|
|
|
* note that we do this regardless of how many dots were in the
|
|
|
|
|
* name or whether it ends with a dot.
|
|
|
|
|
*/
|
|
|
|
|
if (!tried_as_is &&
|
|
|
|
|
(result = GetHostDomain(nsAddrPtr, queryClass, queryType,
|
2002-06-20 15:42:53 +04:00
|
|
|
|
name, (char *)NULL, hostPtr, isServer, merge)
|
1999-11-20 21:53:57 +03:00
|
|
|
|
) == SUCCESS)
|
|
|
|
|
return (result);
|
|
|
|
|
if (got_nodata)
|
|
|
|
|
result = NO_INFO;
|
|
|
|
|
return (result);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Perform a query on the concatenation of name and domain,
|
|
|
|
|
* removing a trailing dot from name if domain is NULL.
|
|
|
|
|
*/
|
2001-01-27 10:21:56 +03:00
|
|
|
|
int
|
2002-06-20 15:42:53 +04:00
|
|
|
|
GetHostDomain(nsAddrPtr, queryClass, queryType, name, domain, hostPtr,
|
|
|
|
|
isServer, merge)
|
|
|
|
|
union res_sockaddr_union *nsAddrPtr;
|
1999-11-20 21:53:57 +03:00
|
|
|
|
int queryClass;
|
|
|
|
|
int queryType;
|
2002-06-20 15:42:53 +04:00
|
|
|
|
const char *name;
|
|
|
|
|
char *domain;
|
1999-11-20 21:53:57 +03:00
|
|
|
|
HostInfo *hostPtr;
|
|
|
|
|
Boolean isServer;
|
2002-06-20 15:42:53 +04:00
|
|
|
|
Boolean merge;
|
1999-11-20 21:53:57 +03:00
|
|
|
|
{
|
|
|
|
|
querybuf buf;
|
|
|
|
|
char nbuf[2*MAXDNAME+2];
|
2002-06-20 15:42:53 +04:00
|
|
|
|
const char *longname = nbuf;
|
1999-11-20 21:53:57 +03:00
|
|
|
|
int n;
|
|
|
|
|
|
|
|
|
|
if (domain == NULL) {
|
|
|
|
|
/*
|
|
|
|
|
* Check for trailing '.';
|
|
|
|
|
* copy without '.' if present.
|
|
|
|
|
*/
|
|
|
|
|
n = strlen(name) - 1;
|
2002-06-20 15:42:53 +04:00
|
|
|
|
if (name[n] == '.' && n < (int)sizeof(nbuf) - 1) {
|
1999-11-20 21:53:57 +03:00
|
|
|
|
memcpy(nbuf, name, n);
|
|
|
|
|
nbuf[n] = '\0';
|
|
|
|
|
} else
|
|
|
|
|
longname = name;
|
|
|
|
|
} else {
|
|
|
|
|
(void)sprintf(nbuf, "%.*s.%.*s",
|
|
|
|
|
MAXDNAME, name, MAXDNAME, domain);
|
|
|
|
|
longname = nbuf;
|
|
|
|
|
}
|
|
|
|
|
n = res_nmkquery(&res, QUERY, longname, queryClass, queryType,
|
|
|
|
|
NULL, 0, 0, buf.qb2, sizeof(buf));
|
|
|
|
|
if (n < 0) {
|
|
|
|
|
if (res.options & RES_DEBUG) {
|
|
|
|
|
printf("Res_nmkquery failed\n");
|
|
|
|
|
}
|
|
|
|
|
return (ERROR);
|
|
|
|
|
}
|
|
|
|
|
|
2002-06-20 15:42:53 +04:00
|
|
|
|
n = GetAnswer(nsAddrPtr, queryType, (char *)&buf, n, 0, hostPtr,
|
|
|
|
|
isServer, merge);
|
1999-11-20 21:53:57 +03:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* GetAnswer didn't find a name, so set it to the specified one.
|
|
|
|
|
*/
|
|
|
|
|
if (n == NONAUTH) {
|
|
|
|
|
if (hostPtr->name == NULL) {
|
|
|
|
|
size_t len = strlen(longname) + 1;
|
|
|
|
|
|
|
|
|
|
hostPtr->name = Calloc(len, sizeof(char));
|
|
|
|
|
memcpy(hostPtr->name, longname, len);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return(n);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*******************************************************************************
|
|
|
|
|
*
|
|
|
|
|
* GetHostInfoByAddr --
|
|
|
|
|
*
|
|
|
|
|
* Performs a PTR lookup in in-addr.arpa to find the host name
|
|
|
|
|
* that corresponds to the given address.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* ERROR - res_nmkquery failed.
|
|
|
|
|
* + return values from GetAnswer()
|
|
|
|
|
*
|
|
|
|
|
*******************************************************************************
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
int
|
2002-06-20 15:42:53 +04:00
|
|
|
|
GetHostInfoByAddr(union res_sockaddr_union *nsAddrPtr,
|
|
|
|
|
union res_sockaddr_union *address,
|
|
|
|
|
HostInfo * hostPtr)
|
1999-11-20 21:53:57 +03:00
|
|
|
|
{
|
|
|
|
|
int n;
|
|
|
|
|
querybuf buf;
|
|
|
|
|
char qbuf[MAXDNAME];
|
2002-06-20 15:42:53 +04:00
|
|
|
|
char qbuf2[MAXDNAME];
|
|
|
|
|
char *p = NULL;
|
|
|
|
|
int ismapped = 0;
|
|
|
|
|
|
|
|
|
|
switch (address->sin.sin_family) {
|
|
|
|
|
case AF_INET:
|
|
|
|
|
p = (char *) &address->sin.sin_addr.s_addr;
|
|
|
|
|
mapped:
|
|
|
|
|
(void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa",
|
|
|
|
|
((unsigned)p[3 + (ismapped ? 12 : 0)] & 0xff),
|
|
|
|
|
((unsigned)p[2 + (ismapped ? 12 : 0)] & 0xff),
|
|
|
|
|
((unsigned)p[1 + (ismapped ? 12 : 0)] & 0xff),
|
|
|
|
|
((unsigned)p[0 + (ismapped ? 12 : 0)] & 0xff));
|
|
|
|
|
break;
|
|
|
|
|
case AF_INET6:
|
|
|
|
|
p = (char *)address->sin6.sin6_addr.s6_addr;
|
|
|
|
|
if (IN6_IS_ADDR_V4MAPPED(&address->sin6.sin6_addr) ||
|
|
|
|
|
IN6_IS_ADDR_V4COMPAT(&address->sin6.sin6_addr)) {
|
|
|
|
|
ismapped = 1;
|
|
|
|
|
goto mapped;
|
|
|
|
|
}
|
|
|
|
|
(void)sprintf(qbuf,
|
|
|
|
|
"%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x."
|
|
|
|
|
"%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x."
|
|
|
|
|
"ip6.arpa",
|
|
|
|
|
p[15] & 0xf, (p[15] >> 4) & 0xf,
|
|
|
|
|
p[14] & 0xf, (p[14] >> 4) & 0xf,
|
|
|
|
|
p[13] & 0xf, (p[13] >> 4) & 0xf,
|
|
|
|
|
p[12] & 0xf, (p[12] >> 4) & 0xf,
|
|
|
|
|
p[11] & 0xf, (p[11] >> 4) & 0xf,
|
|
|
|
|
p[10] & 0xf, (p[10] >> 4) & 0xf,
|
|
|
|
|
p[9] & 0xf, (p[9] >> 4) & 0xf,
|
|
|
|
|
p[8] & 0xf, (p[8] >> 4) & 0xf,
|
|
|
|
|
p[7] & 0xf, (p[7] >> 4) & 0xf,
|
2003-06-03 11:33:24 +04:00
|
|
|
|
p[6] & 0xf, (p[6] >> 4) & 0xf,
|
2002-06-20 15:42:53 +04:00
|
|
|
|
p[5] & 0xf, (p[5] >> 4) & 0xf,
|
|
|
|
|
p[4] & 0xf, (p[4] >> 4) & 0xf,
|
|
|
|
|
p[3] & 0xf, (p[3] >> 4) & 0xf,
|
|
|
|
|
p[2] & 0xf, (p[2] >> 4) & 0xf,
|
|
|
|
|
p[1] & 0xf, (p[1] >> 4) & 0xf,
|
|
|
|
|
p[0] & 0xf, (p[0] >> 4) & 0xf);
|
|
|
|
|
(void)sprintf(qbuf2,
|
|
|
|
|
"%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x."
|
|
|
|
|
"%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x."
|
|
|
|
|
"ip6.int",
|
|
|
|
|
p[15] & 0xf, (p[15] >> 4) & 0xf,
|
|
|
|
|
p[14] & 0xf, (p[14] >> 4) & 0xf,
|
|
|
|
|
p[13] & 0xf, (p[13] >> 4) & 0xf,
|
|
|
|
|
p[12] & 0xf, (p[12] >> 4) & 0xf,
|
|
|
|
|
p[11] & 0xf, (p[11] >> 4) & 0xf,
|
|
|
|
|
p[10] & 0xf, (p[10] >> 4) & 0xf,
|
|
|
|
|
p[9] & 0xf, (p[9] >> 4) & 0xf,
|
|
|
|
|
p[8] & 0xf, (p[8] >> 4) & 0xf,
|
|
|
|
|
p[7] & 0xf, (p[7] >> 4) & 0xf,
|
2003-06-03 11:33:24 +04:00
|
|
|
|
p[6] & 0xf, (p[6] >> 4) & 0xf,
|
2002-06-20 15:42:53 +04:00
|
|
|
|
p[5] & 0xf, (p[5] >> 4) & 0xf,
|
|
|
|
|
p[4] & 0xf, (p[4] >> 4) & 0xf,
|
|
|
|
|
p[3] & 0xf, (p[3] >> 4) & 0xf,
|
|
|
|
|
p[2] & 0xf, (p[2] >> 4) & 0xf,
|
|
|
|
|
p[1] & 0xf, (p[1] >> 4) & 0xf,
|
|
|
|
|
p[0] & 0xf, (p[0] >> 4) & 0xf);
|
|
|
|
|
break;
|
|
|
|
|
}
|
1999-11-20 21:53:57 +03:00
|
|
|
|
n = res_nmkquery(&res, QUERY, qbuf, C_IN, T_PTR, NULL, 0, NULL,
|
|
|
|
|
buf.qb2, sizeof buf);
|
|
|
|
|
if (n < 0) {
|
|
|
|
|
if (res.options & RES_DEBUG) {
|
|
|
|
|
printf("res_nmkquery() failed\n");
|
|
|
|
|
}
|
|
|
|
|
return (ERROR);
|
|
|
|
|
}
|
2002-06-20 15:42:53 +04:00
|
|
|
|
n = GetAnswer(nsAddrPtr, T_PTR, (char *) &buf, n, 1, hostPtr, 1, 0);
|
|
|
|
|
if (n == SUCCESS) {
|
|
|
|
|
switch (address->sin.sin_family) {
|
|
|
|
|
case AF_INET:
|
|
|
|
|
hostPtr->addrList = (AddrInfo **)Calloc(2, sizeof(AddrInfo *));
|
|
|
|
|
hostPtr->addrList[0] = (AddrInfo *)Calloc(1, sizeof(AddrInfo));
|
|
|
|
|
hostPtr->addrList[0]->addr = Calloc(INT32SZ, sizeof(char));
|
|
|
|
|
memcpy(hostPtr->addrList[0]->addr, p, INADDRSZ);
|
|
|
|
|
hostPtr->addrList[0]->addrType = AF_INET;
|
|
|
|
|
hostPtr->addrList[0]->addrLen = 4;
|
|
|
|
|
hostPtr->addrList[1] = NULL;
|
|
|
|
|
break;
|
|
|
|
|
case AF_INET6:
|
|
|
|
|
hostPtr->addrList = (AddrInfo **)Calloc(2, sizeof(AddrInfo *));
|
|
|
|
|
hostPtr->addrList[0] = (AddrInfo *)Calloc(1, sizeof(AddrInfo));
|
|
|
|
|
hostPtr->addrList[0]->addr = Calloc(16, sizeof(char));
|
|
|
|
|
memcpy(hostPtr->addrList[0]->addr, p, 16);
|
|
|
|
|
hostPtr->addrList[0]->addrType = AF_INET6;
|
|
|
|
|
hostPtr->addrList[0]->addrLen = 16;
|
|
|
|
|
hostPtr->addrList[1] = NULL;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (n == SUCCESS || ismapped || address->sin.sin_family != AF_INET6)
|
|
|
|
|
return n;
|
|
|
|
|
n = res_nmkquery(&res, QUERY, qbuf2, C_IN, T_PTR, NULL, 0, NULL,
|
|
|
|
|
buf.qb2, sizeof buf);
|
|
|
|
|
if (n < 0) {
|
|
|
|
|
if (res.options & RES_DEBUG) {
|
|
|
|
|
printf("res_nmkquery() failed\n");
|
|
|
|
|
}
|
|
|
|
|
return (ERROR);
|
|
|
|
|
}
|
|
|
|
|
n = GetAnswer(nsAddrPtr, T_PTR, (char *) &buf, n, 1, hostPtr, 1, 0);
|
1999-11-20 21:53:57 +03:00
|
|
|
|
if (n == SUCCESS) {
|
2002-06-20 15:42:53 +04:00
|
|
|
|
hostPtr->addrList = (AddrInfo **)Calloc(2, sizeof(AddrInfo *));
|
2003-06-03 11:33:24 +04:00
|
|
|
|
hostPtr->addrList[0] = (AddrInfo *)Calloc(1, sizeof(AddrInfo));
|
2002-06-20 15:42:53 +04:00
|
|
|
|
hostPtr->addrList[0]->addr = Calloc(16, sizeof(char));
|
|
|
|
|
memcpy(hostPtr->addrList[0]->addr, p, 16);
|
|
|
|
|
hostPtr->addrList[0]->addrType = AF_INET6;
|
|
|
|
|
hostPtr->addrList[0]->addrLen = 16;
|
1999-11-20 21:53:57 +03:00
|
|
|
|
hostPtr->addrList[1] = NULL;
|
|
|
|
|
}
|
|
|
|
|
return n;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*******************************************************************************
|
|
|
|
|
*
|
|
|
|
|
* FreeHostInfoPtr --
|
|
|
|
|
*
|
|
|
|
|
* Deallocates all the calloc'd areas for a HostInfo variable.
|
|
|
|
|
*
|
|
|
|
|
*******************************************************************************
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
FreeHostInfoPtr(hostPtr)
|
|
|
|
|
register HostInfo *hostPtr;
|
|
|
|
|
{
|
|
|
|
|
int i, j;
|
|
|
|
|
|
|
|
|
|
if (hostPtr->name != NULL) {
|
|
|
|
|
free(hostPtr->name);
|
|
|
|
|
hostPtr->name = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (hostPtr->aliases != NULL) {
|
|
|
|
|
i = 0;
|
|
|
|
|
while (hostPtr->aliases[i] != NULL) {
|
|
|
|
|
free(hostPtr->aliases[i]);
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
free((char *)hostPtr->aliases);
|
|
|
|
|
hostPtr->aliases = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (hostPtr->addrList != NULL) {
|
|
|
|
|
i = 0;
|
|
|
|
|
while (hostPtr->addrList[i] != NULL) {
|
2002-06-20 15:42:53 +04:00
|
|
|
|
free(hostPtr->addrList[i]->addr);
|
1999-11-20 21:53:57 +03:00
|
|
|
|
free(hostPtr->addrList[i]);
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
free((char *)hostPtr->addrList);
|
|
|
|
|
hostPtr->addrList = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (hostPtr->servers != NULL) {
|
|
|
|
|
i = 0;
|
|
|
|
|
while (hostPtr->servers[i] != NULL) {
|
|
|
|
|
|
|
|
|
|
if (hostPtr->servers[i]->name != NULL) {
|
|
|
|
|
free(hostPtr->servers[i]->name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (hostPtr->servers[i]->domains != NULL) {
|
|
|
|
|
j = 0;
|
|
|
|
|
while (hostPtr->servers[i]->domains[j] != NULL) {
|
|
|
|
|
free(hostPtr->servers[i]->domains[j]);
|
|
|
|
|
j++;
|
|
|
|
|
}
|
|
|
|
|
free((char *)hostPtr->servers[i]->domains);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (hostPtr->servers[i]->addrList != NULL) {
|
|
|
|
|
j = 0;
|
|
|
|
|
while (hostPtr->servers[i]->addrList[j] != NULL) {
|
2002-06-20 15:42:53 +04:00
|
|
|
|
free(hostPtr->servers[i]->addrList[j]->addr);
|
1999-11-20 21:53:57 +03:00
|
|
|
|
free(hostPtr->servers[i]->addrList[j]);
|
|
|
|
|
j++;
|
|
|
|
|
}
|
|
|
|
|
free((char *)hostPtr->servers[i]->addrList);
|
|
|
|
|
}
|
|
|
|
|
free((char *)hostPtr->servers[i]);
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
free((char *)hostPtr->servers);
|
|
|
|
|
hostPtr->servers = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|