aboutsummaryrefslogtreecommitdiff
path: root/bin/dig/dighost.c
diff options
context:
space:
mode:
Diffstat (limited to 'bin/dig/dighost.c')
-rw-r--r--bin/dig/dighost.c198
1 files changed, 150 insertions, 48 deletions
diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c
index 8736c0cc75c5..a06c90a3db90 100644
--- a/bin/dig/dighost.c
+++ b/bin/dig/dighost.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: dighost.c,v 1.259.18.49 2008/07/23 23:33:02 marka Exp $ */
+/* $Id: dighost.c,v 1.259.18.58 2009/06/24 03:44:52 marka Exp $ */
/*! \file
* \note
@@ -583,6 +583,11 @@ copy_server_list(lwres_conf_t *confdata, dig_serverlist_t *dest) {
for (i = 0; i < confdata->nsnext; i++) {
af = addr2af(confdata->nameservers[i].family);
+ if (af == AF_INET && !have_ipv4)
+ continue;
+ if (af == AF_INET6 && !have_ipv6)
+ continue;
+
lwres_net_ntop(af, confdata->nameservers[i].address,
tmp, sizeof(tmp));
newsrv = make_server(tmp, tmp);
@@ -770,7 +775,7 @@ make_empty_lookup(void) {
* the query list, since it will be regenerated by the setup_lookup()
* function, nor does it queue up the new lookup for processing.
* Caution: If you don't clone the servers, you MUST clone the server
- * list seperately from somewhere else, or construct it by hand.
+ * list separately from somewhere else, or construct it by hand.
*/
dig_lookup_t *
clone_lookup(dig_lookup_t *lookold, isc_boolean_t servers) {
@@ -1004,10 +1009,18 @@ void
setup_system(void) {
dig_searchlist_t *domain = NULL;
lwres_result_t lwresult;
+ unsigned int lwresflags;
debug("setup_system()");
- lwresult = lwres_context_create(&lwctx, mctx, mem_alloc, mem_free, 1);
+ lwresflags = LWRES_CONTEXT_SERVERMODE;
+ if (have_ipv4)
+ lwresflags |= LWRES_CONTEXT_USEIPV4;
+ if (have_ipv6)
+ lwresflags |= LWRES_CONTEXT_USEIPV6;
+
+ lwresult = lwres_context_create(&lwctx, mctx, mem_alloc, mem_free,
+ lwresflags);
if (lwresult != LWRES_R_SUCCESS)
fatal("lwres_context_create failed");
@@ -1033,8 +1046,12 @@ setup_system(void) {
debug("ndots is %d.", ndots);
}
+ /* If user doesn't specify server use nameservers from resolv.conf. */
+ if (ISC_LIST_EMPTY(server_list))
+ copy_server_list(lwconf, &server_list);
+
/* If we don't find a nameserver fall back to localhost */
- if (lwconf->nsnext == 0) {
+ if (ISC_LIST_EMPTY(server_list)) {
if (have_ipv4) {
lwresult = add_nameserver(lwconf, "127.0.0.1", AF_INET);
if (lwresult != ISC_R_SUCCESS)
@@ -1045,10 +1062,9 @@ setup_system(void) {
if (lwresult != ISC_R_SUCCESS)
fatal("add_nameserver failed");
}
- }
- if (ISC_LIST_EMPTY(server_list))
copy_server_list(lwconf, &server_list);
+ }
#ifdef WITH_IDN
initialize_idn();
@@ -1387,7 +1403,7 @@ start_lookup(void) {
key_name) == ISC_TRUE)
trustedkey = tk_list.key[i];
/*
- * Verifier que la temp est bien la plus basse
+ * Verify temp is really the lowest
* WARNING
*/
}
@@ -2175,6 +2191,21 @@ bringup_timer(dig_query_t *query, unsigned int default_timeout) {
}
static void
+force_timeout(dig_lookup_t *l, dig_query_t *query) {
+ isc_event_t *event;
+
+ event = isc_event_allocate(mctx, query, ISC_TIMEREVENT_IDLE,
+ connect_timeout, l,
+ sizeof(isc_event_t));
+ if (event == NULL) {
+ fatal("isc_event_allocate: %s",
+ isc_result_totext(ISC_R_NOMEMORY));
+ }
+ isc_task_send(global_task, &event);
+}
+
+
+static void
connect_done(isc_task_t *task, isc_event_t *event);
/*%
@@ -2193,7 +2224,16 @@ send_tcp_connect(dig_query_t *query) {
l = query->lookup;
query->waiting_connect = ISC_TRUE;
query->lookup->current_query = query;
- get_address(query->servname, port, &query->sockaddr);
+ result = get_address(query->servname, port, &query->sockaddr);
+ if (result == ISC_R_NOTFOUND) {
+ /*
+ * This servname doesn't have an address. Try the next server
+ * by triggering an immediate 'timeout' (we lie, but the effect
+ * is the same).
+ */
+ force_timeout(l, query);
+ return;
+ }
if (specified_source &&
(isc_sockaddr_pf(&query->sockaddr) !=
@@ -2266,7 +2306,12 @@ send_udp(dig_query_t *query) {
if (!query->recv_made) {
/* XXX Check the sense of this, need assertion? */
query->waiting_connect = ISC_FALSE;
- get_address(query->servname, port, &query->sockaddr);
+ result = get_address(query->servname, port, &query->sockaddr);
+ if (result == ISC_R_NOTFOUND) {
+ /* This servname doesn't have an address. */
+ force_timeout(l, query);
+ return;
+ }
result = isc_socket_create(socketmgr,
isc_sockaddr_pf(&query->sockaddr),
@@ -2337,8 +2382,14 @@ connect_timeout(isc_task_t *task, isc_event_t *event) {
cq = query->lookup->current_query;
if (!l->tcp_mode)
send_udp(ISC_LIST_NEXT(cq, link));
- else
+ else {
+ isc_socket_cancel(query->sock, NULL,
+ ISC_SOCKCANCEL_ALL);
+ isc_socket_detach(&query->sock);
+ sockcount--;
+ debug("sockcount=%d", sockcount);
send_tcp_connect(ISC_LIST_NEXT(cq, link));
+ }
UNLOCK_LOOKUP;
return;
}
@@ -2892,18 +2943,8 @@ recv_done(isc_task_t *task, isc_event_t *event) {
if (result == ISC_R_SUCCESS && (msgflags & DNS_MESSAGEFLAG_QR) == 0)
printf(";; Warning: query response not set\n");
- if (!match) {
- isc_buffer_invalidate(&query->recvbuf);
- isc_buffer_init(&query->recvbuf, query->recvspace, COMMSIZE);
- ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, link);
- result = isc_socket_recvv(query->sock, &query->recvlist, 1,
- global_task, recv_done, query);
- check_result(result, "isc_socket_recvv");
- recvcount++;
- isc_event_free(&event);
- UNLOCK_LOOKUP;
- return;
- }
+ if (!match)
+ goto udp_mismatch;
result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &msg);
check_result(result, "dns_message_create");
@@ -2958,6 +2999,52 @@ recv_done(isc_task_t *task, isc_event_t *event) {
UNLOCK_LOOKUP;
return;
}
+ if (msg->counts[DNS_SECTION_QUESTION] != 0) {
+ match = ISC_TRUE;
+ for (result = dns_message_firstname(msg, DNS_SECTION_QUESTION);
+ result == ISC_R_SUCCESS && match;
+ result = dns_message_nextname(msg, DNS_SECTION_QUESTION)) {
+ dns_name_t *name = NULL;
+ dns_rdataset_t *rdataset;
+
+ dns_message_currentname(msg, DNS_SECTION_QUESTION,
+ &name);
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link)) {
+ if (l->rdtype != rdataset->type ||
+ l->rdclass != rdataset->rdclass ||
+ !dns_name_equal(l->name, name)) {
+ char namestr[DNS_NAME_FORMATSIZE];
+ char typebuf[DNS_RDATATYPE_FORMATSIZE];
+ char classbuf[DNS_RDATACLASS_FORMATSIZE];
+ dns_name_format(name, namestr,
+ sizeof(namestr));
+ dns_rdatatype_format(rdataset->type,
+ typebuf,
+ sizeof(typebuf));
+ dns_rdataclass_format(rdataset->rdclass,
+ classbuf,
+ sizeof(classbuf));
+ printf(";; Question section mismatch: "
+ "got %s/%s/%s\n",
+ namestr, typebuf, classbuf);
+ match = ISC_FALSE;
+ }
+ }
+ }
+ if (!match) {
+ dns_message_destroy(&msg);
+ if (l->tcp_mode) {
+ isc_event_free(&event);
+ clear_query(query);
+ check_next_lookup(l);
+ UNLOCK_LOOKUP;
+ return;
+ } else
+ goto udp_mismatch;
+ }
+ }
if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0 &&
!l->ignore && !l->tcp_mode) {
printf(";; Truncated, retrying in TCP mode.\n");
@@ -3212,6 +3299,19 @@ recv_done(isc_task_t *task, isc_event_t *event) {
}
isc_event_free(&event);
UNLOCK_LOOKUP;
+ return;
+
+ udp_mismatch:
+ isc_buffer_invalidate(&query->recvbuf);
+ isc_buffer_init(&query->recvbuf, query->recvspace, COMMSIZE);
+ ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, link);
+ result = isc_socket_recvv(query->sock, &query->recvlist, 1,
+ global_task, recv_done, query);
+ check_result(result, "isc_socket_recvv");
+ recvcount++;
+ isc_event_free(&event);
+ UNLOCK_LOOKUP;
+ return;
}
/*%
@@ -3219,7 +3319,7 @@ recv_done(isc_task_t *task, isc_event_t *event) {
* used in looking up server names, etc... and needs to use system-supplied
* routines, since they may be using a non-DNS system for these lookups.
*/
-void
+isc_result_t
get_address(char *host, in_port_t port, isc_sockaddr_t *sockaddr) {
int count;
isc_result_t result;
@@ -3228,9 +3328,11 @@ get_address(char *host, in_port_t port, isc_sockaddr_t *sockaddr) {
result = bind9_getaddresses(host, port, sockaddr, 1, &count);
isc_app_unblock();
if (result != ISC_R_SUCCESS)
- fatal("couldn't get address for '%s': %s",
- host, isc_result_totext(result));
+ return (result);
+
INSIST(count == 1);
+
+ return (ISC_R_SUCCESS);
}
/*%
@@ -3284,7 +3386,7 @@ cancel_all(void) {
isc_timer_detach(&current_lookup->timer);
q = ISC_LIST_HEAD(current_lookup->q);
while (q != NULL) {
- debug("cancelling query %p, belonging to %p",
+ debug("canceling query %p, belonging to %p",
q, current_lookup);
nq = ISC_LIST_NEXT(q, link);
if (q->sock != NULL) {
@@ -3600,7 +3702,7 @@ dns_rdataset_t *
search_type(dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers) {
dns_rdataset_t *rdataset;
dns_rdata_sig_t siginfo;
- dns_rdata_t sigrdata;
+ dns_rdata_t sigrdata = DNS_RDATA_INIT;
isc_result_t result;
for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL;
@@ -3610,7 +3712,6 @@ search_type(dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers) {
return (rdataset);
} else if ((type == dns_rdatatype_rrsig) &&
(rdataset->type == dns_rdatatype_rrsig)) {
- dns_rdata_init(&sigrdata);
result = dns_rdataset_first(rdataset);
check_result(result, "empty rdataset");
dns_rdataset_current(rdataset, &sigrdata);
@@ -4133,7 +4234,7 @@ isc_result_t
grandfather_pb_test(dns_name_t *zone_name, dns_rdataset_t *sigrdataset)
{
isc_result_t result;
- dns_rdata_t sigrdata;
+ dns_rdata_t sigrdata = DNS_RDATA_INIT;
dns_rdata_sig_t siginfo;
result = dns_rdataset_first(sigrdataset);
@@ -4153,6 +4254,7 @@ grandfather_pb_test(dns_name_t *zone_name, dns_rdataset_t *sigrdataset)
}
dns_rdata_freestruct(&siginfo);
+ dns_rdata_reset(&sigrdata);
} while (dns_rdataset_next(chase_sigkeyrdataset) == ISC_R_SUCCESS);
@@ -4239,7 +4341,7 @@ contains_trusted_key(dns_name_t *name, dns_rdataset_t *rdataset,
isc_mem_t *mctx)
{
isc_result_t result;
- dns_rdata_t rdata;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
dst_key_t *trustedKey = NULL;
dst_key_t *dnsseckey = NULL;
int i;
@@ -4249,7 +4351,6 @@ contains_trusted_key(dns_name_t *name, dns_rdataset_t *rdataset,
result = dns_rdataset_first(rdataset);
check_result(result, "empty rdataset");
- dns_rdata_init(&rdata);
do {
dns_rdataset_current(rdataset, &rdata);
@@ -4299,7 +4400,7 @@ sigchase_verify_sig(dns_name_t *name, dns_rdataset_t *rdataset,
isc_mem_t *mctx)
{
isc_result_t result;
- dns_rdata_t keyrdata;
+ dns_rdata_t keyrdata = DNS_RDATA_INIT;
dst_key_t *dnsseckey = NULL;
result = dns_rdataset_first(keyrdataset);
@@ -4322,6 +4423,7 @@ sigchase_verify_sig(dns_name_t *name, dns_rdataset_t *rdataset,
return (ISC_R_SUCCESS);
}
dst_key_free(&dnsseckey);
+ dns_rdata_reset(&keyrdata);
} while (dns_rdataset_next(chase_keyrdataset) == ISC_R_SUCCESS);
dns_rdata_reset(&keyrdata);
@@ -4335,7 +4437,7 @@ sigchase_verify_sig_key(dns_name_t *name, dns_rdataset_t *rdataset,
isc_mem_t *mctx)
{
isc_result_t result;
- dns_rdata_t sigrdata;
+ dns_rdata_t sigrdata = DNS_RDATA_INIT;
dns_rdata_sig_t siginfo;
result = dns_rdataset_first(sigrdataset);
@@ -4373,6 +4475,7 @@ sigchase_verify_sig_key(dns_name_t *name, dns_rdataset_t *rdataset,
}
}
dns_rdata_freestruct(&siginfo);
+ dns_rdata_reset(&sigrdata);
} while (dns_rdataset_next(chase_sigkeyrdataset) == ISC_R_SUCCESS);
@@ -4387,25 +4490,23 @@ sigchase_verify_ds(dns_name_t *name, dns_rdataset_t *keyrdataset,
dns_rdataset_t *dsrdataset, isc_mem_t *mctx)
{
isc_result_t result;
- dns_rdata_t keyrdata;
- dns_rdata_t newdsrdata;
- dns_rdata_t dsrdata;
+ dns_rdata_t keyrdata = DNS_RDATA_INIT;
+ dns_rdata_t newdsrdata = DNS_RDATA_INIT;
+ dns_rdata_t dsrdata = DNS_RDATA_INIT;
dns_rdata_ds_t dsinfo;
dst_key_t *dnsseckey = NULL;
unsigned char dsbuf[DNS_DS_BUFFERSIZE];
result = dns_rdataset_first(dsrdataset);
check_result(result, "empty DSset dataset");
- dns_rdata_init(&dsrdata);
do {
dns_rdataset_current(dsrdataset, &dsrdata);
result = dns_rdata_tostruct(&dsrdata, &dsinfo, NULL);
- check_result(result, "dns_rdata_tostruct for DS");
+ check_result(result, "dns_rdata_tostruct for DS");
result = dns_rdataset_first(keyrdataset);
check_result(result, "empty KEY dataset");
- dns_rdata_init(&keyrdata);
do {
dns_rdataset_current(keyrdataset, &keyrdata);
@@ -4420,7 +4521,6 @@ sigchase_verify_ds(dns_name_t *name, dns_rdataset_t *keyrdataset,
* id of DNSKEY referenced by the DS
*/
if (dsinfo.key_tag == dst_key_id(dnsseckey)) {
- dns_rdata_init(&newdsrdata);
result = dns_ds_buildrdata(name, &keyrdata,
dsinfo.digest_type,
@@ -4468,14 +4568,16 @@ sigchase_verify_ds(dns_name_t *name, dns_rdataset_t *keyrdataset,
dns_rdata_reset(&newdsrdata);
}
dst_key_free(&dnsseckey);
+ dns_rdata_reset(&keyrdata);
dnsseckey = NULL;
} while (dns_rdataset_next(chase_keyrdataset) == ISC_R_SUCCESS);
- dns_rdata_reset(&keyrdata);
+ dns_rdata_reset(&dsrdata);
} while (dns_rdataset_next(chase_dsrdataset) == ISC_R_SUCCESS);
-#if 0
- dns_rdata_reset(&dsrdata); WARNING
-#endif
+
+ dns_rdata_reset(&keyrdata);
+ dns_rdata_reset(&newdsrdata);
+ dns_rdata_reset(&dsrdata);
return (ISC_R_NOTFOUND);
}
@@ -4868,7 +4970,7 @@ getneededrr(dns_message_t *msg)
{
isc_result_t result;
dns_name_t *name = NULL;
- dns_rdata_t sigrdata;
+ dns_rdata_t sigrdata = DNS_RDATA_INIT;
dns_rdata_sig_t siginfo;
isc_boolean_t true = ISC_TRUE;
@@ -4922,7 +5024,6 @@ getneededrr(dns_message_t *msg)
/* first find the DNSKEY name */
result = dns_rdataset_first(chase_sigrdataset);
check_result(result, "empty RRSIG dataset");
- dns_rdata_init(&sigrdata);
dns_rdataset_current(chase_sigrdataset, &sigrdata);
result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
check_result(result, "sigrdata tostruct siginfo");
@@ -5300,6 +5401,7 @@ prove_nx_domain(dns_message_t *msg,
}
dns_rdata_freestruct(&nsecstruct);
+ dns_rdata_reset(&nsec);
}
} while (dns_message_nextname(msg, DNS_SECTION_AUTHORITY)
== ISC_R_SUCCESS);
@@ -5367,7 +5469,7 @@ prove_nx(dns_message_t *msg, dns_name_t *name, dns_rdataclass_t class,
isc_result_t ret;
dns_rdataset_t *nsecset = NULL;
- printf("We want to prove the non-existance of a type of rdata %d"
+ printf("We want to prove the non-existence of a type of rdata %d"
" or of the zone: \n", type);
if ((ret = dns_message_firstname(msg, DNS_SECTION_AUTHORITY))