summaryrefslogtreecommitdiff
path: root/bin/dig/dighost.c
diff options
context:
space:
mode:
Diffstat (limited to 'bin/dig/dighost.c')
-rw-r--r--bin/dig/dighost.c303
1 files changed, 153 insertions, 150 deletions
diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c
index 8ea7d8ec03662..b5a3c36d43143 100644
--- a/bin/dig/dighost.c
+++ b/bin/dig/dighost.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2012 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2014 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -46,8 +46,10 @@
#include <dns/byaddr.h>
#ifdef DIG_SIGCHASE
+#include <dns/callbacks.h>
#include <dns/dnssec.h>
#include <dns/ds.h>
+#include <dns/master.h>
#include <dns/nsec.h>
#include <isc/random.h>
#include <ctype.h>
@@ -123,7 +125,8 @@ isc_boolean_t
usesearch = ISC_FALSE,
showsearch = ISC_FALSE,
qr = ISC_FALSE,
- is_dst_up = ISC_FALSE;
+ is_dst_up = ISC_FALSE,
+ keep_open = ISC_FALSE;
in_port_t port = 53;
unsigned int timeout = 0;
unsigned int extrabytes;
@@ -155,6 +158,9 @@ static void idn_check_result(idn_result_t r, const char *msg);
int idnoptions = 0;
#endif
+isc_socket_t *keep = NULL;
+isc_sockaddr_t keepaddr;
+
/*%
* Exit Codes:
*
@@ -178,6 +184,7 @@ isc_boolean_t validated = ISC_TRUE;
isc_entropy_t *entp = NULL;
isc_mempool_t *commctx = NULL;
isc_boolean_t debugging = ISC_FALSE;
+isc_boolean_t debugtiming = ISC_FALSE;
isc_boolean_t memdebugging = ISC_FALSE;
char *progname = NULL;
isc_mutex_t lookup_lock;
@@ -250,11 +257,10 @@ isc_result_t prove_nx(dns_message_t * msg, dns_name_t * name,
dns_rdataset_t ** sigrdataset);
static void nameFromString(const char *str, dns_name_t *p_ret);
int inf_name(dns_name_t * name1, dns_name_t * name2);
-isc_result_t opentmpkey(isc_mem_t *mctx, const char *file,
- char **tempp, FILE **fp);
isc_result_t removetmpkey(isc_mem_t *mctx, const char *file);
void clean_trustedkey(void);
-void insert_trustedkey(dst_key_t **key);
+isc_result_t insert_trustedkey(void *arg, dns_name_t *name,
+ dns_rdataset_t *rdataset);
#if DIG_SIGCHASE_BU
isc_result_t getneededrr(dns_message_t *msg);
void sigchase_bottom_up(dns_message_t *msg);
@@ -444,7 +450,7 @@ static isc_result_t
append(const char *text, int len, char **p, char *end) {
if (len > end - *p)
return (ISC_R_NOSPACE);
- memcpy(*p, text, len);
+ memmove(*p, text, len);
*p += len;
return (ISC_R_SUCCESS);
}
@@ -461,7 +467,7 @@ reverse_octets(const char *in, char **p, char *end) {
result = append(".", 1, p, end);
if (result != ISC_R_SUCCESS)
return (result);
- len = dot - in;
+ len = (int)(dot - in);
} else {
len = strlen(in);
}
@@ -491,7 +497,7 @@ get_reverse(char *reverse, size_t len, char *value, isc_boolean_t ip6_int,
result = dns_byaddr_createptrname2(&addr, options, name);
if (result != ISC_R_SUCCESS)
return (result);
- dns_name_format(name, reverse, len);
+ dns_name_format(name, reverse, (unsigned int)len);
return (ISC_R_SUCCESS);
} else {
/*
@@ -537,9 +543,15 @@ fatal(const char *format, ...) {
void
debug(const char *format, ...) {
va_list args;
+ isc_time_t t;
if (debugging) {
fflush(stdout);
+ if (debugtiming) {
+ TIME_NOW(&t);
+ fprintf(stderr, "%d.%06d: ", isc_time_seconds(&t),
+ isc_time_nanoseconds(&t) / 1000);
+ }
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
@@ -1318,6 +1330,7 @@ setup_libs(void) {
result = isc_mem_create(0, 0, &mctx);
check_result(result, "isc_mem_create");
+ isc_mem_setname(mctx, "dig", NULL);
result = isc_log_create(mctx, &lctx, &logconfig);
check_result(result, "isc_log_create");
@@ -1336,6 +1349,7 @@ setup_libs(void) {
result = isc_task_create(taskmgr, 0, &global_task);
check_result(result, "isc_task_create");
+ isc_task_setname(global_task, "dig", NULL);
result = isc_timermgr_create(mctx, &timermgr);
check_result(result, "isc_timermgr_create");
@@ -1884,6 +1898,9 @@ static isc_boolean_t
next_origin(dig_query_t *query) {
dig_lookup_t *lookup;
dig_searchlist_t *search;
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+ isc_result_t result;
INSIST(!free_now);
@@ -1896,6 +1913,19 @@ next_origin(dig_query_t *query) {
* about finding the next entry.
*/
return (ISC_FALSE);
+
+ /*
+ * Check for a absolute name or ndots being met.
+ */
+ dns_fixedname_init(&fixed);
+ name = dns_fixedname_name(&fixed);
+ result = dns_name_fromstring2(name, query->lookup->textname, NULL,
+ 0, NULL);
+ if (result == ISC_R_SUCCESS &&
+ (dns_name_isabsolute(name) ||
+ (int)dns_name_countlabels(name) > ndots))
+ return (ISC_FALSE);
+
if (query->lookup->origin == NULL && !query->lookup->need_search)
/*
* Then we just did rootorg; there's nothing left.
@@ -2304,6 +2334,7 @@ setup_lookup(dig_lookup_t *lookup) {
query->rr_count = 0;
query->msg_count = 0;
query->byte_count = 0;
+ query->ixfr_axfr = ISC_FALSE;
ISC_LIST_INIT(query->recvlist);
ISC_LIST_INIT(query->lengthlist);
query->sock = NULL;
@@ -2352,8 +2383,10 @@ send_done(isc_task_t *_task, isc_event_t *event) {
for (b = ISC_LIST_HEAD(sevent->bufferlist);
b != NULL;
- b = ISC_LIST_HEAD(sevent->bufferlist))
+ b = ISC_LIST_HEAD(sevent->bufferlist)) {
ISC_LIST_DEQUEUE(sevent->bufferlist, b, link);
+ isc_mem_free(mctx, b);
+ }
query = event->ev_arg;
query->waiting_senddone = ISC_FALSE;
@@ -2508,6 +2541,15 @@ send_tcp_connect(dig_query_t *query) {
}
INSIST(query->sock == NULL);
+
+ if (keep != NULL && isc_sockaddr_equal(&keepaddr, &query->sockaddr)) {
+ sockcount++;
+ isc_socket_attach(keep, &query->sock);
+ query->waiting_connect = ISC_FALSE;
+ launch_next_query(query, ISC_TRUE);
+ goto search;
+ }
+
result = isc_socket_create(socketmgr,
isc_sockaddr_pf(&query->sockaddr),
isc_sockettype_tcp, &query->sock);
@@ -2530,6 +2572,7 @@ send_tcp_connect(dig_query_t *query) {
result = isc_socket_connect(query->sock, &query->sockaddr,
global_task, connect_done, query);
check_result(result, "isc_socket_connect");
+ search:
/*
* If we're at the endgame of a nameserver search, we need to
* immediately bring up all the queries. Do it here.
@@ -2545,6 +2588,17 @@ send_tcp_connect(dig_query_t *query) {
}
}
+static isc_buffer_t *
+clone_buffer(isc_buffer_t *source) {
+ isc_buffer_t *buffer;
+ buffer = isc_mem_allocate(mctx, sizeof(*buffer));
+ if (buffer == NULL)
+ fatal("memory allocation failure in %s:%d",
+ __FILE__, __LINE__);
+ *buffer = *source;
+ return (buffer);
+}
+
/*%
* Send a UDP packet to the remote nameserver, possible starting the
* recv action as well. Also make sure that the timer is running and
@@ -2554,6 +2608,7 @@ static void
send_udp(dig_query_t *query) {
dig_lookup_t *l = NULL;
isc_result_t result;
+ isc_buffer_t *sendbuf;
debug("send_udp(%p)", query);
@@ -2600,14 +2655,16 @@ send_udp(dig_query_t *query) {
debug("recvcount=%d", recvcount);
}
ISC_LIST_INIT(query->sendlist);
- ISC_LIST_ENQUEUE(query->sendlist, &query->sendbuf, link);
+ sendbuf = clone_buffer(&query->sendbuf);
+ ISC_LIST_ENQUEUE(query->sendlist, sendbuf, link);
debug("sending a request");
TIME_NOW(&query->time_sent);
INSIST(query->sock != NULL);
query->waiting_senddone = ISC_TRUE;
- result = isc_socket_sendtov(query->sock, &query->sendlist,
- global_task, send_done, query,
- &query->sockaddr, NULL);
+ result = isc_socket_sendtov2(query->sock, &query->sendlist,
+ global_task, send_done, query,
+ &query->sockaddr, NULL,
+ ISC_SOCKFLAG_NORETRY);
check_result(result, "isc_socket_sendtov");
sendcount++;
}
@@ -2769,6 +2826,7 @@ static void
launch_next_query(dig_query_t *query, isc_boolean_t include_question) {
isc_result_t result;
dig_lookup_t *l;
+ isc_buffer_t *buffer;
INSIST(!free_now);
@@ -2792,9 +2850,15 @@ launch_next_query(dig_query_t *query, isc_boolean_t include_question) {
isc_buffer_putuint16(&query->slbuf, (isc_uint16_t) query->sendbuf.used);
ISC_LIST_INIT(query->sendlist);
ISC_LINK_INIT(&query->slbuf, link);
- ISC_LIST_ENQUEUE(query->sendlist, &query->slbuf, link);
- if (include_question)
- ISC_LIST_ENQUEUE(query->sendlist, &query->sendbuf, link);
+ if (!query->first_soa_rcvd) {
+ buffer = clone_buffer(&query->slbuf);
+ ISC_LIST_ENQUEUE(query->sendlist, buffer, link);
+ if (include_question) {
+ buffer = clone_buffer(&query->sendbuf);
+ ISC_LIST_ENQUEUE(query->sendlist, buffer, link);
+ }
+ }
+
ISC_LINK_INIT(&query->lengthbuf, link);
ISC_LIST_ENQUEUE(query->lengthlist, &query->lengthbuf, link);
@@ -2894,6 +2958,12 @@ connect_done(isc_task_t *task, isc_event_t *event) {
UNLOCK_LOOKUP;
return;
}
+ if (keep_open) {
+ if (keep != NULL)
+ isc_socket_detach(&keep);
+ isc_socket_attach(query->sock, &keep);
+ keepaddr = query->sockaddr;
+ }
launch_next_query(query, ISC_TRUE);
isc_event_free(&event);
UNLOCK_LOOKUP;
@@ -2917,6 +2987,9 @@ check_for_more_data(dig_query_t *query, dns_message_t *msg,
isc_boolean_t ixfr = query->lookup->rdtype == dns_rdatatype_ixfr;
isc_boolean_t axfr = query->lookup->rdtype == dns_rdatatype_axfr;
+ if (ixfr)
+ axfr = query->ixfr_axfr;
+
debug("check_for_more_data()");
/*
@@ -2965,7 +3038,7 @@ check_for_more_data(dig_query_t *query, dns_message_t *msg,
query->second_rr_rcvd = ISC_TRUE;
query->second_rr_serial = 0;
debug("got the second rr as nonsoa");
- axfr = ISC_TRUE;
+ axfr = query->ixfr_axfr = ISC_TRUE;
goto next_rdata;
}
@@ -3401,7 +3474,7 @@ recv_done(isc_task_t *task, isc_event_t *event) {
}
if (!l->doing_xfr || l->xfr_q == query) {
- if (msg->rcode != dns_rcode_noerror &&
+ if (msg->rcode == dns_rcode_nxdomain &&
(l->origin != NULL || l->need_search)) {
if (!next_origin(query) || showsearch) {
printmessage(query, msg, ISC_TRUE);
@@ -3672,18 +3745,31 @@ cancel_all(void) {
if (current_lookup != NULL) {
if (current_lookup->timer != NULL)
isc_timer_detach(&current_lookup->timer);
- q = ISC_LIST_HEAD(current_lookup->q);
- while (q != NULL) {
- debug("canceling query %p, belonging to %p",
- q, current_lookup);
+ for (q = ISC_LIST_HEAD(current_lookup->q);
+ q != NULL;
+ q = nq)
+ {
nq = ISC_LIST_NEXT(q, link);
- if (q->sock != NULL) {
+ debug("canceling pending query %p, belonging to %p",
+ q, current_lookup);
+ if (q->sock != NULL)
isc_socket_cancel(q->sock, NULL,
ISC_SOCKCANCEL_ALL);
- } else {
+ else
+ clear_query(q);
+ }
+ for (q = ISC_LIST_HEAD(current_lookup->connecting);
+ q != NULL;
+ q = nq)
+ {
+ nq = ISC_LIST_NEXT(q, clink);
+ debug("canceling connecting query %p, belonging to %p",
+ q, current_lookup);
+ if (q->sock != NULL)
+ isc_socket_cancel(q->sock, NULL,
+ ISC_SOCKCANCEL_ALL);
+ else
clear_query(q);
- }
- q = nq;
}
}
l = ISC_LIST_HEAD(lookup_list);
@@ -3710,6 +3796,8 @@ destroy_libs(void) {
isc_result_t result;
#endif
+ if (keep != NULL)
+ isc_socket_detach(&keep);
debug("destroy_libs()");
if (global_task != NULL) {
debug("freeing task");
@@ -3861,7 +3949,7 @@ output_filter(isc_buffer_t *buffer, unsigned int used_org,
fromlen = isc_buffer_usedlength(buffer) - used_org;
if (fromlen >= MAXDLEN)
return (ISC_R_SUCCESS);
- memcpy(tmp1, (char *)isc_buffer_base(buffer) + used_org, fromlen);
+ memmove(tmp1, (char *)isc_buffer_base(buffer) + used_org, fromlen);
end_with_dot = (tmp1[fromlen - 1] == '.') ? ISC_TRUE : ISC_FALSE;
if (absolute && !end_with_dot) {
fromlen++;
@@ -3890,8 +3978,8 @@ output_filter(isc_buffer_t *buffer, unsigned int used_org,
return (ISC_R_NOSPACE);
isc_buffer_subtract(buffer, isc_buffer_usedlength(buffer) - used_org);
- memcpy(isc_buffer_used(buffer), tmp1, tolen);
- isc_buffer_add(buffer, tolen);
+ memmove(isc_buffer_used(buffer), tmp1, tolen);
+ isc_buffer_add(buffer, (unsigned int)tolen);
return (ISC_R_SUCCESS);
}
@@ -3910,7 +3998,8 @@ append_textname(char *name, const char *origin, size_t namesize) {
if (namelen + 1 + originlen >= namesize)
return idn_buffer_overflow;
- name[namelen++] = '.';
+ if (*origin != '.')
+ name[namelen++] = '.';
(void)strcpy(name + namelen, origin);
return idn_success;
}
@@ -4133,17 +4222,35 @@ sigchase_scanname(dns_rdatatype_t type, dns_rdatatype_t covers,
return (NULL);
}
-void
-insert_trustedkey(dst_key_t **keyp)
+isc_result_t
+insert_trustedkey(void *arg, dns_name_t *name, dns_rdataset_t *rdataset)
{
- if (*keyp == NULL)
- return;
- if (tk_list.nb_tk >= MAX_TRUSTED_KEY)
- return;
+ isc_result_t result;
+ dst_key_t *key;
- tk_list.key[tk_list.nb_tk++] = *keyp;
- *keyp = NULL;
- return;
+ UNUSED(arg);
+
+ if (rdataset == NULL || rdataset->type != dns_rdatatype_dnskey)
+ return (ISC_R_SUCCESS);
+
+ for (result = dns_rdataset_first(rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset)) {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_buffer_t b;
+
+ dns_rdataset_current(rdataset, &rdata);
+ isc_buffer_init(&b, rdata.data, rdata.length);
+ isc_buffer_add(&b, rdata.length);
+ if (tk_list.nb_tk >= MAX_TRUSTED_KEY)
+ return (ISC_R_SUCCESS);
+ key = NULL;
+ result = dst_key_fromdns(name, rdata.rdclass, &b, mctx, &key);
+ if (result != ISC_R_SUCCESS)
+ continue;
+ tk_list.key[tk_list.nb_tk++] = key;
+ }
+ return (ISC_R_SUCCESS);
}
void
@@ -4190,86 +4297,11 @@ removetmpkey(isc_mem_t *mctx, const char *file)
}
isc_result_t
-opentmpkey(isc_mem_t *mctx, const char *file, char **tempp, FILE **fp) {
- FILE *f = NULL;
- isc_result_t result;
- char *tempname = NULL;
- char *tempnamekey = NULL;
- int tempnamelen;
- int tempnamekeylen;
- char *x;
- char *cp;
- isc_uint32_t which;
-
- while (1) {
- tempnamelen = strlen(file) + 20;
- tempname = isc_mem_allocate(mctx, tempnamelen);
- if (tempname == NULL)
- return (ISC_R_NOMEMORY);
- memset(tempname, 0, tempnamelen);
-
- result = isc_file_mktemplate(file, tempname, tempnamelen);
- if (result != ISC_R_SUCCESS)
- goto cleanup;
-
- cp = tempname;
- while (*cp != '\0')
- cp++;
- if (cp == tempname) {
- isc_mem_free(mctx, tempname);
- return (ISC_R_FAILURE);
- }
-
- x = cp--;
- while (cp >= tempname && *cp == 'X') {
- isc_random_get(&which);
- *cp = alphnum[which % (sizeof(alphnum) - 1)];
- x = cp--;
- }
-
- tempnamekeylen = tempnamelen+5;
- tempnamekey = isc_mem_allocate(mctx, tempnamekeylen);
- if (tempnamekey == NULL)
- return (ISC_R_NOMEMORY);
-
- memset(tempnamekey, 0, tempnamekeylen);
- strlcpy(tempnamekey, tempname, tempnamelen);
- strcat(tempnamekey ,".key");
-
-
- if (isc_file_exists(tempnamekey)) {
- isc_mem_free(mctx, tempnamekey);
- isc_mem_free(mctx, tempname);
- continue;
- }
-
- if ((f = fopen(tempnamekey, "w")) == NULL) {
- printf("get_trusted_key(): trusted key not found %s\n",
- tempnamekey);
- return (ISC_R_FAILURE);
- }
- break;
- }
- isc_mem_free(mctx, tempnamekey);
- *tempp = tempname;
- *fp = f;
- return (ISC_R_SUCCESS);
-
- cleanup:
- isc_mem_free(mctx, tempname);
-
- return (result);
-}
-
-isc_result_t
get_trusted_key(isc_mem_t *mctx)
{
isc_result_t result;
const char *filename = NULL;
- char *filetemp = NULL;
- char buf[1500];
- FILE *fp, *fptemp;
- dst_key_t *key = NULL;
+ dns_rdatacallbacks_t callbacks;
result = isc_file_exists(trustedkey);
if (result != ISC_TRUE) {
@@ -4290,40 +4322,11 @@ get_trusted_key(isc_mem_t *mctx)
return (ISC_R_FAILURE);
}
- if ((fp = fopen(filename, "r")) == NULL) {
- printf("get_trusted_key(): trusted key not found %s\n",
- filename);
- return (ISC_R_FAILURE);
- }
- while (fgets(buf, sizeof(buf), fp) != NULL) {
- result = opentmpkey(mctx,"tmp_file", &filetemp, &fptemp);
- if (result != ISC_R_SUCCESS) {
- fclose(fp);
- return (ISC_R_FAILURE);
- }
- if (fputs(buf, fptemp) < 0) {
- fclose(fp);
- fclose(fptemp);
- return (ISC_R_FAILURE);
- }
- fclose(fptemp);
- result = dst_key_fromnamedfile(filetemp, NULL, DST_TYPE_PUBLIC,
- mctx, &key);
- removetmpkey(mctx, filetemp);
- isc_mem_free(mctx, filetemp);
- if (result != ISC_R_SUCCESS) {
- fclose(fp);
- return (ISC_R_FAILURE);
- }
-#if 0
- dst_key_tofile(key, DST_TYPE_PUBLIC,"/tmp");
-#endif
- insert_trustedkey(&key);
- if (key != NULL)
- dst_key_free(&key);
- }
- fclose(fp);
- return (ISC_R_SUCCESS);
+ dns_rdatacallbacks_init_stdio(&callbacks);
+ callbacks.add = insert_trustedkey;
+ return (dns_master_loadfile(filename, dns_rootname, dns_rootname,
+ current_lookup->rdclass, 0, &callbacks,
+ mctx));
}
@@ -4337,7 +4340,7 @@ nameFromString(const char *str, dns_name_t *p_ret) {
REQUIRE(p_ret != NULL);
REQUIRE(str != NULL);
- isc_buffer_init(&buffer, str, len);
+ isc_buffer_constinit(&buffer, str, len);
isc_buffer_add(&buffer, len);
dns_fixedname_init(&fixedname);