diff options
Diffstat (limited to 'contrib/bind9/lib/dns/resolver.c')
-rw-r--r-- | contrib/bind9/lib/dns/resolver.c | 460 |
1 files changed, 323 insertions, 137 deletions
diff --git a/contrib/bind9/lib/dns/resolver.c b/contrib/bind9/lib/dns/resolver.c index 503f1d2..e21d97e 100644 --- a/contrib/bind9/lib/dns/resolver.c +++ b/contrib/bind9/lib/dns/resolver.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2013 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -21,6 +21,7 @@ #include <config.h> +#include <isc/log.h> #include <isc/platform.h> #include <isc/print.h> #include <isc/string.h> @@ -42,6 +43,8 @@ #include <dns/log.h> #include <dns/message.h> #include <dns/ncache.h> +#include <dns/nsec.h> +#include <dns/nsec3.h> #include <dns/opcode.h> #include <dns/peer.h> #include <dns/rbt.h> @@ -75,7 +78,7 @@ DNS_LOGCATEGORY_RESOLVER, \ DNS_LOGMODULE_RESOLVER, \ ISC_LOG_DEBUG(3), \ - "fctx %p(%s'): %s", fctx, fctx->info, (m)) + "fctx %p(%s): %s", fctx, fctx->info, (m)) #define FCTXTRACE2(m1, m2) \ isc_log_write(dns_lctx, \ DNS_LOGCATEGORY_RESOLVER, \ @@ -130,6 +133,7 @@ * Maximum EDNS0 input packet size. */ #define RECV_BUFFER_SIZE 4096 /* XXXRTH Constant. */ +#define EDNSOPTS 2 /*% * This defines the maximum number of timeouts we will permit before we @@ -468,12 +472,16 @@ static isc_result_t ncache_adderesult(dns_message_t *message, dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t maxttl, isc_boolean_t optout, + isc_boolean_t secure, dns_rdataset_t *ardataset, isc_result_t *eresultp); static void validated(isc_task_t *task, isc_event_t *event); static isc_boolean_t maybe_destroy(fetchctx_t *fctx, isc_boolean_t locked); static void add_bad(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, isc_result_t reason, badnstype_t badtype); +static inline isc_result_t findnoqname(fetchctx_t *fctx, dns_name_t *name, + dns_rdatatype_t type, + dns_name_t **noqname); /*% * Increment resolver-related statistics counters. @@ -1270,67 +1278,15 @@ resquery_senddone(isc_task_t *task, isc_event_t *event) { static inline isc_result_t fctx_addopt(dns_message_t *message, unsigned int version, - isc_uint16_t udpsize, isc_boolean_t request_nsid) + isc_uint16_t udpsize, dns_ednsopt_t *ednsopts, size_t count) { - dns_rdataset_t *rdataset; - dns_rdatalist_t *rdatalist; - dns_rdata_t *rdata; + dns_rdataset_t *rdataset = NULL; isc_result_t result; - rdatalist = NULL; - result = dns_message_gettemprdatalist(message, &rdatalist); - if (result != ISC_R_SUCCESS) - return (result); - rdata = NULL; - result = dns_message_gettemprdata(message, &rdata); - if (result != ISC_R_SUCCESS) - return (result); - rdataset = NULL; - result = dns_message_gettemprdataset(message, &rdataset); + result = dns_message_buildopt(message, &rdataset, version, udpsize, + DNS_MESSAGEEXTFLAG_DO, ednsopts, count); if (result != ISC_R_SUCCESS) return (result); - dns_rdataset_init(rdataset); - - rdatalist->type = dns_rdatatype_opt; - rdatalist->covers = 0; - - /* - * Set Maximum UDP buffer size. - */ - rdatalist->rdclass = udpsize; - - /* - * Set EXTENDED-RCODE and Z to 0, DO to 1. - */ - rdatalist->ttl = (version << 16); - rdatalist->ttl |= DNS_MESSAGEEXTFLAG_DO; - - /* - * Set EDNS options if applicable - */ - if (request_nsid) { - /* Send empty NSID option (RFC5001) */ - 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; - } - - rdata->rdclass = rdatalist->rdclass; - rdata->type = rdatalist->type; - rdata->flags = 0; - - ISC_LIST_INIT(rdatalist->rdata); - ISC_LIST_APPEND(rdatalist->rdata, rdata, link); - RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) == ISC_R_SUCCESS); - return (dns_message_setopt(message, rdataset)); } @@ -1710,6 +1666,8 @@ resquery_send(resquery_t *query) { isc_boolean_t cleanup_cctx = ISC_FALSE; isc_boolean_t secure_domain; isc_boolean_t connecting = ISC_FALSE; + dns_ednsopt_t ednsopts[EDNSOPTS]; + unsigned ednsopt = 0; fctx = query->fctx; QTRACE("send"); @@ -1892,8 +1850,15 @@ resquery_send(resquery_t *query) { /* request NSID for current view or peer? */ if (peer != NULL) (void) dns_peer_getrequestnsid(peer, &reqnsid); + if (reqnsid) { + INSIST(ednsopt < EDNSOPTS); + ednsopts[ednsopt].code = DNS_OPT_NSID; + ednsopts[ednsopt].length = 0; + ednsopts[ednsopt].value = NULL; + ednsopt++; + } result = fctx_addopt(fctx->qmessage, version, - udpsize, reqnsid); + udpsize, ednsopts, ednsopt); if (reqnsid && result == ISC_R_SUCCESS) { query->options |= DNS_FETCHOPT_WANTNSID; } else if (result != ISC_R_SUCCESS) { @@ -2478,7 +2443,7 @@ findname(fetchctx_t *fctx, dns_name_t *name, in_port_t port, isc_result_t result; res = fctx->res; - unshared = ISC_TF((fctx->options | DNS_FETCHOPT_UNSHARED) != 0); + unshared = ISC_TF((fctx->options & DNS_FETCHOPT_UNSHARED) != 0); /* * If this name is a subdomain of the query domain, tell * the ADB to start looking using zone/hint data. This keeps us @@ -4227,7 +4192,7 @@ validated(isc_task_t *task, isc_event_t *event) { result = ncache_adderesult(fctx->rmessage, fctx->cache, node, covers, now, ttl, vevent->optout, - ardataset, &eresult); + vevent->secure, ardataset, &eresult); if (result != ISC_R_SUCCESS) goto noanswer_response; goto answer_response; @@ -4237,7 +4202,6 @@ validated(isc_task_t *task, isc_event_t *event) { FCTXTRACE("validation OK"); if (vevent->proofs[DNS_VALIDATOR_NOQNAMEPROOF] != NULL) { - result = dns_rdataset_addnoqname(vevent->rdataset, vevent->proofs[DNS_VALIDATOR_NOQNAMEPROOF]); RUNTIME_CHECK(result == ISC_R_SUCCESS); @@ -4248,6 +4212,18 @@ validated(isc_task_t *task, isc_event_t *event) { vevent->proofs[DNS_VALIDATOR_CLOSESTENCLOSER]); RUNTIME_CHECK(result == ISC_R_SUCCESS); } + } else if (vevent->rdataset->trust == dns_trust_answer && + vevent->rdataset->type != dns_rdatatype_rrsig) + { + isc_result_t tresult; + dns_name_t *noqname = NULL; + tresult = findnoqname(fctx, vevent->name, + vevent->rdataset->type, &noqname); + if (tresult == ISC_R_SUCCESS && noqname != NULL) { + tresult = dns_rdataset_addnoqname(vevent->rdataset, + noqname); + RUNTIME_CHECK(tresult == ISC_R_SUCCESS); + } } /* @@ -4367,6 +4343,14 @@ validated(isc_task_t *task, isc_event_t *event) { fctx->attributes |= FCTX_ATTR_HAVEANSWER; if (hevent != NULL) { + /* + * Negative results must be indicated in event->result. + */ + if (dns_rdataset_isassociated(hevent->rdataset) && + NEGATIVE(hevent->rdataset)) { + INSIST(eresult == DNS_R_NCACHENXDOMAIN || + eresult == DNS_R_NCACHENXRRSET); + } hevent->result = eresult; RUNTIME_CHECK(dns_name_copy(vevent->name, dns_fixedname_name(&hevent->foundname), NULL) @@ -4388,6 +4372,149 @@ validated(isc_task_t *task, isc_event_t *event) { isc_event_free(&event); } +static void +fctx_log(void *arg, int level, const char *fmt, ...) { + char msgbuf[2048]; + va_list args; + fetchctx_t *fctx = arg; + + va_start(args, fmt); + vsnprintf(msgbuf, sizeof(msgbuf), fmt, args); + va_end(args); + + isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER, + DNS_LOGMODULE_RESOLVER, level, + "fctx %p(%s): %s", fctx, fctx->info, msgbuf); +} + +static inline isc_result_t +findnoqname(fetchctx_t *fctx, dns_name_t *name, dns_rdatatype_t type, + dns_name_t **noqnamep) +{ + dns_rdataset_t *nrdataset, *next, *sigrdataset; + dns_rdata_rrsig_t rrsig; + isc_result_t result; + unsigned int labels; + dns_section_t section; + dns_name_t *zonename; + dns_fixedname_t fzonename; + dns_name_t *closest; + dns_fixedname_t fclosest; + dns_name_t *nearest; + dns_fixedname_t fnearest; + dns_rdatatype_t found = dns_rdatatype_none; + dns_name_t *noqname = NULL; + + FCTXTRACE("findnoqname"); + + REQUIRE(noqnamep != NULL && *noqnamep == NULL); + + /* + * Find the SIG for this rdataset, if we have it. + */ + for (sigrdataset = ISC_LIST_HEAD(name->list); + sigrdataset != NULL; + sigrdataset = ISC_LIST_NEXT(sigrdataset, link)) { + if (sigrdataset->type == dns_rdatatype_rrsig && + sigrdataset->covers == type) + break; + } + + if (sigrdataset == NULL) + return (ISC_R_NOTFOUND); + + labels = dns_name_countlabels(name); + + for (result = dns_rdataset_first(sigrdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(sigrdataset)) { + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdataset_current(sigrdataset, &rdata); + result = dns_rdata_tostruct(&rdata, &rrsig, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + /* Wildcard has rrsig.labels < labels - 1. */ + if (rrsig.labels + 1U >= labels) + continue; + break; + } + + if (result == ISC_R_NOMORE) + return (ISC_R_NOTFOUND); + if (result != ISC_R_SUCCESS) + return (result); + + dns_fixedname_init(&fzonename); + zonename = dns_fixedname_name(&fzonename); + dns_fixedname_init(&fclosest); + closest = dns_fixedname_name(&fclosest); + dns_fixedname_init(&fnearest); + nearest = dns_fixedname_name(&fnearest); + +#define NXND(x) ((x) == ISC_R_SUCCESS) + + section = DNS_SECTION_AUTHORITY; + for (result = dns_message_firstname(fctx->rmessage, section); + result == ISC_R_SUCCESS; + result = dns_message_nextname(fctx->rmessage, section)) { + dns_name_t *nsec = NULL; + dns_message_currentname(fctx->rmessage, section, &nsec); + for (nrdataset = ISC_LIST_HEAD(nsec->list); + nrdataset != NULL; nrdataset = next) { + isc_boolean_t data = ISC_FALSE, exists = ISC_FALSE; + isc_boolean_t optout = ISC_FALSE, unknown = ISC_FALSE; + isc_boolean_t setclosest = ISC_FALSE; + isc_boolean_t setnearest = ISC_FALSE; + + next = ISC_LIST_NEXT(nrdataset, link); + if (nrdataset->type != dns_rdatatype_nsec && + nrdataset->type != dns_rdatatype_nsec3) + continue; + + if (nrdataset->type == dns_rdatatype_nsec && + NXND(dns_nsec_noexistnodata(type, name, nsec, + nrdataset, &exists, + &data, NULL, fctx_log, + fctx))) + { + if (!exists) { + noqname = nsec; + found = dns_rdatatype_nsec; + } + } + + if (nrdataset->type == dns_rdatatype_nsec3 && + NXND(dns_nsec3_noexistnodata(type, name, nsec, + nrdataset, zonename, + &exists, &data, + &optout, &unknown, + &setclosest, + &setnearest, + closest, nearest, + fctx_log, fctx))) + { + if (!exists && setnearest) { + noqname = nsec; + found = dns_rdatatype_nsec3; + } + } + } + } + if (result == ISC_R_NOMORE) + result = ISC_R_SUCCESS; + if (noqname != NULL) { + for (sigrdataset = ISC_LIST_HEAD(noqname->list); + sigrdataset != NULL; + sigrdataset = ISC_LIST_NEXT(sigrdataset, link)) { + if (sigrdataset->type == dns_rdatatype_rrsig && + sigrdataset->covers == found) + break; + } + if (sigrdataset != NULL) + *noqnamep = noqname; + } + return (result); +} + static inline isc_result_t cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo, isc_stdtime_t now) @@ -4521,6 +4648,17 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo, rdataset->ttl = res->view->maxcachettl; /* + * Find the SIG for this rdataset, if we have it. + */ + for (sigrdataset = ISC_LIST_HEAD(name->list); + sigrdataset != NULL; + sigrdataset = ISC_LIST_NEXT(sigrdataset, link)) { + if (sigrdataset->type == dns_rdatatype_rrsig && + sigrdataset->covers == rdataset->type) + break; + } + + /* * If this RRset is in a secure domain, is in bailiwick, * and is not glue, attempt DNSSEC validation. (We do not * attempt to validate glue or out-of-bailiwick data--even @@ -4540,16 +4678,7 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo, */ if (rdataset->type == dns_rdatatype_rrsig) continue; - /* - * Find the SIG for this rdataset, if we have it. - */ - for (sigrdataset = ISC_LIST_HEAD(name->list); - sigrdataset != NULL; - sigrdataset = ISC_LIST_NEXT(sigrdataset, link)) { - if (sigrdataset->type == dns_rdatatype_rrsig && - sigrdataset->covers == rdataset->type) - break; - } + if (sigrdataset == NULL) { if (!ANSWER(rdataset) && need_validation) { /* @@ -4583,6 +4712,22 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo, if (sigrdataset != NULL) sigrdataset->trust = trust; if (!need_validation || !ANSWER(rdataset)) { + if (ANSWER(rdataset) && + rdataset->type != dns_rdatatype_rrsig) { + isc_result_t tresult; + dns_name_t *noqname = NULL; + tresult = findnoqname(fctx, name, + rdataset->type, + &noqname); + if (tresult == ISC_R_SUCCESS && + noqname != NULL) { + tresult = + dns_rdataset_addnoqname( + rdataset, noqname); + RUNTIME_CHECK(tresult == + ISC_R_SUCCESS); + } + } addedrdataset = ardataset; result = dns_db_addrdataset(fctx->cache, node, NULL, now, rdataset, @@ -4710,6 +4855,21 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo, options = DNS_DBADD_FORCE; } else options = 0; + + if (ANSWER(rdataset) && + rdataset->type != dns_rdatatype_rrsig) { + isc_result_t tresult; + dns_name_t *noqname = NULL; + tresult = findnoqname(fctx, name, + rdataset->type, &noqname); + if (tresult == ISC_R_SUCCESS && + noqname != NULL) { + tresult = dns_rdataset_addnoqname( + rdataset, noqname); + RUNTIME_CHECK(tresult == ISC_R_SUCCESS); + } + } + /* * Now we can add the rdataset. */ @@ -4718,6 +4878,7 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo, rdataset, options, addedrdataset); + if (result == DNS_R_UNCHANGED) { if (ANSWER(rdataset) && ardataset != NULL && @@ -4813,8 +4974,8 @@ cache_message(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, isc_stdtime_t now) static isc_result_t ncache_adderesult(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node, dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t maxttl, - isc_boolean_t optout, dns_rdataset_t *ardataset, - isc_result_t *eresultp) + isc_boolean_t optout, isc_boolean_t secure, + dns_rdataset_t *ardataset, isc_result_t *eresultp) { isc_result_t result; dns_rdataset_t rdataset; @@ -4823,8 +4984,12 @@ ncache_adderesult(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node, dns_rdataset_init(&rdataset); ardataset = &rdataset; } - result = dns_ncache_addoptout(message, cache, node, covers, now, - maxttl, optout, ardataset); + if (secure) + result = dns_ncache_addoptout(message, cache, node, covers, + now, maxttl, optout, ardataset); + else + result = dns_ncache_add(message, cache, node, covers, now, + maxttl, ardataset); if (result == DNS_R_UNCHANGED || result == ISC_R_SUCCESS) { /* * If the cache now contains a negative entry and we @@ -4991,7 +5156,7 @@ ncache_message(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, result = ncache_adderesult(fctx->rmessage, fctx->cache, node, covers, now, ttl, ISC_FALSE, - ardataset, &eresult); + ISC_FALSE, ardataset, &eresult); if (result != ISC_R_SUCCESS) goto unlock; @@ -5387,10 +5552,10 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname, { isc_result_t result; dns_message_t *message; - dns_name_t *name, *qname, *ns_name, *soa_name, *ds_name; + dns_name_t *name, *qname, *ns_name, *soa_name, *ds_name, *save_name; dns_rdataset_t *rdataset, *ns_rdataset; isc_boolean_t aa, negative_response; - dns_rdatatype_t type; + dns_rdatatype_t type, save_type; dns_section_t section; FCTXTRACE("noanswer_response"); @@ -5457,6 +5622,8 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname, ns_rdataset = NULL; soa_name = NULL; ds_name = NULL; + save_name = NULL; + save_type = dns_rdatatype_none; result = dns_message_firstname(message, section); while (result == ISC_R_SUCCESS) { name = NULL; @@ -5655,6 +5822,9 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname, dns_trust_additional; } } + } else { + save_name = name; + save_type = ISC_LIST_HEAD(name->list)->type; } result = dns_message_nextname(message, section); if (result == ISC_R_NOMORE) @@ -5690,7 +5860,27 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname, /* * The responder is insane. */ - log_formerr(fctx, "invalid response"); + if (save_name == NULL) { + log_formerr(fctx, "invalid response"); + return (DNS_R_FORMERR); + } + if (!dns_name_issubdomain(save_name, &fctx->domain)) { + char nbuf[DNS_NAME_FORMATSIZE]; + char dbuf[DNS_NAME_FORMATSIZE]; + char tbuf[DNS_RDATATYPE_FORMATSIZE]; + + dns_rdatatype_format(save_type, tbuf, + sizeof(tbuf)); + dns_name_format(save_name, nbuf, sizeof(nbuf)); + dns_name_format(&fctx->domain, dbuf, + sizeof(dbuf)); + + log_formerr(fctx, "Name %s (%s) not subdomain" + " of zone %s -- invalid response", + nbuf, tbuf, dbuf); + } else { + log_formerr(fctx, "invalid response"); + } return (DNS_R_FORMERR); } } @@ -5899,12 +6089,12 @@ answer_response(fetchctx_t *fctx) { * but we found a CNAME. * * Getting a CNAME response for some - * query types is an error. + * query types is an error, see + * RFC 4035, Section 2.5. */ if (type == dns_rdatatype_rrsig || - type == dns_rdatatype_dnskey || - type == dns_rdatatype_nsec || - type == dns_rdatatype_nsec3) { + type == dns_rdatatype_key || + type == dns_rdatatype_nsec) { char buf[DNS_RDATATYPE_FORMATSIZE]; dns_rdatatype_format(fctx->type, buf, sizeof(buf)); @@ -6449,44 +6639,24 @@ checknames(dns_message_t *message) { /* * Log server NSID at log level 'level' */ -static isc_result_t -log_nsid(dns_rdataset_t *opt, resquery_t *query, int level, isc_mem_t *mctx) +static void +log_nsid(isc_buffer_t *opt, size_t nsid_len, resquery_t *query, + int level, isc_mem_t *mctx) { static const char hex[17] = "0123456789abcdef"; char addrbuf[ISC_SOCKADDR_FORMATSIZE]; - isc_uint16_t optcode, nsid_len, buflen, i; - isc_result_t result; - isc_buffer_t nsidbuf; - dns_rdata_t rdata; + isc_uint16_t buflen, i; unsigned char *p, *buf, *nsid; - /* Extract rdata from OPT rdataset */ - result = dns_rdataset_first(opt); - if (result != ISC_R_SUCCESS) - return (ISC_R_FAILURE); - - dns_rdata_init(&rdata); - dns_rdataset_current(opt, &rdata); - if (rdata.length < 4) - return (ISC_R_FAILURE); - - /* Check for NSID */ - isc_buffer_init(&nsidbuf, rdata.data, rdata.length); - isc_buffer_add(&nsidbuf, rdata.length); - optcode = isc_buffer_getuint16(&nsidbuf); - nsid_len = isc_buffer_getuint16(&nsidbuf); - if (optcode != DNS_OPT_NSID || nsid_len == 0) - return (ISC_R_FAILURE); - /* Allocate buffer for storing hex version of the NSID */ buflen = nsid_len * 2 + 1; buf = isc_mem_get(mctx, buflen); if (buf == NULL) - return (ISC_R_NOSPACE); + return; /* Convert to hex */ p = buf; - nsid = rdata.data + 4; + nsid = isc_buffer_current(opt); for (i = 0; i < nsid_len; i++) { *p++ = hex[(nsid[0] >> 4) & 0xf]; *p++ = hex[nsid[0] & 0xf]; @@ -6502,7 +6672,7 @@ log_nsid(dns_rdataset_t *opt, resquery_t *query, int level, isc_mem_t *mctx) /* Clean up */ isc_mem_put(mctx, buf, buflen); - return (ISC_R_SUCCESS); + return; } static void @@ -6576,6 +6746,41 @@ betterreferral(fetchctx_t *fctx) { } static void +process_opt(resquery_t *query, dns_rdataset_t *opt) { + dns_rdata_t rdata; + isc_buffer_t optbuf; + isc_result_t result; + isc_uint16_t optcode; + isc_uint16_t optlen; + + result = dns_rdataset_first(opt); + if (result == ISC_R_SUCCESS) { + dns_rdata_init(&rdata); + dns_rdataset_current(opt, &rdata); + isc_buffer_init(&optbuf, rdata.data, rdata.length); + isc_buffer_add(&optbuf, rdata.length); + while (isc_buffer_remaininglength(&optbuf) >= 4) { + optcode = isc_buffer_getuint16(&optbuf); + optlen = isc_buffer_getuint16(&optbuf); + INSIST(optlen <= isc_buffer_remaininglength(&optbuf)); + switch (optcode) { + case DNS_OPT_NSID: + if (query->options & DNS_FETCHOPT_WANTNSID) + log_nsid(&optbuf, optlen, query, + ISC_LOG_INFO, + query->fctx->res->mctx); + isc_buffer_forward(&optbuf, optlen); + break; + default: + isc_buffer_forward(&optbuf, optlen); + break; + } + } + INSIST(isc_buffer_remaininglength(&optbuf) == 0U); + } +} + +static void resquery_response(isc_task_t *task, isc_event_t *event) { isc_result_t result = ISC_R_SUCCESS; resquery_t *query = event->ev_arg; @@ -6650,13 +6855,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) { */ options |= DNS_FETCHOPT_NOEDNS0; resend = ISC_TRUE; - /* - * Remember that they don't like EDNS0. - */ - dns_adb_changeflags(fctx->adb, - query->addrinfo, - DNS_FETCHOPT_NOEDNS0, - DNS_FETCHOPT_NOEDNS0); + add_bad_edns(fctx, &query->addrinfo->sockaddr); } else { /* * There's no hope for this query. @@ -6723,14 +6922,8 @@ resquery_response(isc_task_t *task, isc_event_t *event) { */ options |= DNS_FETCHOPT_NOEDNS0; resend = ISC_TRUE; - /* - * Remember that they don't like EDNS0. - */ - dns_adb_changeflags( - fctx->adb, - query->addrinfo, - DNS_FETCHOPT_NOEDNS0, - DNS_FETCHOPT_NOEDNS0); + add_bad_edns(fctx, + &query->addrinfo->sockaddr); inc_stats(fctx->res, dns_resstatscounter_edns0fail); } else { @@ -6754,13 +6947,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) { */ options |= DNS_FETCHOPT_NOEDNS0; resend = ISC_TRUE; - /* - * Remember that they don't like EDNS0. - */ - dns_adb_changeflags(fctx->adb, - query->addrinfo, - DNS_FETCHOPT_NOEDNS0, - DNS_FETCHOPT_NOEDNS0); + add_bad_edns(fctx, &query->addrinfo->sockaddr); inc_stats(fctx->res, dns_resstatscounter_edns0fail); } else { @@ -6783,12 +6970,11 @@ resquery_response(isc_task_t *task, isc_event_t *event) { log_packet(message, ISC_LOG_DEBUG(10), fctx->res->mctx); /* - * Did we request NSID? If so, and if the response contains - * NSID data, log it at INFO level. + * Process receive opt record. */ opt = dns_message_getopt(message); - if (opt != NULL && (query->options & DNS_FETCHOPT_WANTNSID) != 0) - log_nsid(opt, query, ISC_LOG_INFO, fctx->res->mctx); + if (opt != NULL) + process_opt(query, opt); /* * If the message is signed, check the signature. If not, this |