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