diff options
Diffstat (limited to 'contrib/bind9/bin/dig/dighost.c')
-rw-r--r-- | contrib/bind9/bin/dig/dighost.c | 232 |
1 files changed, 174 insertions, 58 deletions
diff --git a/contrib/bind9/bin/dig/dighost.c b/contrib/bind9/bin/dig/dighost.c index 8736c0c..470261c 100644 --- a/contrib/bind9/bin/dig/dighost.c +++ b/contrib/bind9/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.311.70.8 2009/02/25 02:39:21 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); @@ -724,6 +729,7 @@ make_empty_lookup(void) { looknew->servfail_stops = ISC_TRUE; looknew->besteffort = ISC_TRUE; looknew->dnssec = ISC_FALSE; + looknew->nsid = ISC_FALSE; #ifdef DIG_SIGCHASE looknew->sigchase = ISC_FALSE; #if DIG_SIGCHASE_TD @@ -770,7 +776,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) { @@ -803,6 +809,7 @@ clone_lookup(dig_lookup_t *lookold, isc_boolean_t servers) { looknew->servfail_stops = lookold->servfail_stops; looknew->besteffort = lookold->besteffort; looknew->dnssec = lookold->dnssec; + looknew->nsid = lookold->nsid; #ifdef DIG_SIGCHASE looknew->sigchase = lookold->sigchase; #if DIG_SIGCHASE_TD @@ -1004,10 +1011,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 +1048,10 @@ setup_system(void) { debug("ndots is %d.", ndots); } + 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(); @@ -1155,11 +1171,11 @@ setup_libs(void) { /*% * Add EDNS0 option record to a message. Currently, the only supported - * options are UDP buffer size and the DO bit. + * options are UDP buffer size, the DO bit, and NSID request. */ static void add_opt(dns_message_t *msg, isc_uint16_t udpsize, isc_uint16_t edns, - isc_boolean_t dnssec) + isc_boolean_t dnssec, isc_boolean_t nsid) { dns_rdataset_t *rdataset = NULL; dns_rdatalist_t *rdatalist = NULL; @@ -1182,8 +1198,19 @@ add_opt(dns_message_t *msg, isc_uint16_t udpsize, isc_uint16_t edns, rdatalist->ttl = edns << 16; if (dnssec) rdatalist->ttl |= DNS_MESSAGEEXTFLAG_DO; - rdata->data = NULL; - rdata->length = 0; + if (nsid) { + unsigned char data[4]; + isc_buffer_t buf; + + isc_buffer_init(&buf, data, sizeof(data)); + isc_buffer_putuint16(&buf, DNS_OPT_NSID); + isc_buffer_putuint16(&buf, 0); + rdata->data = data; + rdata->length = sizeof(data); + } else { + rdata->data = NULL; + rdata->length = 0; + } ISC_LIST_INIT(rdatalist->rdata); ISC_LIST_APPEND(rdatalist->rdata, rdata, link); dns_rdatalist_tordataset(rdatalist, rdataset); @@ -1387,7 +1414,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 */ } @@ -1848,7 +1875,7 @@ setup_lookup(dig_lookup_t *lookup) { &lookup->name); dns_message_puttempname(lookup->sendmsg, &lookup->oname); - fatal("Origin '%s' is not in legal name syntax (%s)", + fatal("'%s' is not in legal name syntax (%s)", lookup->origin->origin, isc_result_totext(result)); } @@ -1953,12 +1980,15 @@ setup_lookup(dig_lookup_t *lookup) { if ((lookup->rdtype == dns_rdatatype_axfr) || (lookup->rdtype == dns_rdatatype_ixfr)) { - lookup->doing_xfr = ISC_TRUE; /* - * Force TCP mode if we're doing an xfr. - * XXX UDP ixfr's would be useful + * Force TCP mode if we're doing an axfr. */ - lookup->tcp_mode = ISC_TRUE; + if (lookup->rdtype == dns_rdatatype_axfr) { + lookup->doing_xfr = ISC_TRUE; + lookup->tcp_mode = ISC_TRUE; + } else if (lookup->tcp_mode) { + lookup->doing_xfr = ISC_TRUE; + } } add_question(lookup->sendmsg, lookup->name, lookup->rdclass, @@ -1995,7 +2025,7 @@ setup_lookup(dig_lookup_t *lookup) { if (lookup->edns < 0) lookup->edns = 0; add_opt(lookup->sendmsg, lookup->udpsize, - lookup->edns, lookup->dnssec); + lookup->edns, lookup->dnssec, lookup->nsid); } result = dns_message_rendersection(lookup->sendmsg, @@ -2175,6 +2205,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 +2238,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 +2320,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 +2396,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 +2957,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 +3013,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 +3313,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 +3333,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 +3342,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 +3400,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 +3716,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 +3726,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 +4248,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 +4268,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 +4355,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 +4365,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 +4414,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 +4437,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 +4451,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 +4489,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 +4504,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 +4535,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 +4582,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 +4984,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 +5038,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 +5415,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 +5483,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)) |