diff --git a/CHANGES b/CHANGES index 019388d575..a76cd699d9 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,8 @@ + 556. [func] The DNSSEC OK bit in the EDNS extended flags + is now implemented. Responses to queries without + this bit set will not contain any DNSSEC records. + 555. [bug] A slave server attempting a zone transfer could crash with an assertion failure on certain malformed responses from the master. [RT #457] diff --git a/bin/dig/dig.c b/bin/dig/dig.c index f67f48b13d..6d942c764a 100644 --- a/bin/dig/dig.c +++ b/bin/dig/dig.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dig.c,v 1.126 2000/11/08 00:47:15 mws Exp $ */ +/* $Id: dig.c,v 1.127 2000/11/13 21:33:50 bwelling Exp $ */ #include #include @@ -180,6 +180,7 @@ show_usage(void) { " +[no]trace (Trace delegation down from root)\n" " +rrlimit=### (Limit number of rr's in xfr)\n" " +namelimit=### (Limit number of names in xfr)\n" +" +[no]dnssec (Request DNSSEC records)\n" " global d-opts and servers (before host name) affect all queries.\n" " local d-opts and servers (after host name) affect only that lookup.\n" , stderr); @@ -679,9 +680,12 @@ plus_option(char *option, isc_boolean_t is_batchfile, break; case 'd': switch (cmd[1]) { - case 'e': + case 'e': /* defname */ lookup->defname = state; break; + case 'n': /* dnssec */ + lookup->dnssec = state; + break; case 'o': /* domain */ if (value == NULL) goto need_value; diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c index d08ee6980b..6f7974d5f4 100644 --- a/bin/dig/dighost.c +++ b/bin/dig/dighost.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dighost.c,v 1.161 2000/11/08 01:23:27 gson Exp $ */ +/* $Id: dighost.c,v 1.162 2000/11/13 21:33:51 bwelling Exp $ */ /* * Notice to programmers: Do not use this code as an example of how to @@ -356,6 +356,7 @@ make_empty_lookup(void) { looknew->ignore = ISC_FALSE; looknew->servfail_stops = ISC_FALSE; looknew->besteffort = ISC_TRUE; + looknew->dnssec = ISC_FALSE; looknew->udpsize = 0; looknew->recurse = ISC_TRUE; looknew->aaonly = ISC_FALSE; @@ -415,6 +416,7 @@ clone_lookup(dig_lookup_t *lookold, isc_boolean_t servers) { looknew->ignore = lookold->ignore; looknew->servfail_stops = lookold->servfail_stops; looknew->besteffort = lookold->besteffort; + looknew->dnssec = lookold->dnssec; looknew->udpsize = lookold->udpsize; looknew->recurse = lookold->recurse; looknew->aaonly = lookold->aaonly; @@ -757,7 +759,9 @@ setup_libs(void) { * option is UDP buffer size. */ static void -add_opt(dns_message_t *msg, isc_uint16_t udpsize, dns_optlist_t optlist) { +add_opt(dns_message_t *msg, isc_uint16_t udpsize, isc_boolean_t dnssec, + dns_optlist_t optlist) +{ dns_rdataset_t *rdataset = NULL; dns_rdatalist_t *rdatalist = NULL; dns_rdata_t *rdata = NULL; @@ -784,6 +788,8 @@ add_opt(dns_message_t *msg, isc_uint16_t udpsize, dns_optlist_t optlist) { rdatalist->covers = 0; rdatalist->rdclass = udpsize; rdatalist->ttl = 0; + if (dnssec) + rdatalist->ttl = DNS_MESSAGEEXTFLAG_DO; rdata->data = NULL; rdata->length = 0; #ifdef DNS_OPT_NEWCODES_LIVE @@ -1422,10 +1428,10 @@ setup_lookup(dig_lookup_t *lookup) { result = dns_message_renderbegin(lookup->sendmsg, &lookup->sendbuf); check_result(result, "dns_message_renderbegin"); #ifndef DNS_OPT_NEWCODES_LIVE - if (lookup->udpsize > 0) { + if (lookup->udpsize > 0 || lookup->dnssec) { #else /* DNS_OPT_NEWCODES_LIVE */ - if (lookup->udpsize > 0 || lookup->zonename[0] !=0 || - lookup->viewname[0] != 0) { + if (lookup->udpsize > 0 || || lookup->dnssec || + lookup->zonename[0] !=0 || lookup->viewname[0] != 0) { dns_fixedname_t fname; isc_buffer_t namebuf, *wirebuf = NULL; dns_compress_t cctx; @@ -1475,7 +1481,8 @@ setup_lookup(dig_lookup_t *lookup) { optlist.used++; } #endif /* DNS_OPT_NEWCODES_LIVE */ - add_opt(lookup->sendmsg, lookup->udpsize, optlist); + add_opt(lookup->sendmsg, lookup->udpsize, lookup->dnssec, + optlist); #ifdef DNS_OPT_NEWCODES_LIVE if (wirebuf != NULL) isc_buffer_free(&wirebuf); diff --git a/bin/dig/include/dig/dig.h b/bin/dig/include/dig/dig.h index 676936e696..8b32c865c3 100644 --- a/bin/dig/include/dig/dig.h +++ b/bin/dig/include/dig/dig.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dig.h,v 1.56 2000/11/08 00:47:18 mws Exp $ */ +/* $Id: dig.h,v 1.57 2000/11/13 21:33:53 bwelling Exp $ */ #ifndef DIG_H #define DIG_H @@ -96,7 +96,8 @@ struct dig_lookup { section_additional, servfail_stops, new_search, - besteffort; + besteffort, + dnssec; char textname[MXNAME]; /* Name we're going to be looking up */ char cmdline[MXNAME]; dns_rdatatype_t rdtype; diff --git a/bin/named/client.c b/bin/named/client.c index 2392bf9486..9028c68842 100644 --- a/bin/named/client.c +++ b/bin/named/client.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: client.c,v 1.126 2000/11/03 17:39:37 gson Exp $ */ +/* $Id: client.c,v 1.127 2000/11/13 21:33:54 bwelling Exp $ */ #include @@ -538,6 +538,7 @@ ns_client_endrequest(ns_client_t *client) { } client->udpsize = 512; + client->extflags = 0; dns_message_reset(client->message, DNS_MESSAGE_INTENTPARSE); if (client->recursionquota != NULL) @@ -1233,6 +1234,11 @@ client_request(isc_task_t *task, isc_event_t *event) { * Set the client's UDP buffer size. */ client->udpsize = opt->rdclass; + + /* + * Get the flags out of the OPT record. + */ + client->extflags = DNS_OPT_FLAGS(opt); #ifdef DNS_OPT_NEWCODES /* @@ -1533,6 +1539,7 @@ client_create(ns_clientmgr_t *manager, ns_client_t **clientp) client->tcpbuf = NULL; client->opt = NULL; client->udpsize = 512; + client->extflags = 0; #ifdef DNS_OPT_NEWCODES client->opt_zone = NULL; client->opt_view = NULL; diff --git a/bin/named/include/named/client.h b/bin/named/include/named/client.h index 5e15f6ae5a..e135a31f3f 100644 --- a/bin/named/include/named/client.h +++ b/bin/named/include/named/client.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: client.h,v 1.45 2000/10/12 21:51:48 mws Exp $ */ +/* $Id: client.h,v 1.46 2000/11/13 21:33:57 bwelling Exp $ */ #ifndef NAMED_CLIENT_H #define NAMED_CLIENT_H 1 @@ -109,6 +109,7 @@ struct ns_client { unsigned char * sendbuf; dns_rdataset_t * opt; isc_uint16_t udpsize; + isc_uint16_t extflags; #ifdef DNS_OPT_NEWCODES dns_fixedname_t * opt_zone; isc_buffer_t * opt_view; diff --git a/bin/named/include/named/query.h b/bin/named/include/named/query.h index b15c65a9b4..50bbc17b36 100644 --- a/bin/named/include/named/query.h +++ b/bin/named/include/named/query.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: query.h,v 1.22 2000/09/06 20:35:22 gson Exp $ */ +/* $Id: query.h,v 1.23 2000/11/13 21:33:58 bwelling Exp $ */ #ifndef NAMED_QUERY_H #define NAMED_QUERY_H 1 @@ -61,6 +61,7 @@ struct ns_query { #define NS_QUERYATTR_QUERYOKVALID 0x0040 #define NS_QUERYATTR_QUERYOK 0x0080 #define NS_QUERYATTR_WANTRECURSION 0x0100 +#define NS_QUERYATTR_WANTDNSSEC 0x0200 isc_result_t ns_query_init(ns_client_t *client); diff --git a/bin/named/query.c b/bin/named/query.c index fd581659e1..78e2338ae8 100644 --- a/bin/named/query.c +++ b/bin/named/query.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: query.c,v 1.147 2000/11/13 20:10:19 bwelling Exp $ */ +/* $Id: query.c,v 1.148 2000/11/13 21:33:55 bwelling Exp $ */ #include @@ -58,6 +58,8 @@ NS_QUERYATTR_CACHEGLUEOK) != 0) #define WANTRECURSION(c) (((c)->query.attributes & \ NS_QUERYATTR_WANTRECURSION) != 0) +#define WANTDNSSEC(c) (((c)->query.attributes & \ + NS_QUERYATTR_WANTDNSSEC) != 0) #if 0 #define CTRACE(m) isc_log_write(ns_g_lctx, \ @@ -740,10 +742,10 @@ query_simplefind(void *arg, dns_name_t *name, dns_rdatatype_t type, REQUIRE(NS_CLIENT_VALID(client)); REQUIRE(rdataset != NULL); - REQUIRE(sigrdataset != NULL); dns_rdataset_init(&zrdataset); - dns_rdataset_init(&zsigrdataset); + if (sigrdataset != NULL) + dns_rdataset_init(&zsigrdataset); /* * Find a database to answer the query. @@ -770,7 +772,8 @@ query_simplefind(void *arg, dns_name_t *name, dns_rdatatype_t type, result == ISC_R_NOTFOUND) { if (dns_rdataset_isassociated(rdataset)) dns_rdataset_disassociate(rdataset); - if (dns_rdataset_isassociated(sigrdataset)) + if (sigrdataset != NULL && + dns_rdataset_isassociated(sigrdataset)) dns_rdataset_disassociate(sigrdataset); if (is_zone) { ns_server_querycount(zone, is_zone, @@ -793,7 +796,8 @@ query_simplefind(void *arg, dns_name_t *name, dns_rdatatype_t type, */ if (dns_rdataset_isassociated(&zrdataset)) { dns_rdataset_clone(&zrdataset, rdataset); - if (dns_rdataset_isassociated(&zsigrdataset)) + if (sigrdataset != NULL && + dns_rdataset_isassociated(&zsigrdataset)) dns_rdataset_clone(&zsigrdataset, sigrdataset); result = ISC_R_SUCCESS; @@ -814,7 +818,9 @@ query_simplefind(void *arg, dns_name_t *name, dns_rdatatype_t type, version = NULL; dns_rdataset_clone(rdataset, &zrdataset); dns_rdataset_disassociate(rdataset); - if (dns_rdataset_isassociated(sigrdataset)) { + if (sigrdataset != NULL && + dns_rdataset_isassociated(sigrdataset)) + { dns_rdataset_clone(sigrdataset, &zsigrdataset); dns_rdataset_disassociate(sigrdataset); } @@ -829,7 +835,8 @@ query_simplefind(void *arg, dns_name_t *name, dns_rdatatype_t type, } else if (result != ISC_R_SUCCESS) { if (dns_rdataset_isassociated(rdataset)) dns_rdataset_disassociate(rdataset); - if (dns_rdataset_isassociated(sigrdataset)) + if (sigrdataset != NULL && + dns_rdataset_isassociated(sigrdataset)) dns_rdataset_disassociate(sigrdataset); result = ISC_R_NOTFOUND; } @@ -844,7 +851,8 @@ query_simplefind(void *arg, dns_name_t *name, dns_rdatatype_t type, cleanup: if (dns_rdataset_isassociated(&zrdataset)) { dns_rdataset_disassociate(&zrdataset); - if (dns_rdataset_isassociated(&zsigrdataset)) + if (sigrdataset != NULL && + dns_rdataset_isassociated(&zsigrdataset)) dns_rdataset_disassociate(&zsigrdataset); } if (db != NULL) @@ -918,6 +926,9 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) { REQUIRE(NS_CLIENT_VALID(client)); REQUIRE(qtype != dns_rdatatype_any); + if (!WANTDNSSEC(client) && dns_rdatatype_isdnssec(qtype)) + return (ISC_R_SUCCESS); + CTRACE("query_addadditional"); /* @@ -955,9 +966,13 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) { goto cleanup; fname = query_newname(client, dbuf, &b); rdataset = query_newrdataset(client); - sigrdataset = query_newrdataset(client); - if (fname == NULL || rdataset == NULL || sigrdataset == NULL) + if (fname == NULL || rdataset == NULL) goto cleanup; + if (WANTDNSSEC(client)) { + sigrdataset = query_newrdataset(client); + if (sigrdataset == NULL) + goto cleanup; + } /* * Look for a zone database that might contain authoritative @@ -984,7 +999,7 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) { if (dns_rdataset_isassociated(rdataset)) dns_rdataset_disassociate(rdataset); - if (dns_rdataset_isassociated(sigrdataset)) + if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) dns_rdataset_disassociate(sigrdataset); if (node != NULL) dns_db_detachnode(db, &node); @@ -1011,7 +1026,7 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) { if (dns_rdataset_isassociated(rdataset)) dns_rdataset_disassociate(rdataset); - if (dns_rdataset_isassociated(sigrdataset)) + if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) dns_rdataset_disassociate(sigrdataset); if (node != NULL) dns_db_detachnode(db, &node); @@ -1074,7 +1089,9 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) { * so we do not need to check if the SIG rdataset is already * in the response. */ - if (dns_rdataset_isassociated(sigrdataset)) { + if (sigrdataset != NULL && + dns_rdataset_isassociated(sigrdataset)) + { ISC_LIST_APPEND(fname->list, sigrdataset, link); sigrdataset = NULL; } @@ -1098,7 +1115,7 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) { if (sigrdataset != NULL) { if (dns_rdataset_isassociated(sigrdataset)) dns_rdataset_disassociate(sigrdataset); - } else { + } else if (WANTDNSSEC(client)) { sigrdataset = query_newrdataset(client); if (sigrdataset == NULL) goto addname; @@ -1114,7 +1131,8 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) { /* * Negative cache entries don't have sigrdatasets. */ - INSIST(! dns_rdataset_isassociated(sigrdataset)); + INSIST(sigrdataset == NULL || + ! dns_rdataset_isassociated(sigrdataset)); } if (result == ISC_R_SUCCESS) { mname = NULL; @@ -1127,18 +1145,23 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) { need_addname = ISC_TRUE; ISC_LIST_APPEND(fname->list, rdataset, link); added_something = ISC_TRUE; - if (dns_rdataset_isassociated(sigrdataset)) { + if (sigrdataset != NULL && + dns_rdataset_isassociated(sigrdataset)) + { ISC_LIST_APPEND(fname->list, sigrdataset, link); sigrdataset = query_newrdataset(client); } rdataset = query_newrdataset(client); - if (rdataset == NULL || sigrdataset == NULL) + if (rdataset == NULL) + goto addname; + if (WANTDNSSEC(client) && sigrdataset == NULL) goto addname; } else { dns_rdataset_disassociate(rdataset); - if (dns_rdataset_isassociated(sigrdataset)) + if (sigrdataset != NULL && + dns_rdataset_isassociated(sigrdataset)) dns_rdataset_disassociate(sigrdataset); } } @@ -1150,7 +1173,8 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) { goto addname; if (result == DNS_R_NCACHENXRRSET) { dns_rdataset_disassociate(rdataset); - INSIST(! dns_rdataset_isassociated(sigrdataset)); + INSIST(sigrdataset == NULL || + ! dns_rdataset_isassociated(sigrdataset)); } if (result == ISC_R_SUCCESS) { mname = NULL; @@ -1164,14 +1188,18 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) { a6rdataset = rdataset; ISC_LIST_APPEND(fname->list, rdataset, link); added_something = ISC_TRUE; - if (dns_rdataset_isassociated(sigrdataset)) { + if (sigrdataset != NULL && + dns_rdataset_isassociated(sigrdataset)) + { ISC_LIST_APPEND(fname->list, sigrdataset, link); sigrdataset = query_newrdataset(client); } rdataset = query_newrdataset(client); - if (rdataset == NULL || sigrdataset == NULL) + if (rdataset == NULL) + goto addname; + if (WANTDNSSEC(client) && sigrdataset == NULL) goto addname; } else dns_rdataset_disassociate(rdataset); @@ -1184,7 +1212,8 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) { goto addname; if (result == DNS_R_NCACHENXRRSET) { dns_rdataset_disassociate(rdataset); - INSIST(! dns_rdataset_isassociated(sigrdataset)); + INSIST(sigrdataset == NULL || + ! dns_rdataset_isassociated(sigrdataset)); } if (result == ISC_R_SUCCESS) { mname = NULL; @@ -1197,7 +1226,9 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) { need_addname = ISC_TRUE; ISC_LIST_APPEND(fname->list, rdataset, link); added_something = ISC_TRUE; - if (dns_rdataset_isassociated(sigrdataset)) { + if (sigrdataset != NULL && + dns_rdataset_isassociated(sigrdataset)) + { ISC_LIST_APPEND(fname->list, sigrdataset, link); sigrdataset = NULL; @@ -1273,7 +1304,8 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) { cleanup: CTRACE("query_addadditional: cleanup"); query_putrdataset(client, &rdataset); - query_putrdataset(client, &sigrdataset); + if (sigrdataset != NULL) + query_putrdataset(client, &sigrdataset); if (fname != NULL) query_releasename(client, &fname); if (node != NULL) @@ -1314,14 +1346,18 @@ query_adda6rrset(void *arg, dns_name_t *name, dns_rdataset_t *rdataset, goto cleanup; fname = query_newname(client, dbuf, &b); crdataset = query_newrdataset(client); - csigrdataset = query_newrdataset(client); - if (fname == NULL || crdataset == NULL || csigrdataset == NULL) + if (fname == NULL || crdataset == NULL) goto cleanup; + if (sigrdataset != NULL) { + csigrdataset = query_newrdataset(client); + if (csigrdataset == NULL) + goto cleanup; + } if (dns_name_concatenate(name, NULL, fname, NULL) != ISC_R_SUCCESS) goto cleanup; dns_rdataset_clone(rdataset, crdataset); - if (dns_rdataset_isassociated(sigrdataset)) + if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) dns_rdataset_clone(sigrdataset, csigrdataset); mname = NULL; @@ -1343,7 +1379,7 @@ query_adda6rrset(void *arg, dns_name_t *name, dns_rdataset_t *rdataset, * we do not need to check if the SIG rdataset is already in the * response. */ - if (dns_rdataset_isassociated(csigrdataset)) { + if (sigrdataset != NULL && dns_rdataset_isassociated(csigrdataset)) { ISC_LIST_APPEND(fname->list, csigrdataset, link); csigrdataset = NULL; } @@ -1357,7 +1393,8 @@ query_adda6rrset(void *arg, dns_name_t *name, dns_rdataset_t *rdataset, cleanup: query_putrdataset(client, &crdataset); - query_putrdataset(client, &csigrdataset); + if (sigrdataset != NULL) + query_putrdataset(client, &csigrdataset); if (fname != NULL) query_releasename(client, &fname); } @@ -1488,7 +1525,8 @@ query_addsoa(ns_client_t *client, dns_db_t *db, isc_boolean_t zero_ttl) { dns_dbnode_t *node; isc_result_t result, eresult; dns_fixedname_t foundname; - dns_rdataset_t *rdataset, *sigrdataset; + dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL; + dns_rdataset_t **sigrdatasetp = NULL; CTRACE("query_addsoa"); /* @@ -1510,11 +1548,17 @@ query_addsoa(ns_client_t *client, dns_db_t *db, isc_boolean_t zero_ttl) { dns_name_init(name, NULL); dns_name_clone(dns_db_origin(db), name); rdataset = query_newrdataset(client); - sigrdataset = query_newrdataset(client); - if (rdataset == NULL || sigrdataset == NULL) { + if (rdataset == NULL) { eresult = DNS_R_SERVFAIL; goto cleanup; } + if (WANTDNSSEC(client)) { + sigrdataset = query_newrdataset(client); + if (sigrdataset == NULL) { + eresult = DNS_R_SERVFAIL; + goto cleanup; + } + } /* * Find the SOA. @@ -1541,7 +1585,8 @@ query_addsoa(ns_client_t *client, dns_db_t *db, isc_boolean_t zero_ttl) { if (zero_ttl) { rdataset->ttl = 0; - sigrdataset->ttl = 0; + if (sigrdataset != NULL) + sigrdataset->ttl = 0; } /* @@ -1550,15 +1595,21 @@ query_addsoa(ns_client_t *client, dns_db_t *db, isc_boolean_t zero_ttl) { */ if (rdataset->ttl > soa.minimum) rdataset->ttl = soa.minimum; - if (sigrdataset->ttl > soa.minimum) + if (sigrdataset != NULL && sigrdataset->ttl > soa.minimum) sigrdataset->ttl = soa.minimum; - query_addrrset(client, &name, &rdataset, &sigrdataset, NULL, + + if (sigrdataset != NULL) + sigrdatasetp = &sigrdataset; + else + sigrdatasetp = NULL; + query_addrrset(client, &name, &rdataset, sigrdatasetp, NULL, DNS_SECTION_AUTHORITY); } cleanup: query_putrdataset(client, &rdataset); - query_putrdataset(client, &sigrdataset); + if (sigrdataset != NULL) + query_putrdataset(client, &sigrdataset); if (name != NULL) query_releasename(client, &name); if (node != NULL) @@ -1573,7 +1624,8 @@ query_addns(ns_client_t *client, dns_db_t *db) { dns_dbnode_t *node; isc_result_t result, eresult; dns_fixedname_t foundname; - dns_rdataset_t *rdataset, *sigrdataset; + dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL; + dns_rdataset_t **sigrdatasetp = NULL; CTRACE("query_addns"); /* @@ -1597,12 +1649,19 @@ query_addns(ns_client_t *client, dns_db_t *db) { dns_name_init(name, NULL); dns_name_clone(dns_db_origin(db), name); rdataset = query_newrdataset(client); - sigrdataset = query_newrdataset(client); - if (rdataset == NULL || sigrdataset == NULL) { + if (rdataset == NULL) { CTRACE("query_addns: query_newrdataset failed"); eresult = DNS_R_SERVFAIL; goto cleanup; } + if (WANTDNSSEC(client)) { + sigrdataset = query_newrdataset(client); + if (sigrdataset == NULL) { + CTRACE("query_addns: query_newrdataset failed"); + eresult = DNS_R_SERVFAIL; + goto cleanup; + } + } /* * Find the NS rdataset. @@ -1620,14 +1679,19 @@ query_addns(ns_client_t *client, dns_db_t *db) { */ eresult = DNS_R_SERVFAIL; } else { - query_addrrset(client, &name, &rdataset, &sigrdataset, NULL, + if (sigrdataset != NULL) + sigrdatasetp = &sigrdataset; + else + sigrdatasetp = NULL; + query_addrrset(client, &name, &rdataset, sigrdatasetp, NULL, DNS_SECTION_AUTHORITY); } cleanup: CTRACE("query_addns: cleanup"); query_putrdataset(client, &rdataset); - query_putrdataset(client, &sigrdataset); + if (sigrdataset != NULL) + query_putrdataset(client, &sigrdataset); if (name != NULL) query_releasename(client, &name); if (node != NULL) @@ -1742,9 +1806,13 @@ query_addbestns(ns_client_t *client) { goto cleanup; fname = query_newname(client, dbuf, &b); rdataset = query_newrdataset(client); - sigrdataset = query_newrdataset(client); - if (fname == NULL || rdataset == NULL || sigrdataset == NULL) + if (fname == NULL || rdataset == NULL) goto cleanup; + if (WANTDNSSEC(client)) { + sigrdataset = query_newrdataset(client); + if (sigrdataset == NULL) + goto cleanup; + } /* * Now look for the zonecut. @@ -1805,7 +1873,8 @@ query_addbestns(ns_client_t *client) { */ dbuf = NULL; query_putrdataset(client, &rdataset); - query_putrdataset(client, &sigrdataset); + if (sigrdataset != NULL) + query_putrdataset(client, &sigrdataset); rdataset = zrdataset; zrdataset = NULL; sigrdataset = zsigrdataset; @@ -1814,7 +1883,7 @@ query_addbestns(ns_client_t *client) { if ((client->query.dboptions & DNS_DBFIND_PENDINGOK) == 0 && (rdataset->trust == dns_trust_pending || - sigrdataset->trust == dns_trust_pending)) + (sigrdataset != NULL && sigrdataset->trust == dns_trust_pending))) goto cleanup; query_addrrset(client, &fname, &rdataset, &sigrdataset, dbuf, @@ -1822,7 +1891,8 @@ query_addbestns(ns_client_t *client) { cleanup: query_putrdataset(client, &rdataset); - query_putrdataset(client, &sigrdataset); + if (sigrdataset != NULL) + query_putrdataset(client, &sigrdataset); if (fname != NULL) query_releasename(client, &fname); if (node != NULL) @@ -1833,7 +1903,8 @@ query_addbestns(ns_client_t *client) { dns_zone_detach(&zone); if (zdb != NULL) { query_putrdataset(client, &zrdataset); - query_putrdataset(client, &zsigrdataset); + if (zsigrdataset != NULL) + query_putrdataset(client, &zsigrdataset); if (zfname != NULL) query_releasename(client, &zfname); dns_db_detach(&zdb); @@ -1916,7 +1987,8 @@ query_resume(isc_task_t *task, isc_event_t *event) { if (devent->db != NULL) dns_db_detach(&devent->db); query_putrdataset(client, &devent->rdataset); - query_putrdataset(client, &devent->sigrdataset); + if (devent->sigrdataset != NULL) + query_putrdataset(client, &devent->sigrdataset); isc_event_free(&event); ns_client_next(client, ISC_R_CANCELED); /* @@ -1978,11 +2050,14 @@ query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qdomain, rdataset = query_newrdataset(client); if (rdataset == NULL) return (ISC_R_NOMEMORY); - sigrdataset = query_newrdataset(client); - if (rdataset == NULL) { - query_putrdataset(client, &rdataset); - return (ISC_R_NOMEMORY); - } + if (WANTDNSSEC(client)) { + sigrdataset = query_newrdataset(client); + if (sigrdataset == NULL) { + query_putrdataset(client, &rdataset); + return (ISC_R_NOMEMORY); + } + } else + sigrdataset = NULL; result = dns_resolver_createfetch(client->view->resolver, client->query.qname, @@ -2001,7 +2076,8 @@ query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qdomain, */ } else { query_putrdataset(client, &rdataset); - query_putrdataset(client, &sigrdataset); + if (sigrdataset != NULL) + query_putrdataset(client, &sigrdataset); } return (result); @@ -2017,6 +2093,7 @@ query_findparentkey(ns_client_t *client, dns_name_t *name, dns_dbnode_t *pnode; dns_dbversion_t *pversion; dns_rdataset_t prdataset, psigrdataset; + dns_rdataset_t *psigrdatasetp; isc_result_t result; dns_zone_t *pzone; isc_boolean_t is_zone; @@ -2035,7 +2112,8 @@ query_findparentkey(ns_client_t *client, dns_name_t *name, pnode = NULL; pversion = NULL; dns_rdataset_init(&prdataset); - dns_rdataset_init(&psigrdataset); + if (sigrdataset != NULL) + dns_rdataset_init(&psigrdataset); is_zone = ISC_FALSE; dns_fixedname_init(&pfoundname); @@ -2048,19 +2126,25 @@ query_findparentkey(ns_client_t *client, dns_name_t *name, goto cleanup; } + if (sigrdataset != NULL) + psigrdatasetp = &psigrdataset; + else + psigrdatasetp = NULL; result = dns_db_find(pdb, name, pversion, dns_rdatatype_key, client->query.dboptions, client->now, &pnode, dns_fixedname_name(&pfoundname), - &prdataset, &psigrdataset); + &prdataset, psigrdatasetp); if (result == ISC_R_SUCCESS) { if (dns_rdataset_isassociated(rdataset)) dns_rdataset_disassociate(rdataset); - if (dns_rdataset_isassociated(sigrdataset)) - dns_rdataset_disassociate(sigrdataset); dns_rdataset_clone(&prdataset, rdataset); - if (dns_rdataset_isassociated(&psigrdataset)) - dns_rdataset_clone(&psigrdataset, sigrdataset); + if (sigrdataset != NULL) { + if (dns_rdataset_isassociated(sigrdataset)) + dns_rdataset_disassociate(sigrdataset); + if (dns_rdataset_isassociated(&psigrdataset)) + dns_rdataset_clone(&psigrdataset, sigrdataset); + } if (*nodep != NULL) dns_db_detachnode(*dbp, nodep); *nodep = pnode; @@ -2079,7 +2163,7 @@ query_findparentkey(ns_client_t *client, dns_name_t *name, cleanup: if (dns_rdataset_isassociated(&prdataset)) dns_rdataset_disassociate(&prdataset); - if (dns_rdataset_isassociated(&psigrdataset)) + if (sigrdataset != NULL && dns_rdataset_isassociated(&psigrdataset)) dns_rdataset_disassociate(&psigrdataset); if (pnode != NULL) dns_db_detachnode(pdb, &pnode); @@ -2245,6 +2329,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event) { dns_name_t *fname, *zfname, *tname, *prefix; dns_rdataset_t *rdataset, *trdataset; dns_rdataset_t *sigrdataset, *zrdataset, *zsigrdataset; + dns_rdataset_t **sigrdatasetp; dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdatasetiter_t *rdsiter; isc_boolean_t want_restart, authoritative, is_zone; @@ -2424,12 +2509,20 @@ query_find(ns_client_t *client, dns_fetchevent_t *event) { } fname = query_newname(client, dbuf, &b); rdataset = query_newrdataset(client); - sigrdataset = query_newrdataset(client); - if (fname == NULL || rdataset == NULL || sigrdataset == NULL) { + if (fname == NULL || rdataset == NULL) { ns_server_querycount(zone, is_zone, dns_zonecount_failure); QUERY_ERROR(DNS_R_SERVFAIL); goto cleanup; } + if (WANTDNSSEC(client)) { + sigrdataset = query_newrdataset(client); + if (sigrdataset == NULL) { + ns_server_querycount(zone, is_zone, + dns_zonecount_failure); + QUERY_ERROR(DNS_R_SERVFAIL); + goto cleanup; + } + } /* * Now look for an answer in the database. @@ -2586,8 +2679,12 @@ query_find(ns_client_t *client, dns_fetchevent_t *event) { * database by setting client->query.gluedb. */ client->query.gluedb = db; + if (sigrdataset != NULL) + sigrdatasetp = &sigrdataset; + else + sigrdatasetp = NULL; query_addrrset(client, &fname, &rdataset, - &sigrdataset, dbuf, + sigrdatasetp, dbuf, DNS_SECTION_AUTHORITY); client->query.gluedb = NULL; } else { @@ -2631,7 +2728,9 @@ query_find(ns_client_t *client, dns_fetchevent_t *event) { */ dbuf = NULL; query_putrdataset(client, &rdataset); - query_putrdataset(client, &sigrdataset); + if (sigrdataset != NULL) + query_putrdataset(client, + &sigrdataset); rdataset = zrdataset; zrdataset = NULL; sigrdataset = zsigrdataset; @@ -2672,8 +2771,12 @@ query_find(ns_client_t *client, dns_fetchevent_t *event) { client->query.gluedb = zdb; client->query.attributes |= NS_QUERYATTR_CACHEGLUEOK; + if (sigrdataset != NULL) + sigrdatasetp = &sigrdataset; + else + sigrdatasetp = NULL; query_addrrset(client, &fname, - &rdataset, &sigrdataset, + &rdataset, sigrdatasetp, dbuf, DNS_SECTION_AUTHORITY); client->query.gluedb = NULL; client->query.attributes &= @@ -2719,8 +2822,10 @@ query_find(ns_client_t *client, dns_fetchevent_t *event) { * Add NXT record if we found one. */ if (dns_rdataset_isassociated(rdataset)) { - query_addrrset(client, &tname, &rdataset, &sigrdataset, - NULL, DNS_SECTION_AUTHORITY); + if (WANTDNSSEC(client)) + query_addrrset(client, &tname, &rdataset, + &sigrdataset, + NULL, DNS_SECTION_AUTHORITY); if (tname != NULL) dns_message_puttempname(client->message, &tname); @@ -2776,8 +2881,10 @@ query_find(ns_client_t *client, dns_fetchevent_t *event) { * Add NXT record if we found one. */ if (dns_rdataset_isassociated(rdataset)) { - query_addrrset(client, &tname, &rdataset, &sigrdataset, - NULL, DNS_SECTION_AUTHORITY); + if (WANTDNSSEC(client)) + query_addrrset(client, &tname, &rdataset, + &sigrdataset, + NULL, DNS_SECTION_AUTHORITY); if (tname != NULL) dns_message_puttempname(client->message, &tname); @@ -2822,7 +2929,11 @@ query_find(ns_client_t *client, dns_fetchevent_t *event) { /* * Add the CNAME to the answer section. */ - query_addrrset(client, &fname, &rdataset, &sigrdataset, dbuf, + if (sigrdataset != NULL) + sigrdatasetp = &sigrdataset; + else + sigrdatasetp = NULL; + query_addrrset(client, &fname, &rdataset, sigrdatasetp, dbuf, DNS_SECTION_ANSWER); /* * We set the PARTIALANSWER attribute so that if anything goes @@ -2870,7 +2981,11 @@ query_find(ns_client_t *client, dns_fetchevent_t *event) { /* * Add the DNAME to the answer section. */ - query_addrrset(client, &fname, &rdataset, &sigrdataset, dbuf, + if (sigrdataset != NULL) + sigrdatasetp = &sigrdataset; + else + sigrdatasetp = NULL; + query_addrrset(client, &fname, &rdataset, sigrdatasetp, dbuf, DNS_SECTION_ANSWER); /* * We set the PARTIALANSWER attribute so that if anything goes @@ -3061,7 +3176,11 @@ query_find(ns_client_t *client, dns_fetchevent_t *event) { * This is the "normal" case -- an ordinary question to which * we know the answer. */ - query_addrrset(client, &fname, &rdataset, &sigrdataset, dbuf, + if (sigrdataset != NULL) + sigrdatasetp = &sigrdataset; + else + sigrdatasetp = NULL; + query_addrrset(client, &fname, &rdataset, sigrdatasetp, dbuf, DNS_SECTION_ANSWER); /* * We shouldn't ever fail to add 'rdataset' @@ -3100,7 +3219,8 @@ query_find(ns_client_t *client, dns_fetchevent_t *event) { * General cleanup. */ query_putrdataset(client, &rdataset); - query_putrdataset(client, &sigrdataset); + if (sigrdataset != NULL) + query_putrdataset(client, &sigrdataset); if (fname != NULL) query_releasename(client, &fname); if (node != NULL) @@ -3111,7 +3231,8 @@ query_find(ns_client_t *client, dns_fetchevent_t *event) { dns_zone_detach(&zone); if (zdb != NULL) { query_putrdataset(client, &zrdataset); - query_putrdataset(client, &zsigrdataset); + if (zsigrdataset != NULL) + query_putrdataset(client, &zsigrdataset); if (zfname != NULL) query_releasename(client, &zfname); dns_db_detach(&zdb); @@ -3217,6 +3338,10 @@ ns_query_start(ns_client_t *client) { if ((message->flags & DNS_MESSAGEFLAG_RD) != 0) client->query.attributes |= NS_QUERYATTR_WANTRECURSION; + if ((client->extflags & DNS_MESSAGEEXTFLAG_DO) != 0 || + (message->flags & DNS_MESSAGEFLAG_AD) != 0) + client->query.attributes |= NS_QUERYATTR_WANTDNSSEC; + if ((client->view->cachedb == NULL) || (!client->view->additionalfromcache)) { /* diff --git a/lib/dns/include/dns/message.h b/lib/dns/include/dns/message.h index 90e920a4d2..303f9eb1f8 100644 --- a/lib/dns/include/dns/message.h +++ b/lib/dns/include/dns/message.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: message.h,v 1.82 2000/11/13 20:12:03 bwelling Exp $ */ +/* $Id: message.h,v 1.83 2000/11/13 21:34:01 bwelling Exp $ */ #ifndef DNS_MESSAGE_H #define DNS_MESSAGE_H 1 @@ -95,6 +95,8 @@ #define DNS_MESSAGEFLAG_AD 0x0020U #define DNS_MESSAGEFLAG_CD 0x0010U +#define DNS_MESSAGEEXTFLAG_DO 0x8000U + #define DNS_MESSAGE_REPLYPRESERVE (DNS_MESSAGEFLAG_RD) #define DNS_MESSAGE_HEADERLEN 12 /* 6 isc_uint16_t's */ diff --git a/lib/dns/include/dns/opt.h b/lib/dns/include/dns/opt.h index 2ec69a519c..0cb94b10f6 100644 --- a/lib/dns/include/dns/opt.h +++ b/lib/dns/include/dns/opt.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: opt.h,v 1.2 2000/10/12 21:51:57 mws Exp $ */ +/* $Id: opt.h,v 1.3 2000/11/13 21:34:03 bwelling Exp $ */ #ifndef DNS_OPT_H #define DNS_OPT_H 1 @@ -49,6 +49,8 @@ #define DNS_OPTCODE_VIEW 0xfff1 #endif /* DNS_OPT_NEWCODES */ +#define DNS_OPT_FLAGS(opt) ((opt)->ttl & 0xFFFF) + /* * OPT records contain a series of attributes which contain different types. * These structures are used for holding the individual attribute diff --git a/lib/dns/opt.c b/lib/dns/opt.c index 8bc881c73e..d003819c35 100644 --- a/lib/dns/opt.c +++ b/lib/dns/opt.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: opt.c,v 1.4 2000/10/25 04:26:42 marka Exp $ */ +/* $Id: opt.c,v 1.5 2000/11/13 21:33:59 bwelling Exp $ */ #include @@ -231,9 +231,13 @@ dns_opt_totext(dns_rdataset_t *opt, isc_buffer_t *target, 0x00ff0000 >> 16))); ADD_STRING(target, buf, fail); ADD_STRING(target, ", udp=", fail); - sprintf(buf, "%7u\n", + sprintf(buf, "%7u", (unsigned int)opt->rdclass); ADD_STRING(target, buf, fail); + ADD_STRING(target, ", flags:", fail); + if ((DNS_OPT_FLAGS(opt) & DNS_MESSAGEEXTFLAG_DO) != 0) + ADD_STRING(target, " do", fail); + ADD_STRING(target, "\n", fail); list.attrs = &attr; list.size = 1; diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index 6d568be957..7a96b82ee5 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: resolver.c,v 1.180 2000/11/11 02:14:50 gson Exp $ */ +/* $Id: resolver.c,v 1.181 2000/11/13 21:34:00 bwelling Exp $ */ #include @@ -607,12 +607,12 @@ fctx_addopt(dns_message_t *message) { rdatalist->rdclass = SEND_BUFFER_SIZE; /* - * Set EXTENDED-RCODE, VERSION, and Z to 0. + * Set EXTENDED-RCODE, VERSION, and Z to 0, and the DO bit to 1. */ - rdatalist->ttl = 0; + rdatalist->ttl = DNS_MESSAGEEXTFLAG_DO; /* - * No ENDS options. + * No EDNS options. */ rdata->data = NULL; rdata->length = 0; @@ -936,11 +936,12 @@ resquery_send(resquery_t *query) { } /* - * If we're using EDNS, set AD and CD so we'll get DNSSEC data. + * If we're using EDNS, set CD. CD and EDNS aren't really related, + * but if we send a non EDNS query, there's a chance the server + * won't understand CD either. */ if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0) - fctx->qmessage->flags |= - (DNS_MESSAGEFLAG_AD|DNS_MESSAGEFLAG_CD); + fctx->qmessage->flags |= DNS_MESSAGEFLAG_CD; /* * Add TSIG record tailored to the current recipient.