dighost.c revision e79be811b0c99f46ab5d1303d4eb4e8159300484
/*
* Copyright (C) 2000 Internet Software Consortium.
*
* 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.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
* CONSORTIUM 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.
*/
#include <config.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
extern int h_errno;
#include <isc/assertions.h>
#include <isc/sockaddr.h>
#include <dns/fixedname.h>
#include <dns/rdatalist.h>
#include <dns/rdataset.h>
#include <dns/rdataclass.h>
#include <dns/rdatatype.h>
#ifdef TWIDDLE
#endif
unsigned int timeout = 5;
int sendcount = 0;
int ndots = -1;
int tries = 3;
static void
free_lists(void);
static int
count_dots(char *string) {
char *s;
int i=0;
s = string;
while (*s != 0) {
if (*s == '.')
i++;
s++;
}
return (i);
}
static void
hex_dump(isc_buffer_t *b) {
unsigned int len;
isc_region_t r;
isc_buffer_remainingregion(b, &r);
printf("\n");
}
if (len % 16 != 0)
printf("\n");
}
void
#ifdef NEVER
free_lists();
#ifdef MEMDEBUG
#endif
}
#endif
exit(1);
}
#ifdef DEBUG
void
}
#else
void
}
#endif
void
if (result != ISC_R_SUCCESS)
}
/* Tests if a field is a class, without needing isc libs
* initialized. This list will have to be manually kept in
* sync with what the libs support.
*/
const int numclasses = 3;
int i;
for (i = 0; i < numclasses; i++)
return ISC_TRUE;
return ISC_FALSE;
}
/* Tests if a field is a type, without needing isc libs
* initialized. This list will have to be manually kept in
* sync with what the libs support.
*/
"soa", "mb", "mg", "mr", "null",
"wks", "ptr", "hinfo", "minfo",
"mx", "txt", "rp", "afsdb",
"x25", "isdn", "rt", "nsap",
"nsap_ptr", "sig", "key", "px",
"gpos", "aaaa", "loc", "nxt",
"srv", "naptr", "kx", "cert",
"a6", "dname", "opt", "unspec",
"tkey", "tsig", "axfr"};
const int numtypes = 41;
int i;
for (i = 0; i < numtypes; i++) {
return ISC_TRUE;
}
return ISC_FALSE;
}
#ifdef TWIDDLE
void
isc_region_t r;
unsigned char bitfield;
int i, tw;
for (i=0;i<tw;i++) {
isc_buffer_usedregion (&buf, &r);
}
puts ("");
}
#endif
static void
setup_system(void) {
char *ptr;
dig_lookup_t *l;
if (fixeddomain[0]!=0) {
fatal("Memory allocation failure.");
}
debug ("setup_system()");
if (get_servers &&
debug ("Got a nameserver line");
sizeof(struct dig_server));
fatal("Memory "
"allocation "
"failure.");
ptr,
MXNAME - 1);
}
6) == 0) &&
(ndots == -1)) {
&ptr[6]);
debug ("ndots is "
"%d.",
ndots);
}
}
&& usesearch){
!= NULL) {
mctx, sizeof(struct
dig_server));
fatal("Memory "
"allocation "
"failure.");
ptr,
MXNAME - 1);
link);
}
(fixeddomain[0] == 0 )){
!= NULL) {
mctx, sizeof(struct
dig_server));
fatal("Memory "
"allocation "
"failure.");
ptr,
MXNAME - 1);
link);
}
}
}
}
}
if (ndots == -1)
ndots = 1;
fatal("Memory allocation failure");
}
for (l = ISC_LIST_HEAD(lookup_list) ;
l != NULL;
l = ISC_LIST_NEXT(l, link) ) {
}
}
static void
setup_libs(void) {
isc_buffer_t b;
debug ("setup_libs()");
result = isc_app_start();
result = isc_net_probeipv4();
result = isc_net_probeipv6();
if (result == ISC_R_SUCCESS)
isc_buffer_add(&b, 1);
}
static void
{
debug ("add_type()");
}
static void
isc_buffer_t *b = NULL;
isc_region_t r;
int len;
debug ("followup_lookup()");
if (result != ISC_R_SUCCESS) {
debug ("Firstname returned %s",
return;
}
for (;;) {
&name);
while (loopresult == ISC_R_SUCCESS) {
BUFSIZE);
"isc_buffer_allocate");
NULL,
b);
"dns_rdata_totext");
isc_buffer_usedregion(b, &r);
/* Initialize lookup if we've not yet */
debug ("Found NS %d %.*s",
(char *)r.base);
(mctx,
sizeof(struct
dig_lookup));
fatal ("Memory "
"allocation "
"failure.");
rttext, 32);
rctext, 32);
ISC_LIST_INIT(lookup->q);
sizeof(
struct
dig_server));
fatal("Memory allocation "
"failure.");
isc_buffer_free (&b);
}
debug ("Before insertion, init@%lx "
"-> %lx, new@%lx "
link);
debug ("After insertion, init -> "
"%lx, new = %lx, "
"new -> %lx", (long int)query->
}
}
if (result != ISC_R_SUCCESS)
break;
}
return; /* We didn't get a NS. Just give up. */
}
static void
dig_server_t *s;
debug ("next_origin()");
there's nothing left. */
debug ("Made it to the root whith nowhere to go.");
return;
}
(mctx, sizeof(struct dig_lookup));
fatal ("Memory allocation failure.");
ISC_LIST_INIT(lookup->q);
if (lookup->use_my_server_list) {
while (s != NULL) {
dig_server));
fatal("Memory allocation failure.");
link);
s = ISC_LIST_NEXT(s, link);
}
}
debug ("Before insertion, init@%ld "
"-> %ld, new@%ld "
link);
debug ("After insertion, init -> "
"%ld, new = %ld, "
"new -> %ld", (long int)query->
}
void
int len;
isc_region_t r;
isc_buffer_t b;
debug("setup_lookup()");
debug("Setting up for looking up %s @%lx->%lx",
isc_buffer_add(&b, len);
if (result != ISC_R_SUCCESS) {
fatal("Aborting: %s is not a legal name syntax. (%s)",
}
isc_buffer_add(&b, len);
if (result != ISC_R_SUCCESS) {
fatal("Aborting: %s is not a legal name syntax. (%s)",
}
} else {
debug ("Using root origin.");
isc_buffer_add(&b, len);
if (result != ISC_R_SUCCESS) {
isc_buffer_usedregion (&b, &r);
fatal("Aborting: %s/%.*s is not a legal name syntax. "
}
}
isc_buffer_usedregion (&b, &r);
#ifdef DEBUG
debug ("This is an absolute name.");
else
debug ("This is a relative name (which is wrong).");
#endif
debug ("Recursive query");
}
if (!lookup->ns_search_only) {
} else {
}
if (rdtype == dns_rdatatype_axfr) {
/*
* Force TCP mode if we're doing an xfr.
*/
}
if (!lookup->ns_search_only) {
} else {
}
debug ("Starting to render the message");
DNS_SECTION_QUESTION, 0);
debug ("Done rendering.");
if (lookup->use_my_server_list)
else
fatal("Memory allocation failure.");
}
}
static void
debug("send_done()");
}
static void
debug("cancel_lookup()");
return;
}
}
}
static void
static void
void
debug ("send_udp()");
sendcount++;
#ifdef TWIDDLE
if (twiddle) {
}
#endif
debug("Sending a request.");
}
}
/* connect_timeout is used for both UDP recieves and TCP connects. */
static void
dig_query_t *q=NULL;
isc_buffer_t *b=NULL;
isc_region_t r;
debug("connect_timeout()");
debug ("Buffer Allocate connect_timeout");
for (q = ISC_LIST_HEAD(lookup->q);
q != NULL;
q = ISC_LIST_NEXT(q, link)) {
if (q->working) {
if (!free_now) {
isc_buffer_clear(b);
isc_buffer_usedregion(b, &r);
printf(";; Connection to server %.*s "
"for %s timed out. "
"Retrying %d.\n",
else
printf(";; Connection to server %.*s "
"for %s timed out. "
"Giving up.\n",
}
}
}
isc_buffer_free(&b);
debug ("Done with connect_timeout()");
}
static void
isc_buffer_t *b=NULL;
isc_region_t r;
debug("tcp_length_done()");
return;
}
debug ("Buffer Allocate connect_timeout");
isc_buffer_usedregion(b, &r);
isc_buffer_free(&b);
return;
}
length = isc_buffer_getuint16(b);
isc_event_free (&event);
fatal ("Length of %X was longer than I can handle!",
length);
}
/*
* Even though the buffer was already init'ed, we need
* to redo it now, to force the length we want.
*/
}
static void
debug("launch_next_query()");
debug("Ignoring launch_next_query because !pending.");
return;
}
if (include_question) {
#ifdef TWIDDLE
if (twiddle) {
}
#endif
link);
}
sendcount++;
if (!query->first_soa_rcvd) {
debug("Sending a request.");
}
return;
}
static void
isc_buffer_t *b=NULL;
isc_region_t r;
debug("connect_done()");
debug ("Buffer Allocate connect_timeout");
isc_buffer_usedregion(b, &r);
printf(";; Connection to server %.*s for %s failed: %s.\n",
isc_buffer_free(&b);
return;
}
}
static isc_boolean_t
debug("msg_contains_soa()");
if (result == ISC_R_SUCCESS) {
return (ISC_TRUE);
} else {
debug("Didn't find SOA, result=%d:%s",
return (ISC_FALSE);
}
}
static void
isc_buffer_t *b = NULL;
isc_region_t r;
debug("recv_done()");
if (free_now) {
debug("Bailing out, since freeing now.");
isc_event_free (&event);
return;
}
sendcount--;
debug("No longer pending. Got %s",
return;
}
&msg);
if (result != ISC_R_SUCCESS)
hex_dump(b);
if (show_details) {
}
} else
if (show_details) {
}
} else {
if (query->first_soa_rcvd &&
else
}
}
#ifdef DEBUG
debug("Still pending.");
#endif
if (!query->first_soa_rcvd) {
debug("Not yet got first SOA");
puts("; Transfer failed. "
"Didn't start with SOA answer.");
isc_event_free (&event);
return;
}
else {
}
}
else {
"isc_buffer_init");
&ab);
"isc_sockaddr_totext");
isc_buffer_usedregion(&ab, &r);
return;
}
else {
}
}
}
else {
&ab);
isc_buffer_usedregion(&ab, &r);
query);
}
}
}
return;
}
/* In truth, we should never get into the CANCELED routine, since
the cancel_lookup() routine clears the pending flag. */
debug ("In cancel handler");
return;
}
fatal("recv_done got result %s",
}
static void
debug("get_address()");
else {
fatal("Couldn't look up your server host %s. errno=%d",
port);
}
}
void
debug("do_lookup_tcp()");
}
}
void
#ifdef DEBUG
debug("do_lookup_udp()");
if (tcp_mode)
debug("I'm starting UDP with tcp_mode set!!!");
#endif
}
}
static void
free_lists(void) {
void *ptr;
dig_lookup_t *l;
dig_query_t *q;
dig_server_t *s;
dig_searchlist_t *o;
debug("free_lists()");
if (free_now)
return;
l = ISC_LIST_HEAD(lookup_list);
while (l != NULL) {
q = ISC_LIST_HEAD(l->q);
while (q != NULL) {
isc_socket_detach(&q->sock);
}
link);
link);
isc_buffer_invalidate(&q->recvbuf);
ptr = q;
q = ISC_LIST_NEXT(q, link);
}
if (l->use_my_server_list) {
s = ISC_LIST_HEAD(l->my_server_list);
while (s != NULL) {
debug ("Freeing lookup server %s",
s->servername);
ptr = s;
s = ISC_LIST_NEXT(s, link);
}
}
dns_message_destroy (&l->sendmsg);
isc_timer_detach (&l->timer);
ptr = l;
l = ISC_LIST_NEXT(l, link);
}
debug ("Starting to free things globally.");
s = ISC_LIST_HEAD(server_list);
while (s != NULL) {
debug ("Freeing global server list entry %s",
s->servername);
ptr = s;
s = ISC_LIST_NEXT(s, link);
}
o = ISC_LIST_HEAD(search_list);
while (o != NULL) {
debug ("Freeing origin list entry %s",
o->origin);
ptr = o;
o = ISC_LIST_NEXT(o, link);
}
#ifdef MEMDEBUG
#endif
exit(0);
}
int
#ifdef TWIDDLE
int i, p;
#endif
#ifdef TWIDDLE
srandom(i);
}
else {
}
for (i=0 ; i<p; i++);
#endif
setup_libs();
setup_system();
if (tcp_mode)
else
isc_app_run();
free_lists();
}