* Copyright (c) 1988 Regents of the University of California.
* %sccs.include.redist.c%
* 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
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid
[] = "@(#)res_query.c 5.12 (Berkeley) %G%";
static char rcsid
[] = "$Id: res_query.c,v 1.1 1993/06/01 09:42:14 vixie Exp vixie $";
#endif /* LIBC_SCCS and not lint */
#include <arpa/nameser.h>
#define MAXPACKET PACKETSZ
* Formulate a normal query, send, and await answer.
* Returned answer is placed in supplied buffer "answer".
* Perform preliminary check of answer, returning success only
* if no error is indicated and the answer count is nonzero.
* Return the size of the response on success, -1 on error.
* Error number is left in h_errno.
* Caller must parse answer and determine whether it answers the question.
res_query(name
, class, type
, answer
, anslen
)
char *name
; /* domain name */
int class, type
; /* class and type of query */
u_char
*answer
; /* buffer to put answer */
int anslen
; /* size of answer buffer */
if ((_res
.options
& RES_INIT
) == 0 && res_init() == -1)
if (_res
.options
& RES_DEBUG
)
printf(";; res_query(%s, %d, %d)\n", name
, class, type
);
n
= res_mkquery(QUERY
, name
, class, type
, (char *)NULL
, 0, NULL
,
if (_res
.options
& RES_DEBUG
)
printf(";; res_query: mkquery failed\n");
n
= res_send(buf
, n
, (char *)answer
, anslen
);
if (_res
.options
& RES_DEBUG
)
printf(";; res_query: send error\n");
if (hp
->rcode
!= NOERROR
|| ntohs(hp
->ancount
) == 0) {
if (_res
.options
& RES_DEBUG
)
printf(";; rcode = %d, ancount=%d\n", hp
->rcode
,
h_errno
= HOST_NOT_FOUND
;
* Formulate a normal query, send, and retrieve answer in supplied buffer.
* Return the size of the response on success, -1 on error.
* If enabled, implement search rules until answer or unrecoverable failure
* is detected. Error number is left in h_errno.
* Only useful for queries in the same name hierarchy as the local host
* (not, for example, for host address-to-name lookups in domain in-addr.arpa).
res_search(name
, class, type
, answer
, anslen
)
char *name
; /* domain name */
int class, type
; /* class and type of query */
u_char
*answer
; /* buffer to put answer */
int anslen
; /* size of answer */
register char *cp
, **domain
;
int n
, ret
, got_nodata
= 0;
if ((_res
.options
& RES_INIT
) == 0 && res_init() == -1)
h_errno
= HOST_NOT_FOUND
; /* default, if we never query */
for (cp
= name
, n
= 0; *cp
; cp
++)
if (n
== 0 && (cp
= __hostalias(name
)))
return (res_query(cp
, class, type
, answer
, anslen
));
* 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,
if ((n
== 0 && _res
.options
& RES_DEFNAMES
) ||
(n
!= 0 && *--cp
!= '.' && _res
.options
& RES_DNSRCH
))
for (domain
= _res
.dnsrch
; *domain
; domain
++) {
ret
= res_querydomain(name
, *domain
, class, type
,
* If no server present, give up.
* If name isn't found in this domain,
* keep trying higher domains in the search list
* On a NO_DATA 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 (errno
== ECONNREFUSED
) {
if ((h_errno
!= HOST_NOT_FOUND
&& h_errno
!= NO_DATA
) ||
(_res
.options
& RES_DNSRCH
) == 0)
* If the search/default failed, try the name as fully-qualified,
* but only if it contained at least one dot (even trailing).
* This is purely a heuristic; we assume that any reasonable query
* about a top-level domain (for servers, SOA, etc) will not use
if (n
&& (ret
= res_querydomain(name
, (char *)NULL
, class, type
,
* Perform a call on res_query on the concatenation of name and domain,
* removing a trailing dot from name if domain is NULL.
res_querydomain(name
, domain
, class, type
, answer
, anslen
)
int class, type
; /* class and type of query */
u_char
*answer
; /* buffer to put answer */
int anslen
; /* size of answer */
if (_res
.options
& RES_DEBUG
)
printf(";; res_querydomain(%s, %s, %d, %d)\n",
name
, domain
, class, type
);
* Check for trailing '.';
* copy without '.' if present.
if (name
[n
] == '.' && n
< sizeof(nbuf
) - 1) {
(void)sprintf(nbuf
, "%.*s.%.*s",
MAXDNAME
, name
, MAXDNAME
, domain
);
return (res_query(longname
, class, type
, answer
, anslen
));
register const char *name
;
char *file
, *getenv(), *strcpy(), *strncpy();
static char abuf
[MAXDNAME
];
file
= getenv("HOSTALIASES");
if (file
== NULL
|| (fp
= fopen(file
, "r")) == NULL
)
buf
[sizeof(buf
) - 1] = '\0';
while (fgets(buf
, sizeof(buf
), fp
)) {
for (C1
= buf
; *C1
&& !isspace(*C1
); ++C1
);
if (!strcasecmp(buf
, name
)) {
for (C2
= C1
+ 1; *C2
&& !isspace(*C2
); ++C2
);
abuf
[sizeof(abuf
) - 1] = *C2
= '\0';
(void)strncpy(abuf
, C1
, sizeof(abuf
) - 1);