diff options
Diffstat (limited to 'bin/dig/dighost.c')
-rw-r--r-- | bin/dig/dighost.c | 303 |
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(¤t_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); |