From 03be5a6b4e6311b14a12dec5b15a62f55586aaf4 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Sat, 22 Apr 2017 08:25:10 +0530 Subject: [PATCH] Improve performance for delegation heavy answers and also general query performance (#44029) --- CHANGES | 12 + bin/named/config.c | 8 +- bin/named/include/named/server.h | 2 - bin/named/query.c | 650 +----- bin/named/server.c | 92 +- bin/tests/system/additional/ns1/named1.conf | 1 - bin/tests/system/additional/ns1/named2.conf | 1 - bin/tests/system/additional/ns1/named3.conf | 1 - bin/tests/system/additional/ns1/named4.conf | 1 - bin/tests/system/autosign/clean.sh | 3 +- bin/tests/system/autosign/ns2/keygen.sh | 14 +- bin/tests/system/autosign/ns4/named.conf | 4 +- bin/tests/system/autosign/ns5/named.conf | 1 - bin/tests/system/autosign/tests.sh | 13 +- bin/tests/system/cacheclean/ns1/named.conf | 3 +- bin/tests/system/case/ns1/named.conf | 1 + bin/tests/system/case/ns2/named.conf | 1 + bin/tests/system/checknames/ns2/named.conf | 1 - bin/tests/system/checknames/ns3/named.conf | 1 - bin/tests/system/checknames/ns4/named.conf | 1 - bin/tests/system/cookie/ns1/named.conf | 1 - bin/tests/system/cookie/ns2/named.conf | 1 - bin/tests/system/cookie/ns3/named.conf | 1 - bin/tests/system/digdelv/ns3/named.conf | 1 - bin/tests/system/dlv/ns5/named.conf | 1 - bin/tests/system/dnssec/ns2/named.conf | 3 +- bin/tests/system/dnssec/ns3/named.conf | 3 +- bin/tests/system/dnssec/ns4/named1.conf | 4 +- bin/tests/system/dnssec/ns4/named2.conf | 4 +- bin/tests/system/dnssec/ns4/named3.conf | 4 +- bin/tests/system/dnssec/ns4/named4.conf | 44 + bin/tests/system/dnssec/ns5/named1.conf | 1 - bin/tests/system/dnssec/ns6/named.conf | 1 - bin/tests/system/dnssec/tests.sh | 8 +- bin/tests/system/emptyzones/ns1/named1.conf | 1 - bin/tests/system/emptyzones/ns1/named2.conf | 1 - bin/tests/system/filter-aaaa/ns1/named1.conf | 1 + bin/tests/system/filter-aaaa/ns1/named2.conf | 1 + bin/tests/system/filter-aaaa/ns1/root.db | 12 +- bin/tests/system/filter-aaaa/ns1/signed.db.in | 10 +- bin/tests/system/filter-aaaa/ns1/unsigned.db | 10 +- bin/tests/system/filter-aaaa/ns2/named1.conf | 1 + bin/tests/system/filter-aaaa/ns2/named2.conf | 1 + bin/tests/system/filter-aaaa/ns3/named1.conf | 1 + bin/tests/system/filter-aaaa/ns3/named2.conf | 1 + bin/tests/system/filter-aaaa/ns4/named1.conf | 1 + bin/tests/system/filter-aaaa/ns4/named2.conf | 1 + bin/tests/system/filter-aaaa/ns4/root.db | 16 +- bin/tests/system/filter-aaaa/ns4/signed.db.in | 10 +- bin/tests/system/filter-aaaa/ns4/unsigned.db | 10 +- bin/tests/system/glue/ns1/root.db | 10 - bin/tests/system/glue/tests.sh | 8 - bin/tests/system/limits/ns1/named.conf | 3 +- bin/tests/system/notify/ns3/named.conf | 1 - bin/tests/system/notify/ns4/named.conf | 1 - bin/tests/system/notify/ns5/named.conf | 1 - bin/tests/system/nsupdate/ns1/named.conf | 3 +- bin/tests/system/nsupdate/ns2/named.conf | 1 - bin/tests/system/resolver/ns1/named.conf | 1 - bin/tests/system/rpz/ns1/named.conf | 3 +- bin/tests/system/rpz/ns2/named.conf | 4 +- bin/tests/system/rpz/ns3/named.conf | 4 +- bin/tests/system/rpz/ns4/named.conf | 3 +- bin/tests/system/rpz/ns5/named.conf | 4 +- bin/tests/system/rpz/ns6/named.conf | 1 + bin/tests/system/rpz/ns7/named.conf | 1 + bin/tests/system/rrl/broken.conf | 2 - bin/tests/system/rrl/ns2/named.conf | 2 - bin/tests/system/rrl/ns4/named.conf | 2 - bin/tests/system/rrsetorder/clean.sh | 4 +- bin/tests/system/rrsetorder/ns1/root.db | 5 + bin/tests/system/rrsetorder/ns3/named.conf | 1 - bin/tests/system/rrsetorder/ns4/named.conf | 1 - bin/tests/system/rrsetorder/tests.sh | 10 +- bin/tests/system/sfcache/ns5/named.conf | 1 - bin/tests/system/statschannel/ns2/named.conf | 1 + bin/tests/system/stress/ns3/named.conf | 1 - bin/tests/system/stress/ns4/named.conf | 1 - bin/tests/system/stub/ns1/named.conf | 3 +- bin/tests/system/stub/ns2/named.conf | 3 +- bin/tests/system/stub/ns3/named.conf | 4 +- bin/tests/system/tkey/ns1/named.conf.in | 2 - bin/tests/system/tkey/tests.sh | 6 +- bin/tests/system/upforwd/ns1/named.conf | 1 - bin/tests/system/upforwd/ns2/named.conf | 1 - bin/tests/system/upforwd/ns3/named.conf | 1 - bin/tests/system/v6synth/ns2/named.conf | 1 - bin/tests/system/v6synth/ns3/named.conf | 1 - bin/tests/system/xfer/ns3/named.conf | 1 - bin/tests/system/zero/ns1/named.conf | 1 - bin/tests/system/zero/ns2/named.conf | 1 - bin/tests/system/zero/ns3/named.conf | 1 - bin/tests/system/zero/ns4/named.conf | 1 - doc/arm/Bv9ARM-book.xml | 264 +-- doc/misc/options | 20 +- lib/bind9/check.c | 3 +- lib/dns/Makefile.in | 4 +- lib/dns/acache.c | 1790 ----------------- lib/dns/compress.c | 293 ++- lib/dns/ecdb.c | 6 +- lib/dns/include/dns/Makefile.in | 2 +- lib/dns/include/dns/acache.h | 440 ---- lib/dns/include/dns/compress.h | 17 +- lib/dns/include/dns/log.h | 2 +- lib/dns/include/dns/rdataset.h | 162 +- lib/dns/include/dns/types.h | 3 - lib/dns/include/dns/view.h | 3 - lib/dns/include/dns/zone.h | 13 - lib/dns/log.c | 2 +- lib/dns/message.c | 8 +- lib/dns/name.c | 40 +- lib/dns/ncache.c | 22 +- lib/dns/order.c | 6 +- lib/dns/rbtdb.c | 1231 +++++++----- lib/dns/rdatalist.c | 12 +- lib/dns/rdataset.c | 237 +-- lib/dns/rdataslab.c | 22 +- lib/dns/sdb.c | 18 +- lib/dns/sdlz.c | 18 +- lib/dns/ssu_external.c | 2 +- lib/dns/view.c | 20 - lib/dns/win32/libdns.def.in | 20 +- lib/dns/win32/libdns.dsp.in | 8 - lib/dns/win32/libdns.mak.in | 24 - lib/dns/win32/libdns.vcxproj.filters.in | 8 +- lib/dns/win32/libdns.vcxproj.in | 4 +- lib/dns/zone.c | 46 - lib/isc/hash.c | 61 +- lib/isc/include/isc/buffer.h | 50 +- lib/isc/include/isc/msgs.h | 1 + lib/isc/mem.c | 41 +- lib/isc/rwlock.c | 25 +- lib/isccfg/namedconf.c | 15 +- util/copyrights | 2 - 134 files changed, 1619 insertions(+), 4420 deletions(-) delete mode 100644 lib/dns/acache.c delete mode 100644 lib/dns/include/dns/acache.h diff --git a/CHANGES b/CHANGES index e26704590f..5180259f3b 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,15 @@ +4605. [performance] Improve performance for delegation heavy answers + and also general query performance. Removes the + acache feature that didn't significantly improve + performance. Adds a glue cache. Removes + additional-from-cache and additional-from-auth + features. Enables minimal-responses by + default. Improves performance of compression + code, owner case restoration, hash function, + etc. Uses inline buffer implementation by + default. Many other performance changes and fixes. + [RT #44029] + 4604. [bug] Don't use ERR_load_crypto_strings() when building with OpenSSL 1.1.0. [RT #45117] diff --git a/bin/named/config.c b/bin/named/config.c index c8fbcf682d..585528fc84 100644 --- a/bin/named/config.c +++ b/bin/named/config.c @@ -94,7 +94,6 @@ options {\n\ "\ recursive-clients 1000;\n\ resolver-query-timeout 10;\n\ - rrset-order { order random; };\n\ # serial-queries ;\n\ serial-query-rate 20;\n\ server-id none;\n\ @@ -140,15 +139,13 @@ options {\n\ # topology \n\ auth-nxdomain false;\n\ minimal-any false;\n\ - minimal-responses false;\n\ + minimal-responses true;\n\ recursion true;\n\ provide-ixfr true;\n\ request-ixfr true;\n\ request-expire true;\n\ # fetch-glue ;\n\ # rfc2308-type1 ;\n\ - additional-from-auth true;\n\ - additional-from-cache true;\n\ query-source address *;\n\ query-source-v6 address *;\n\ notify-source *;\n\ @@ -167,9 +164,6 @@ options {\n\ check-dup-records warn;\n\ check-mx warn;\n\ check-spf warn;\n\ - acache-enable no;\n\ - acache-cleaning-interval 60;\n\ - max-acache-size 16M;\n\ dnssec-enable yes;\n\ dnssec-validation yes; \n\ dnssec-accept-expired no;\n\ diff --git a/bin/named/include/named/server.h b/bin/named/include/named/server.h index 65a45d2416..355c64d53d 100644 --- a/bin/named/include/named/server.h +++ b/bin/named/include/named/server.h @@ -108,8 +108,6 @@ struct ns_server { unsigned int dispatchgen; ns_dispatchlist_t dispatches; - dns_acache_t *acache; - ns_statschannellist_t statschannels; dns_tsigkey_t *sessionkey; diff --git a/bin/named/query.c b/bin/named/query.c index a8ceba16ea..1c63f2ce0b 100644 --- a/bin/named/query.c +++ b/bin/named/query.c @@ -210,11 +210,6 @@ client_trace(ns_client_t *client, int level, const char *message) { #define SAVE(a, b) do { INSIST(a == NULL); a = b; b = NULL; } while (0) #define RESTORE(a, b) SAVE(a, b) -typedef struct client_additionalctx { - ns_client_t *client; - dns_rdataset_t *rdataset; -} client_additionalctx_t; - static isc_boolean_t validate(ns_client_t *client, dns_db_t *db, dns_name_t *name, dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset); @@ -1032,10 +1027,11 @@ query_validatezonedb(ns_client_t *client, const dns_name_t *name, * CNAMES or DNAMES into other zones and prevents returning * additional data from other zones. */ - if (!client->view->additionalfromauth && - client->query.authdbset && - db != client->query.authdb) + if (client->query.rpz_st == NULL && + client->query.authdbset && db != client->query.authdb) + { return (DNS_R_REFUSED); + } /* * Non recursive query to a static-stub zone is prohibited; its @@ -1580,9 +1576,9 @@ query_addadditional(void *arg, const dns_name_t *name, dns_rdatatype_t qtype) { dns_rdataset_t *rdataset, *sigrdataset, *trdataset; isc_buffer_t *dbuf; isc_buffer_t b; + ns_dbversion_t *dbversion; dns_dbversion_t *version; isc_boolean_t added_something, need_addname; - dns_zone_t *zone; dns_rdatatype_t type; dns_clientinfomethods_t cm; dns_clientinfo_t ci; @@ -1609,7 +1605,6 @@ query_addadditional(void *arg, const dns_name_t *name, dns_rdatatype_t qtype) { node = NULL; added_something = ISC_FALSE; need_addname = ISC_FALSE; - zone = NULL; additionaltype = dns_rdatasetadditional_fromauth; dns_clientinfomethods_init(&cm, ns_client_sourceip); @@ -1643,14 +1638,26 @@ query_addadditional(void *arg, const dns_name_t *name, dns_rdatatype_t qtype) { } /* - * Look for a zone database that might contain authoritative + * If we want only minimal responses and are here, then it must + * be for glue. + */ + if (client->view->minimalresponses == dns_minimal_yes) + goto try_glue; + + /* + * Look within the same zone database for authoritative * additional data. */ - result = query_getzonedb(client, name, qtype, DNS_GETDB_NOLOG, - &zone, &db, &version); - if (result != ISC_R_SUCCESS) + if (!client->query.authdbset || client->query.authdb == NULL) goto try_cache; + dbversion = query_findversion(client, client->query.authdb); + if (dbversion == NULL) + goto try_cache; + + dns_db_attach(client->query.authdb, &db); + version = dbversion->version; + CTRACE(ISC_LOG_DEBUG(3), "query_addadditional: db_find"); /* @@ -1684,13 +1691,17 @@ query_addadditional(void *arg, const dns_name_t *name, dns_rdatatype_t qtype) { */ try_cache: + if (!client->view->recursion) + goto try_glue; + additionaltype = dns_rdatasetadditional_fromcache; result = query_getcachedb(client, name, qtype, &db, DNS_GETDB_NOLOG); - if (result != ISC_R_SUCCESS) + if (result != ISC_R_SUCCESS) { /* * Most likely the client isn't allowed to query the cache. */ goto try_glue; + } /* * Attempt to validate glue. */ @@ -1699,6 +1710,8 @@ query_addadditional(void *arg, const dns_name_t *name, dns_rdatatype_t qtype) { if (sigrdataset == NULL) goto cleanup; } + + version = NULL; result = dns_db_findext(db, name, version, type, client->query.dboptions | DNS_DBFIND_GLUEOK | DNS_DBFIND_ADDITIONALOK, @@ -1744,8 +1757,12 @@ query_addadditional(void *arg, const dns_name_t *name, dns_rdatatype_t qtype) { if (!dns_name_issubdomain(name, dns_db_origin(client->query.gluedb))) goto cleanup; - dns_db_attach(client->query.gluedb, &db); + dbversion = query_findversion(client, client->query.gluedb); + if (dbversion == NULL) + goto cleanup; + dns_db_attach(client->query.gluedb, &db); + version = dbversion->version; additionaltype = dns_rdatasetadditional_fromglue; result = dns_db_findext(db, name, version, type, client->query.dboptions | DNS_DBFIND_GLUEOK, @@ -1826,15 +1843,14 @@ query_addadditional(void *arg, const dns_name_t *name, dns_rdatatype_t qtype) { dns_rdatatype_a, 0, client->now, rdataset, sigrdataset); - if (result == DNS_R_NCACHENXDOMAIN) + if (result == DNS_R_NCACHENXDOMAIN) { goto addname; - if (result == DNS_R_NCACHENXRRSET) { + } else if (result == DNS_R_NCACHENXRRSET) { dns_rdataset_disassociate(rdataset); if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) dns_rdataset_disassociate(sigrdataset); - } - if (result == ISC_R_SUCCESS) { + } else if (result == ISC_R_SUCCESS) { mname = NULL; #ifdef ALLOW_FILTER_AAAA have_a = ISC_TRUE; @@ -1887,15 +1903,14 @@ query_addadditional(void *arg, const dns_name_t *name, dns_rdatatype_t qtype) { dns_rdatatype_aaaa, 0, client->now, rdataset, sigrdataset); - if (result == DNS_R_NCACHENXDOMAIN) + if (result == DNS_R_NCACHENXDOMAIN) { goto addname; - if (result == DNS_R_NCACHENXRRSET) { + } else if (result == DNS_R_NCACHENXRRSET) { dns_rdataset_disassociate(rdataset); if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) dns_rdataset_disassociate(sigrdataset); - } - if (result == ISC_R_SUCCESS) { + } else if (result == ISC_R_SUCCESS) { mname = NULL; /* * There's an A; check whether we're filtering AAAA @@ -1992,562 +2007,15 @@ query_addadditional(void *arg, const dns_name_t *name, dns_rdatatype_t qtype) { dns_db_detachnode(db, &node); if (db != NULL) dns_db_detach(&db); - if (zone != NULL) - dns_zone_detach(&zone); CTRACE(ISC_LOG_DEBUG(3), "query_addadditional: done"); return (eresult); } -static inline void -query_discardcache(ns_client_t *client, dns_rdataset_t *rdataset_base, - dns_rdatasetadditional_t additionaltype, - dns_rdatatype_t type, dns_zone_t **zonep, dns_db_t **dbp, - dns_dbversion_t **versionp, dns_dbnode_t **nodep, - dns_name_t *fname) -{ - dns_rdataset_t *rdataset; - - while ((rdataset = ISC_LIST_HEAD(fname->list)) != NULL) { - ISC_LIST_UNLINK(fname->list, rdataset, link); - query_putrdataset(client, &rdataset); - } - if (*versionp != NULL) - dns_db_closeversion(*dbp, versionp, ISC_FALSE); - if (*nodep != NULL) - dns_db_detachnode(*dbp, nodep); - if (*dbp != NULL) - dns_db_detach(dbp); - if (*zonep != NULL) - dns_zone_detach(zonep); - (void)dns_rdataset_putadditional(client->view->acache, rdataset_base, - additionaltype, type); -} - -static inline isc_result_t -query_iscachevalid(dns_zone_t *zone, dns_db_t *db, dns_db_t *db0, - dns_dbversion_t *version) -{ - isc_result_t result = ISC_R_SUCCESS; - dns_dbversion_t *version_current = NULL; - dns_db_t *db_current = db0; - - if (db_current == NULL) { - result = dns_zone_getdb(zone, &db_current); - if (result != ISC_R_SUCCESS) - return (result); - } - dns_db_currentversion(db_current, &version_current); - if (db_current != db || version_current != version) { - result = ISC_R_FAILURE; - goto cleanup; - } - - cleanup: - dns_db_closeversion(db_current, &version_current, ISC_FALSE); - if (db0 == NULL && db_current != NULL) - dns_db_detach(&db_current); - - return (result); -} - -static isc_result_t -query_addadditional2(void *arg, const dns_name_t *name, dns_rdatatype_t qtype) { - client_additionalctx_t *additionalctx = arg; - dns_rdataset_t *rdataset_base; - ns_client_t *client; - isc_result_t result, eresult; - dns_dbnode_t *node, *cnode; - dns_db_t *db, *cdb; - dns_name_t *fname, *mname0, cfname; - dns_rdataset_t *rdataset, *sigrdataset; - dns_rdataset_t *crdataset, *crdataset_next; - isc_buffer_t *dbuf; - isc_buffer_t b; - dns_dbversion_t *version, *cversion; - isc_boolean_t added_something, need_addname, needadditionalcache; - isc_boolean_t need_sigrrset; - dns_zone_t *zone; - dns_rdatatype_t type; - dns_rdatasetadditional_t additionaltype; - dns_clientinfomethods_t cm; - dns_clientinfo_t ci; - - /* - * If we don't have an additional cache call query_addadditional. - */ - client = additionalctx->client; - REQUIRE(NS_CLIENT_VALID(client)); - - if (qtype != dns_rdatatype_a || client->view->acache == NULL) { - /* - * This function is optimized for "address" types. For other - * types, use a generic routine. - * XXX: ideally, this function should be generic enough. - */ - return (query_addadditional(additionalctx->client, - name, qtype)); - } - - /* - * Initialization. - */ - rdataset_base = additionalctx->rdataset; - eresult = ISC_R_SUCCESS; - fname = NULL; - rdataset = NULL; - sigrdataset = NULL; - db = NULL; - cdb = NULL; - version = NULL; - cversion = NULL; - node = NULL; - cnode = NULL; - added_something = ISC_FALSE; - need_addname = ISC_FALSE; - zone = NULL; - needadditionalcache = ISC_FALSE; - POST(needadditionalcache); - additionaltype = dns_rdatasetadditional_fromauth; - dns_name_init(&cfname, NULL); - dns_clientinfomethods_init(&cm, ns_client_sourceip); - dns_clientinfo_init(&ci, client, NULL); - - CTRACE(ISC_LOG_DEBUG(3), "query_addadditional2"); - - /* - * We treat type A additional section processing as if it - * were "any address type" additional section processing. - * To avoid multiple lookups, we do an 'any' database - * lookup and iterate over the node. - * XXXJT: this approach can cause a suboptimal result when the cache - * DB only has partial address types and the glue DB has remaining - * ones. - */ - type = dns_rdatatype_any; - - /* - * Get some resources. - */ - dbuf = query_getnamebuf(client); - if (dbuf == NULL) - goto cleanup; - fname = query_newname(client, dbuf, &b); - if (fname == NULL) - goto cleanup; - dns_name_setbuffer(&cfname, &b); /* share the buffer */ - - /* Check additional cache */ - result = dns_rdataset_getadditional(rdataset_base, additionaltype, - type, client->view->acache, &zone, - &cdb, &cversion, &cnode, &cfname, - client->message, client->now); - if (result != ISC_R_SUCCESS) - goto findauthdb; - if (zone == NULL) { - CTRACE(ISC_LOG_DEBUG(3), - "query_addadditional2: auth zone not found"); - goto try_cache; - } - - /* Is the cached DB up-to-date? */ - result = query_iscachevalid(zone, cdb, NULL, cversion); - if (result != ISC_R_SUCCESS) { - CTRACE(ISC_LOG_DEBUG(3), - "query_addadditional2: old auth additional cache"); - query_discardcache(client, rdataset_base, additionaltype, - type, &zone, &cdb, &cversion, &cnode, - &cfname); - goto findauthdb; - } - - if (cnode == NULL) { - /* - * We have a negative cache. We don't have to check the zone - * ACL, since the result (not using this zone) would be same - * regardless of the result. - */ - CTRACE(ISC_LOG_DEBUG(3), - "query_addadditional2: negative auth additional cache"); - dns_db_closeversion(cdb, &cversion, ISC_FALSE); - dns_db_detach(&cdb); - dns_zone_detach(&zone); - goto try_cache; - } - - result = query_validatezonedb(client, name, qtype, DNS_GETDB_NOLOG, - zone, cdb, NULL); - if (result != ISC_R_SUCCESS) { - query_discardcache(client, rdataset_base, additionaltype, - type, &zone, &cdb, &cversion, &cnode, - &cfname); - goto try_cache; - } - - /* We've got an active cache. */ - CTRACE(ISC_LOG_DEBUG(3), - "query_addadditional2: auth additional cache"); - dns_db_closeversion(cdb, &cversion, ISC_FALSE); - db = cdb; - node = cnode; - dns_name_clone(&cfname, fname); - query_keepname(client, fname, dbuf); - goto foundcache; - - /* - * Look for a zone database that might contain authoritative - * additional data. - */ - findauthdb: - result = query_getzonedb(client, name, qtype, DNS_GETDB_NOLOG, - &zone, &db, &version); - if (result != ISC_R_SUCCESS) { - /* Cache the negative result */ - (void)dns_rdataset_setadditional(rdataset_base, additionaltype, - type, client->view->acache, - NULL, NULL, NULL, NULL, - NULL); - goto try_cache; - } - - CTRACE(ISC_LOG_DEBUG(3), "query_addadditional2: db_find"); - - /* - * Since we are looking for authoritative data, we do not set - * the GLUEOK flag. Glue will be looked for later, but not - * necessarily in the same database. - */ - node = NULL; - result = dns_db_findext(db, name, version, type, - client->query.dboptions, - client->now, &node, fname, &cm, &ci, - NULL, NULL); - if (result == ISC_R_SUCCESS) - goto found; - - /* Cache the negative result */ - (void)dns_rdataset_setadditional(rdataset_base, additionaltype, - type, client->view->acache, zone, db, - version, NULL, fname); - - if (node != NULL) - dns_db_detachnode(db, &node); - version = NULL; - dns_db_detach(&db); - - /* - * No authoritative data was found. The cache is our next best bet. - */ - - try_cache: - additionaltype = dns_rdatasetadditional_fromcache; - result = query_getcachedb(client, name, qtype, &db, DNS_GETDB_NOLOG); - if (result != ISC_R_SUCCESS) - /* - * Most likely the client isn't allowed to query the cache. - */ - goto try_glue; - - result = dns_db_findext(db, name, version, type, - client->query.dboptions | - DNS_DBFIND_GLUEOK | DNS_DBFIND_ADDITIONALOK, - client->now, &node, fname, &cm, &ci, - NULL, NULL); - if (result == ISC_R_SUCCESS) - goto found; - - if (node != NULL) - dns_db_detachnode(db, &node); - dns_db_detach(&db); - - try_glue: - /* - * No cached data was found. Glue is our last chance. - * RFC1035 sayeth: - * - * NS records cause both the usual additional section - * processing to locate a type A record, and, when used - * in a referral, a special search of the zone in which - * they reside for glue information. - * - * This is the "special search". Note that we must search - * the zone where the NS record resides, not the zone it - * points to, and that we only do the search in the delegation - * case (identified by client->query.gluedb being set). - */ - if (client->query.gluedb == NULL) - goto cleanup; - - /* - * Don't poison caches using the bailiwick protection model. - */ - if (!dns_name_issubdomain(name, dns_db_origin(client->query.gluedb))) - goto cleanup; - - /* Check additional cache */ - additionaltype = dns_rdatasetadditional_fromglue; - result = dns_rdataset_getadditional(rdataset_base, additionaltype, - type, client->view->acache, NULL, - &cdb, &cversion, &cnode, &cfname, - client->message, client->now); - if (result != ISC_R_SUCCESS) - goto findglue; - - result = query_iscachevalid(zone, cdb, client->query.gluedb, cversion); - if (result != ISC_R_SUCCESS) { - CTRACE(ISC_LOG_DEBUG(3), - "query_addadditional2: old glue additional cache"); - query_discardcache(client, rdataset_base, additionaltype, - type, &zone, &cdb, &cversion, &cnode, - &cfname); - goto findglue; - } - - if (cnode == NULL) { - /* We have a negative cache. */ - CTRACE(ISC_LOG_DEBUG(3), - "query_addadditional2: negative glue additional cache"); - dns_db_closeversion(cdb, &cversion, ISC_FALSE); - dns_db_detach(&cdb); - goto cleanup; - } - - /* Cache hit. */ - CTRACE(ISC_LOG_DEBUG(3), "query_addadditional2: glue additional cache"); - dns_db_closeversion(cdb, &cversion, ISC_FALSE); - db = cdb; - node = cnode; - dns_name_clone(&cfname, fname); - query_keepname(client, fname, dbuf); - goto foundcache; - - findglue: - dns_db_attach(client->query.gluedb, &db); - result = dns_db_findext(db, name, version, type, - client->query.dboptions | DNS_DBFIND_GLUEOK, - client->now, &node, fname, &cm, &ci, - NULL, NULL); - if (!(result == ISC_R_SUCCESS || - result == DNS_R_ZONECUT || - result == DNS_R_GLUE)) { - /* cache the negative result */ - (void)dns_rdataset_setadditional(rdataset_base, additionaltype, - type, client->view->acache, - NULL, db, version, NULL, - fname); - goto cleanup; - } - - found: - /* - * We have found a DB node to iterate over from a DB. - * We are going to look for address RRsets (i.e., A and AAAA) in the DB - * node we've just found. We'll then store the complete information - * in the additional data cache. - */ - dns_name_clone(fname, &cfname); - query_keepname(client, fname, dbuf); - needadditionalcache = ISC_TRUE; - - rdataset = query_newrdataset(client); - if (rdataset == NULL) - goto cleanup; - - sigrdataset = query_newrdataset(client); - if (sigrdataset == NULL) - goto cleanup; - - if (additionaltype == dns_rdatasetadditional_fromcache && - query_isduplicate(client, fname, dns_rdatatype_a, NULL)) - goto aaaa_lookup; - /* - * Find A RRset with sig RRset. Even if we don't find a sig RRset - * for a client using DNSSEC, we'll continue the process to make a - * complete list to be cached. However, we need to cancel the - * caching when something unexpected happens, in order to avoid - * caching incomplete information. - */ - result = dns_db_findrdataset(db, node, version, dns_rdatatype_a, 0, - client->now, rdataset, sigrdataset); - /* - * If we can't promote glue/pending from the cache to secure - * then drop it. - */ - if (result == ISC_R_SUCCESS && - additionaltype == dns_rdatasetadditional_fromcache && - (DNS_TRUST_PENDING(rdataset->trust) || - DNS_TRUST_GLUE(rdataset->trust)) && - !validate(client, db, fname, rdataset, sigrdataset)) { - dns_rdataset_disassociate(rdataset); - if (dns_rdataset_isassociated(sigrdataset)) - dns_rdataset_disassociate(sigrdataset); - result = ISC_R_NOTFOUND; - } - if (result == DNS_R_NCACHENXDOMAIN) - goto setcache; - if (result == DNS_R_NCACHENXRRSET) { - dns_rdataset_disassociate(rdataset); - if (dns_rdataset_isassociated(sigrdataset)) - dns_rdataset_disassociate(sigrdataset); - } - if (result == ISC_R_SUCCESS) { - /* Remember the result as a cache */ - ISC_LIST_APPEND(cfname.list, rdataset, link); - if (dns_rdataset_isassociated(sigrdataset)) { - ISC_LIST_APPEND(cfname.list, sigrdataset, link); - sigrdataset = query_newrdataset(client); - } - rdataset = query_newrdataset(client); - if (sigrdataset == NULL || rdataset == NULL) { - /* do not cache incomplete information */ - goto foundcache; - } - } - - aaaa_lookup: - if (additionaltype == dns_rdatasetadditional_fromcache && - query_isduplicate(client, fname, dns_rdatatype_aaaa, NULL)) - goto foundcache; - /* Find AAAA RRset with sig RRset */ - result = dns_db_findrdataset(db, node, version, dns_rdatatype_aaaa, - 0, client->now, rdataset, sigrdataset); - /* - * If we can't promote glue/pending from the cache to secure - * then drop it. - */ - if (result == ISC_R_SUCCESS && - additionaltype == dns_rdatasetadditional_fromcache && - (DNS_TRUST_PENDING(rdataset->trust) || - DNS_TRUST_GLUE(rdataset->trust)) && - !validate(client, db, fname, rdataset, sigrdataset)) { - dns_rdataset_disassociate(rdataset); - if (dns_rdataset_isassociated(sigrdataset)) - dns_rdataset_disassociate(sigrdataset); - result = ISC_R_NOTFOUND; - } - if (result == ISC_R_SUCCESS) { - ISC_LIST_APPEND(cfname.list, rdataset, link); - rdataset = NULL; - if (dns_rdataset_isassociated(sigrdataset)) { - ISC_LIST_APPEND(cfname.list, sigrdataset, link); - sigrdataset = NULL; - } - } - - setcache: - /* - * Set the new result in the cache if required. We do not support - * caching additional data from a cache DB. - */ - if (needadditionalcache == ISC_TRUE && - (additionaltype == dns_rdatasetadditional_fromauth || - additionaltype == dns_rdatasetadditional_fromglue)) { - (void)dns_rdataset_setadditional(rdataset_base, additionaltype, - type, client->view->acache, - zone, db, version, node, - &cfname); - } - - foundcache: - need_sigrrset = ISC_FALSE; - mname0 = NULL; - for (crdataset = ISC_LIST_HEAD(cfname.list); - crdataset != NULL; - crdataset = crdataset_next) { - dns_name_t *mname; - - crdataset_next = ISC_LIST_NEXT(crdataset, link); - - mname = NULL; - if (crdataset->type == dns_rdatatype_a || - crdataset->type == dns_rdatatype_aaaa) { - if (!query_isduplicate(client, fname, crdataset->type, - &mname)) { - if (mname != fname) { - if (mname != NULL) { - /* - * A different type of this - * name is already stored - * in the additional - * section. We'll reuse - * the name. Note that - * this should happen at - * most once. Otherwise, - * fname->link could leak - * below. - */ - INSIST(mname0 == NULL); - - query_releasename(client, - &fname); - fname = mname; - mname0 = mname; - } else - need_addname = ISC_TRUE; - } - ISC_LIST_UNLINK(cfname.list, crdataset, link); - ISC_LIST_APPEND(fname->list, crdataset, link); - added_something = ISC_TRUE; - need_sigrrset = ISC_TRUE; - } else - need_sigrrset = ISC_FALSE; - } else if (crdataset->type == dns_rdatatype_rrsig && - need_sigrrset && WANTDNSSEC(client)) { - ISC_LIST_UNLINK(cfname.list, crdataset, link); - ISC_LIST_APPEND(fname->list, crdataset, link); - added_something = ISC_TRUE; /* just in case */ - need_sigrrset = ISC_FALSE; - } - } - - CTRACE(ISC_LOG_DEBUG(3), "query_addadditional2: addname"); - - /* - * If we haven't added anything, then we're done. - */ - if (!added_something) - goto cleanup; - - /* - * We may have added our rdatasets to an existing name, if so, then - * need_addname will be ISC_FALSE. Whether we used an existing name - * or a new one, we must set fname to NULL to prevent cleanup. - */ - if (need_addname) - dns_message_addname(client->message, fname, - DNS_SECTION_ADDITIONAL); - fname = NULL; - - cleanup: - CTRACE(ISC_LOG_DEBUG(3), "query_addadditional2: cleanup"); - - if (rdataset != NULL) - query_putrdataset(client, &rdataset); - if (sigrdataset != NULL) - query_putrdataset(client, &sigrdataset); - while ((crdataset = ISC_LIST_HEAD(cfname.list)) != NULL) { - ISC_LIST_UNLINK(cfname.list, crdataset, link); - query_putrdataset(client, &crdataset); - } - if (fname != NULL) - query_releasename(client, &fname); - if (node != NULL) - dns_db_detachnode(db, &node); - if (db != NULL) - dns_db_detach(&db); - if (zone != NULL) - dns_zone_detach(&zone); - - CTRACE(ISC_LOG_DEBUG(3), "query_addadditional2: done"); - return (eresult); -} - static inline void query_addrdataset(ns_client_t *client, dns_name_t *fname, dns_rdataset_t *rdataset) { - client_additionalctx_t additionalctx; - /* * Add 'rdataset' and any pertinent additional data to * 'fname', a name in the response message for 'client'. @@ -2566,15 +2034,44 @@ query_addrdataset(ns_client_t *client, dns_name_t *fname, if (NOADDITIONAL(client)) return; + /* + * Try to process glue directly. + */ + if ((client->view->minimalresponses == dns_minimal_yes) && + (rdataset->type == dns_rdatatype_ns) && + (client->query.gluedb != NULL) && + dns_db_iszone(client->query.gluedb)) + { + isc_result_t result; + ns_dbversion_t *dbversion; + unsigned int options = 0; + + dbversion = query_findversion(client, client->query.gluedb); + if (dbversion == NULL) + goto regular; + +#ifdef ALLOW_FILTER_AAAA + if (client->filter_aaaa == dns_aaaa_filter || + client->filter_aaaa == dns_aaaa_break_dnssec) + { + options |= DNS_RDATASETADDGLUE_FILTERAAAA; + } +#endif + + result = dns_rdataset_addglue(rdataset, dbversion->version, + options, client->message); + if (result == ISC_R_SUCCESS) + return; + } + +regular: /* * Add additional data. * * We don't care if dns_rdataset_additionaldata() fails. */ - additionalctx.client = client; - additionalctx.rdataset = rdataset; - (void)dns_rdataset_additionaldata(rdataset, query_addadditional2, - &additionalctx); + (void)dns_rdataset_additionaldata(rdataset, query_addadditional, + client); CTRACE(ISC_LOG_DEBUG(3), "query_addrdataset: done"); } @@ -9894,8 +9391,7 @@ ns_query_start(ns_client_t *client) { break; } - if (client->view->cachedb == NULL || !client->view->additionalfromcache) - { + if (client->view->cachedb == NULL || !client->view->recursion) { /* * We don't have a cache. Turn off cache support and * recursion. diff --git a/bin/named/server.c b/bin/named/server.c index d9f779a3d1..e7cebcdcc3 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -52,7 +52,6 @@ #include -#include #include #include #include @@ -1279,12 +1278,14 @@ configure_order(dns_order_t *order, const cfg_obj_t *ent) { #if DNS_RDATASET_FIXED mode = DNS_RDATASETATTR_FIXEDORDER; #else - mode = 0; + mode = DNS_RDATASETATTR_CYCLIC; #endif /* DNS_RDATASET_FIXED */ else if (!strcasecmp(str, "random")) mode = DNS_RDATASETATTR_RANDOMIZE; else if (!strcasecmp(str, "cyclic")) - mode = 0; + mode = DNS_RDATASETATTR_CYCLIC; + else if (!strcasecmp(str, "none")) + mode = DNS_RDATASETATTR_NONE; else INSIST(0); @@ -2517,8 +2518,6 @@ configure_catz_zone(dns_view_t *view, const cfg_obj_t *config, RUNTIME_CHECK(tresult == ISC_R_SUCCESS); dns_zone_setview(dnszone, view); - if (view->acache != NULL) - dns_zone_setacache(dnszone, view->acache); dns_view_addzone(view, dnszone); } @@ -3310,7 +3309,6 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, unsigned int cleaning_interval; size_t max_cache_size; isc_uint32_t max_cache_size_percent = 0; - size_t max_acache_size; size_t max_adb_size; isc_uint32_t lame_ttl, fail_ttl; dns_tsig_keyring_t *ring = NULL; @@ -3377,53 +3375,6 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, CHECKM(ns_config_getport(config, &port), "port"); dns_view_setdstport(view, port); - /* - * Create additional cache for this view and zones under the view - * if explicitly enabled. - * XXX950 default to on. - */ - obj = NULL; - (void)ns_config_get(maps, "acache-enable", &obj); - if (obj != NULL && cfg_obj_asboolean(obj)) { - cmctx = NULL; - CHECK(isc_mem_create(0, 0, &cmctx)); - CHECK(dns_acache_create(&view->acache, cmctx, ns_g_taskmgr, - ns_g_timermgr)); - isc_mem_setname(cmctx, "acache", NULL); - isc_mem_detach(&cmctx); - } - if (view->acache != NULL) { - obj = NULL; - result = ns_config_get(maps, "acache-cleaning-interval", &obj); - INSIST(result == ISC_R_SUCCESS); - dns_acache_setcleaninginterval(view->acache, - cfg_obj_asuint32(obj) * 60); - - obj = NULL; - result = ns_config_get(maps, "max-acache-size", &obj); - INSIST(result == ISC_R_SUCCESS); - if (cfg_obj_isstring(obj)) { - str = cfg_obj_asstring(obj); - INSIST(strcasecmp(str, "unlimited") == 0); - max_acache_size = 0; - } else { - isc_resourcevalue_t value; - value = cfg_obj_asuint64(obj); - if (value > SIZE_MAX) { - cfg_obj_log(obj, ns_g_lctx, - ISC_LOG_WARNING, - "'max-acache-size " - "%" ISC_PRINT_QUADFORMAT "u' " - "is too large for this " - "system; reducing to %lu", - value, (unsigned long)SIZE_MAX); - value = SIZE_MAX; - } - max_acache_size = (size_t) value; - } - dns_acache_setcachesize(view->acache, max_acache_size); - } - CHECK(configure_view_acl(vconfig, config, "allow-query", NULL, actx, ns_g_mctx, &view->queryacl)); if (view->queryacl == NULL) { @@ -4305,32 +4256,6 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, INSIST(result == ISC_R_SUCCESS); view->trust_anchor_telemetry = cfg_obj_asboolean(obj); - /* - * Set sources where additional data and CNAME/DNAME - * targets for authoritative answers may be found. - */ - obj = NULL; - result = ns_config_get(maps, "additional-from-auth", &obj); - INSIST(result == ISC_R_SUCCESS); - view->additionalfromauth = cfg_obj_asboolean(obj); - if (view->recursion && ! view->additionalfromauth) { - cfg_obj_log(obj, ns_g_lctx, ISC_LOG_WARNING, - "'additional-from-auth no' is only supported " - "with 'recursion no'"); - view->additionalfromauth = ISC_TRUE; - } - - obj = NULL; - result = ns_config_get(maps, "additional-from-cache", &obj); - INSIST(result == ISC_R_SUCCESS); - view->additionalfromcache = cfg_obj_asboolean(obj); - if (view->recursion && ! view->additionalfromcache) { - cfg_obj_log(obj, ns_g_lctx, ISC_LOG_WARNING, - "'additional-from-cache no' is only supported " - "with 'recursion no'"); - view->additionalfromcache = ISC_TRUE; - } - /* * Set "allow-query-cache", "allow-query-cache-on", * "allow-recursion", and "allow-recursion-on" acls if @@ -5600,8 +5525,6 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, * new view. */ dns_zone_setview(zone, view); - if (view->acache != NULL) - dns_zone_setacache(zone, view->acache); } else { /* * We cannot reuse an existing zone, we have @@ -5610,8 +5533,6 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, CHECK(dns_zonemgr_createzone(ns_g_server->zonemgr, &zone)); CHECK(dns_zone_setorigin(zone, origin)); dns_zone_setview(zone, view); - if (view->acache != NULL) - dns_zone_setacache(zone, view->acache); CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone)); dns_zone_setstats(zone, ns_g_server->zonestats); } @@ -5670,8 +5591,6 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, CHECK(dns_zone_create(&raw, mctx)); CHECK(dns_zone_setorigin(raw, origin)); dns_zone_setview(raw, view); - if (view->acache != NULL) - dns_zone_setacache(raw, view->acache); dns_zone_setstats(raw, ns_g_server->zonestats); CHECK(dns_zone_link(zone, raw)); } @@ -5768,9 +5687,6 @@ add_keydata_zone(dns_view_t *view, const char *directory, isc_mem_t *mctx) { CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone)); - if (view->acache != NULL) - dns_zone_setacache(zone, view->acache); - CHECK(dns_acl_none(mctx, &none)); dns_zone_setqueryacl(zone, none); dns_zone_setqueryonacl(zone, none); diff --git a/bin/tests/system/additional/ns1/named1.conf b/bin/tests/system/additional/ns1/named1.conf index 4defa26fc5..526896fdef 100644 --- a/bin/tests/system/additional/ns1/named1.conf +++ b/bin/tests/system/additional/ns1/named1.conf @@ -13,7 +13,6 @@ options { notify-source 10.53.0.1; transfer-source 10.53.0.1; recursion no; - additional-from-auth no; port 5300; pid-file "named.pid"; listen-on { 10.53.0.1; }; diff --git a/bin/tests/system/additional/ns1/named2.conf b/bin/tests/system/additional/ns1/named2.conf index c509807b84..d24d05f736 100644 --- a/bin/tests/system/additional/ns1/named2.conf +++ b/bin/tests/system/additional/ns1/named2.conf @@ -13,7 +13,6 @@ options { notify-source 10.53.0.1; transfer-source 10.53.0.1; recursion no; - additional-from-auth no; port 5300; pid-file "named.pid"; listen-on { 10.53.0.1; }; diff --git a/bin/tests/system/additional/ns1/named3.conf b/bin/tests/system/additional/ns1/named3.conf index 43b3bcaab1..b18a7e016e 100644 --- a/bin/tests/system/additional/ns1/named3.conf +++ b/bin/tests/system/additional/ns1/named3.conf @@ -11,7 +11,6 @@ options { notify-source 10.53.0.1; transfer-source 10.53.0.1; recursion no; - additional-from-auth no; port 5300; pid-file "named.pid"; listen-on { 10.53.0.1; }; diff --git a/bin/tests/system/additional/ns1/named4.conf b/bin/tests/system/additional/ns1/named4.conf index 234225c57c..1c98d82bf2 100644 --- a/bin/tests/system/additional/ns1/named4.conf +++ b/bin/tests/system/additional/ns1/named4.conf @@ -11,7 +11,6 @@ options { notify-source 10.53.0.1; transfer-source 10.53.0.1; recursion no; - additional-from-auth no; port 5300; pid-file "named.pid"; listen-on { 10.53.0.1; }; diff --git a/bin/tests/system/autosign/clean.sh b/bin/tests/system/autosign/clean.sh index 45d7c4115f..c3c7183d12 100644 --- a/bin/tests/system/autosign/clean.sh +++ b/bin/tests/system/autosign/clean.sh @@ -6,7 +6,8 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -rm -f */K* */dsset-* */*.signed */trusted.conf */tmp* */*.jnl */*.bk +rm -f */K* */dsset-* */*.signed */tmp* */*.jnl */*.bk +rm -f */trusted.conf */private.conf rm -f */core rm -f */example.bk rm -f */named.memstats diff --git a/bin/tests/system/autosign/ns2/keygen.sh b/bin/tests/system/autosign/ns2/keygen.sh index 5acb99a315..8a7617a772 100644 --- a/bin/tests/system/autosign/ns2/keygen.sh +++ b/bin/tests/system/autosign/ns2/keygen.sh @@ -31,9 +31,19 @@ $DSFROMKEY $kskname.key > dsset-${zone}$TP zone=private.secure.example zonefile="${zone}.db" infile="${zonefile}.in" -cp $infile $zonefile -$KEYGEN -3 -q -r $RANDFILE -fk $zone > /dev/null +ksk=`$KEYGEN -3 -q -r $RANDFILE -fk $zone` $KEYGEN -3 -q -r $RANDFILE $zone > /dev/null +cat $ksk.key | grep -v '^; ' | $PERL -n -e ' +local ($dn, $class, $type, $flags, $proto, $alg, @rest) = split; +local $key = join("", @rest); +print < private.conf +cp private.conf ../ns4/private.conf +$SIGNER -S -3 beef -A -o $zone -f $zonefile $infile > /dev/null 2>&1 # Extract saved keys for the revoke-to-duplicate-key test zone=bar diff --git a/bin/tests/system/autosign/ns4/named.conf b/bin/tests/system/autosign/ns4/named.conf index d4884ea42a..adde75600c 100644 --- a/bin/tests/system/autosign/ns4/named.conf +++ b/bin/tests/system/autosign/ns4/named.conf @@ -6,8 +6,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* $Id: named.conf,v 1.3 2009/11/30 23:48:02 tbox Exp $ */ - // NS4 controls { /* empty */ }; @@ -21,7 +19,6 @@ options { listen-on { 10.53.0.4; }; listen-on-v6 { none; }; recursion yes; - acache-enable yes; dnssec-enable yes; dnssec-validation yes; dnssec-must-be-secure mustbesecure.example yes; @@ -33,3 +30,4 @@ zone "." { }; include "trusted.conf"; +include "private.conf"; diff --git a/bin/tests/system/autosign/ns5/named.conf b/bin/tests/system/autosign/ns5/named.conf index 0655efe3c1..5e342475fb 100644 --- a/bin/tests/system/autosign/ns5/named.conf +++ b/bin/tests/system/autosign/ns5/named.conf @@ -21,7 +21,6 @@ options { listen-on { 10.53.0.5; }; listen-on-v6 { none; }; recursion yes; - acache-enable yes; dnssec-enable yes; dnssec-validation yes; }; diff --git a/bin/tests/system/autosign/tests.sh b/bin/tests/system/autosign/tests.sh index e22523d1e4..df13fdd8a0 100644 --- a/bin/tests/system/autosign/tests.sh +++ b/bin/tests/system/autosign/tests.sh @@ -692,8 +692,7 @@ $DIG $DIGOPTS +noauth a.private.secure.example. a @10.53.0.4 \ > dig.out.ns4.test$n || ret=1 $PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1 -# Note - this is looking for failure, hence the && -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1 n=`expr $n + 1` if [ $ret != 0 ]; then echo "I:failed"; fi status=`expr $status + $ret` @@ -714,13 +713,9 @@ status=`expr $status + $ret` echo "I:checking privately secure to nxdomain works ($n)" ret=0 -$DIG $DIGOPTS +noauth private2secure-nxdomain.private.secure.example. SOA @10.53.0.2 \ - > dig.out.ns2.test$n || ret=1 -$DIG $DIGOPTS +noauth private2secure-nxdomain.private.secure.example. SOA @10.53.0.4 \ - > dig.out.ns4.test$n || ret=1 -$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 -# Note - this is looking for failure, hence the && -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1 +$DIG $DIGOPTS +noauth private2secure-nxdomain.private.secure.example. SOA @10.53.0.4 > dig.out.ns4.test$n || ret=1 +grep "NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1 n=`expr $n + 1` if [ $ret != 0 ]; then echo "I:failed"; fi status=`expr $status + $ret` diff --git a/bin/tests/system/cacheclean/ns1/named.conf b/bin/tests/system/cacheclean/ns1/named.conf index c14cf10908..d8721f3306 100644 --- a/bin/tests/system/cacheclean/ns1/named.conf +++ b/bin/tests/system/cacheclean/ns1/named.conf @@ -6,8 +6,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* $Id: named.conf,v 1.11 2011/08/02 23:47:52 tbox Exp $ */ - controls { /* empty */ }; options { @@ -21,6 +19,7 @@ options { recursion no; notify yes; check-integrity no; + minimal-responses no; }; zone "." { diff --git a/bin/tests/system/case/ns1/named.conf b/bin/tests/system/case/ns1/named.conf index c6c2c781b0..4828e85e35 100644 --- a/bin/tests/system/case/ns1/named.conf +++ b/bin/tests/system/case/ns1/named.conf @@ -20,6 +20,7 @@ options { notify yes; ixfr-from-differences yes; check-integrity no; + minimal-responses no; }; zone "example" { diff --git a/bin/tests/system/case/ns2/named.conf b/bin/tests/system/case/ns2/named.conf index c00fff8c40..6c64816786 100644 --- a/bin/tests/system/case/ns2/named.conf +++ b/bin/tests/system/case/ns2/named.conf @@ -21,6 +21,7 @@ options { ixfr-from-differences yes; check-integrity no; no-case-compress { 10.53.0.2; }; + minimal-responses no; }; zone "example" { diff --git a/bin/tests/system/checknames/ns2/named.conf b/bin/tests/system/checknames/ns2/named.conf index ab31b71b9a..d4c82b93ad 100644 --- a/bin/tests/system/checknames/ns2/named.conf +++ b/bin/tests/system/checknames/ns2/named.conf @@ -19,7 +19,6 @@ options { listen-on { 10.53.0.2; }; listen-on-v6 { none; }; recursion yes; - acache-enable yes; check-names response warn; notify yes; }; diff --git a/bin/tests/system/checknames/ns3/named.conf b/bin/tests/system/checknames/ns3/named.conf index 952d3640c5..03f98410c8 100644 --- a/bin/tests/system/checknames/ns3/named.conf +++ b/bin/tests/system/checknames/ns3/named.conf @@ -19,7 +19,6 @@ options { listen-on { 10.53.0.3; }; listen-on-v6 { none; }; recursion yes; - acache-enable yes; check-names response fail; notify yes; }; diff --git a/bin/tests/system/checknames/ns4/named.conf b/bin/tests/system/checknames/ns4/named.conf index 96505936e2..b89e383f13 100644 --- a/bin/tests/system/checknames/ns4/named.conf +++ b/bin/tests/system/checknames/ns4/named.conf @@ -19,7 +19,6 @@ options { listen-on { 10.53.0.4; }; listen-on-v6 { none; }; recursion yes; - acache-enable yes; check-names master ignore; notify yes; }; diff --git a/bin/tests/system/cookie/ns1/named.conf b/bin/tests/system/cookie/ns1/named.conf index e667155710..c80634dd57 100644 --- a/bin/tests/system/cookie/ns1/named.conf +++ b/bin/tests/system/cookie/ns1/named.conf @@ -24,7 +24,6 @@ options { listen-on { 10.53.0.1; }; listen-on-v6 { none; }; recursion yes; - acache-enable yes; deny-answer-addresses { 192.0.2.0/24; 2001:db8:beef::/48; } except-from { "example.org"; }; deny-answer-aliases { "example.org"; } diff --git a/bin/tests/system/cookie/ns2/named.conf b/bin/tests/system/cookie/ns2/named.conf index 58fe79655b..c734c1d734 100644 --- a/bin/tests/system/cookie/ns2/named.conf +++ b/bin/tests/system/cookie/ns2/named.conf @@ -17,7 +17,6 @@ options { listen-on { 10.53.0.2; }; listen-on-v6 { none; }; recursion no; - acache-enable yes; send-cookie yes; nocookie-udp-size 512; }; diff --git a/bin/tests/system/cookie/ns3/named.conf b/bin/tests/system/cookie/ns3/named.conf index 220dd3e4b6..904130ae94 100644 --- a/bin/tests/system/cookie/ns3/named.conf +++ b/bin/tests/system/cookie/ns3/named.conf @@ -24,7 +24,6 @@ options { listen-on { 10.53.0.3; }; listen-on-v6 { none; }; recursion yes; - acache-enable yes; deny-answer-addresses { 192.0.2.0/24; 2001:db8:beef::/48; } except-from { "example.org"; }; deny-answer-aliases { "example.org"; } diff --git a/bin/tests/system/digdelv/ns3/named.conf b/bin/tests/system/digdelv/ns3/named.conf index fcd2abc6dd..8f20f222de 100644 --- a/bin/tests/system/digdelv/ns3/named.conf +++ b/bin/tests/system/digdelv/ns3/named.conf @@ -15,7 +15,6 @@ options { listen-on { 10.53.0.3; }; listen-on-v6 { fd92:7065:b8e:ffff::3; }; recursion yes; - acache-enable yes; dnssec-enable no; dnssec-validation no; server-id "ns3"; diff --git a/bin/tests/system/dlv/ns5/named.conf b/bin/tests/system/dlv/ns5/named.conf index 49b192f3bc..261f29d758 100644 --- a/bin/tests/system/dlv/ns5/named.conf +++ b/bin/tests/system/dlv/ns5/named.conf @@ -49,7 +49,6 @@ options { listen-on { 10.53.0.5; }; listen-on-v6 { none; }; recursion yes; - acache-enable yes; notify yes; dnssec-enable yes; dnssec-validation yes; diff --git a/bin/tests/system/dnssec/ns2/named.conf b/bin/tests/system/dnssec/ns2/named.conf index fa13a4d70c..ca3ce877b5 100644 --- a/bin/tests/system/dnssec/ns2/named.conf +++ b/bin/tests/system/dnssec/ns2/named.conf @@ -6,8 +6,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* $Id: named.conf,v 1.36 2011/03/21 23:47:21 tbox Exp $ */ - // NS2 controls { /* empty */ }; @@ -25,6 +23,7 @@ options { dnssec-enable yes; dnssec-validation yes; notify-delay 1; + minimal-responses no; }; zone "." { diff --git a/bin/tests/system/dnssec/ns3/named.conf b/bin/tests/system/dnssec/ns3/named.conf index 5eb6913200..4ed21a5638 100644 --- a/bin/tests/system/dnssec/ns3/named.conf +++ b/bin/tests/system/dnssec/ns3/named.conf @@ -6,8 +6,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* $Id: named.conf,v 1.49 2011/10/28 06:20:05 each Exp $ */ - // NS3 controls { /* empty */ }; @@ -25,6 +23,7 @@ options { dnssec-enable yes; dnssec-validation yes; session-keyfile "session.key"; + minimal-responses no; }; key rndc_key { diff --git a/bin/tests/system/dnssec/ns4/named1.conf b/bin/tests/system/dnssec/ns4/named1.conf index b350389b6b..755db47085 100644 --- a/bin/tests/system/dnssec/ns4/named1.conf +++ b/bin/tests/system/dnssec/ns4/named1.conf @@ -6,8 +6,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* $Id: named1.conf,v 1.3 2011/01/04 23:47:13 tbox Exp $ */ - // NS4 controls { /* empty */ }; @@ -21,10 +19,10 @@ options { listen-on { 10.53.0.4; }; listen-on-v6 { none; }; recursion yes; - acache-enable yes; dnssec-enable yes; dnssec-validation yes; dnssec-must-be-secure mustbesecure.example yes; + minimal-responses no; nta-lifetime 10s; nta-recheck 7s; diff --git a/bin/tests/system/dnssec/ns4/named2.conf b/bin/tests/system/dnssec/ns4/named2.conf index 511a243c86..6fa51f6acb 100644 --- a/bin/tests/system/dnssec/ns4/named2.conf +++ b/bin/tests/system/dnssec/ns4/named2.conf @@ -6,8 +6,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* $Id: named2.conf,v 1.3 2011/01/04 23:47:13 tbox Exp $ */ - // NS4 controls { /* empty */ }; @@ -22,10 +20,10 @@ options { listen-on { 10.53.0.4; }; listen-on-v6 { none; }; recursion yes; - acache-enable yes; dnssec-enable yes; dnssec-validation auto; bindkeys-file "managed.conf"; + minimal-responses no; }; key rndc_key { diff --git a/bin/tests/system/dnssec/ns4/named3.conf b/bin/tests/system/dnssec/ns4/named3.conf index 57648ae966..b54465f192 100644 --- a/bin/tests/system/dnssec/ns4/named3.conf +++ b/bin/tests/system/dnssec/ns4/named3.conf @@ -6,8 +6,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* $Id: named2.conf,v 1.3 2011/01/04 23:47:13 tbox Exp $ */ - // NS4 controls { /* empty */ }; @@ -21,11 +19,11 @@ options { listen-on { 10.53.0.4; }; listen-on-v6 { none; }; recursion yes; - acache-enable yes; dnssec-enable yes; dnssec-validation auto; bindkeys-file "managed.conf"; dnssec-accept-expired yes; + minimal-responses no; }; key rndc_key { diff --git a/bin/tests/system/dnssec/ns4/named4.conf b/bin/tests/system/dnssec/ns4/named4.conf index 98f52f49d1..d63f37676e 100644 --- a/bin/tests/system/dnssec/ns4/named4.conf +++ b/bin/tests/system/dnssec/ns4/named4.conf @@ -38,4 +38,48 @@ controls { zone "." { type hint; file "../../common/root.hint"; +} + +key auth { + secret "1234abcd8765"; + algorithm hmac-sha256; +}; + +include "trusted.conf"; + +view rec { + match-recursive-only yes; + recursion yes; + dnssec-validation yes; + dnssec-accept-expired yes; + + zone "." { + type hint; + file "../../common/root.hint"; + }; + + zone secure.example { + type static-stub; + server-addresses { 10.53.0.4; }; + }; + + zone insecure.secure.example { + type static-stub; + server-addresses { 10.53.0.4; }; + }; +}; + +view auth { + recursion no; + allow-recursion { none; }; + + zone secure.example { + type slave; + masters { 10.53.0.3; }; + }; + + zone insecure.secure.example { + type slave; + masters { 10.53.0.2; }; + }; }; diff --git a/bin/tests/system/dnssec/ns5/named1.conf b/bin/tests/system/dnssec/ns5/named1.conf index 9d03236a86..4bac1daa25 100644 --- a/bin/tests/system/dnssec/ns5/named1.conf +++ b/bin/tests/system/dnssec/ns5/named1.conf @@ -19,7 +19,6 @@ options { listen-on { 10.53.0.5; }; listen-on-v6 { none; }; recursion yes; - acache-enable yes; dnssec-enable yes; dnssec-validation yes; }; diff --git a/bin/tests/system/dnssec/ns6/named.conf b/bin/tests/system/dnssec/ns6/named.conf index 1153abc90c..b071e80e31 100644 --- a/bin/tests/system/dnssec/ns6/named.conf +++ b/bin/tests/system/dnssec/ns6/named.conf @@ -21,7 +21,6 @@ options { listen-on { 10.53.0.6; }; listen-on-v6 { none; }; recursion yes; - acache-enable yes; notify yes; disable-algorithms . { DSA; }; dnssec-enable yes; diff --git a/bin/tests/system/dnssec/tests.sh b/bin/tests/system/dnssec/tests.sh index 9f6d6703be..f365a91b24 100644 --- a/bin/tests/system/dnssec/tests.sh +++ b/bin/tests/system/dnssec/tests.sh @@ -1187,11 +1187,9 @@ status=`expr $status + $ret` echo "I:checking privately secure to nxdomain works ($n)" ret=0 -$DIG $DIGOPTS +noauth private2secure-nxdomain.private.secure.example. SOA @10.53.0.2 \ - > dig.out.ns2.test$n || ret=1 $DIG $DIGOPTS +noauth private2secure-nxdomain.private.secure.example. SOA @10.53.0.4 \ > dig.out.ns4.test$n || ret=1 -$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 +grep "NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1 # Note - this is looking for failure, hence the && grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1 n=`expr $n + 1` @@ -1200,11 +1198,9 @@ status=`expr $status + $ret` echo "I:checking privately secure wildcard to nxdomain works ($n)" ret=0 -$DIG $DIGOPTS +noauth a.wild.private.secure.example. SOA @10.53.0.2 \ - > dig.out.ns2.test$n || ret=1 $DIG $DIGOPTS +noauth a.wild.private.secure.example. SOA @10.53.0.4 \ > dig.out.ns4.test$n || ret=1 -$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 +grep "NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1 # Note - this is looking for failure, hence the && grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1 n=`expr $n + 1` diff --git a/bin/tests/system/emptyzones/ns1/named1.conf b/bin/tests/system/emptyzones/ns1/named1.conf index a409356e65..088bfd73c7 100644 --- a/bin/tests/system/emptyzones/ns1/named1.conf +++ b/bin/tests/system/emptyzones/ns1/named1.conf @@ -26,7 +26,6 @@ options { listen-on { 10.53.0.1; }; listen-on-v6 { none; }; recursion yes; - acache-enable yes; deny-answer-addresses { 192.0.2.0/24; 2001:db8:beef::/48; } except-from { "example.org"; }; deny-answer-aliases { "example.org"; } diff --git a/bin/tests/system/emptyzones/ns1/named2.conf b/bin/tests/system/emptyzones/ns1/named2.conf index 9989a68020..109eba2f7b 100644 --- a/bin/tests/system/emptyzones/ns1/named2.conf +++ b/bin/tests/system/emptyzones/ns1/named2.conf @@ -26,7 +26,6 @@ options { listen-on { 10.53.0.1; }; listen-on-v6 { none; }; recursion yes; - acache-enable yes; deny-answer-addresses { 192.0.2.0/24; 2001:db8:beef::/48; } except-from { "example.org"; }; deny-answer-aliases { "example.org"; } diff --git a/bin/tests/system/filter-aaaa/ns1/named1.conf b/bin/tests/system/filter-aaaa/ns1/named1.conf index 2d2c2fe87e..4c6f8f9825 100644 --- a/bin/tests/system/filter-aaaa/ns1/named1.conf +++ b/bin/tests/system/filter-aaaa/ns1/named1.conf @@ -22,6 +22,7 @@ options { notify yes; filter-aaaa-on-v4 yes; filter-aaaa { 10.53.0.1; }; + minimal-responses no; }; key rndc_key { diff --git a/bin/tests/system/filter-aaaa/ns1/named2.conf b/bin/tests/system/filter-aaaa/ns1/named2.conf index 6feb6c3dd4..a97a41265a 100644 --- a/bin/tests/system/filter-aaaa/ns1/named2.conf +++ b/bin/tests/system/filter-aaaa/ns1/named2.conf @@ -22,6 +22,7 @@ options { notify yes; filter-aaaa-on-v6 yes; filter-aaaa { fd92:7065:b8e:ffff::1; }; + minimal-responses no; }; key rndc_key { diff --git a/bin/tests/system/filter-aaaa/ns1/root.db b/bin/tests/system/filter-aaaa/ns1/root.db index 6610f2743f..654e8fc72f 100644 --- a/bin/tests/system/filter-aaaa/ns1/root.db +++ b/bin/tests/system/filter-aaaa/ns1/root.db @@ -4,13 +4,17 @@ ; License, v. 2.0. If a copy of the MPL was not distributed with this ; file, You can obtain one at http://mozilla.org/MPL/2.0/. -; $Id: root.db,v 1.4 2012/01/31 23:47:32 tbox Exp $ - $TTL 120 @ SOA ns.utld hostmaster.ns.utld ( 1 3600 1200 604800 60 ) @ NS ns.utld ns.utld A 10.53.0.1 ns.utld AAAA fd92:7065:b8e:ffff::1 ; -signed NS ns.utld -unsigned NS ns.utld + +signed NS ns.signed +ns.signed A 10.53.0.1 +ns.signed AAAA fd92:7065:b8e:ffff::1 + +unsigned NS ns.unsigned +ns.unsigned A 10.53.0.1 +ns.unsigned AAAA fd92:7065:b8e:ffff::1 diff --git a/bin/tests/system/filter-aaaa/ns1/signed.db.in b/bin/tests/system/filter-aaaa/ns1/signed.db.in index 19ca8144b6..48ced0c20e 100644 --- a/bin/tests/system/filter-aaaa/ns1/signed.db.in +++ b/bin/tests/system/filter-aaaa/ns1/signed.db.in @@ -4,12 +4,14 @@ ; License, v. 2.0. If a copy of the MPL was not distributed with this ; file, You can obtain one at http://mozilla.org/MPL/2.0/. -; $Id: signed.db.in,v 1.4 2012/01/31 23:47:32 tbox Exp $ - $TTL 120 -@ SOA ns.utld. hostmaster.ns.utld. ( 1 3600 1200 604800 60 ) -@ NS ns.utld. +@ SOA ns.signed. hostmaster.ns.signed. ( 1 3600 1200 604800 60 ) +@ NS ns @ MX 10 mx + +ns A 10.53.0.1 + AAAA fd92:7065:b8e:ffff::1 + a-only NS 1.0.0.1 aaaa-only AAAA 2001:db8::2 dual A 1.0.0.3 diff --git a/bin/tests/system/filter-aaaa/ns1/unsigned.db b/bin/tests/system/filter-aaaa/ns1/unsigned.db index 69816a86b7..b2ffea9c83 100644 --- a/bin/tests/system/filter-aaaa/ns1/unsigned.db +++ b/bin/tests/system/filter-aaaa/ns1/unsigned.db @@ -4,12 +4,14 @@ ; License, v. 2.0. If a copy of the MPL was not distributed with this ; file, You can obtain one at http://mozilla.org/MPL/2.0/. -; $Id: unsigned.db,v 1.4 2012/01/31 23:47:32 tbox Exp $ - $TTL 120 -@ SOA ns.utld. hostmaster.ns.utld. ( 1 3600 1200 604800 60 ) -@ NS ns.utld. +@ SOA ns.unsigned. hostmaster.ns.unsigned. ( 1 3600 1200 604800 60 ) +@ NS ns @ MX 10 mx + +ns A 10.53.0.1 + AAAA fd92:7065:b8e:ffff::1 + a-only NS 1.0.0.4 aaaa-only AAAA 2001:db8::5 dual A 1.0.0.6 diff --git a/bin/tests/system/filter-aaaa/ns2/named1.conf b/bin/tests/system/filter-aaaa/ns2/named1.conf index 96355eba11..44c9afb106 100644 --- a/bin/tests/system/filter-aaaa/ns2/named1.conf +++ b/bin/tests/system/filter-aaaa/ns2/named1.conf @@ -22,6 +22,7 @@ options { notify yes; filter-aaaa-on-v4 yes; filter-aaaa { 10.53.0.2; }; + minimal-responses no; }; key rndc_key { diff --git a/bin/tests/system/filter-aaaa/ns2/named2.conf b/bin/tests/system/filter-aaaa/ns2/named2.conf index be0c566cca..bd4880e165 100644 --- a/bin/tests/system/filter-aaaa/ns2/named2.conf +++ b/bin/tests/system/filter-aaaa/ns2/named2.conf @@ -22,6 +22,7 @@ options { notify yes; filter-aaaa-on-v6 yes; filter-aaaa { fd92:7065:b8e:ffff::2; }; + minimal-responses no; }; key rndc_key { diff --git a/bin/tests/system/filter-aaaa/ns3/named1.conf b/bin/tests/system/filter-aaaa/ns3/named1.conf index 5b451187e6..7f76f0ddc4 100644 --- a/bin/tests/system/filter-aaaa/ns3/named1.conf +++ b/bin/tests/system/filter-aaaa/ns3/named1.conf @@ -22,6 +22,7 @@ options { notify yes; filter-aaaa-on-v4 break-dnssec; filter-aaaa { 10.53.0.3; }; + minimal-responses no; }; key rndc_key { diff --git a/bin/tests/system/filter-aaaa/ns3/named2.conf b/bin/tests/system/filter-aaaa/ns3/named2.conf index 4284fb3600..239b6768f0 100644 --- a/bin/tests/system/filter-aaaa/ns3/named2.conf +++ b/bin/tests/system/filter-aaaa/ns3/named2.conf @@ -22,6 +22,7 @@ options { notify yes; filter-aaaa-on-v6 break-dnssec; filter-aaaa { fd92:7065:b8e:ffff::3; }; + minimal-responses no; }; key rndc_key { diff --git a/bin/tests/system/filter-aaaa/ns4/named1.conf b/bin/tests/system/filter-aaaa/ns4/named1.conf index 6666f04f03..2b4cb8b550 100644 --- a/bin/tests/system/filter-aaaa/ns4/named1.conf +++ b/bin/tests/system/filter-aaaa/ns4/named1.conf @@ -22,6 +22,7 @@ options { notify yes; filter-aaaa-on-v4 break-dnssec; filter-aaaa { 10.53.0.4; }; + minimal-responses no; }; key rndc_key { diff --git a/bin/tests/system/filter-aaaa/ns4/named2.conf b/bin/tests/system/filter-aaaa/ns4/named2.conf index c85ba5a5ac..5abefc0b9d 100644 --- a/bin/tests/system/filter-aaaa/ns4/named2.conf +++ b/bin/tests/system/filter-aaaa/ns4/named2.conf @@ -22,6 +22,7 @@ options { notify yes; filter-aaaa-on-v6 break-dnssec; filter-aaaa { fd92:7065:b8e:ffff::4; }; + minimal-responses no; }; key rndc_key { diff --git a/bin/tests/system/filter-aaaa/ns4/root.db b/bin/tests/system/filter-aaaa/ns4/root.db index 6610f2743f..ba2a5d55c6 100644 --- a/bin/tests/system/filter-aaaa/ns4/root.db +++ b/bin/tests/system/filter-aaaa/ns4/root.db @@ -5,12 +5,16 @@ ; file, You can obtain one at http://mozilla.org/MPL/2.0/. ; $Id: root.db,v 1.4 2012/01/31 23:47:32 tbox Exp $ - -$TTL 120 @ SOA ns.utld hostmaster.ns.utld ( 1 3600 1200 604800 60 ) @ NS ns.utld -ns.utld A 10.53.0.1 -ns.utld AAAA fd92:7065:b8e:ffff::1 +ns.utld A 10.53.0.4 +ns.utld AAAA fd92:7065:b8e:ffff::4 ; -signed NS ns.utld -unsigned NS ns.utld + +signed NS ns.signed +ns.signed A 10.53.0.4 +ns.signed AAAA fd92:7065:b8e:ffff::4 + +unsigned NS ns.unsigned +ns.unsigned A 10.53.0.4 +ns.unsigned AAAA fd92:7065:b8e:ffff::4 diff --git a/bin/tests/system/filter-aaaa/ns4/signed.db.in b/bin/tests/system/filter-aaaa/ns4/signed.db.in index 19ca8144b6..c17b82849f 100644 --- a/bin/tests/system/filter-aaaa/ns4/signed.db.in +++ b/bin/tests/system/filter-aaaa/ns4/signed.db.in @@ -4,12 +4,14 @@ ; License, v. 2.0. If a copy of the MPL was not distributed with this ; file, You can obtain one at http://mozilla.org/MPL/2.0/. -; $Id: signed.db.in,v 1.4 2012/01/31 23:47:32 tbox Exp $ - $TTL 120 -@ SOA ns.utld. hostmaster.ns.utld. ( 1 3600 1200 604800 60 ) -@ NS ns.utld. +@ SOA ns.signed. hostmaster.ns.signed. ( 1 3600 1200 604800 60 ) +@ NS ns @ MX 10 mx + +ns A 10.53.0.4 + AAAA fd92:7065:b8e:ffff::4 + a-only NS 1.0.0.1 aaaa-only AAAA 2001:db8::2 dual A 1.0.0.3 diff --git a/bin/tests/system/filter-aaaa/ns4/unsigned.db b/bin/tests/system/filter-aaaa/ns4/unsigned.db index 69816a86b7..8c660bb53a 100644 --- a/bin/tests/system/filter-aaaa/ns4/unsigned.db +++ b/bin/tests/system/filter-aaaa/ns4/unsigned.db @@ -4,12 +4,14 @@ ; License, v. 2.0. If a copy of the MPL was not distributed with this ; file, You can obtain one at http://mozilla.org/MPL/2.0/. -; $Id: unsigned.db,v 1.4 2012/01/31 23:47:32 tbox Exp $ - $TTL 120 -@ SOA ns.utld. hostmaster.ns.utld. ( 1 3600 1200 604800 60 ) -@ NS ns.utld. +@ SOA ns.unsigned. hostmaster.ns.unsigned. ( 1 3600 1200 604800 60 ) +@ NS ns @ MX 10 mx + +ns A 10.53.0.4 + AAAA fd92:7065:b8e:ffff::4 + a-only NS 1.0.0.4 aaaa-only AAAA 2001:db8::5 dual A 1.0.0.6 diff --git a/bin/tests/system/glue/ns1/root.db b/bin/tests/system/glue/ns1/root.db index b90b43d2d1..5353d3131d 100644 --- a/bin/tests/system/glue/ns1/root.db +++ b/bin/tests/system/glue/ns1/root.db @@ -55,13 +55,3 @@ NISC.JVNC.NET. 172800 IN A 128.121.50.7 NS.EU.NET. 172800 IN A 192.16.202.11 SPARKY.ARL.MIL. 172800 IN A 128.63.58.18 SUNIC.SUNET.SE. 172800 IN A 192.36.125.2 - -; -; A hypothetical ccTLD where we are authoritative for the NS glue. -; -xx. 172800 IN NS b.root-servers.nil. - -; -; A hypothetical ccTLD where we have cached NS glue. -; -yy. 172800 IN NS ns.zz. diff --git a/bin/tests/system/glue/tests.sh b/bin/tests/system/glue/tests.sh index 1d357867f3..98a41b22b3 100644 --- a/bin/tests/system/glue/tests.sh +++ b/bin/tests/system/glue/tests.sh @@ -21,14 +21,6 @@ echo "I:testing that a ccTLD referral gets a full glue set from the root zone" $DIG +norec @10.53.0.1 -p 5300 foo.bar.fi. A >dig.out || status=1 $PERL ../digcomp.pl --lc fi.good dig.out || status=1 -echo "I:testing that we find glue A RRs we are authoritative for" -$DIG +norec @10.53.0.1 -p 5300 foo.bar.xx. a >dig.out || status=1 -$PERL ../digcomp.pl xx.good dig.out || status=1 - -echo "I:testing that we find glue A/AAAA RRs in the cache" -$DIG +norec @10.53.0.1 -p 5300 foo.bar.yy. a >dig.out || status=1 -$PERL ../digcomp.pl yy.good dig.out || status=1 - echo "I:testing that we don't find out-of-zone glue" $DIG +norec @10.53.0.1 -p 5300 example.net. a > dig.out || status=1 $PERL ../digcomp.pl noglue.good dig.out || status=1 diff --git a/bin/tests/system/limits/ns1/named.conf b/bin/tests/system/limits/ns1/named.conf index 2c62c84dc2..7fb72a8fb5 100644 --- a/bin/tests/system/limits/ns1/named.conf +++ b/bin/tests/system/limits/ns1/named.conf @@ -6,8 +6,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* $Id: named.conf,v 1.14 2007/06/19 23:47:03 tbox Exp $ */ - controls { /* empty */ }; options { @@ -20,6 +18,7 @@ options { listen-on-v6 { none; }; recursion no; notify yes; + minimal-responses no; }; zone "." { diff --git a/bin/tests/system/notify/ns3/named.conf b/bin/tests/system/notify/ns3/named.conf index abb5e390f1..3a8ad09d23 100644 --- a/bin/tests/system/notify/ns3/named.conf +++ b/bin/tests/system/notify/ns3/named.conf @@ -19,7 +19,6 @@ options { listen-on { 10.53.0.3; }; listen-on-v6 { none; }; recursion yes; - acache-enable yes; notify yes; }; diff --git a/bin/tests/system/notify/ns4/named.conf b/bin/tests/system/notify/ns4/named.conf index f279a65ce1..fe7d6f94e2 100644 --- a/bin/tests/system/notify/ns4/named.conf +++ b/bin/tests/system/notify/ns4/named.conf @@ -19,7 +19,6 @@ options { listen-on { 10.53.0.4; }; listen-on-v6 { none; }; recursion yes; - acache-enable yes; notify yes; }; diff --git a/bin/tests/system/notify/ns5/named.conf b/bin/tests/system/notify/ns5/named.conf index 24232903ba..989e709b06 100644 --- a/bin/tests/system/notify/ns5/named.conf +++ b/bin/tests/system/notify/ns5/named.conf @@ -34,7 +34,6 @@ options { listen-on { 10.53.0.5; }; listen-on-v6 { none; }; recursion yes; - acache-enable yes; notify yes; }; diff --git a/bin/tests/system/nsupdate/ns1/named.conf b/bin/tests/system/nsupdate/ns1/named.conf index 350792837e..78d1cbfb66 100644 --- a/bin/tests/system/nsupdate/ns1/named.conf +++ b/bin/tests/system/nsupdate/ns1/named.conf @@ -6,8 +6,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* $Id: named.conf,v 1.22 2011/07/01 02:25:47 marka Exp $ */ - controls { /* empty */ }; options { @@ -21,6 +19,7 @@ options { listen-on-v6 { none; }; recursion no; notify yes; + minimal-responses no; }; key rndc_key { diff --git a/bin/tests/system/nsupdate/ns2/named.conf b/bin/tests/system/nsupdate/ns2/named.conf index a14af0e2d9..4a6ea2c28f 100644 --- a/bin/tests/system/nsupdate/ns2/named.conf +++ b/bin/tests/system/nsupdate/ns2/named.conf @@ -19,7 +19,6 @@ options { listen-on { 10.53.0.2; }; listen-on-v6 { none; }; recursion yes; - acache-enable yes; notify yes; }; diff --git a/bin/tests/system/resolver/ns1/named.conf b/bin/tests/system/resolver/ns1/named.conf index d775c365ae..2b370d1bfc 100644 --- a/bin/tests/system/resolver/ns1/named.conf +++ b/bin/tests/system/resolver/ns1/named.conf @@ -19,7 +19,6 @@ options { listen-on { 10.53.0.1; }; listen-on-v6 { none; }; recursion yes; - acache-enable yes; deny-answer-addresses { 192.0.2.0/24; 2001:db8:beef::/48; } except-from { "example.org"; }; deny-answer-aliases { "example.org"; } diff --git a/bin/tests/system/rpz/ns1/named.conf b/bin/tests/system/rpz/ns1/named.conf index d0aeb83512..d64d150c27 100644 --- a/bin/tests/system/rpz/ns1/named.conf +++ b/bin/tests/system/rpz/ns1/named.conf @@ -6,8 +6,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* $Id$ */ - controls { /* empty */ }; @@ -21,6 +19,7 @@ options { listen-on { 10.53.0.1; }; listen-on-v6 { none; }; notify no; + minimal-responses no; }; zone "." {type master; file "root.db";}; diff --git a/bin/tests/system/rpz/ns2/named.conf b/bin/tests/system/rpz/ns2/named.conf index bbb6a0d6e4..7c4dab4c0a 100644 --- a/bin/tests/system/rpz/ns2/named.conf +++ b/bin/tests/system/rpz/ns2/named.conf @@ -6,9 +6,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* $Id$ */ - - controls { /* empty */ }; @@ -22,6 +19,7 @@ options { listen-on { 10.53.0.2; }; listen-on-v6 { none; }; notify no; + minimal-responses no; }; key rndc_key { diff --git a/bin/tests/system/rpz/ns3/named.conf b/bin/tests/system/rpz/ns3/named.conf index d935845ee9..5bb696b7c1 100644 --- a/bin/tests/system/rpz/ns3/named.conf +++ b/bin/tests/system/rpz/ns3/named.conf @@ -6,9 +6,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* $Id$ */ - - /* * Main rpz test DNS server. @@ -25,6 +22,7 @@ options { listen-on { 10.53.0.3; }; listen-on-v6 { none; }; notify no; + minimal-responses no; response-policy { zone "bl" max-policy-ttl 100; diff --git a/bin/tests/system/rpz/ns4/named.conf b/bin/tests/system/rpz/ns4/named.conf index 097e34f2a5..61cbf01d75 100644 --- a/bin/tests/system/rpz/ns4/named.conf +++ b/bin/tests/system/rpz/ns4/named.conf @@ -6,8 +6,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* $Id$ */ - controls { /* empty */ }; @@ -21,6 +19,7 @@ options { listen-on { 10.53.0.4; }; listen-on-v6 { none; }; notify no; + minimal-responses no; }; include "../trusted.conf"; diff --git a/bin/tests/system/rpz/ns5/named.conf b/bin/tests/system/rpz/ns5/named.conf index 80aaa5713f..1535f29bfb 100644 --- a/bin/tests/system/rpz/ns5/named.conf +++ b/bin/tests/system/rpz/ns5/named.conf @@ -6,9 +6,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* $Id$ */ - - /* * Test rpz performance. @@ -27,6 +24,7 @@ options { ixfr-from-differences yes; notify-delay 1; notify yes; + minimal-responses no; # turn rpz on or off include "rpz-switch"; diff --git a/bin/tests/system/rpz/ns6/named.conf b/bin/tests/system/rpz/ns6/named.conf index 30d7638c35..e7015e7f1f 100644 --- a/bin/tests/system/rpz/ns6/named.conf +++ b/bin/tests/system/rpz/ns6/named.conf @@ -18,6 +18,7 @@ options { listen-on-v6 { none; }; forward only; forwarders { 10.53.0.3; }; + minimal-responses no; response-policy { zone "policy1" min-update-interval 0; }; }; diff --git a/bin/tests/system/rpz/ns7/named.conf b/bin/tests/system/rpz/ns7/named.conf index df84a1f939..54627736b8 100644 --- a/bin/tests/system/rpz/ns7/named.conf +++ b/bin/tests/system/rpz/ns7/named.conf @@ -16,6 +16,7 @@ options { session-keyfile "session.key"; listen-on { 10.53.0.7; }; listen-on-v6 { none; }; + minimal-responses no; response-policy { zone "policy2"; } qname-wait-recurse no diff --git a/bin/tests/system/rrl/broken.conf b/bin/tests/system/rrl/broken.conf index 648f788ec5..a5b3b2c6ae 100644 --- a/bin/tests/system/rrl/broken.conf +++ b/bin/tests/system/rrl/broken.conf @@ -30,8 +30,6 @@ options { min-table-size 0; max-table-size 0; }; - - additional-from-cache no; }; key rndc_key { diff --git a/bin/tests/system/rrl/ns2/named.conf b/bin/tests/system/rrl/ns2/named.conf index 0ef65f5052..292bae5000 100644 --- a/bin/tests/system/rrl/ns2/named.conf +++ b/bin/tests/system/rrl/ns2/named.conf @@ -30,8 +30,6 @@ options { // small enough to force a table expansion min-table-size 75; }; - - additional-from-cache no; }; key rndc_key { diff --git a/bin/tests/system/rrl/ns4/named.conf b/bin/tests/system/rrl/ns4/named.conf index 0cd1258474..9f6a310a66 100644 --- a/bin/tests/system/rrl/ns4/named.conf +++ b/bin/tests/system/rrl/ns4/named.conf @@ -31,8 +31,6 @@ options { // small enough to force a table expansion min-table-size 75; }; - - additional-from-cache no; }; key rndc_key { diff --git a/bin/tests/system/rrsetorder/clean.sh b/bin/tests/system/rrsetorder/clean.sh index 9bc608afac..0fe762c2c7 100644 --- a/bin/tests/system/rrsetorder/clean.sh +++ b/bin/tests/system/rrsetorder/clean.sh @@ -6,10 +6,8 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -# $Id: clean.sh,v 1.10 2011/12/23 23:47:13 tbox Exp $ - rm -f dig.out.test* -rm -f dig.out.cyclic dig.out.fixed dig.out.random +rm -f dig.out.cyclic dig.out.fixed dig.out.random dig.out.nomatch rm -f dig.out.0 dig.out.1 dig.out.2 dig.out.3 rm -f dig.out.cyclic2 rm -f ns2/root.bk diff --git a/bin/tests/system/rrsetorder/ns1/root.db b/bin/tests/system/rrsetorder/ns1/root.db index 70ca5e3049..806ee2d4d5 100644 --- a/bin/tests/system/rrsetorder/ns1/root.db +++ b/bin/tests/system/rrsetorder/ns1/root.db @@ -36,3 +36,8 @@ cyclic2.example. A 1.2.3.4 cyclic2.example. A 1.2.3.3 cyclic2.example. A 1.2.3.2 cyclic2.example. A 1.2.3.1 +; +nomatch.example. A 1.2.3.1 +nomatch.example. A 1.2.3.2 +nomatch.example. A 1.2.3.3 +nomatch.example. A 1.2.3.4 diff --git a/bin/tests/system/rrsetorder/ns3/named.conf b/bin/tests/system/rrsetorder/ns3/named.conf index 268ec01824..4e4d16f118 100644 --- a/bin/tests/system/rrsetorder/ns3/named.conf +++ b/bin/tests/system/rrsetorder/ns3/named.conf @@ -19,7 +19,6 @@ options { listen-on { 10.53.0.3; }; listen-on-v6 { none; }; recursion yes; - acache-enable yes; notify yes; rrset-order { name "fixed.example" order fixed; diff --git a/bin/tests/system/rrsetorder/ns4/named.conf b/bin/tests/system/rrsetorder/ns4/named.conf index 9eca63d87d..1839c77f81 100644 --- a/bin/tests/system/rrsetorder/ns4/named.conf +++ b/bin/tests/system/rrsetorder/ns4/named.conf @@ -19,7 +19,6 @@ options { listen-on { 10.53.0.4; }; listen-on-v6 { none; }; recursion yes; - acache-enable yes; notify yes; rrset-order { class IN type A name "host.example.com" order random; diff --git a/bin/tests/system/rrsetorder/tests.sh b/bin/tests/system/rrsetorder/tests.sh index b2b5db3a8d..445764d57c 100644 --- a/bin/tests/system/rrsetorder/tests.sh +++ b/bin/tests/system/rrsetorder/tests.sh @@ -438,7 +438,7 @@ echo "I: Random selection return $match of 24 possible orders in 36 samples" if [ $match -lt 8 ]; then echo ret=1; fi if [ $ret != 0 ]; then echo "I:failed"; fi -echo "I: Checking default order no match in rrset-order (random)" +echo "I: Checking default order no match in rrset-order (no shuffling)" ret=0 for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 do @@ -447,11 +447,11 @@ done for i in a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 9 do $DIG +nosea +nocomm +nocmd +noquest +noadd +noauth +nocomm +nostat +short \ - -p 5300 @10.53.0.4 random.example > dig.out.random|| ret=1 + -p 5300 @10.53.0.4 nomatch.example > dig.out.nomatch|| ret=1 match=0 for j in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 do - eval "$DIFF dig.out.random dig.out.random.good$j >/dev/null && match$j=1 match=1" + eval "$DIFF dig.out.nomatch dig.out.random.good$j >/dev/null && match$j=1 match=1" if [ $match -eq 1 ]; then break; fi done if [ $match -eq 0 ]; then ret=1; fi @@ -461,8 +461,8 @@ for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 do eval "match=\`expr \$match + \$match$i\`" done -echo "I: Random selection return $match of 24 possible orders in 36 samples" -if [ $match -lt 8 ]; then echo ret=1; fi +echo "I: Consistent selection return $match of 24 possible orders in 36 samples" +if [ $match -ne 1 ]; then echo ret=1; fi if [ $ret != 0 ]; then echo "I:failed"; fi status=`expr $status + $ret` diff --git a/bin/tests/system/sfcache/ns5/named.conf b/bin/tests/system/sfcache/ns5/named.conf index eda50aecbf..ae1b997a36 100644 --- a/bin/tests/system/sfcache/ns5/named.conf +++ b/bin/tests/system/sfcache/ns5/named.conf @@ -19,7 +19,6 @@ options { listen-on { 10.53.0.5; }; listen-on-v6 { none; }; recursion yes; - acache-enable yes; dnssec-enable yes; dnssec-validation yes; servfail-ttl 30; diff --git a/bin/tests/system/statschannel/ns2/named.conf b/bin/tests/system/statschannel/ns2/named.conf index 1798f5fdce..ff7b2c221f 100644 --- a/bin/tests/system/statschannel/ns2/named.conf +++ b/bin/tests/system/statschannel/ns2/named.conf @@ -18,6 +18,7 @@ options { listen-on-v6 { none; }; recursion no; notify yes; + minimal-responses no; version none; // make statistics independent of the version number }; diff --git a/bin/tests/system/stress/ns3/named.conf b/bin/tests/system/stress/ns3/named.conf index afe85ac2c8..965eae48a2 100644 --- a/bin/tests/system/stress/ns3/named.conf +++ b/bin/tests/system/stress/ns3/named.conf @@ -19,7 +19,6 @@ options { listen-on { 10.53.0.3; }; listen-on-v6 { none; }; recursion yes; - acache-enable yes; notify yes; }; diff --git a/bin/tests/system/stress/ns4/named.conf b/bin/tests/system/stress/ns4/named.conf index 72540ab558..c88bbff978 100644 --- a/bin/tests/system/stress/ns4/named.conf +++ b/bin/tests/system/stress/ns4/named.conf @@ -19,7 +19,6 @@ options { listen-on { 10.53.0.4; }; listen-on-v6 { none; }; recursion yes; - acache-enable yes; notify yes; }; diff --git a/bin/tests/system/stub/ns1/named.conf b/bin/tests/system/stub/ns1/named.conf index 7b70dd6955..da7e82c466 100644 --- a/bin/tests/system/stub/ns1/named.conf +++ b/bin/tests/system/stub/ns1/named.conf @@ -6,8 +6,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* $Id: named.conf,v 1.14 2007/06/19 23:47:05 tbox Exp $ */ - controls { /* empty */ }; options { @@ -20,6 +18,7 @@ options { listen-on-v6 { none; }; recursion no; notify yes; + minimal-responses no; }; zone "." { diff --git a/bin/tests/system/stub/ns2/named.conf b/bin/tests/system/stub/ns2/named.conf index 584f620d26..04d4a5113a 100644 --- a/bin/tests/system/stub/ns2/named.conf +++ b/bin/tests/system/stub/ns2/named.conf @@ -6,8 +6,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* $Id: named.conf,v 1.14 2007/06/19 23:47:05 tbox Exp $ */ - controls { /* empty */ }; options { @@ -20,6 +18,7 @@ options { listen-on-v6 { none; }; recursion no; notify yes; + minimal-responses no; }; zone "." { diff --git a/bin/tests/system/stub/ns3/named.conf b/bin/tests/system/stub/ns3/named.conf index 36711256e9..78ce6ab972 100644 --- a/bin/tests/system/stub/ns3/named.conf +++ b/bin/tests/system/stub/ns3/named.conf @@ -6,8 +6,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* $Id: named.conf,v 1.16 2007/06/18 23:47:31 tbox Exp $ */ - controls { /* empty */ }; options { @@ -19,8 +17,8 @@ options { listen-on { 10.53.0.3; }; listen-on-v6 { none; }; recursion yes; - acache-enable yes; notify yes; + minimal-responses no; }; zone "." { diff --git a/bin/tests/system/tkey/ns1/named.conf.in b/bin/tests/system/tkey/ns1/named.conf.in index 50c1de943e..2cec631d36 100644 --- a/bin/tests/system/tkey/ns1/named.conf.in +++ b/bin/tests/system/tkey/ns1/named.conf.in @@ -6,8 +6,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* $Id: named.conf.in,v 1.10 2011/11/03 23:46:26 tbox Exp $ */ - controls { /* empty */ }; options { diff --git a/bin/tests/system/tkey/tests.sh b/bin/tests/system/tkey/tests.sh index 04d179fe29..beca196d7e 100644 --- a/bin/tests/system/tkey/tests.sh +++ b/bin/tests/system/tkey/tests.sh @@ -6,8 +6,6 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -# $Id: tests.sh,v 1.11 2011/11/03 23:46:26 tbox Exp $ - SYSTEMTESTTOP=.. . $SYSTEMTESTTOP/conf.sh @@ -41,7 +39,7 @@ do echo "I:checking the new key" ret=0 - $DIG $DIGOPTS . ns -k $keyname > dig.out.1 || ret=1 + $DIG $DIGOPTS txt txt.example -k $keyname > dig.out.1 || ret=1 grep "status: NOERROR" dig.out.1 > /dev/null || ret=1 grep "TSIG.*hmac-md5.*NOERROR" dig.out.1 > /dev/null || ret=1 grep "Some TSIG could not be validated" dig.out.1 > /dev/null && ret=1 @@ -60,7 +58,7 @@ do echo "I:checking that new key has been deleted" ret=0 - $DIG $DIGOPTS . ns -k $keyname > dig.out.2 || ret=1 + $DIG $DIGOPTS txt txt.example -k $keyname > dig.out.2 || ret=1 grep "status: NOERROR" dig.out.2 > /dev/null && ret=1 grep "TSIG.*hmac-md5.*NOERROR" dig.out.2 > /dev/null && ret=1 grep "Some TSIG could not be validated" dig.out.2 > /dev/null || ret=1 diff --git a/bin/tests/system/upforwd/ns1/named.conf b/bin/tests/system/upforwd/ns1/named.conf index bc5f97d034..ed2f3038e7 100644 --- a/bin/tests/system/upforwd/ns1/named.conf +++ b/bin/tests/system/upforwd/ns1/named.conf @@ -24,7 +24,6 @@ options { listen-on { 10.53.0.1; }; listen-on-v6 { none; }; recursion yes; - acache-enable yes; notify yes; }; diff --git a/bin/tests/system/upforwd/ns2/named.conf b/bin/tests/system/upforwd/ns2/named.conf index 77ccb34390..c53c1e3e05 100644 --- a/bin/tests/system/upforwd/ns2/named.conf +++ b/bin/tests/system/upforwd/ns2/named.conf @@ -19,7 +19,6 @@ options { listen-on { 10.53.0.2; }; listen-on-v6 { none; }; recursion yes; - acache-enable yes; notify yes; }; diff --git a/bin/tests/system/upforwd/ns3/named.conf b/bin/tests/system/upforwd/ns3/named.conf index 7a0268ed32..297fe8b388 100644 --- a/bin/tests/system/upforwd/ns3/named.conf +++ b/bin/tests/system/upforwd/ns3/named.conf @@ -19,7 +19,6 @@ options { listen-on { 10.53.0.3; }; listen-on-v6 { none; }; recursion yes; - acache-enable yes; notify yes; }; diff --git a/bin/tests/system/v6synth/ns2/named.conf b/bin/tests/system/v6synth/ns2/named.conf index 7474de4219..b7d0506d5a 100644 --- a/bin/tests/system/v6synth/ns2/named.conf +++ b/bin/tests/system/v6synth/ns2/named.conf @@ -19,7 +19,6 @@ options { listen-on { 10.53.0.2; }; listen-on-v6 { none; }; recursion yes; - acache-enable yes; notify yes; }; diff --git a/bin/tests/system/v6synth/ns3/named.conf b/bin/tests/system/v6synth/ns3/named.conf index 088c8d7f42..3fbc58ae7a 100644 --- a/bin/tests/system/v6synth/ns3/named.conf +++ b/bin/tests/system/v6synth/ns3/named.conf @@ -19,7 +19,6 @@ options { listen-on { 10.53.0.3; }; listen-on-v6 { none; }; recursion yes; - acache-enable yes; notify yes; allow-v6-synthesis { any; }; }; diff --git a/bin/tests/system/xfer/ns3/named.conf b/bin/tests/system/xfer/ns3/named.conf index 1cb5bb8667..6e19f9e488 100644 --- a/bin/tests/system/xfer/ns3/named.conf +++ b/bin/tests/system/xfer/ns3/named.conf @@ -19,7 +19,6 @@ options { listen-on { 10.53.0.3; }; listen-on-v6 { none; }; recursion yes; - acache-enable yes; notify yes; }; diff --git a/bin/tests/system/zero/ns1/named.conf b/bin/tests/system/zero/ns1/named.conf index 254bbbbc3b..62cd0c44d9 100644 --- a/bin/tests/system/zero/ns1/named.conf +++ b/bin/tests/system/zero/ns1/named.conf @@ -19,7 +19,6 @@ options { listen-on { 10.53.0.1; }; listen-on-v6 { none; }; recursion no; - acache-enable yes; }; zone "." { diff --git a/bin/tests/system/zero/ns2/named.conf b/bin/tests/system/zero/ns2/named.conf index 41ff034ba5..13f9d27a14 100644 --- a/bin/tests/system/zero/ns2/named.conf +++ b/bin/tests/system/zero/ns2/named.conf @@ -19,7 +19,6 @@ options { listen-on { 10.53.0.2; }; listen-on-v6 { none; }; recursion no; - acache-enable yes; }; zone "example" { diff --git a/bin/tests/system/zero/ns3/named.conf b/bin/tests/system/zero/ns3/named.conf index 6ed386441f..698e953367 100644 --- a/bin/tests/system/zero/ns3/named.conf +++ b/bin/tests/system/zero/ns3/named.conf @@ -19,7 +19,6 @@ options { listen-on { 10.53.0.3; }; listen-on-v6 { none; }; recursion yes; - acache-enable yes; }; zone "." { diff --git a/bin/tests/system/zero/ns4/named.conf b/bin/tests/system/zero/ns4/named.conf index 9eac45891d..8d04d6ebe4 100644 --- a/bin/tests/system/zero/ns4/named.conf +++ b/bin/tests/system/zero/ns4/named.conf @@ -19,7 +19,6 @@ options { listen-on { 10.53.0.4; }; listen-on-v6 { none; }; recursion no; - acache-enable yes; }; zone "example" { diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml index 6d6fa2cf33..cf0bb519f9 100644 --- a/doc/arm/Bv9ARM-book.xml +++ b/doc/arm/Bv9ARM-book.xml @@ -578,11 +578,6 @@ option can be used to limit the amount of memory used by the cache, at the expense of reducing cache hit rates and causing more DNS traffic. - Additionally, if additional section caching - () is enabled, - the max-acache-size option can be used to - limit the amount - of memory used by the mechanism. It is still good practice to have enough memory to load all zone and cache data into memory — unfortunately, the best way @@ -4626,8 +4621,6 @@ badresp:1,adberr:0,findfail:0,valfail:0] [ nta-recheck duration ; ] [ port ip_port ; ] [ dscp ip_dscp ; ] - [ additional-from-auth yes_or_no ; ] - [ additional-from-cache yes_or_no ; ] [ random-device path_name ; ] [ max-cache-size size_or_percent ; ] [ match-mapped-addresses yes_or_no ; ] @@ -4653,9 +4646,6 @@ badresp:1,adberr:0,findfail:0,valfail:0] [ querylog yes_or_no ; ] [ disable-algorithms domain { algorithm ; ... } ; ] [ disable-ds-digests domain { digest_type ; ... } ; ] - [ acache-enable yes_or_no ; ] - [ acache-cleaning-interval number ; ] - [ max-acache-size size_spec ; ] [ max-recursion-depth number ; ] [ max-recursion-queries number ; ] [ masterfile-format ( | | ) ; ] @@ -6342,7 +6332,7 @@ options { both authoritative and recursive queries. - The default is no. + The default is yes. @@ -6733,94 +6723,6 @@ options { - - additional-from-auth - additional-from-cache - - - - These options control the behavior of an authoritative - server when - answering queries which have additional data, or when - following CNAME - and DNAME chains. - - - - When both of these options are set to yes - (the default) and a - query is being answered from authoritative data (a zone - configured into the server), the additional data section of - the - reply will be filled in using data from other authoritative - zones - and from the cache. In some situations this is undesirable, - such - as when there is concern over the correctness of the cache, - or - in servers where slave zones may be added and modified by - untrusted third parties. Also, avoiding - the search for this additional data will speed up server - operations - at the possible expense of additional queries to resolve - what would - otherwise be provided in the additional section. - - - - For example, if a query asks for an MX record for host foo.example.com, - and the record found is "MX 10 mail.example.net", normally the address - records (A and AAAA) for mail.example.net will be provided as well, - if known, even though they are not in the example.com zone. - Setting these options to no - disables this behavior and makes - the server only search for additional data in the zone it - answers from. - - - - These options are intended for use in authoritative-only - servers, or in authoritative-only views. Attempts to set - them to no without also - specifying - recursion no will cause the - server to - ignore the options and log a warning message. - - - - Specifying additional-from-cache no actually - disables the use of the cache not only for additional data - lookups - but also when looking up the answer. This is usually the - desired - behavior in an authoritative-only server where the - correctness of - the cached data is an issue. - - - - When a name server is non-recursively queried for a name - that is not - below the apex of any served zone, it normally answers with - an - "upwards referral" to the root servers or the servers of - some other - known parent of the query name. Since the data in an - upwards referral - comes from the cache, the server will not be able to provide - upwards - referrals when additional-from-cache no - has been specified. Instead, it will respond to such - queries - with REFUSED. This should not cause any problems since - upwards referrals are not required for the resolution - process. - - - - - match-mapped-addresses @@ -9055,7 +8957,7 @@ avoid-v6-udp-ports { 40000; range 50000 60000; }; The response to a DNS query may consist of multiple resource - records (RRs) forming a resource records set (RRset). + records (RRs) forming a resource record set (RRset). The name server will normally return the RRs within the RRset in an indeterminate order (but see the rrset-order @@ -9169,17 +9071,14 @@ avoid-v6-udp-ports { 40000; range 50000 60000; }; When multiple records are returned in an answer it may be useful to configure the order of the records placed into the - response. - The rrset-order statement permits - configuration - of the ordering of the records in a multiple record response. + response. The rrset-order statement permits + configuration of the ordering of the records in a + multiple-record response. See also the sortlist statement, . - - An order_spec is defined as - follows: + An order_spec is defined as follows: class class_name @@ -9207,7 +9106,10 @@ avoid-v6-udp-ports { 40000; range 50000 60000; }; Records are returned in the order they - are defined in the zone file. + are defined in the zone file. This option + is only available if BIND + is configured with "--enable-fixed-rrset" at + compile time. @@ -9227,29 +9129,45 @@ avoid-v6-udp-ports { 40000; range 50000 60000; }; - Records are returned in a cyclic round-robin order. + Records are returned in a cyclic round-robin order, + rotating by one record per query. - If BIND is configured with the - "--enable-fixed-rrset" option at compile time, then + If BIND is configured with + "--enable-fixed-rrset" at compile time, then the initial ordering of the RRset will match the - one specified in the zone file. + one specified in the zone file; otherwise the + initial ordering is indeterminate. + + + + + + none + + + + Records are returned in whatever order they were + retrieved from the database. This order is + indeterminate, but will be consistent as long as the + database is not modified. When no ordering is + specified, this is the default. + + For example: - rrset-order { class IN type A name "host.example.com" order random; order cyclic; }; - will cause any responses for type A records in class IN that have "host.example.com" as a @@ -9261,7 +9179,8 @@ avoid-v6-udp-ports { 40000; range 50000 60000; }; appear, they are not combined — the last one applies. - By default, all records are returned in random order. + By default, records are returned in indeterminate but + consistent order (see none above). @@ -10020,121 +9939,6 @@ avoid-v6-udp-ports { 40000; range 50000 60000; }; -
Additional Section Caching - - - - The additional section cache, also called acache, - is an internal cache to improve the response performance of BIND 9. - When additional section caching is enabled, BIND 9 will - cache an internal short-cut to the additional section content for - each answer RR. - Note that acache is an internal caching - mechanism of BIND 9, and is not related to the DNS caching - server function. - - - - Additional section caching does not change the - response content (except the RRsets ordering of the additional - section, see below), but can improve the response performance - significantly. - It is particularly effective when BIND 9 acts as an authoritative - server for a zone that has many delegations with many glue RRs. - - - - In order to obtain the maximum performance improvement - from additional section caching, setting - additional-from-cache - to no is recommended, since the current - implementation of acache - does not short-cut of additional section information from the - DNS cache data. - - - - One obvious disadvantage of acache is - that it requires much more - memory for the internal cached data. - Thus, if the response performance does not matter and memory - consumption is much more critical, the - acache mechanism can be - disabled by setting acache-enable to - no. - It is also possible to specify the upper limit of memory - consumption - for acache by using max-acache-size. - - - - Additional section caching also has a minor effect on the - RRset ordering in the additional section. - Without acache, - cyclic order is effective for the additional - section as well as the answer and authority sections. - However, additional section caching fixes the ordering when it - first caches an RRset for the additional section, and the same - ordering will be kept in succeeding responses, regardless of the - setting of rrset-order. - The effect of this should be minor, however, since an - RRset in the additional section - typically only contains a small number of RRs (and in many cases - it only contains a single RR), in which case the - ordering does not matter much. - - - - The following is a summary of options related to - acache. - - - - - - acache-enable - - - If yes, additional section caching is - enabled. The default value is no. - - - - - - acache-cleaning-interval - - - The server will remove stale cache entries, based on an LRU - based - algorithm, every acache-cleaning-interval minutes. - The default is 60 minutes. - If set to 0, no periodic cleaning will occur. - - - - - - max-acache-size - - - The maximum amount of memory in bytes to use for the server's acache. - When the amount of data in the acache reaches this limit, - the server - will clean more aggressively so that the limit is not - exceeded. - In a server with multiple views, the limit applies - separately to the - acache of each view. - The default is 16M. - - - - - - -
-
Content Filtering diff --git a/doc/misc/options b/doc/misc/options index a210730414..1111b09252 100644 --- a/doc/misc/options +++ b/doc/misc/options @@ -64,10 +64,10 @@ masters [ port ] [ dscp ] ) [ key ]; ... }; // may occur multiple times options { - acache-cleaning-interval ; - acache-enable ; - additional-from-auth ; - additional-from-cache ; + acache-cleaning-interval ; // obsolete + acache-enable ; // obsolete + additional-from-auth ; // obsolete + additional-from-cache ; // obsolete allow-new-zones ; allow-notify { ; ... }; allow-query { ; ... }; @@ -213,7 +213,7 @@ options { masterfile-format ( map | raw | text ); masterfile-style ( full | relative ); match-mapped-addresses ; - max-acache-size ( unlimited | ); + max-acache-size ( unlimited | ); // obsolete max-cache-size ( default | unlimited | | ); max-cache-ttl ; max-clients-per-query ; @@ -418,10 +418,10 @@ trusted-keys { ; ... }; // may occur multiple times view [ ] { - acache-cleaning-interval ; - acache-enable ; - additional-from-auth ; - additional-from-cache ; + acache-cleaning-interval ; // obsolete + acache-enable ; // obsolete + additional-from-auth ; // obsolete + additional-from-cache ; // obsolete allow-new-zones ; allow-notify { ; ... }; allow-query { ; ... }; @@ -535,7 +535,7 @@ view [ ] { match-clients { ; ... }; match-destinations { ; ... }; match-recursive-only ; - max-acache-size ( unlimited | ); + max-acache-size ( unlimited | ); // obsolete max-cache-size ( default | unlimited | | ); max-cache-ttl ; max-clients-per-query ; diff --git a/lib/bind9/check.c b/lib/bind9/check.c index ab5f6ae3d6..e691d4b07e 100644 --- a/lib/bind9/check.c +++ b/lib/bind9/check.c @@ -133,7 +133,8 @@ check_orderent(const cfg_obj_t *ent, isc_log_t *logctx) { "compilation time"); #endif } else if (strcasecmp(cfg_obj_asstring(obj), "random") != 0 && - strcasecmp(cfg_obj_asstring(obj), "cyclic") != 0) { + strcasecmp(cfg_obj_asstring(obj), "cyclic") != 0 && + strcasecmp(cfg_obj_asstring(obj), "none") != 0) { cfg_obj_log(obj, logctx, ISC_LOG_ERROR, "rrset-order: invalid order '%s'", cfg_obj_asstring(obj)); diff --git a/lib/dns/Makefile.in b/lib/dns/Makefile.in index 4346fb1faa..33bc87f279 100644 --- a/lib/dns/Makefile.in +++ b/lib/dns/Makefile.in @@ -55,7 +55,7 @@ GEOIPLINKOBJS = geoip.@O@ DNSTAPOBJS = dnstap.@O@ dnstap.pb-c.@O@ # Alphabetically -DNSOBJS = acache.@O@ acl.@O@ adb.@O@ badcache.@O@ byaddr.@O@ \ +DNSOBJS = acl.@O@ adb.@O@ badcache.@O@ byaddr.@O@ \ cache.@O@ callbacks.@O@ catz.@O@ clientinfo.@O@ compress.@O@ \ db.@O@ dbiterator.@O@ dbtable.@O@ diff.@O@ dispatch.@O@ \ dlz.@O@ dns64.@O@ dnssec.@O@ ds.@O@ dyndb.@O@ ecs.@O@ \ @@ -95,7 +95,7 @@ GEOIPLINKSRCS = geoip.c DNSTAPSRCS = dnstap.c dnstap.pb-c.c -DNSSRCS = acache.c acl.c adb.c badcache. byaddr.c \ +DNSSRCS = acl.c adb.c badcache. byaddr.c \ cache.c callbacks.c clientinfo.c compress.c \ db.c dbiterator.c dbtable.c diff.c dispatch.c \ dlz.c dns64.c dnssec.c ds.c dyndb.c ecs.c forward.c \ diff --git a/lib/dns/acache.c b/lib/dns/acache.c deleted file mode 100644 index 2fc18710c5..0000000000 --- a/lib/dns/acache.c +++ /dev/null @@ -1,1790 +0,0 @@ -/* - * Copyright (C) 2004-2008, 2012, 2013, 2015, 2016 Internet Systems Consortium, Inc. ("ISC") - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -/* $Id: acache.c,v 1.22 2008/02/07 23:46:54 tbox Exp $ */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define ACACHE_MAGIC ISC_MAGIC('A', 'C', 'H', 'E') -#define DNS_ACACHE_VALID(acache) ISC_MAGIC_VALID(acache, ACACHE_MAGIC) - -#define ACACHEENTRY_MAGIC ISC_MAGIC('A', 'C', 'E', 'T') -#define DNS_ACACHEENTRY_VALID(entry) ISC_MAGIC_VALID(entry, ACACHEENTRY_MAGIC) - -#define DBBUCKETS 67 - -#if 0 -#define ATRACE(m) isc_log_write(dns_lctx, \ - DNS_LOGCATEGORY_DATABASE, \ - DNS_LOGMODULE_ACACHE, \ - ISC_LOG_DEBUG(3), \ - "acache %p: %s", acache, (m)) -#define AATRACE(a,m) isc_log_write(dns_lctx, \ - DNS_LOGCATEGORY_DATABASE, \ - DNS_LOGMODULE_ACACHE, \ - ISC_LOG_DEBUG(3), \ - "acache %p: %s", (a), (m)) -#else -#define ATRACE(m) -#define AATRACE(a, m) -#endif - -/* - * The following variables control incremental cleaning. - * MINSIZE is how many bytes is the floor for dns_acache_setcachesize(). - * CLEANERINCREMENT is how many entries are examined in one pass. - * (XXX simply derived from definitions in cache.c There may be better - * constants here.) - */ -#define DNS_ACACHE_MINSIZE 2097152U /* Bytes. 2097152 = 2 MB */ -#define DNS_ACACHE_CLEANERINCREMENT 1000 /* Number of entries. */ - -#define DEFAULT_ACACHE_ENTRY_LOCK_COUNT 1009 /*%< Should be prime. */ - -#if defined(ISC_RWLOCK_USEATOMIC) && defined(ISC_PLATFORM_HAVEATOMICSTORE) -#define ACACHE_USE_RWLOCK 1 -#endif - -#ifdef ACACHE_USE_RWLOCK -#define ACACHE_INITLOCK(l) isc_rwlock_init((l), 0, 0) -#define ACACHE_DESTROYLOCK(l) isc_rwlock_destroy(l) -#define ACACHE_LOCK(l, t) RWLOCK((l), (t)) -#define ACACHE_UNLOCK(l, t) RWUNLOCK((l), (t)) - -#define acache_storetime(entry, t) \ - (isc_atomic_store((isc_int32_t *)&(entry)->lastused, (t))) -#else -#define ACACHE_INITLOCK(l) isc_mutex_init(l) -#define ACACHE_DESTROYLOCK(l) DESTROYLOCK(l) -#define ACACHE_LOCK(l, t) LOCK(l) -#define ACACHE_UNLOCK(l, t) UNLOCK(l) - -#define acache_storetime(entry, t) ((entry)->lastused = (t)) -#endif - -/* Locked by acache lock */ -typedef struct dbentry { - ISC_LINK(struct dbentry) link; - - dns_db_t *db; - ISC_LIST(dns_acacheentry_t) originlist; - ISC_LIST(dns_acacheentry_t) referlist; -} dbentry_t; - -typedef ISC_LIST(dbentry_t) dbentrylist_t; - -typedef struct acache_cleaner acache_cleaner_t; - -typedef enum { - cleaner_s_idle, /* Waiting for cleaning-interval to expire. */ - cleaner_s_busy, /* Currently cleaning. */ - cleaner_s_done /* Freed enough memory after being overmem. */ -} cleaner_state_t; - -/* - * Convenience macros for comprehensive assertion checking. - */ -#define CLEANER_IDLE(c) ((c)->state == cleaner_s_idle && \ - (c)->resched_event != NULL) -#define CLEANER_BUSY(c) ((c)->state == cleaner_s_busy && \ - (c)->resched_event == NULL) - -struct acache_cleaner { - isc_mutex_t lock; - /* - * Locks overmem_event, overmem. (See cache.c) - */ - - dns_acache_t *acache; - unsigned int cleaning_interval; /* The cleaning-interval - from named.conf, - in seconds. */ - - isc_stdtime_t last_cleanup_time; /* The time when the last - cleanup task completed */ - - isc_timer_t *cleaning_timer; - isc_event_t *resched_event; /* Sent by cleaner task to - itself to reschedule */ - isc_event_t *overmem_event; - - dns_acacheentry_t *current_entry; /* The bookmark entry to - restart the cleaning. - Locked by acache lock. */ - int increment; /* Number of entries to - clean in one increment */ - - unsigned long ncleaned; /* Number of entries cleaned - up (for logging purposes) */ - cleaner_state_t state; /* Idle/Busy/Done. */ - isc_boolean_t overmem; /* The acache is in an overmem - state. */ -}; - -struct dns_acachestats { - unsigned int hits; - unsigned int queries; - unsigned int misses; - unsigned int adds; - unsigned int deleted; - unsigned int cleaned; - unsigned int cleaner_runs; - unsigned int overmem; - unsigned int overmem_nocreates; - unsigned int nomem; -}; - -/* - * The actual acache object. - */ - -struct dns_acache { - unsigned int magic; - - isc_mem_t *mctx; - isc_refcount_t refs; - -#ifdef ACACHE_USE_RWLOCK - isc_rwlock_t *entrylocks; -#else - isc_mutex_t *entrylocks; -#endif - - isc_mutex_t lock; - - int live_cleaners; - acache_cleaner_t cleaner; - ISC_LIST(dns_acacheentry_t) entries; - unsigned int dbentries; - dbentrylist_t dbbucket[DBBUCKETS]; - - isc_boolean_t shutting_down; - - isc_task_t *task; - isc_event_t cevent; - isc_boolean_t cevent_sent; - - dns_acachestats_t stats; -}; - -struct dns_acacheentry { - unsigned int magic; - - unsigned int locknum; - isc_refcount_t references; - - dns_acache_t *acache; - - /* Data for Management of cache entries */ - ISC_LINK(dns_acacheentry_t) link; - ISC_LINK(dns_acacheentry_t) olink; - ISC_LINK(dns_acacheentry_t) rlink; - - dns_db_t *origdb; /* reference to the DB - holding this entry */ - - /* Cache data */ - dns_zone_t *zone; /* zone this entry - belongs to */ - dns_db_t *db; /* DB this entry belongs to */ - dns_dbversion_t *version; /* the version of the DB */ - dns_dbnode_t *node; /* node this entry - belongs to */ - dns_name_t *foundname; /* corresponding DNS name - and rdataset */ - - /* Callback function and its argument */ - void (*callback)(dns_acacheentry_t *, void **); - void *cbarg; - - /* Timestamp of the last time this entry is referred to */ - isc_stdtime32_t lastused; -}; - -/* - * Internal functions (and prototypes). - */ -static inline isc_boolean_t check_noentry(dns_acache_t *acache); -static void destroy(dns_acache_t *acache); -static void shutdown_entries(dns_acache_t *acache); -static void shutdown_buckets(dns_acache_t *acache); -static void destroy_entry(dns_acacheentry_t *ent); -static inline void unlink_dbentries(dns_acache_t *acache, - dns_acacheentry_t *ent); -static inline isc_result_t finddbent(dns_acache_t *acache, - dns_db_t *db, dbentry_t **dbentryp); -static inline void clear_entry(dns_acache_t *acache, dns_acacheentry_t *entry); -static isc_result_t acache_cleaner_init(dns_acache_t *acache, - isc_timermgr_t *timermgr, - acache_cleaner_t *cleaner); -static void acache_cleaning_timer_action(isc_task_t *task, isc_event_t *event); -static void acache_incremental_cleaning_action(isc_task_t *task, - isc_event_t *event); -static void acache_overmem_cleaning_action(isc_task_t *task, - isc_event_t *event); -static void acache_cleaner_shutdown_action(isc_task_t *task, - isc_event_t *event); - -/* - * acache should be locked. If it is not, the stats can get out of whack, - * which is not a big deal for us since this is for debugging / stats - */ -static void -reset_stats(dns_acache_t *acache) { - acache->stats.hits = 0; - acache->stats.queries = 0; - acache->stats.misses = 0; - acache->stats.adds = 0; - acache->stats.deleted = 0; - acache->stats.cleaned = 0; - acache->stats.overmem = 0; - acache->stats.overmem_nocreates = 0; - acache->stats.nomem = 0; -} - -/* - * The acache must be locked before calling. - */ -static inline isc_boolean_t -check_noentry(dns_acache_t *acache) { - if (ISC_LIST_EMPTY(acache->entries) && acache->dbentries == 0) { - return (ISC_TRUE); - } - - return (ISC_FALSE); -} - -/* - * The acache must be locked before calling. - */ -static void -shutdown_entries(dns_acache_t *acache) { - dns_acacheentry_t *entry, *entry_next; - - REQUIRE(DNS_ACACHE_VALID(acache)); - INSIST(acache->shutting_down); - - /* - * Release the dependency of all entries, and detach them. - */ - for (entry = ISC_LIST_HEAD(acache->entries); - entry != NULL; - entry = entry_next) { - entry_next = ISC_LIST_NEXT(entry, link); - - ACACHE_LOCK(&acache->entrylocks[entry->locknum], - isc_rwlocktype_write); - - /* - * If the cleaner holds this entry, it will be unlinked and - * freed in the cleaner later. - */ - if (acache->cleaner.current_entry != entry) - ISC_LIST_UNLINK(acache->entries, entry, link); - unlink_dbentries(acache, entry); - if (entry->callback != NULL) { - (entry->callback)(entry, &entry->cbarg); - entry->callback = NULL; - } - - ACACHE_UNLOCK(&acache->entrylocks[entry->locknum], - isc_rwlocktype_write); - - if (acache->cleaner.current_entry != entry) - dns_acache_detachentry(&entry); - } -} - -/* - * The acache must be locked before calling. - */ -static void -shutdown_buckets(dns_acache_t *acache) { - int i; - dbentry_t *dbent; - - REQUIRE(DNS_ACACHE_VALID(acache)); - INSIST(acache->shutting_down); - - for (i = 0; i < DBBUCKETS; i++) { - while ((dbent = ISC_LIST_HEAD(acache->dbbucket[i])) != NULL) { - INSIST(ISC_LIST_EMPTY(dbent->originlist) && - ISC_LIST_EMPTY(dbent->referlist)); - ISC_LIST_UNLINK(acache->dbbucket[i], dbent, link); - - dns_db_detach(&dbent->db); - - isc_mem_put(acache->mctx, dbent, sizeof(*dbent)); - - acache->dbentries--; - } - } - - INSIST(acache->dbentries == 0); -} - -static void -shutdown_task(isc_task_t *task, isc_event_t *ev) { - dns_acache_t *acache; - - UNUSED(task); - - acache = ev->ev_arg; - INSIST(DNS_ACACHE_VALID(acache)); - - isc_event_free(&ev); - - LOCK(&acache->lock); - - shutdown_entries(acache); - shutdown_buckets(acache); - - UNLOCK(&acache->lock); - - dns_acache_detach(&acache); -} - -/* The acache and the entry must be locked before calling. */ -static inline void -unlink_dbentries(dns_acache_t *acache, dns_acacheentry_t *ent) { - isc_result_t result; - dbentry_t *dbent; - - if (ISC_LINK_LINKED(ent, olink)) { - INSIST(ent->origdb != NULL); - dbent = NULL; - result = finddbent(acache, ent->origdb, &dbent); - INSIST(result == ISC_R_SUCCESS); - - ISC_LIST_UNLINK(dbent->originlist, ent, olink); - } - if (ISC_LINK_LINKED(ent, rlink)) { - INSIST(ent->db != NULL); - dbent = NULL; - result = finddbent(acache, ent->db, &dbent); - INSIST(result == ISC_R_SUCCESS); - - ISC_LIST_UNLINK(dbent->referlist, ent, rlink); - } -} - -/* There must not be a reference to this entry. */ -static void -destroy_entry(dns_acacheentry_t *entry) { - dns_acache_t *acache; - - REQUIRE(DNS_ACACHEENTRY_VALID(entry)); - - acache = entry->acache; - REQUIRE(DNS_ACACHE_VALID(acache)); - - /* - * Since there is no reference to this entry, it is safe to call - * clear_entry() here. - */ - clear_entry(acache, entry); - - isc_mem_put(acache->mctx, entry, sizeof(*entry)); - - dns_acache_detach(&acache); -} - -static void -destroy(dns_acache_t *acache) { - int i; - - REQUIRE(DNS_ACACHE_VALID(acache)); - - ATRACE("destroy"); - - isc_mem_setwater(acache->mctx, NULL, NULL, 0, 0); - - if (acache->cleaner.overmem_event != NULL) - isc_event_free(&acache->cleaner.overmem_event); - - if (acache->cleaner.resched_event != NULL) - isc_event_free(&acache->cleaner.resched_event); - - if (acache->task != NULL) - isc_task_detach(&acache->task); - - for (i = 0; i < DEFAULT_ACACHE_ENTRY_LOCK_COUNT; i++) - ACACHE_DESTROYLOCK(&acache->entrylocks[i]); - isc_mem_put(acache->mctx, acache->entrylocks, - sizeof(*acache->entrylocks) * - DEFAULT_ACACHE_ENTRY_LOCK_COUNT); - - DESTROYLOCK(&acache->cleaner.lock); - - DESTROYLOCK(&acache->lock); - acache->magic = 0; - - isc_mem_putanddetach(&acache->mctx, acache, sizeof(*acache)); -} - -static inline isc_result_t -finddbent(dns_acache_t *acache, dns_db_t *db, dbentry_t **dbentryp) { - int bucket; - dbentry_t *dbentry; - - REQUIRE(DNS_ACACHE_VALID(acache)); - REQUIRE(db != NULL); - REQUIRE(dbentryp != NULL && *dbentryp == NULL); - - /* - * The caller must be holding the acache lock. - */ - - bucket = isc_hash_function(&db, sizeof(db), ISC_TRUE, NULL) % DBBUCKETS; - - for (dbentry = ISC_LIST_HEAD(acache->dbbucket[bucket]); - dbentry != NULL; - dbentry = ISC_LIST_NEXT(dbentry, link)) { - if (dbentry->db == db) - break; - } - - *dbentryp = dbentry; - - if (dbentry == NULL) - return (ISC_R_NOTFOUND); - else - return (ISC_R_SUCCESS); -} - -static inline void -clear_entry(dns_acache_t *acache, dns_acacheentry_t *entry) { - REQUIRE(DNS_ACACHE_VALID(acache)); - REQUIRE(DNS_ACACHEENTRY_VALID(entry)); - - /* - * The caller must be holing the entry lock. - */ - - if (entry->foundname) { - dns_rdataset_t *rdataset, *rdataset_next; - - for (rdataset = ISC_LIST_HEAD(entry->foundname->list); - rdataset != NULL; - rdataset = rdataset_next) { - rdataset_next = ISC_LIST_NEXT(rdataset, link); - ISC_LIST_UNLINK(entry->foundname->list, - rdataset, link); - dns_rdataset_disassociate(rdataset); - isc_mem_put(acache->mctx, rdataset, sizeof(*rdataset)); - } - if (dns_name_dynamic(entry->foundname)) - dns_name_free(entry->foundname, acache->mctx); - isc_mem_put(acache->mctx, entry->foundname, - sizeof(*entry->foundname)); - entry->foundname = NULL; - } - - if (entry->node != NULL) { - INSIST(entry->db != NULL); - dns_db_detachnode(entry->db, &entry->node); - } - if (entry->version != NULL) { - INSIST(entry->db != NULL); - dns_db_closeversion(entry->db, &entry->version, ISC_FALSE); - } - if (entry->db != NULL) - dns_db_detach(&entry->db); - if (entry->zone != NULL) - dns_zone_detach(&entry->zone); - - if (entry->origdb != NULL) - dns_db_detach(&entry->origdb); -} - -static isc_result_t -acache_cleaner_init(dns_acache_t *acache, isc_timermgr_t *timermgr, - acache_cleaner_t *cleaner) -{ - int result; - - ATRACE("acache cleaner init"); - - result = isc_mutex_init(&cleaner->lock); - if (result != ISC_R_SUCCESS) - goto fail; - - cleaner->increment = DNS_ACACHE_CLEANERINCREMENT; - cleaner->state = cleaner_s_idle; - cleaner->acache = acache; - cleaner->overmem = ISC_FALSE; - - cleaner->cleaning_timer = NULL; - cleaner->resched_event = NULL; - cleaner->overmem_event = NULL; - cleaner->current_entry = NULL; - - if (timermgr != NULL) { - cleaner->acache->live_cleaners++; - - result = isc_task_onshutdown(acache->task, - acache_cleaner_shutdown_action, - acache); - if (result != ISC_R_SUCCESS) { - UNEXPECTED_ERROR(__FILE__, __LINE__, - "acache cleaner: " - "isc_task_onshutdown() failed: %s", - dns_result_totext(result)); - goto cleanup; - } - - cleaner->cleaning_interval = 0; /* Initially turned off. */ - isc_stdtime_get(&cleaner->last_cleanup_time); - result = isc_timer_create(timermgr, isc_timertype_inactive, - NULL, NULL, - acache->task, - acache_cleaning_timer_action, - cleaner, &cleaner->cleaning_timer); - if (result != ISC_R_SUCCESS) { - UNEXPECTED_ERROR(__FILE__, __LINE__, - "isc_timer_create() failed: %s", - dns_result_totext(result)); - result = ISC_R_UNEXPECTED; - goto cleanup; - } - - cleaner->resched_event = - isc_event_allocate(acache->mctx, cleaner, - DNS_EVENT_ACACHECLEAN, - acache_incremental_cleaning_action, - cleaner, sizeof(isc_event_t)); - if (cleaner->resched_event == NULL) { - result = ISC_R_NOMEMORY; - goto cleanup; - } - - cleaner->overmem_event = - isc_event_allocate(acache->mctx, cleaner, - DNS_EVENT_ACACHEOVERMEM, - acache_overmem_cleaning_action, - cleaner, sizeof(isc_event_t)); - if (cleaner->overmem_event == NULL) { - result = ISC_R_NOMEMORY; - goto cleanup; - } - } - - return (ISC_R_SUCCESS); - - cleanup: - if (cleaner->overmem_event != NULL) - isc_event_free(&cleaner->overmem_event); - if (cleaner->resched_event != NULL) - isc_event_free(&cleaner->resched_event); - if (cleaner->cleaning_timer != NULL) - isc_timer_detach(&cleaner->cleaning_timer); - cleaner->acache->live_cleaners--; - DESTROYLOCK(&cleaner->lock); - fail: - return (result); -} - -static void -begin_cleaning(acache_cleaner_t *cleaner) { - dns_acacheentry_t *head; - dns_acache_t *acache = cleaner->acache; - - /* - * This function does not have to lock the cleaner, since critical - * parameters (except current_entry, which is locked by acache lock,) - * are only used in a single task context. - */ - - REQUIRE(CLEANER_IDLE(cleaner)); - INSIST(DNS_ACACHE_VALID(acache)); - INSIST(cleaner->current_entry == NULL); - - isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, - DNS_LOGMODULE_ACACHE, ISC_LOG_DEBUG(1), - "begin acache cleaning, mem inuse %lu", - (unsigned long)isc_mem_inuse(cleaner->acache->mctx)); - - LOCK(&acache->lock); - - head = ISC_LIST_HEAD(acache->entries); - if (head != NULL) - dns_acache_attachentry(head, &cleaner->current_entry); - - UNLOCK(&acache->lock); - - if (cleaner->current_entry != NULL) { - cleaner->ncleaned = 0; - cleaner->state = cleaner_s_busy; - isc_task_send(acache->task, &cleaner->resched_event); - } - - return; -} - -static void -end_cleaning(acache_cleaner_t *cleaner, isc_event_t *event) { - dns_acache_t *acache = cleaner->acache; - - REQUIRE(CLEANER_BUSY(cleaner)); - REQUIRE(event != NULL); - REQUIRE(DNS_ACACHEENTRY_VALID(cleaner->current_entry)); - - /* No need to lock the cleaner (see begin_cleaning()). */ - - LOCK(&acache->lock); - - /* - * Even if the cleaner has the last reference to the entry, which means - * the entry has been unused, it may still be linked if unlinking the - * entry has been delayed due to the reference. - */ - if (isc_refcount_current(&cleaner->current_entry->references) == 1) { - INSIST(cleaner->current_entry->callback == NULL); - - if (ISC_LINK_LINKED(cleaner->current_entry, link)) { - ISC_LIST_UNLINK(acache->entries, - cleaner->current_entry, link); - } - } - dns_acache_detachentry(&cleaner->current_entry); - - if (cleaner->overmem) - acache->stats.overmem++; - acache->stats.cleaned += cleaner->ncleaned; - acache->stats.cleaner_runs++; - - isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_ACACHE, - ISC_LOG_NOTICE, - "acache %p stats: hits=%d misses=%d queries=%d " - "adds=%d deleted=%d " - "cleaned=%d cleaner_runs=%d overmem=%d " - "overmem_nocreates=%d nomem=%d", - acache, - acache->stats.hits, acache->stats.misses, - acache->stats.queries, - acache->stats.adds, acache->stats.deleted, - acache->stats.cleaned, acache->stats.cleaner_runs, - acache->stats.overmem, acache->stats.overmem_nocreates, - acache->stats.nomem); - reset_stats(acache); - - isc_stdtime_get(&cleaner->last_cleanup_time); - - UNLOCK(&acache->lock); - - dns_acache_setcleaninginterval(cleaner->acache, - cleaner->cleaning_interval); - - isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_ACACHE, - ISC_LOG_DEBUG(1), "end acache cleaning, " - "%lu entries cleaned, mem inuse %lu", - cleaner->ncleaned, - (unsigned long)isc_mem_inuse(cleaner->acache->mctx)); - - if (cleaner->overmem) { - isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, - DNS_LOGMODULE_ACACHE, ISC_LOG_NOTICE, - "acache is still in overmem state " - "after cleaning"); - } - - cleaner->ncleaned = 0; - cleaner->state = cleaner_s_idle; - cleaner->resched_event = event; -} - -/* - * This is run once for every acache-cleaning-interval as defined - * in named.conf. - */ -static void -acache_cleaning_timer_action(isc_task_t *task, isc_event_t *event) { - acache_cleaner_t *cleaner = event->ev_arg; - - UNUSED(task); - - INSIST(event->ev_type == ISC_TIMEREVENT_TICK); - - isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_ACACHE, - ISC_LOG_DEBUG(1), "acache cleaning timer fired, " - "cleaner state = %d", cleaner->state); - - if (cleaner->state == cleaner_s_idle) - begin_cleaning(cleaner); - - isc_event_free(&event); -} - -/* The caller must hold entry lock. */ -static inline isc_boolean_t -entry_stale(acache_cleaner_t *cleaner, dns_acacheentry_t *entry, - isc_stdtime32_t now32, unsigned int interval) -{ - /* - * If the callback has been canceled, we definitely do not need the - * entry. - */ - if (entry->callback == NULL) - return (ISC_TRUE); - - if (interval > cleaner->cleaning_interval) - interval = cleaner->cleaning_interval; - - if (entry->lastused + interval < now32) - return (ISC_TRUE); - - /* - * If the acache is in the overmem state, probabilistically decide if - * the entry should be purged, based on the time passed from its last - * use and the cleaning interval. - */ - if (cleaner->overmem) { - unsigned int passed; - isc_uint32_t val; - - if (isc_serial_ge(now32, entry->lastused)) - passed = now32 - entry->lastused; /* <= interval */ - else - passed = 0; - - if (passed > interval / 2) - return (ISC_TRUE); - isc_random_get(&val); - if (passed > interval / 4) - return (ISC_TF(val % 4 == 0)); - return (ISC_TF(val % 8 == 0)); - } - - return (ISC_FALSE); -} - -/* - * Do incremental cleaning. - */ -static void -acache_incremental_cleaning_action(isc_task_t *task, isc_event_t *event) { - acache_cleaner_t *cleaner = event->ev_arg; - dns_acache_t *acache = cleaner->acache; - dns_acacheentry_t *entry, *next = NULL; - int n_entries; - isc_stdtime32_t now32, last32; - isc_stdtime_t now; - unsigned int interval; - - INSIST(DNS_ACACHE_VALID(acache)); - INSIST(task == acache->task); - INSIST(event->ev_type == DNS_EVENT_ACACHECLEAN); - - if (cleaner->state == cleaner_s_done) { - cleaner->state = cleaner_s_busy; - end_cleaning(cleaner, event); - return; - } - - INSIST(CLEANER_BUSY(cleaner)); - - n_entries = cleaner->increment; - - isc_stdtime_get(&now); - isc_stdtime_convert32(now, &now32); - - LOCK(&acache->lock); - - entry = cleaner->current_entry; - isc_stdtime_convert32(cleaner->last_cleanup_time, &last32); - if (isc_serial_ge(now32, last32)) - interval = now32 - last32; - else - interval = 0; - - while (n_entries-- > 0) { - isc_boolean_t is_stale = ISC_FALSE; - - INSIST(entry != NULL); - - next = ISC_LIST_NEXT(entry, link); - - ACACHE_LOCK(&acache->entrylocks[entry->locknum], - isc_rwlocktype_write); - - is_stale = entry_stale(cleaner, entry, now32, interval); - if (is_stale) { - ISC_LIST_UNLINK(acache->entries, entry, link); - unlink_dbentries(acache, entry); - if (entry->callback != NULL) - (entry->callback)(entry, &entry->cbarg); - entry->callback = NULL; - - cleaner->ncleaned++; - } - - ACACHE_UNLOCK(&acache->entrylocks[entry->locknum], - isc_rwlocktype_write); - - if (is_stale) - dns_acache_detachentry(&entry); - - if (next == NULL) { - if (cleaner->overmem) { - entry = ISC_LIST_HEAD(acache->entries); - if (entry != NULL) { - /* - * If we are still in the overmem - * state, keep cleaning. In case we - * exit from the loop immediately after - * this, reset next to the head entry - * as we'll expect it will be never - * NULL. - */ - isc_log_write(dns_lctx, - DNS_LOGCATEGORY_DATABASE, - DNS_LOGMODULE_ACACHE, - ISC_LOG_DEBUG(1), - "acache cleaner: " - "still overmem, " - "reset and try again"); - next = entry; - continue; - } - } - - UNLOCK(&acache->lock); - end_cleaning(cleaner, event); - return; - } - - entry = next; - } - - /* - * We have successfully performed a cleaning increment but have - * not gone through the entire cache. Remember the entry that will - * be the starting point in the next clean-up, and reschedule another - * batch. If it fails, just try to continue anyway. - */ - INSIST(next != NULL); - dns_acache_detachentry(&cleaner->current_entry); - dns_acache_attachentry(next, &cleaner->current_entry); - - UNLOCK(&acache->lock); - - isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_ACACHE, - ISC_LOG_DEBUG(1), "acache cleaner: checked %d entries, " - "mem inuse %lu, sleeping", cleaner->increment, - (unsigned long)isc_mem_inuse(cleaner->acache->mctx)); - - isc_task_send(task, &event); - INSIST(CLEANER_BUSY(cleaner)); - - return; -} - -/* - * This is called when the acache either surpasses its upper limit - * or shrinks beyond its lower limit. - */ -static void -acache_overmem_cleaning_action(isc_task_t *task, isc_event_t *event) { - acache_cleaner_t *cleaner = event->ev_arg; - isc_boolean_t want_cleaning = ISC_FALSE; - - UNUSED(task); - - INSIST(event->ev_type == DNS_EVENT_ACACHEOVERMEM); - INSIST(cleaner->overmem_event == NULL); - - isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_ACACHE, - ISC_LOG_DEBUG(1), "overmem_cleaning_action called, " - "overmem = %d, state = %d", cleaner->overmem, - cleaner->state); - - LOCK(&cleaner->lock); - - if (cleaner->overmem) { - if (cleaner->state == cleaner_s_idle) - want_cleaning = ISC_TRUE; - } else { - if (cleaner->state == cleaner_s_busy) - /* - * end_cleaning() can't be called here because - * then both cleaner->overmem_event and - * cleaner->resched_event will point to this - * event. Set the state to done, and then - * when the acache_incremental_cleaning_action() event - * is posted, it will handle the end_cleaning. - */ - cleaner->state = cleaner_s_done; - } - - cleaner->overmem_event = event; - - UNLOCK(&cleaner->lock); - - if (want_cleaning) - begin_cleaning(cleaner); -} - -static void -water(void *arg, int mark) { - dns_acache_t *acache = arg; - isc_boolean_t overmem = ISC_TF(mark == ISC_MEM_HIWATER); - - REQUIRE(DNS_ACACHE_VALID(acache)); - - isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, - DNS_LOGMODULE_ACACHE, ISC_LOG_DEBUG(1), - "acache memory reaches %s watermark, mem inuse %lu", - overmem ? "high" : "low", - (unsigned long)isc_mem_inuse(acache->mctx)); - - LOCK(&acache->cleaner.lock); - - if (acache->cleaner.overmem != overmem) { - acache->cleaner.overmem = overmem; - - if (acache->cleaner.overmem_event != NULL) - isc_task_send(acache->task, - &acache->cleaner.overmem_event); - isc_mem_waterack(acache->mctx, mark); - } - - UNLOCK(&acache->cleaner.lock); -} - -/* - * The cleaner task is shutting down; do the necessary cleanup. - */ -static void -acache_cleaner_shutdown_action(isc_task_t *task, isc_event_t *event) { - dns_acache_t *acache = event->ev_arg; - isc_boolean_t should_free = ISC_FALSE; - - INSIST(task == acache->task); - INSIST(event->ev_type == ISC_TASKEVENT_SHUTDOWN); - INSIST(DNS_ACACHE_VALID(acache)); - - ATRACE("acache cleaner shutdown"); - - if (CLEANER_BUSY(&acache->cleaner)) - end_cleaning(&acache->cleaner, event); - else - isc_event_free(&event); - - LOCK(&acache->lock); - - acache->live_cleaners--; - INSIST(acache->live_cleaners == 0); - - if (isc_refcount_current(&acache->refs) == 0) { - INSIST(check_noentry(acache) == ISC_TRUE); - should_free = ISC_TRUE; - } - - /* - * By detaching the timer in the context of its task, - * we are guaranteed that there will be no further timer - * events. - */ - if (acache->cleaner.cleaning_timer != NULL) - isc_timer_detach(&acache->cleaner.cleaning_timer); - - /* Make sure we don't reschedule anymore. */ - (void)isc_task_purge(task, NULL, DNS_EVENT_ACACHECLEAN, NULL); - - UNLOCK(&acache->lock); - - if (should_free) - destroy(acache); -} - -/* - * Public functions. - */ - -isc_result_t -dns_acache_create(dns_acache_t **acachep, isc_mem_t *mctx, - isc_taskmgr_t *taskmgr, isc_timermgr_t *timermgr) -{ - int i; - isc_result_t result; - dns_acache_t *acache; - - REQUIRE(acachep != NULL && *acachep == NULL); - REQUIRE(mctx != NULL); - REQUIRE(taskmgr != NULL); - - acache = isc_mem_get(mctx, sizeof(*acache)); - if (acache == NULL) - return (ISC_R_NOMEMORY); - - ATRACE("create"); - - result = isc_refcount_init(&acache->refs, 1); - if (result != ISC_R_SUCCESS) { - isc_mem_put(mctx, acache, sizeof(*acache)); - return (result); - } - - result = isc_mutex_init(&acache->lock); - if (result != ISC_R_SUCCESS) { - isc_refcount_decrement(&acache->refs, NULL); - isc_refcount_destroy(&acache->refs); - isc_mem_put(mctx, acache, sizeof(*acache)); - return (result); - } - - acache->mctx = NULL; - isc_mem_attach(mctx, &acache->mctx); - ISC_LIST_INIT(acache->entries); - - acache->shutting_down = ISC_FALSE; - - acache->task = NULL; - acache->entrylocks = NULL; - - result = isc_task_create(taskmgr, 1, &acache->task); - if (result != ISC_R_SUCCESS) { - UNEXPECTED_ERROR(__FILE__, __LINE__, - "isc_task_create() failed(): %s", - dns_result_totext(result)); - result = ISC_R_UNEXPECTED; - goto cleanup; - } - isc_task_setname(acache->task, "acachetask", acache); - ISC_EVENT_INIT(&acache->cevent, sizeof(acache->cevent), 0, NULL, - DNS_EVENT_ACACHECONTROL, shutdown_task, NULL, - NULL, NULL, NULL); - acache->cevent_sent = ISC_FALSE; - - acache->dbentries = 0; - for (i = 0; i < DBBUCKETS; i++) - ISC_LIST_INIT(acache->dbbucket[i]); - - acache->entrylocks = isc_mem_get(mctx, sizeof(*acache->entrylocks) * - DEFAULT_ACACHE_ENTRY_LOCK_COUNT); - if (acache->entrylocks == NULL) { - result = ISC_R_NOMEMORY; - goto cleanup; - } - for (i = 0; i < DEFAULT_ACACHE_ENTRY_LOCK_COUNT; i++) { - result = ACACHE_INITLOCK(&acache->entrylocks[i]); - if (result != ISC_R_SUCCESS) { - while (i-- > 0) - ACACHE_DESTROYLOCK(&acache->entrylocks[i]); - isc_mem_put(mctx, acache->entrylocks, - sizeof(*acache->entrylocks) * - DEFAULT_ACACHE_ENTRY_LOCK_COUNT); - acache->entrylocks = NULL; - goto cleanup; - } - } - - acache->live_cleaners = 0; - result = acache_cleaner_init(acache, timermgr, &acache->cleaner); - if (result != ISC_R_SUCCESS) - goto cleanup; - - acache->stats.cleaner_runs = 0; - reset_stats(acache); - - acache->magic = ACACHE_MAGIC; - - *acachep = acache; - return (ISC_R_SUCCESS); - - cleanup: - if (acache->task != NULL) - isc_task_detach(&acache->task); - DESTROYLOCK(&acache->lock); - isc_refcount_decrement(&acache->refs, NULL); - isc_refcount_destroy(&acache->refs); - if (acache->entrylocks != NULL) { - for (i = 0; i < DEFAULT_ACACHE_ENTRY_LOCK_COUNT; i++) - ACACHE_DESTROYLOCK(&acache->entrylocks[i]); - isc_mem_put(mctx, acache->entrylocks, - sizeof(*acache->entrylocks) * - DEFAULT_ACACHE_ENTRY_LOCK_COUNT); - } - isc_mem_put(mctx, acache, sizeof(*acache)); - isc_mem_detach(&mctx); - - return (result); -} - -void -dns_acache_attach(dns_acache_t *source, dns_acache_t **targetp) { - REQUIRE(DNS_ACACHE_VALID(source)); - REQUIRE(targetp != NULL && *targetp == NULL); - - AATRACE(source, "attach"); - - isc_refcount_increment(&source->refs, NULL); - - *targetp = source; -} - -void -dns_acache_countquerymiss(dns_acache_t *acache) { - acache->stats.misses++; /* XXXSK danger: unlocked! */ - acache->stats.queries++; /* XXXSK danger: unlocked! */ -} - -void -dns_acache_detach(dns_acache_t **acachep) { - dns_acache_t *acache; - unsigned int refs; - isc_boolean_t should_free = ISC_FALSE; - - REQUIRE(acachep != NULL && DNS_ACACHE_VALID(*acachep)); - acache = *acachep; - - ATRACE("detach"); - - isc_refcount_decrement(&acache->refs, &refs); - if (refs == 0) { - INSIST(check_noentry(acache) == ISC_TRUE); - should_free = ISC_TRUE; - } - - *acachep = NULL; - - /* - * If we're exiting and the cleaner task exists, let it free the cache. - */ - if (should_free && acache->live_cleaners > 0) { - isc_task_shutdown(acache->task); - should_free = ISC_FALSE; - } - - if (should_free) - destroy(acache); -} - -void -dns_acache_shutdown(dns_acache_t *acache) { - REQUIRE(DNS_ACACHE_VALID(acache)); - - LOCK(&acache->lock); - - ATRACE("shutdown"); - - if (!acache->shutting_down) { - isc_event_t *event; - dns_acache_t *acache_evarg = NULL; - - INSIST(!acache->cevent_sent); - - acache->shutting_down = ISC_TRUE; - - isc_mem_setwater(acache->mctx, NULL, NULL, 0, 0); - - /* - * Self attach the object in order to prevent it from being - * destroyed while waiting for the event. - */ - dns_acache_attach(acache, &acache_evarg); - event = &acache->cevent; - event->ev_arg = acache_evarg; - isc_task_send(acache->task, &event); - acache->cevent_sent = ISC_TRUE; - } - - UNLOCK(&acache->lock); -} - -isc_result_t -dns_acache_setdb(dns_acache_t *acache, dns_db_t *db) { - int bucket; - dbentry_t *dbentry; - isc_result_t result = ISC_R_SUCCESS; - - REQUIRE(DNS_ACACHE_VALID(acache)); - REQUIRE(db != NULL); - - ATRACE("setdb"); - - LOCK(&acache->lock); - - dbentry = NULL; - result = finddbent(acache, db, &dbentry); - if (result == ISC_R_SUCCESS) { - result = ISC_R_EXISTS; - goto end; - } - result = ISC_R_SUCCESS; - - dbentry = isc_mem_get(acache->mctx, sizeof(*dbentry)); - if (dbentry == NULL) { - result = ISC_R_NOMEMORY; - goto end; - } - - ISC_LINK_INIT(dbentry, link); - ISC_LIST_INIT(dbentry->originlist); - ISC_LIST_INIT(dbentry->referlist); - - dbentry->db = NULL; - dns_db_attach(db, &dbentry->db); - - bucket = isc_hash_function(&db, sizeof(db), ISC_TRUE, NULL) % DBBUCKETS; - - ISC_LIST_APPEND(acache->dbbucket[bucket], dbentry, link); - - acache->dbentries++; - - end: - UNLOCK(&acache->lock); - - return (result); -} - -isc_result_t -dns_acache_putdb(dns_acache_t *acache, dns_db_t *db) { - int bucket; - isc_result_t result; - dbentry_t *dbentry; - dns_acacheentry_t *entry; - - REQUIRE(DNS_ACACHE_VALID(acache)); - REQUIRE(db != NULL); - - ATRACE("putdb"); - - LOCK(&acache->lock); - - dbentry = NULL; - result = finddbent(acache, db, &dbentry); - if (result != ISC_R_SUCCESS) { - /* - * The entry may have not been created due to memory shortage. - */ - UNLOCK(&acache->lock); - return (ISC_R_NOTFOUND); - } - - /* - * Release corresponding cache entries: for each entry, release all - * links the entry has, and then callback to the entry holder (if any). - * If no other external references exist (this can happen if the - * original holder has canceled callback,) destroy it here. - */ - while ((entry = ISC_LIST_HEAD(dbentry->originlist)) != NULL) { - ACACHE_LOCK(&acache->entrylocks[entry->locknum], - isc_rwlocktype_write); - - /* - * Releasing olink first would avoid finddbent() in - * unlink_dbentries(). - */ - ISC_LIST_UNLINK(dbentry->originlist, entry, olink); - if (acache->cleaner.current_entry != entry) - ISC_LIST_UNLINK(acache->entries, entry, link); - unlink_dbentries(acache, entry); - - if (entry->callback != NULL) - (entry->callback)(entry, &entry->cbarg); - entry->callback = NULL; - - ACACHE_UNLOCK(&acache->entrylocks[entry->locknum], - isc_rwlocktype_write); - - if (acache->cleaner.current_entry != entry) - dns_acache_detachentry(&entry); - } - while ((entry = ISC_LIST_HEAD(dbentry->referlist)) != NULL) { - ACACHE_LOCK(&acache->entrylocks[entry->locknum], - isc_rwlocktype_write); - - ISC_LIST_UNLINK(dbentry->referlist, entry, rlink); - if (acache->cleaner.current_entry != entry) - ISC_LIST_UNLINK(acache->entries, entry, link); - unlink_dbentries(acache, entry); - - if (entry->callback != NULL) - (entry->callback)(entry, &entry->cbarg); - entry->callback = NULL; - - ACACHE_UNLOCK(&acache->entrylocks[entry->locknum], - isc_rwlocktype_write); - - if (acache->cleaner.current_entry != entry) - dns_acache_detachentry(&entry); - } - - INSIST(ISC_LIST_EMPTY(dbentry->originlist) && - ISC_LIST_EMPTY(dbentry->referlist)); - - bucket = isc_hash_function(&db, sizeof(db), ISC_TRUE, NULL) % DBBUCKETS; - - ISC_LIST_UNLINK(acache->dbbucket[bucket], dbentry, link); - dns_db_detach(&dbentry->db); - - isc_mem_put(acache->mctx, dbentry, sizeof(*dbentry)); - - acache->dbentries--; - - acache->stats.deleted++; - - UNLOCK(&acache->lock); - - return (ISC_R_SUCCESS); -} - -isc_result_t -dns_acache_createentry(dns_acache_t *acache, dns_db_t *origdb, - void (*callback)(dns_acacheentry_t *, void **), - void *cbarg, dns_acacheentry_t **entryp) -{ - dns_acacheentry_t *newentry; - isc_result_t result; - isc_uint32_t r; - - REQUIRE(DNS_ACACHE_VALID(acache)); - REQUIRE(entryp != NULL && *entryp == NULL); - REQUIRE(origdb != NULL); - - /* - * Should we exceed our memory limit for some reason (for - * example, if the cleaner does not run aggressively enough), - * then we will not create additional entries. - * - * XXXSK: It might be better to lock the acache->cleaner->lock, - * but locking may be an expensive bottleneck. If we misread - * the value, we will occasionally refuse to create a few - * cache entries, or create a few that we should not. I do not - * expect this to happen often, and it will not have very bad - * effects when it does. So no lock for now. - */ - if (acache->cleaner.overmem) { - acache->stats.overmem_nocreates++; /* XXXSK danger: unlocked! */ - return (ISC_R_NORESOURCES); - } - - newentry = isc_mem_get(acache->mctx, sizeof(*newentry)); - if (newentry == NULL) { - acache->stats.nomem++; /* XXXMLG danger: unlocked! */ - return (ISC_R_NOMEMORY); - } - - isc_random_get(&r); - newentry->locknum = r % DEFAULT_ACACHE_ENTRY_LOCK_COUNT; - - result = isc_refcount_init(&newentry->references, 1); - if (result != ISC_R_SUCCESS) { - isc_mem_put(acache->mctx, newentry, sizeof(*newentry)); - return (result); - }; - - ISC_LINK_INIT(newentry, link); - ISC_LINK_INIT(newentry, olink); - ISC_LINK_INIT(newentry, rlink); - - newentry->acache = NULL; - dns_acache_attach(acache, &newentry->acache); - - newentry->zone = NULL; - newentry->db = NULL; - newentry->version = NULL; - newentry->node = NULL; - newentry->foundname = NULL; - - newentry->callback = callback; - newentry->cbarg = cbarg; - newentry->origdb = NULL; - dns_db_attach(origdb, &newentry->origdb); - - isc_stdtime_get(&newentry->lastused); - - newentry->magic = ACACHEENTRY_MAGIC; - - *entryp = newentry; - - return (ISC_R_SUCCESS); -} - -isc_result_t -dns_acache_getentry(dns_acacheentry_t *entry, dns_zone_t **zonep, - dns_db_t **dbp, dns_dbversion_t **versionp, - dns_dbnode_t **nodep, dns_name_t *fname, - dns_message_t *msg, isc_stdtime_t now) -{ - isc_result_t result = ISC_R_SUCCESS; - dns_rdataset_t *erdataset; - isc_stdtime32_t now32; - dns_acache_t *acache; - int locknum; - - REQUIRE(DNS_ACACHEENTRY_VALID(entry)); - REQUIRE(zonep == NULL || *zonep == NULL); - REQUIRE(dbp != NULL && *dbp == NULL); - REQUIRE(versionp != NULL && *versionp == NULL); - REQUIRE(nodep != NULL && *nodep == NULL); - REQUIRE(fname != NULL); - REQUIRE(msg != NULL); - acache = entry->acache; - REQUIRE(DNS_ACACHE_VALID(acache)); - - locknum = entry->locknum; - ACACHE_LOCK(&acache->entrylocks[locknum], isc_rwlocktype_read); - - isc_stdtime_convert32(now, &now32); - acache_storetime(entry, now32); - - if (entry->zone != NULL && zonep != NULL) - dns_zone_attach(entry->zone, zonep); - - if (entry->db == NULL) { - *dbp = NULL; - *versionp = NULL; - } else { - dns_db_attach(entry->db, dbp); - dns_db_attachversion(entry->db, entry->version, versionp); - } - if (entry->node == NULL) - *nodep = NULL; - else { - dns_db_attachnode(entry->db, entry->node, nodep); - - INSIST(entry->foundname != NULL); - dns_name_copy(entry->foundname, fname, NULL); - for (erdataset = ISC_LIST_HEAD(entry->foundname->list); - erdataset != NULL; - erdataset = ISC_LIST_NEXT(erdataset, link)) { - dns_rdataset_t *ardataset; - - ardataset = NULL; - result = dns_message_gettemprdataset(msg, &ardataset); - if (result != ISC_R_SUCCESS) { - ACACHE_UNLOCK(&acache->entrylocks[locknum], - isc_rwlocktype_read); - goto fail; - } - - /* - * XXXJT: if we simply clone the rdataset, we'll get - * lost wrt cyclic ordering. We'll need an additional - * trick to get the latest counter from the original - * header. - */ - dns_rdataset_clone(erdataset, ardataset); - ISC_LIST_APPEND(fname->list, ardataset, link); - } - } - - entry->acache->stats.hits++; /* XXXMLG danger: unlocked! */ - entry->acache->stats.queries++; - - ACACHE_UNLOCK(&acache->entrylocks[locknum], isc_rwlocktype_read); - - return (result); - - fail: - while ((erdataset = ISC_LIST_HEAD(fname->list)) != NULL) { - ISC_LIST_UNLINK(fname->list, erdataset, link); - dns_rdataset_disassociate(erdataset); - dns_message_puttemprdataset(msg, &erdataset); - } - if (*nodep != NULL) - dns_db_detachnode(*dbp, nodep); - if (*versionp != NULL) - dns_db_closeversion(*dbp, versionp, ISC_FALSE); - if (*dbp != NULL) - dns_db_detach(dbp); - if (zonep != NULL && *zonep != NULL) - dns_zone_detach(zonep); - - return (result); -} - -isc_result_t -dns_acache_setentry(dns_acache_t *acache, dns_acacheentry_t *entry, - dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version, - dns_dbnode_t *node, dns_name_t *fname) -{ - isc_result_t result; - dbentry_t *odbent; - dbentry_t *rdbent = NULL; - isc_boolean_t close_version = ISC_FALSE; - dns_acacheentry_t *dummy_entry = NULL; - - REQUIRE(DNS_ACACHE_VALID(acache)); - REQUIRE(DNS_ACACHEENTRY_VALID(entry)); - - LOCK(&acache->lock); /* XXX: need to lock it here for ordering */ - ACACHE_LOCK(&acache->entrylocks[entry->locknum], isc_rwlocktype_write); - - /* Set zone */ - if (zone != NULL) - dns_zone_attach(zone, &entry->zone); - /* Set DB */ - if (db != NULL) - dns_db_attach(db, &entry->db); - /* - * Set DB version. If the version is not given by the caller, - * which is the case for glue or cache DBs, use the current version. - */ - if (version == NULL) { - if (db != NULL) { - dns_db_currentversion(db, &version); - close_version = ISC_TRUE; - } - } - if (version != NULL) { - INSIST(db != NULL); - dns_db_attachversion(db, version, &entry->version); - } - if (close_version) - dns_db_closeversion(db, &version, ISC_FALSE); - /* Set DB node. */ - if (node != NULL) { - INSIST(db != NULL); - dns_db_attachnode(db, node, &entry->node); - } - - /* - * Set list of the corresponding rdatasets, if given. - * To minimize the overhead and memory consumption, we'll do this for - * positive cache only, in which case the DB node is non NULL. - * We do not want to cache incomplete information, so give up the - * entire entry when a memory shortage happen during the process. - */ - if (node != NULL) { - dns_rdataset_t *ardataset, *crdataset; - - entry->foundname = isc_mem_get(acache->mctx, - sizeof(*entry->foundname)); - - if (entry->foundname == NULL) { - result = ISC_R_NOMEMORY; - goto fail; - } - dns_name_init(entry->foundname, NULL); - result = dns_name_dup(fname, acache->mctx, - entry->foundname); - if (result != ISC_R_SUCCESS) - goto fail; - - for (ardataset = ISC_LIST_HEAD(fname->list); - ardataset != NULL; - ardataset = ISC_LIST_NEXT(ardataset, link)) { - crdataset = isc_mem_get(acache->mctx, - sizeof(*crdataset)); - if (crdataset == NULL) { - result = ISC_R_NOMEMORY; - goto fail; - } - - dns_rdataset_init(crdataset); - dns_rdataset_clone(ardataset, crdataset); - ISC_LIST_APPEND(entry->foundname->list, crdataset, - link); - } - } - - odbent = NULL; - result = finddbent(acache, entry->origdb, &odbent); - if (result != ISC_R_SUCCESS) - goto fail; - if (db != NULL) { - rdbent = NULL; - result = finddbent(acache, db, &rdbent); - if (result != ISC_R_SUCCESS) - goto fail; - } - - ISC_LIST_APPEND(acache->entries, entry, link); - ISC_LIST_APPEND(odbent->originlist, entry, olink); - if (rdbent != NULL) - ISC_LIST_APPEND(rdbent->referlist, entry, rlink); - - /* - * The additional cache needs an implicit reference to entries in its - * link. - */ - dns_acache_attachentry(entry, &dummy_entry); - - ACACHE_UNLOCK(&acache->entrylocks[entry->locknum], - isc_rwlocktype_write); - - acache->stats.adds++; - UNLOCK(&acache->lock); - - return (ISC_R_SUCCESS); - - fail: - clear_entry(acache, entry); - - ACACHE_UNLOCK(&acache->entrylocks[entry->locknum], - isc_rwlocktype_write); - UNLOCK(&acache->lock); - - return (result); -} - -isc_boolean_t -dns_acache_cancelentry(dns_acacheentry_t *entry) { - dns_acache_t *acache; - isc_boolean_t callback_active; - - REQUIRE(DNS_ACACHEENTRY_VALID(entry)); - - acache = entry->acache; - - INSIST(DNS_ACACHE_VALID(entry->acache)); - - LOCK(&acache->lock); - ACACHE_LOCK(&acache->entrylocks[entry->locknum], isc_rwlocktype_write); - - callback_active = ISC_TF(entry->cbarg != NULL); - - /* - * Release dependencies stored in this entry as much as possible. - * The main link cannot be released, since the acache object has - * a reference to this entry; the empty entry will be released in - * the next cleaning action. - */ - unlink_dbentries(acache, entry); - clear_entry(entry->acache, entry); - - entry->callback = NULL; - entry->cbarg = NULL; - - ACACHE_UNLOCK(&acache->entrylocks[entry->locknum], - isc_rwlocktype_write); - UNLOCK(&acache->lock); - - return (callback_active); -} - -void -dns_acache_attachentry(dns_acacheentry_t *source, - dns_acacheentry_t **targetp) -{ - REQUIRE(DNS_ACACHEENTRY_VALID(source)); - REQUIRE(targetp != NULL && *targetp == NULL); - - isc_refcount_increment(&source->references, NULL); - - *targetp = source; -} - -void -dns_acache_detachentry(dns_acacheentry_t **entryp) { - dns_acacheentry_t *entry; - unsigned int refs; - - REQUIRE(entryp != NULL && DNS_ACACHEENTRY_VALID(*entryp)); - entry = *entryp; - - isc_refcount_decrement(&entry->references, &refs); - - /* - * If there are no references to the entry, the entry must have been - * unlinked and can be destroyed safely. - */ - if (refs == 0) { - INSIST(!ISC_LINK_LINKED(entry, link)); - (*entryp)->acache->stats.deleted++; - destroy_entry(entry); - } - - *entryp = NULL; -} - -void -dns_acache_setcleaninginterval(dns_acache_t *acache, unsigned int t) { - isc_interval_t interval; - isc_result_t result; - - REQUIRE(DNS_ACACHE_VALID(acache)); - - ATRACE("dns_acache_setcleaninginterval"); - - LOCK(&acache->lock); - - /* - * It may be the case that the acache has already shut down. - * If so, it has no timer. (Not sure if this can really happen.) - */ - if (acache->cleaner.cleaning_timer == NULL) - goto unlock; - - acache->cleaner.cleaning_interval = t; - - if (t == 0) { - result = isc_timer_reset(acache->cleaner.cleaning_timer, - isc_timertype_inactive, - NULL, NULL, ISC_TRUE); - } else { - isc_interval_set(&interval, acache->cleaner.cleaning_interval, - 0); - result = isc_timer_reset(acache->cleaner.cleaning_timer, - isc_timertype_ticker, - NULL, &interval, ISC_FALSE); - } - if (result != ISC_R_SUCCESS) - isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, - DNS_LOGMODULE_ACACHE, ISC_LOG_WARNING, - "could not set acache cleaning interval: %s", - isc_result_totext(result)); - else - isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, - DNS_LOGMODULE_ACACHE, ISC_LOG_NOTICE, - "acache %p cleaning interval set to %d.", - acache, t); - - unlock: - UNLOCK(&acache->lock); -} - -/* - * This function was derived from cache.c:dns_cache_setcachesize(). See the - * function for more details about the logic. - */ -void -dns_acache_setcachesize(dns_acache_t *acache, size_t size) { - size_t hiwater, lowater; - - REQUIRE(DNS_ACACHE_VALID(acache)); - - if (size != 0U && size < DNS_ACACHE_MINSIZE) - size = DNS_ACACHE_MINSIZE; - - hiwater = size - (size >> 3); - lowater = size - (size >> 2); - - if (size == 0U || hiwater == 0U || lowater == 0U) - isc_mem_setwater(acache->mctx, water, acache, 0, 0); - else - isc_mem_setwater(acache->mctx, water, acache, - hiwater, lowater); -} diff --git a/lib/dns/compress.c b/lib/dns/compress.c index c876fa155e..3234243626 100644 --- a/lib/dns/compress.c +++ b/lib/dns/compress.c @@ -27,16 +27,110 @@ #define DCTX_MAGIC ISC_MAGIC('D', 'C', 'T', 'X') #define VALID_DCTX(x) ISC_MAGIC_VALID(x, DCTX_MAGIC) -#define TABLE_READY \ - do { \ - unsigned int i; \ - \ - if ((cctx->allowed & DNS_COMPRESS_READY) == 0) { \ - cctx->allowed |= DNS_COMPRESS_READY; \ - for (i = 0; i < DNS_COMPRESS_TABLESIZE; i++) \ - cctx->table[i] = NULL; \ - } \ - } while (0) +static unsigned char maptolower[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff +}; + +/* + * The tableindex array below is of size 256, one entry for each + * unsigned char value. The tableindex array elements are dependent on + * DNS_COMPRESS_TABLESIZE. The table was created using the following + * function. + * + * static void + * gentable(unsigned char *table) { + * unsigned int i; + * const unsigned int left = DNS_COMPRESS_TABLESIZE - 38; + * long r; + * + * for (i = 0; i < 26; i++) { + * table['A' + i] = i; + * table['a' + i] = i; + * } + * + * for (i = 0; i <= 9; i++) + * table['0' + i] = i + 26; + * + * table['-'] = 36; + * table['_'] = 37; + * + * for (i = 0; i < 256; i++) { + * if ((i >= 'a' && i <= 'z') || + * (i >= 'A' && i <= 'Z') || + * (i >= '0' && i <= '9') || + * (i == '-') || + * (i == '_')) + * continue; + * r = random() % left; + * table[i] = 38 + r; + * } + * } + */ +static unsigned char tableindex[256] = { + 0x3e, 0x3e, 0x33, 0x2d, 0x30, 0x38, 0x31, 0x3c, + 0x2b, 0x33, 0x30, 0x3f, 0x2d, 0x3c, 0x36, 0x3a, + 0x28, 0x2c, 0x2a, 0x37, 0x3d, 0x34, 0x35, 0x2d, + 0x39, 0x2b, 0x2f, 0x2c, 0x3b, 0x32, 0x2b, 0x39, + 0x30, 0x38, 0x28, 0x3c, 0x32, 0x33, 0x39, 0x38, + 0x27, 0x2b, 0x39, 0x30, 0x27, 0x24, 0x2f, 0x2b, + 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, + 0x22, 0x3a, 0x29, 0x36, 0x31, 0x3c, 0x35, 0x26, + 0x31, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, + 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, + 0x17, 0x18, 0x19, 0x3e, 0x3b, 0x39, 0x2f, 0x25, + 0x27, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, + 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, + 0x17, 0x18, 0x19, 0x36, 0x3b, 0x2f, 0x2f, 0x2e, + 0x29, 0x33, 0x2a, 0x36, 0x28, 0x3f, 0x2e, 0x29, + 0x2c, 0x29, 0x36, 0x2d, 0x32, 0x3d, 0x33, 0x2a, + 0x2e, 0x2f, 0x3b, 0x30, 0x3d, 0x39, 0x2b, 0x36, + 0x2a, 0x2f, 0x2c, 0x26, 0x3a, 0x37, 0x30, 0x3d, + 0x2a, 0x36, 0x33, 0x2c, 0x38, 0x3d, 0x32, 0x3e, + 0x26, 0x2a, 0x2c, 0x35, 0x27, 0x39, 0x3b, 0x31, + 0x2a, 0x37, 0x3c, 0x27, 0x32, 0x29, 0x39, 0x37, + 0x34, 0x3f, 0x39, 0x2e, 0x38, 0x2b, 0x2c, 0x3e, + 0x3b, 0x3b, 0x2d, 0x33, 0x3b, 0x3b, 0x32, 0x3d, + 0x3f, 0x3a, 0x34, 0x26, 0x35, 0x30, 0x31, 0x39, + 0x27, 0x2f, 0x3d, 0x35, 0x35, 0x36, 0x2e, 0x29, + 0x38, 0x27, 0x34, 0x32, 0x2c, 0x3c, 0x31, 0x28, + 0x37, 0x38, 0x37, 0x34, 0x33, 0x29, 0x32, 0x34, + 0x3f, 0x26, 0x34, 0x34, 0x32, 0x27, 0x30, 0x33, + 0x33, 0x2d, 0x2b, 0x28, 0x3f, 0x33, 0x2b, 0x39, + 0x37, 0x39, 0x2c, 0x3d, 0x35, 0x39, 0x27, 0x2f +}; /*** *** Compression @@ -51,7 +145,11 @@ dns_compress_init(dns_compress_t *cctx, int edns, isc_mem_t *mctx) { cctx->mctx = mctx; cctx->count = 0; cctx->allowed = DNS_COMPRESS_ENABLED; + + memset(&cctx->table[0], 0, sizeof(cctx->table)); + cctx->magic = CCTX_MAGIC; + return (ISC_R_SUCCESS); } @@ -62,20 +160,19 @@ dns_compress_invalidate(dns_compress_t *cctx) { REQUIRE(VALID_CCTX(cctx)); - if ((cctx->allowed & DNS_COMPRESS_READY) != 0) { - for (i = 0; i < DNS_COMPRESS_TABLESIZE; i++) { - while (cctx->table[i] != NULL) { - node = cctx->table[i]; - cctx->table[i] = cctx->table[i]->next; - if ((node->offset & 0x8000) != 0) - isc_mem_put(cctx->mctx, node->r.base, - node->r.length); - if (node->count < DNS_COMPRESS_INITIALNODES) - continue; - isc_mem_put(cctx->mctx, node, sizeof(*node)); - } + for (i = 0; i < DNS_COMPRESS_TABLESIZE; i++) { + while (cctx->table[i] != NULL) { + node = cctx->table[i]; + cctx->table[i] = cctx->table[i]->next; + if ((node->offset & 0x8000) != 0) + isc_mem_put(cctx->mctx, node->r.base, + node->r.length); + if (node->count < DNS_COMPRESS_INITIALNODES) + continue; + isc_mem_put(cctx->mctx, node, sizeof(*node)); } } + cctx->magic = 0; cctx->allowed = 0; cctx->edns = -1; @@ -124,14 +221,6 @@ dns_compress_getedns(dns_compress_t *cctx) { return (cctx->edns); } -#define NODENAME(node, name) \ -do { \ - (name)->length = (node)->r.length; \ - (name)->labels = (node)->labels; \ - (name)->ndata = (node)->r.base; \ - (name)->attributes = DNS_NAMEATTR_ABSOLUTE; \ -} while (0) - /* * Find the longest match of name in the table. * If match is found return ISC_TRUE. prefix, suffix and offset are updated. @@ -141,19 +230,19 @@ isc_boolean_t dns_compress_findglobal(dns_compress_t *cctx, const dns_name_t *name, dns_name_t *prefix, isc_uint16_t *offset) { - dns_name_t tname, nname; + dns_name_t tname; dns_compressnode_t *node = NULL; - unsigned int labels, hash, n; + unsigned int labels, index, n; + unsigned int numlabels; + unsigned char *p; REQUIRE(VALID_CCTX(cctx)); REQUIRE(dns_name_isabsolute(name) == ISC_TRUE); REQUIRE(offset != NULL); - if ((cctx->allowed & DNS_COMPRESS_ENABLED) == 0) + if (ISC_UNLIKELY((cctx->allowed & DNS_COMPRESS_ENABLED) == 0)) return (ISC_FALSE); - TABLE_READY; - if (cctx->count == 0) return (ISC_FALSE); @@ -161,27 +250,101 @@ dns_compress_findglobal(dns_compress_t *cctx, const dns_name_t *name, INSIST(labels > 0); dns_name_init(&tname, NULL); - dns_name_init(&nname, NULL); - for (n = 0; n < labels - 1; n++) { - dns_name_getlabelsequence(name, n, labels - n, &tname); - hash = dns_name_hash(&tname, ISC_FALSE) % - DNS_COMPRESS_TABLESIZE; - for (node = cctx->table[hash]; node != NULL; node = node->next) + numlabels = labels > 3U ? 3U : labels; + p = name->ndata; + + for (n = 0; n < numlabels - 1; n++) { + unsigned char ch, llen; + unsigned int firstoffset, length; + + firstoffset = p - name->ndata; + length = name->length - firstoffset; + + /* + * We calculate the table index using the first + * character in the first label of the suffix name. + */ + ch = p[1]; + index = tableindex[ch]; + if (ISC_LIKELY((cctx->allowed & + DNS_COMPRESS_CASESENSITIVE) != 0)) { - NODENAME(node, &nname); - if ((cctx->allowed & DNS_COMPRESS_CASESENSITIVE) != 0) { - if (dns_name_caseequal(&nname, &tname)) - break; - } else { - if (dns_name_equal(&nname, &tname)) - break; + for (node = cctx->table[index]; + node != NULL; + node = node->next) + { + if (ISC_UNLIKELY(node->name.length != length)) + continue; + + if (ISC_LIKELY(memcmp(node->name.ndata, + p, length) == 0)) + goto found; + } + } else { + for (node = cctx->table[index]; + node != NULL; + node = node->next) + { + unsigned int l, count; + unsigned char c; + unsigned char *label1, *label2; + + if (ISC_UNLIKELY(node->name.length != length)) + continue; + + l = labels - n; + if (ISC_UNLIKELY(node->name.labels != l)) + continue; + + label1 = node->name.ndata; + label2 = p; + while (ISC_LIKELY(l-- > 0)) { + count = *label1++; + if (count != *label2++) + goto cont1; + + /* no bitstring support */ + INSIST(count <= 63); + + /* Loop unrolled for performance */ + while (ISC_LIKELY(count > 3)) { + c = maptolower[label1[0]]; + if (c != maptolower[label2[0]]) + goto cont1; + c = maptolower[label1[1]]; + if (c != maptolower[label2[1]]) + goto cont1; + c = maptolower[label1[2]]; + if (c != maptolower[label2[2]]) + goto cont1; + c = maptolower[label1[3]]; + if (c != maptolower[label2[3]]) + goto cont1; + count -= 4; + label1 += 4; + label2 += 4; + } + while (ISC_LIKELY(count-- > 0)) { + c = maptolower[*label1++]; + if (c != maptolower[*label2++]) + goto cont1; + } + } + break; + cont1: + continue; } } + if (node != NULL) break; + + llen = *p; + p += llen + 1; } + found: /* * If node == NULL, we found no match at all. */ @@ -212,7 +375,7 @@ dns_compress_add(dns_compress_t *cctx, const dns_name_t *name, unsigned int start; unsigned int n; unsigned int count; - unsigned int hash; + unsigned int index; dns_compressnode_t *node; unsigned int length; unsigned int tlength; @@ -223,11 +386,9 @@ dns_compress_add(dns_compress_t *cctx, const dns_name_t *name, REQUIRE(VALID_CCTX(cctx)); REQUIRE(dns_name_isabsolute(name)); - if ((cctx->allowed & DNS_COMPRESS_ENABLED) == 0) + if (ISC_UNLIKELY((cctx->allowed & DNS_COMPRESS_ENABLED) == 0)) return; - TABLE_READY; - if (offset >= 0x4000) return; dns_name_init(&tname, NULL); @@ -252,10 +413,19 @@ dns_compress_add(dns_compress_t *cctx, const dns_name_t *name, r.base = tmp; dns_name_fromregion(&xname, &r); + if (count > 2U) + count = 2U; + while (count > 0) { + unsigned char ch; + dns_name_getlabelsequence(&xname, start, n, &tname); - hash = dns_name_hash(&tname, ISC_FALSE) % - DNS_COMPRESS_TABLESIZE; + /* + * We calculate the table index using the first + * character in the first label of tname. + */ + ch = tname.ndata[1]; + index = tableindex[ch]; tlength = name_length(&tname); toffset = (isc_uint16_t)(offset + (length - tlength)); if (toffset >= 0x4000) @@ -280,9 +450,13 @@ dns_compress_add(dns_compress_t *cctx, const dns_name_t *name, toffset |= 0x8000; node->offset = toffset; dns_name_toregion(&tname, &node->r); - node->labels = (isc_uint8_t)dns_name_countlabels(&tname); - node->next = cctx->table[hash]; - cctx->table[hash] = node; + dns_name_init(&node->name, NULL); + node->name.length = node->r.length; + node->name.ndata = node->r.base; + node->name.labels = tname.labels; + node->name.attributes = DNS_NAMEATTR_ABSOLUTE; + node->next = cctx->table[index]; + cctx->table[index] = node; start++; n--; count--; @@ -299,10 +473,7 @@ dns_compress_rollback(dns_compress_t *cctx, isc_uint16_t offset) { REQUIRE(VALID_CCTX(cctx)); - if ((cctx->allowed & DNS_COMPRESS_ENABLED) == 0) - return; - - if ((cctx->allowed & DNS_COMPRESS_READY) == 0) + if (ISC_UNLIKELY((cctx->allowed & DNS_COMPRESS_ENABLED) == 0)) return; for (i = 0; i < DNS_COMPRESS_TABLESIZE; i++) { diff --git a/lib/dns/ecdb.c b/lib/dns/ecdb.c index 163441b33b..3e1c8d3dbb 100644 --- a/lib/dns/ecdb.c +++ b/lib/dns/ecdb.c @@ -101,14 +101,12 @@ static dns_rdatasetmethods_t rdataset_methods = { NULL, /* getnoqname */ NULL, /* addclosest */ NULL, /* getclosest */ - NULL, /* getadditional */ - NULL, /* setadditional */ - NULL, /* putadditional */ rdataset_settrust, /* settrust */ NULL, /* expire */ NULL, /* clearprefetch */ NULL, /* setownercase */ - NULL /* getownercase */ + NULL, /* getownercase */ + NULL /* addglue */ }; typedef struct ecdb_rdatasetiter { diff --git a/lib/dns/include/dns/Makefile.in b/lib/dns/include/dns/Makefile.in index c7ae21dff6..0f13808f91 100644 --- a/lib/dns/include/dns/Makefile.in +++ b/lib/dns/include/dns/Makefile.in @@ -10,7 +10,7 @@ top_srcdir = @top_srcdir@ VERSION=@BIND9_VERSION@ -HEADERS = acache.h acl.h adb.h badcache.h bit.h byaddr.h \ +HEADERS = acl.h adb.h badcache.h bit.h byaddr.h \ cache.h callbacks.h catz.h cert.h \ client.h clientinfo.h compress.h \ db.h dbiterator.h dbtable.h diff.h dispatch.h \ diff --git a/lib/dns/include/dns/acache.h b/lib/dns/include/dns/acache.h deleted file mode 100644 index 1f05c30f29..0000000000 --- a/lib/dns/include/dns/acache.h +++ /dev/null @@ -1,440 +0,0 @@ -/* - * Copyright (C) 2004, 2006, 2007, 2013, 2016 Internet Systems Consortium, Inc. ("ISC") - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -/* $Id: acache.h,v 1.8 2007/06/19 23:47:16 tbox Exp $ */ - -#ifndef DNS_ACACHE_H -#define DNS_ACACHE_H 1 - -/***** - ***** Module Info - *****/ - -/* - * Acache - * - * The Additional Cache Object - * - * This module manages internal caching entries that correspond to - * the additional section data of a DNS DB node (an RRset header, more - * accurately). An additional cache entry is expected to be (somehow) - * attached to a particular RR in a particular DB node, and contains a set - * of information of an additional data for the DB node. - * - * An additional cache object is intended to be created as a per-view - * object, and manages all cache entries within the view. - * - * The intended usage of the additional caching is to provide a short cut - * to additional glue RRs of an NS RR. For each NS RR, it is often - * necessary to look for glue RRs to make a proper response. Once the - * glue RRs are known, the additional caching allows the client to - * associate the information to the original NS RR so that further - * expensive lookups can be avoided for the NS RR. - * - * Each additional cache entry contains information to identify a - * particular DB node and (optionally) an associated RRset. The - * information consists of its zone, database, the version of the - * database, database node, and RRset. - * - * A "negative" information can also be cached. For example, if a glue - * RR does not exist as an authoritative data in the same zone as that - * of the NS RR, this fact can be cached by specifying a NULL pointer - * for the database, version, and node. (See the description for - * dns_acache_getentry() below for more details.) - * - * Since each member stored in an additional cache entry holds a reference - * to a corresponding object, a stale cache entry may cause unnecessary - * memory consumption. For instance, when a zone is reloaded, additional - * cache entries that have a reference to the zone (and its DB and/or - * DB nodes) can delay the cleanup of the referred objects. In order to - * minimize such a bad effect, this module provides several cleanup - * mechanisms. - * - * The first one is a shutdown procedure called when the associated view - * is shut down. In this case, dns_acache_shutdown() will be called and - * all cache entries will be purged. This mechanism will help the - * situation when the configuration is reloaded or the main server is - * stopped. - * - * Per-DB cleanup mechanism is also provided. Each additional cache entry - * is associated with related DB, which is expected to have been - * registered when the DB was created by dns_acache_setdb(). If a - * particular DB is going to be destroyed, the primary holder of the DB, - * a typical example of which is a zone, will call dns_acache_putdb(). - * Then this module will clean-up all cache entries associated with the - * DB. This mechanism is effective when a secondary zone DB is going to - * be stale after a zone transfer. - * - * Finally, this module supports for periodic clean-up of stale entries. - * Each cache entry has a timestamp field, which is updated every time - * the entry is referred. A periodically invoked cleaner checks the - * timestamp of each entry, and purge entries that have not been referred - * for a certain period. The cleaner interval can be specified by - * dns_acache_setcleaninginterval(). If the periodic clean-up is not - * enough, it is also possible to specify the upper limit of entries - * in terms of the memory consumption. If the maximum value is - * specified, the cleaner is invoked when the memory consumption reaches - * the high watermark inferred from the maximum value. In this case, - * the cleaner will use more aggressive algorithm to decide the "victim" - * entries. The maximum value can be specified by - * dns_acache_setcachesize(). - * - * When a cache entry is going to be purged within this module, the - * callback function specified at the creation time will be called. - * The callback function is expected to release all internal resources - * related to the entry, which will typically be specific to DB - * implementation, and to call dns_acache_detachentry(). The callback - * mechanism is very important, since the holder of an additional cache - * entry may not be able to initiate the clean-up of the entry, due to - * the reference ordering. For example, as long as an additional cache - * entry has a reference to a DB object, the DB cannot be freed, in which - * a DB node may have a reference to the cache entry. - * - * Credits: - * The basic idea of this kind of short-cut for frequently used - * information is similar to the "pre-compiled answer" approach adopted - * in nsd by NLnet LABS with RIPE NCC. Our work here is an independent - * effort, but the success of nsd encouraged us to pursue this path. - * - * The design and implementation of the periodic memory management and - * the upper limitation of memory consumption was derived from the cache - * DB implementation of BIND9. - * - * MP: - * There are two main locks in this module. One is for each entry, and - * the other is for the additional cache object. - * - * Reliability: - * The callback function for a cache entry is called with holding the - * entry lock. Thus, it implicitly assumes the callback function does not - * call a function that can require the lock. Typically, the only - * function that can be called from the callback function safely is - * dns_acache_detachentry(). The breakage of this implicit assumption - * may cause a deadlock. - * - * Resources: - * In a 32-bit architecture (such as i386), the following additional - * memory is required comparing to the case that disables this module. - * - 76 bytes for each additional cache entry - * - if the entry has a DNS name and associated RRset, - * * 44 bytes + size of the name (1-255 bytes) - * * 52 bytes x number_of_RRs - * - 28 bytes for each DB related to this module - * - * Using the additional cache also requires extra memory consumption in - * the DB implementation. In the current implementation for rbtdb, we - * need: - * - two additional pointers for each DB node (8 bytes for a 32-bit - * architecture - * - for each RR associated to an RR in a DB node, we also need - * a pointer and management objects to support the additional cache - * function. These are allocated on-demand. The total size is - * 32 bytes for a 32-bit architecture. - * - * Security: - * Since this module does not handle any low-level data directly, - * no security issue specific to this module is anticipated. - * - * Standards: - * None. - */ - -/*** - *** Imports - ***/ - -#include -#include -#include -#include - -#include - -/*** - *** Functions - ***/ -ISC_LANG_BEGINDECLS - -isc_result_t -dns_acache_create(dns_acache_t **acachep, isc_mem_t *mctx, - isc_taskmgr_t *taskmgr, isc_timermgr_t *timermgr); -/* - * Create a new DNS additional cache object. - * - * Requires: - * - * 'mctx' is a valid memory context - * - * 'taskmgr' is a valid task manager - * - * 'timermgr' is a valid timer or NULL. If NULL, no periodic cleaning of - * the cache will take place. - * - * 'acachep' is a valid pointer, and *acachep == NULL - * - * Ensures: - * - * '*acachep' is attached to the newly created cache - * - * Returns: - * - * ISC_R_SUCCESS - * ISC_R_NOMEMORY - * ISC_R_UNEXPECTED - */ - -void -dns_acache_attach(dns_acache_t *source, dns_acache_t **targetp); -/* - * Attach *targetp to cache. - * - * Requires: - * - * 'acache' is a valid additional cache. - * - * 'targetp' points to a NULL dns_acache_t *. - * - * Ensures: - * - * *targetp is attached to the 'source' additional cache. - */ - -void -dns_acache_detach(dns_acache_t **acachep); -/* - * Detach *acachep from its cache. - * - * Requires: - * - * '*acachep' points to a valid additional cache. - * - * Ensures: - * - * *acachep is NULL. - * - * If '*acachep' is the last reference to the cache and the additional - * cache does not have an outstanding task, all resources used by the - * cache will be freed. - */ - -void -dns_acache_setcleaninginterval(dns_acache_t *acache, unsigned int t); -/* - * Set the periodic cleaning interval of an additional cache to 'interval' - * seconds. - */ - -void -dns_acache_setcachesize(dns_acache_t *acache, size_t size); -/* - * Set the maximum additional cache size. 0 means unlimited. - */ - -isc_result_t -dns_acache_setdb(dns_acache_t *acache, dns_db_t *db); -/* - * Set 'db' in 'acache' when the db can be referred from acache, in order - * to provide a hint for resolving the back reference. - * - * Requires: - * 'acache' is a valid acache pointer. - * 'db' is a valid DNS DB pointer. - * - * Ensures: - * 'acache' will have a reference to 'db'. - * - * Returns: - * ISC_R_SUCCESS - * ISC_R_EXISTS (which means the specified 'db' is already set) - * ISC_R_NOMEMORY - */ - -isc_result_t -dns_acache_putdb(dns_acache_t *acache, dns_db_t *db); -/* - * Release 'db' from 'acache' if it has been set by dns_acache_setdb(). - * - * Requires: - * 'acache' is a valid acache pointer. - * 'db' is a valid DNS DB pointer. - * - * Ensures: - * 'acache' will release the reference to 'db'. Additionally, the content - * of each cache entry that is related to the 'db' will be released via - * the callback function. - * - * Returns: - * ISC_R_SUCCESS - * ISC_R_NOTFOUND (which means the specified 'db' is not set in 'acache') - * ISC_R_NOMEMORY - */ - -void -dns_acache_shutdown(dns_acache_t *acache); -/* - * Shutdown 'acache'. - * - * Requires: - * - * '*acache' is a valid additional cache. - */ - -isc_result_t -dns_acache_createentry(dns_acache_t *acache, dns_db_t *origdb, - void (*callback)(dns_acacheentry_t *, void **), - void *cbarg, dns_acacheentry_t **entryp); -/* - * Create an additional cache entry. A new entry is created and attached to - * the given additional cache object. A callback function is also associated - * with the created entry, which will be called when the cache entry is purged - * for some reason. - * - * Requires: - * - * 'acache' is a valid additional cache. - * 'entryp' is a valid pointer, and *entryp == NULL - * 'origdb' is a valid DNS DB pointer. - * 'callback' and 'cbarg' can be NULL. In this case, however, the entry - * is meaningless (and will be cleaned-up in the next periodical - * cleaning). - * - * Ensures: - * '*entryp' will point to a new additional cache entry. - * - * Returns: - * ISC_R_SUCCESS - * ISC_R_NOMEMORY - */ - -isc_result_t -dns_acache_getentry(dns_acacheentry_t *entry, dns_zone_t **zonep, - dns_db_t **dbp, dns_dbversion_t **versionp, - dns_dbnode_t **nodep, dns_name_t *fname, - dns_message_t *msg, isc_stdtime_t now); -/* - * Get content from a particular additional cache entry. - * - * Requires: - * - * 'entry' is a valid additional cache entry. - * 'zonep' is a NULL pointer or '*zonep' == NULL (this is the only - * optional parameter.) - * 'dbp' is a valid pointer, and '*dbp' == NULL - * 'versionp' is a valid pointer, and '*versionp' == NULL - * 'nodep' is a valid pointer, and '*nodep' == NULL - * 'fname' is a valid DNS name. - * 'msg' is a valid DNS message. - * - * Ensures: - * Several possible cases can happen according to the content. - * 1. For a positive cache entry, - * '*zonep' will point to the corresponding zone (if zonep is a valid - * pointer), - * '*dbp' will point to a DB for the zone, - * '*versionp' will point to its version, and - * '*nodep' will point to the corresponding DB node. - * 'fname' will have the DNS name of the DB node and contain a list of - * rdataset for the node (which can be an empty list). - * - * 2. For a negative cache entry that means no corresponding zone exists, - * '*zonep' == NULL (if zonep is a valid pointer) - * '*dbp', '*versionp', and '*nodep' will be NULL. - * - * 3. For a negative cache entry that means no corresponding DB node - * exists, '*zonep' will point to the corresponding zone (if zonep is a - * valid pointer), - * '*dbp' will point to a corresponding DB for zone, - * '*versionp' will point to its version. - * '*nodep' will be kept as NULL. - * 'fname' will not change. - * - * On failure, no new references will be created. - * - * Returns: - * ISC_R_SUCCESS - * ISC_R_NOMEMORY - */ - -isc_result_t -dns_acache_setentry(dns_acache_t *acache, dns_acacheentry_t *entry, - dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version, - dns_dbnode_t *node, dns_name_t *fname); -/* - * Set content to a particular additional cache entry. - * - * Requires: - * 'acache' is a valid additional cache. - * 'entry' is a valid additional cache entry. - * All the others pointers are NULL or a valid pointer of the - * corresponding type. - * - * Returns: - * ISC_R_SUCCESS - * ISC_R_NOMEMORY - * ISC_R_NOTFOUND - */ - -isc_boolean_t -dns_acache_cancelentry(dns_acacheentry_t *entry); -/* - * Cancel the use of the cache entry 'entry'. This function is supposed to - * be called when the node that holds the entry finds the content is not - * correct any more. This function will try to release as much dependency as - * possible, and will be ready to be cleaned-up. The registered callback - * function will be canceled and will never called. - * - * Requires: - * 'entry' is a valid additional cache entry. - * - * Returns: - * ISC_TRUE if the entry was active when canceled - */ - -void -dns_acache_attachentry(dns_acacheentry_t *source, dns_acacheentry_t **targetp); -/* - * Attach *targetp to the cache entry 'source'. - * - * Requires: - * - * 'source' is a valid additional cache entry. - * - * 'targetp' points to a NULL dns_acacheentry_t *. - * - * Ensures: - * - * *targetp is attached to 'source'. - */ - -void -dns_acache_detachentry(dns_acacheentry_t **entryp); -/* - * Detach *entryp from its cache. - * - * Requires: - * - * '*entryp' points to a valid additional cache entry. - * - * Ensures: - * - * *entryp is NULL. - * - * If '*entryp' is the last reference to the entry, - * cache does not have an outstanding task, all resources used by the - * entry (including the entry object itself) will be freed. - */ - -void -dns_acache_countquerymiss(dns_acache_t *acache); -/* - * Count up a missed acache query. XXXMLG need more docs. - */ - -ISC_LANG_ENDDECLS - -#endif /* DNS_ACACHE_H */ diff --git a/lib/dns/include/dns/compress.h b/lib/dns/include/dns/compress.h index d72d7db5bc..adfb73121b 100644 --- a/lib/dns/include/dns/compress.h +++ b/lib/dns/include/dns/compress.h @@ -13,6 +13,7 @@ #include #include +#include ISC_LANG_BEGINDECLS @@ -37,19 +38,23 @@ ISC_LANG_BEGINDECLS #define DNS_COMPRESS_CASESENSITIVE 0x02 /*%< case sensitive compression. */ #define DNS_COMPRESS_ENABLED 0x04 -#define DNS_COMPRESS_READY 0x80000000 - -#define DNS_COMPRESS_TABLESIZE 64 +/* + * DNS_COMPRESS_TABLESIZE must be a power of 2. The compress code + * utilizes this assumption. + */ +#define DNS_COMPRESS_TABLEBITS 6 +#define DNS_COMPRESS_TABLESIZE (1U << DNS_COMPRESS_TABLEBITS) +#define DNS_COMPRESS_TABLEMASK (DNS_COMPRESS_TABLESIZE - 1) #define DNS_COMPRESS_INITIALNODES 16 typedef struct dns_compressnode dns_compressnode_t; struct dns_compressnode { - isc_region_t r; + dns_compressnode_t *next; isc_uint16_t offset; isc_uint16_t count; - isc_uint8_t labels; - dns_compressnode_t *next; + isc_region_t r; + dns_name_t name; }; struct dns_compress { diff --git a/lib/dns/include/dns/log.h b/lib/dns/include/dns/log.h index 118d59fc30..223e83f4b6 100644 --- a/lib/dns/include/dns/log.h +++ b/lib/dns/include/dns/log.h @@ -65,7 +65,7 @@ LIBDNS_EXTERNAL_DATA extern isc_logmodule_t dns_modules[]; #define DNS_LOGMODULE_SDB (&dns_modules[22]) #define DNS_LOGMODULE_DIFF (&dns_modules[23]) #define DNS_LOGMODULE_HINTS (&dns_modules[24]) -#define DNS_LOGMODULE_ACACHE (&dns_modules[25]) +#define DNS_LOGMODULE_UNUSED1 (&dns_modules[25]) #define DNS_LOGMODULE_DLZ (&dns_modules[26]) #define DNS_LOGMODULE_DNSSEC (&dns_modules[27]) #define DNS_LOGMODULE_CRYPTO (&dns_modules[28]) diff --git a/lib/dns/include/dns/rdataset.h b/lib/dns/include/dns/rdataset.h index fa6ce450b4..abf72eb20c 100644 --- a/lib/dns/include/dns/rdataset.h +++ b/lib/dns/include/dns/rdataset.h @@ -76,37 +76,18 @@ typedef struct dns_rdatasetmethods { dns_name_t *name, dns_rdataset_t *neg, dns_rdataset_t *negsig); - isc_result_t (*getadditional)(dns_rdataset_t *rdataset, - dns_rdatasetadditional_t type, - dns_rdatatype_t qtype, - dns_acache_t *acache, - dns_zone_t **zonep, - dns_db_t **dbp, - dns_dbversion_t **versionp, - dns_dbnode_t **nodep, - dns_name_t *fname, - dns_message_t *msg, - isc_stdtime_t now); - isc_result_t (*setadditional)(dns_rdataset_t *rdataset, - dns_rdatasetadditional_t type, - dns_rdatatype_t qtype, - dns_acache_t *acache, - dns_zone_t *zone, - dns_db_t *db, - dns_dbversion_t *version, - dns_dbnode_t *node, - dns_name_t *fname); - isc_result_t (*putadditional)(dns_acache_t *acache, - dns_rdataset_t *rdataset, - dns_rdatasetadditional_t type, - dns_rdatatype_t qtype); void (*settrust)(dns_rdataset_t *rdataset, dns_trust_t trust); void (*expire)(dns_rdataset_t *rdataset); void (*clearprefetch)(dns_rdataset_t *rdataset); void (*setownercase)(dns_rdataset_t *rdataset, const dns_name_t *name); - void (*getownercase)(const dns_rdataset_t *rdataset, dns_name_t *name); + void (*getownercase)(const dns_rdataset_t *rdataset, + dns_name_t *name); + isc_result_t (*addglue)(dns_rdataset_t *rdataset, + dns_dbversion_t *version, + unsigned int options, + dns_message_t *msg); } dns_rdatasetmethods_t; #define DNS_RDATASET_MAGIC ISC_MAGIC('D','N','S','R') @@ -176,6 +157,7 @@ struct dns_rdataset { * Output the RRset in load order. */ +#define DNS_RDATASETATTR_NONE 0x00000000 /*%< No ordering. */ #define DNS_RDATASETATTR_QUESTION 0x00000001 #define DNS_RDATASETATTR_RENDERED 0x00000002 /*%< Used by message.c */ #define DNS_RDATASETATTR_ANSWERED 0x00000004 /*%< Used by server. */ @@ -186,8 +168,8 @@ struct dns_rdataset { #define DNS_RDATASETATTR_NCACHE 0x00000080 /*%< Used by resolver. */ #define DNS_RDATASETATTR_CHAINING 0x00000100 /*%< Used by resolver. */ #define DNS_RDATASETATTR_TTLADJUSTED 0x00000200 /*%< Used by message.c */ -#define DNS_RDATASETATTR_FIXEDORDER 0x00000400 -#define DNS_RDATASETATTR_RANDOMIZE 0x00000800 +#define DNS_RDATASETATTR_FIXEDORDER 0x00000400 /*%< Fixed ordering. */ +#define DNS_RDATASETATTR_RANDOMIZE 0x00000800 /*%< Random ordering. */ #define DNS_RDATASETATTR_CHASE 0x00001000 /*%< Used by resolver. */ #define DNS_RDATASETATTR_NXDOMAIN 0x00002000 #define DNS_RDATASETATTR_NOQNAME 0x00004000 @@ -200,6 +182,7 @@ struct dns_rdataset { #define DNS_RDATASETATTR_OPTOUT 0x00100000 /*%< OPTOUT proof */ #define DNS_RDATASETATTR_NEGATIVE 0x00200000 #define DNS_RDATASETATTR_PREFETCH 0x00400000 +#define DNS_RDATASETATTR_CYCLIC 0x00800000 /*%< Cyclic ordering. */ /*% * _OMITDNSSEC: @@ -207,6 +190,13 @@ struct dns_rdataset { */ #define DNS_RDATASETTOWIRE_OMITDNSSEC 0x0001 +/*% + * _FILTERAAAA + * If A records are present, omit AAAA records when adding + * glue + */ +#define DNS_RDATASETADDGLUE_FILTERAAAA 0x0001 + void dns_rdataset_init(dns_rdataset_t *rdataset); /*%< @@ -542,98 +532,6 @@ dns_rdataset_addclosest(dns_rdataset_t *rdataset, const dns_name_t *name); *\li 'name' to be valid and have NSEC3 and RRSIG(NSEC3) rdatasets. */ -isc_result_t -dns_rdataset_getadditional(dns_rdataset_t *rdataset, - dns_rdatasetadditional_t type, - dns_rdatatype_t qtype, - dns_acache_t *acache, - dns_zone_t **zonep, - dns_db_t **dbp, - dns_dbversion_t **versionp, - dns_dbnode_t **nodep, - dns_name_t *fname, - dns_message_t *msg, - isc_stdtime_t now); -/*%< - * Get cached additional information from the DB node for a particular - * 'rdataset.' 'type' is one of dns_rdatasetadditional_fromauth, - * dns_rdatasetadditional_fromcache, and dns_rdatasetadditional_fromglue, - * which specifies the origin of the information. 'qtype' is intended to - * be used for specifying a particular rdata type in the cached information. - * - * Requires: - * \li 'rdataset' is a valid rdataset. - * \li 'acache' can be NULL, in which case this function will simply return - * ISC_R_FAILURE. - * \li For the other pointers, see dns_acache_getentry(). - * - * Ensures: - * \li See dns_acache_getentry(). - * - * Returns: - * \li #ISC_R_SUCCESS - * \li #ISC_R_FAILURE - additional information caching is not supported. - * \li #ISC_R_NOTFOUND - the corresponding DB node has not cached additional - * information for 'rdataset.' - * \li Any error that dns_acache_getentry() can return. - */ - -isc_result_t -dns_rdataset_setadditional(dns_rdataset_t *rdataset, - dns_rdatasetadditional_t type, - dns_rdatatype_t qtype, - dns_acache_t *acache, - dns_zone_t *zone, - dns_db_t *db, - dns_dbversion_t *version, - dns_dbnode_t *node, - dns_name_t *fname); -/*%< - * Set cached additional information to the DB node for a particular - * 'rdataset.' See dns_rdataset_getadditional for the semantics of 'type' - * and 'qtype'. - * - * Requires: - * \li 'rdataset' is a valid rdataset. - * \li 'acache' can be NULL, in which case this function will simply return - * ISC_R_FAILURE. - * \li For the other pointers, see dns_acache_setentry(). - * - * Ensures: - * \li See dns_acache_setentry(). - * - * Returns: - * \li #ISC_R_SUCCESS - * \li #ISC_R_FAILURE - additional information caching is not supported. - * \li #ISC_R_NOMEMORY - * \li Any error that dns_acache_setentry() can return. - */ - -isc_result_t -dns_rdataset_putadditional(dns_acache_t *acache, - dns_rdataset_t *rdataset, - dns_rdatasetadditional_t type, - dns_rdatatype_t qtype); -/*%< - * Discard cached additional information stored in the DB node for a particular - * 'rdataset.' See dns_rdataset_getadditional for the semantics of 'type' - * and 'qtype'. - * - * Requires: - * \li 'rdataset' is a valid rdataset. - * \li 'acache' can be NULL, in which case this function will simply return - * ISC_R_FAILURE. - * - * Ensures: - * \li See dns_acache_cancelentry(). - * - * Returns: - * \li #ISC_R_SUCCESS - * \li #ISC_R_FAILURE - additional information caching is not supported. - * \li #ISC_R_NOTFOUND - the corresponding DB node has not cached additional - * information for 'rdataset.' - */ - void dns_rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust); /*%< @@ -674,6 +572,32 @@ dns_rdataset_getownercase(const dns_rdataset_t *rdataset, dns_name_t *name); * according to it. If CASESET is not set, do nothing. */ +isc_result_t +dns_rdataset_addglue(dns_rdataset_t *rdataset, + dns_dbversion_t *version, + unsigned int options, + dns_message_t *msg); +/*%< + * Add glue records for rdataset to the additional section of message in + * 'msg'. 'rdataset' must be of type NS. If DNS_RDATASETADDGLUE_FILTERAAAA + * is set in 'options' there is type A glue, type AAAA glue is not added. + * + * In case a successful result is not returned, the caller should try to + * add glue directly to the message by iterating for additional data. + * + * Requires: + * \li 'rdataset' is a valid NS rdataset. + * \li 'version' is the DB version. + * \li 'options' is options; currently only _FILTERAAAA is defined. + * \li 'msg' is the DNS message to which the glue should be added. + * + * Returns: + *\li #ISC_R_SUCCESS + *\li #ISC_R_NOTIMPLEMENTED + *\li #ISC_R_FAILURE + *\li Any error that dns_rdata_additionaldata() can return. + */ + void dns_rdataset_trimttl(dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset, dns_rdata_rrsig_t *rrsig, isc_stdtime_t now, diff --git a/lib/dns/include/dns/types.h b/lib/dns/include/dns/types.h index 0e74817b9e..3e79760c55 100644 --- a/lib/dns/include/dns/types.h +++ b/lib/dns/include/dns/types.h @@ -22,9 +22,6 @@ #include -typedef struct dns_acache dns_acache_t; -typedef struct dns_acacheentry dns_acacheentry_t; -typedef struct dns_acachestats dns_acachestats_t; typedef struct dns_acl dns_acl_t; typedef struct dns_aclelement dns_aclelement_t; typedef struct dns_aclenv dns_aclenv_t; diff --git a/lib/dns/include/dns/view.h b/lib/dns/include/dns/view.h index 2e45f9d214..f08c3d8536 100644 --- a/lib/dns/include/dns/view.h +++ b/lib/dns/include/dns/view.h @@ -83,7 +83,6 @@ struct dns_view { dns_resolver_t * resolver; dns_adb_t * adb; dns_requestmgr_t * requestmgr; - dns_acache_t * acache; dns_cache_t * cache; dns_db_t * cachedb; dns_db_t * hints; @@ -114,8 +113,6 @@ struct dns_view { dns_fwdtable_t * fwdtable; isc_boolean_t recursion; isc_boolean_t auth_nxdomain; - isc_boolean_t additionalfromcache; - isc_boolean_t additionalfromauth; isc_boolean_t minimal_any; dns_minimaltype_t minimalresponses; isc_boolean_t enablednssec; diff --git a/lib/dns/include/dns/zone.h b/lib/dns/include/dns/zone.h index 7eb7c3e8d0..1bf291d497 100644 --- a/lib/dns/include/dns/zone.h +++ b/lib/dns/include/dns/zone.h @@ -2040,19 +2040,6 @@ dns_zone_checknames(dns_zone_t *zone, const dns_name_t *name, * DNS_R_BADNAME failed rdata checks. */ -void -dns_zone_setacache(dns_zone_t *zone, dns_acache_t *acache); -/*%< - * Associate the zone with an additional cache. - * - * Require: - * 'zone' to be a valid zone. - * 'acache' to be a non NULL pointer. - * - * Ensures: - * 'zone' will have a reference to 'acache' - */ - void dns_zone_setcheckmx(dns_zone_t *zone, dns_checkmxfunc_t checkmx); /*%< diff --git a/lib/dns/log.c b/lib/dns/log.c index 3030de012d..b3004d1c97 100644 --- a/lib/dns/log.c +++ b/lib/dns/log.c @@ -71,7 +71,7 @@ LIBDNS_EXTERNAL_DATA isc_logmodule_t dns_modules[] = { { "dns/sdb", 0 }, { "dns/diff", 0 }, { "dns/hints", 0 }, - { "dns/acache", 0 }, + { "dns/unused1", 0 }, { "dns/dlz", 0 }, { "dns/dnssec", 0 }, { "dns/crypto", 0 }, diff --git a/lib/dns/message.c b/lib/dns/message.c index f34b994b62..f2bc44197c 100644 --- a/lib/dns/message.c +++ b/lib/dns/message.c @@ -96,11 +96,11 @@ hexdump(const char *msg, const char *msg2, void *base, size_t len) { * XXXMLG These should come from a config setting. */ #define SCRATCHPAD_SIZE 512 -#define NAME_COUNT 8 +#define NAME_COUNT 64 #define OFFSET_COUNT 4 #define RDATA_COUNT 8 #define RDATALIST_COUNT 8 -#define RDATASET_COUNT RDATALIST_COUNT +#define RDATASET_COUNT 64 /*% * Text representation of the different items, for message_totext @@ -742,6 +742,7 @@ dns_message_create(isc_mem_t *mctx, unsigned int intent, dns_message_t **msgp) result = isc_mempool_create(m->mctx, sizeof(dns_name_t), &m->namepool); if (result != ISC_R_SUCCESS) goto cleanup; + isc_mempool_setfillcount(m->namepool, NAME_COUNT); isc_mempool_setfreemax(m->namepool, NAME_COUNT); isc_mempool_setname(m->namepool, "msg:names"); @@ -749,7 +750,8 @@ dns_message_create(isc_mem_t *mctx, unsigned int intent, dns_message_t **msgp) &m->rdspool); if (result != ISC_R_SUCCESS) goto cleanup; - isc_mempool_setfreemax(m->rdspool, NAME_COUNT); + isc_mempool_setfillcount(m->rdspool, RDATASET_COUNT); + isc_mempool_setfreemax(m->rdspool, RDATASET_COUNT); isc_mempool_setname(m->rdspool, "msg:rdataset"); dynbuf = NULL; diff --git a/lib/dns/name.c b/lib/dns/name.c index f8c0dcb4e1..b5f62399d8 100644 --- a/lib/dns/name.c +++ b/lib/dns/name.c @@ -956,9 +956,9 @@ dns_name_getlabelsequence(const dns_name_t *source, unsigned int first, unsigned int n, dns_name_t *target) { - unsigned char *offsets; - dns_offsets_t odata; + unsigned char *p, l; unsigned int firstoffset, endoffset; + unsigned int i; /* * Make 'target' refer to the 'n' labels including and following @@ -971,17 +971,26 @@ dns_name_getlabelsequence(const dns_name_t *source, REQUIRE(n <= source->labels - first); /* note first+n could overflow */ REQUIRE(BINDABLE(target)); - SETUP_OFFSETS(source, offsets, odata); - - if (first == source->labels) + p = source->ndata; + if (ISC_UNLIKELY(first == source->labels)) { firstoffset = source->length; - else - firstoffset = offsets[first]; + } else { + for (i = 0; i < first; i++) { + l = *p; + p += l + 1; + } + firstoffset = p - source->ndata; + } - if (first + n == source->labels) + if (ISC_LIKELY(first + n == source->labels)) endoffset = source->length; - else - endoffset = offsets[first + n]; + else { + for (i = 0; i < n; i++) { + l = *p; + p += l + 1; + } + endoffset = p - source->ndata; + } target->ndata = &source->ndata[firstoffset]; target->length = endoffset - firstoffset; @@ -1775,16 +1784,15 @@ set_offsets(const dns_name_t *name, unsigned char *offsets, offset = 0; nlabels = 0; absolute = ISC_FALSE; - while (offset != length) { + while (ISC_LIKELY(offset != length)) { INSIST(nlabels < 128); offsets[nlabels++] = offset; - count = *ndata++; - offset++; + count = *ndata; INSIST(count <= 63); - offset += count; - ndata += count; + offset += count + 1; + ndata += count + 1; INSIST(offset <= length); - if (count == 0) { + if (ISC_UNLIKELY(count == 0)) { absolute = ISC_TRUE; break; } diff --git a/lib/dns/ncache.c b/lib/dns/ncache.c index e328778ad8..24a123a482 100644 --- a/lib/dns/ncache.c +++ b/lib/dns/ncache.c @@ -484,18 +484,16 @@ static dns_rdatasetmethods_t rdataset_methods = { rdataset_current, rdataset_clone, rdataset_count, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - rdataset_settrust, - NULL, - NULL, - NULL, - NULL + NULL, /* addnoqname */ + NULL, /* getnoqname */ + NULL, /* addclosest */ + NULL, /* getclosest */ + rdataset_settrust, /* settrust */ + NULL, /* expire */ + NULL, /* clearprefetch */ + NULL, /* setownercase */ + NULL, /* getownercase */ + NULL /* addglue */ }; isc_result_t diff --git a/lib/dns/order.c b/lib/dns/order.c index bda589e7ec..0cdf2c855f 100644 --- a/lib/dns/order.c +++ b/lib/dns/order.c @@ -6,8 +6,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* $Id: order.c,v 1.10 2007/06/19 23:47:16 tbox Exp $ */ - /*! \file */ #include @@ -80,7 +78,7 @@ dns_order_add(dns_order_t *order, const dns_name_t *name, REQUIRE(DNS_ORDER_VALID(order)); REQUIRE(mode == DNS_RDATASETATTR_RANDOMIZE || mode == DNS_RDATASETATTR_FIXEDORDER || - mode == 0 /* DNS_RDATASETATTR_CYCLIC */ ); + mode == DNS_RDATASETATTR_CYCLIC); ent = isc_mem_get(order->mctx, sizeof(*ent)); if (ent == NULL) @@ -123,7 +121,7 @@ dns_order_find(dns_order_t *order, const dns_name_t *name, if (match(name, dns_fixedname_name(&ent->name))) return (ent->mode); } - return (DNS_RDATASETATTR_RANDOMIZE); + return (DNS_RDATASETATTR_NONE); } void diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c index f17a12a354..42ae89a367 100644 --- a/lib/dns/rbtdb.c +++ b/lib/dns/rbtdb.c @@ -40,8 +40,8 @@ #include #include #include +#include -#include #include #include #include @@ -143,8 +143,6 @@ typedef isc_uint64_t rbtdb_serial_t; #define slab_methods slab_methods64 #define zone_methods zone_methods64 -#define acache_callback acache_callback64 -#define acache_cancelentry acache_cancelentry64 #define activeempty activeempty64 #define activeemtpynode activeemtpynode64 #define add32 add64 @@ -195,7 +193,8 @@ typedef isc_uint64_t rbtdb_serial_t; #define findnodeintree findnodeintree64 #define findnsec3node findnsec3node64 #define flush_deletions flush_deletions64 -#define free_acachearray free_acachearray64 +#define free_gluelist free_gluelist64 +#define free_gluetable free_gluetable64 #define free_noqname free_noqname64 #define free_rbtdb free_rbtdb64 #define free_rbtdb_callback free_rbtdb_callback64 @@ -205,6 +204,7 @@ typedef isc_uint64_t rbtdb_serial_t; #define getoriginnode getoriginnode64 #define getrrsetstats getrrsetstats64 #define getsigningtime getsigningtime64 +#define glue_nsdname_cb glue_nsdname_cb64 #define hashsize hashsize64 #define init_file_version init_file_version64 #define isdnssec isdnssec64 @@ -225,6 +225,7 @@ typedef isc_uint64_t rbtdb_serial_t; #define prune_tree prune_tree64 #define rbt_datafixer rbt_datafixer64 #define rbt_datawriter rbt_datawriter64 +#define rdataset_addglue rdataset_addglue64 #define rdataset_clearprefetch rdataset_clearprefetch64 #define rdataset_clone rdataset_clone64 #define rdataset_count rdataset_count64 @@ -232,13 +233,10 @@ typedef isc_uint64_t rbtdb_serial_t; #define rdataset_disassociate rdataset_disassociate64 #define rdataset_expire rdataset_expire64 #define rdataset_first rdataset_first64 -#define rdataset_getadditional rdataset_getadditional64 #define rdataset_getclosest rdataset_getclosest64 #define rdataset_getnoqname rdataset_getnoqname64 #define rdataset_getownercase rdataset_getownercase64 #define rdataset_next rdataset_next64 -#define rdataset_putadditional rdataset_putadditional64 -#define rdataset_setadditional rdataset_setadditional64 #define rdataset_setownercase rdataset_setownercase64 #define rdataset_settrust rdataset_settrust64 #define rdatasetiter_current rdatasetiter_current64 @@ -391,8 +389,6 @@ struct noqname { dns_rdatatype_t type; }; -typedef struct acachectl acachectl_t; - typedef struct rdatasetheader { /*% * Locked by the owning node's lock. @@ -436,9 +432,6 @@ typedef struct rdatasetheader { * performance reasons. */ - acachectl_t *additional_auth; - acachectl_t *additional_glue; - dns_rbtnode_t *node; isc_stdtime_t last_used; ISC_LINK(struct rdatasetheader) link; @@ -471,19 +464,7 @@ typedef ISC_LIST(dns_rbtnode_t) rbtnodelist_t; #define RDATASET_ATTR_PREFETCH 0x0200 #define RDATASET_ATTR_CASESET 0x0400 #define RDATASET_ATTR_ZEROTTL 0x0800 - -typedef struct acache_cbarg { - dns_rdatasetadditional_t type; - unsigned int count; - dns_db_t *db; - dns_dbnode_t *node; - rdatasetheader_t *header; -} acache_cbarg_t; - -struct acachectl { - dns_acacheentry_t *entry; - acache_cbarg_t *cbarg; -}; +#define RDATASET_ATTR_CASEFULLYLOWER 0x1000 /* * XXX @@ -519,12 +500,15 @@ struct acachectl { (((header)->attributes & RDATASET_ATTR_CASESET) != 0) #define ZEROTTL(header) \ (((header)->attributes & RDATASET_ATTR_ZEROTTL) != 0) +#define CASEFULLYLOWER(header) \ + (((header)->attributes & RDATASET_ATTR_CASEFULLYLOWER) != 0) #define ACTIVE(header, now) \ (((header)->rdh_ttl > (now)) || \ ((header)->rdh_ttl == (now) && ZEROTTL(header))) #define DEFAULT_NODE_LOCK_COUNT 7 /*%< Should be prime. */ +#define RBTDB_GLUE_TABLE_INIT_SIZE 2U /*% * Number of buckets for cache DB entries (locks, LRU lists, TTL heaps). @@ -577,6 +561,14 @@ typedef enum { expire_flush } expire_t; +typedef struct rbtdb_glue rbtdb_glue_t; + +typedef struct rbtdb_glue_table_node { + struct rbtdb_glue_table_node *next; + dns_rbtnode_t *node; + rbtdb_glue_t *glue_list; +} rbtdb_glue_table_node_t; + typedef struct rbtdb_version { /* Not locked */ rbtdb_serial_t serial; @@ -608,6 +600,11 @@ typedef struct rbtdb_version { isc_rwlock_t rwlock; isc_uint64_t records; isc_uint64_t bytes; + + isc_rwlock_t glue_rwlock; + size_t glue_table_size; + size_t glue_table_nodecount; + rbtdb_glue_table_node_t **glue_table; } rbtdb_version_t; typedef ISC_LIST(rbtdb_version_t) rbtdb_versionlist_t; @@ -725,30 +722,6 @@ static isc_result_t rdataset_getclosest(dns_rdataset_t *rdataset, dns_name_t *name, dns_rdataset_t *neg, dns_rdataset_t *negsig); -static isc_result_t rdataset_getadditional(dns_rdataset_t *rdataset, - dns_rdatasetadditional_t type, - dns_rdatatype_t qtype, - dns_acache_t *acache, - dns_zone_t **zonep, - dns_db_t **dbp, - dns_dbversion_t **versionp, - dns_dbnode_t **nodep, - dns_name_t *fname, - dns_message_t *msg, - isc_stdtime_t now); -static isc_result_t rdataset_setadditional(dns_rdataset_t *rdataset, - dns_rdatasetadditional_t type, - dns_rdatatype_t qtype, - dns_acache_t *acache, - dns_zone_t *zone, - dns_db_t *db, - dns_dbversion_t *version, - dns_dbnode_t *node, - dns_name_t *fname); -static isc_result_t rdataset_putadditional(dns_acache_t *acache, - dns_rdataset_t *rdataset, - dns_rdatasetadditional_t type, - dns_rdatatype_t qtype); static inline isc_boolean_t need_headerupdate(rdatasetheader_t *header, isc_stdtime_t now); static void update_header(dns_rbtdb_t *rbtdb, rdatasetheader_t *header, @@ -769,6 +742,11 @@ static void rdataset_setownercase(dns_rdataset_t *rdataset, const dns_name_t *name); static void rdataset_getownercase(const dns_rdataset_t *rdataset, dns_name_t *name); +static isc_result_t rdataset_addglue(dns_rdataset_t *rdataset, + dns_dbversion_t *version, + unsigned int options, + dns_message_t *msg); +static void free_gluetable(rbtdb_version_t *version); static dns_rdatasetmethods_t rdataset_methods = { rdataset_disassociate, @@ -777,18 +755,16 @@ static dns_rdatasetmethods_t rdataset_methods = { rdataset_current, rdataset_clone, rdataset_count, - NULL, + NULL, /* addnoqname */ rdataset_getnoqname, - NULL, + NULL, /* addclosest */ rdataset_getclosest, - rdataset_getadditional, - rdataset_setadditional, - rdataset_putadditional, rdataset_settrust, rdataset_expire, rdataset_clearprefetch, rdataset_setownercase, - rdataset_getownercase + rdataset_getownercase, + rdataset_addglue }; static dns_rdatasetmethods_t slab_methods = { @@ -798,18 +774,16 @@ static dns_rdatasetmethods_t slab_methods = { rdataset_current, rdataset_clone, rdataset_count, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL + NULL, /* addnoqname */ + NULL, /* getnoqname */ + NULL, /* addclosest */ + NULL, /* getclosest */ + NULL, /* settrust */ + NULL, /* expire */ + NULL, /* clearprefetch */ + NULL, /* setownercase */ + NULL, /* getownercase */ + NULL /* addglue */ }; static void rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp); @@ -1172,6 +1146,7 @@ free_rbtdb(dns_rbtdb_t *rbtdb, isc_boolean_t log, isc_event_t *event) { &refs); INSIST(refs == 0); UNLINK(rbtdb->open_versions, rbtdb->current_version, link); + isc_rwlock_destroy(&rbtdb->current_version->glue_rwlock); isc_refcount_destroy(&rbtdb->current_version->references); isc_rwlock_destroy(&rbtdb->current_version->rwlock); isc_mem_put(rbtdb->common.mctx, rbtdb->current_version, @@ -1331,6 +1306,15 @@ maybe_free_rbtdb(dns_rbtdb_t *rbtdb) { if (rbtdb->nsnode != NULL) dns_db_detachnode((dns_db_t *)rbtdb, &rbtdb->nsnode); + /* + * The current version's glue table needs to be freed early + * so the nodes are dereferenced before we check the active + * node count below. + */ + if (rbtdb->current_version != NULL) { + free_gluetable(rbtdb->current_version); + } + /* * Even though there are no external direct references, there still * may be nodes in use. @@ -1339,8 +1323,8 @@ maybe_free_rbtdb(dns_rbtdb_t *rbtdb) { NODE_LOCK(&rbtdb->node_locks[i].lock, isc_rwlocktype_write); rbtdb->node_locks[i].exiting = ISC_TRUE; NODE_UNLOCK(&rbtdb->node_locks[i].lock, isc_rwlocktype_write); - if (isc_refcount_current(&rbtdb->node_locks[i].references) - == 0) { + if (isc_refcount_current(&rbtdb->node_locks[i].references) == 0) + { inactive++; } } @@ -1348,16 +1332,18 @@ maybe_free_rbtdb(dns_rbtdb_t *rbtdb) { if (inactive != 0) { RBTDB_LOCK(&rbtdb->lock, isc_rwlocktype_write); rbtdb->active -= inactive; - if (rbtdb->active == 0) + if (rbtdb->active == 0) { want_free = ISC_TRUE; + } RBTDB_UNLOCK(&rbtdb->lock, isc_rwlocktype_write); if (want_free) { char buf[DNS_NAME_FORMATSIZE]; - if (dns_name_dynamic(&rbtdb->common.origin)) + if (dns_name_dynamic(&rbtdb->common.origin)) { dns_name_format(&rbtdb->common.origin, buf, sizeof(buf)); - else + } else { strcpy(buf, ""); + } isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_CACHE, ISC_LOG_DEBUG(1), "calling free_rbtdb(%s)", buf); @@ -1403,6 +1389,7 @@ allocate_version(isc_mem_t *mctx, rbtdb_serial_t serial, { isc_result_t result; rbtdb_version_t *version; + size_t i; version = isc_mem_get(mctx, sizeof(*version)); if (version == NULL) @@ -1413,12 +1400,34 @@ allocate_version(isc_mem_t *mctx, rbtdb_serial_t serial, isc_mem_put(mctx, version, sizeof(*version)); return (NULL); } + result = isc_rwlock_init(&version->glue_rwlock, 0, 0); + if (result != ISC_R_SUCCESS) { + isc_refcount_destroy(&version->references); + isc_mem_put(mctx, version, sizeof(*version)); + return (NULL); + } + + version->glue_table_size = RBTDB_GLUE_TABLE_INIT_SIZE; + version->glue_table_nodecount = 0U; + version->glue_table = (rbtdb_glue_table_node_t **) + isc_mem_get(mctx, (version->glue_table_size * + sizeof(*version->glue_table))); + if (version->glue_table == NULL) { + isc_rwlock_destroy(&version->glue_rwlock); + isc_refcount_destroy(&version->references); + isc_mem_put(mctx, version, sizeof(*version)); + return (NULL); + } + version->writer = writer; version->commit_ok = ISC_FALSE; ISC_LIST_INIT(version->changed_list); ISC_LIST_INIT(version->resigned_list); ISC_LINK_INIT(version, link); + for (i = 0; i < version->glue_table_size; i++) + version->glue_table[i] = NULL; + return (version); } @@ -1459,6 +1468,8 @@ newversion(dns_db_t *db, dns_dbversion_t **versionp) { } result = isc_rwlock_init(&version->rwlock, 0, 0); if (result != ISC_R_SUCCESS) { + free_gluetable(version); + isc_rwlock_destroy(&version->glue_rwlock); isc_refcount_destroy(&version->references); isc_mem_put(rbtdb->common.mctx, version, sizeof(*version)); @@ -1534,35 +1545,6 @@ add_changed(dns_rbtdb_t *rbtdb, rbtdb_version_t *version, return (changed); } -static void -free_acachearray(isc_mem_t *mctx, rdatasetheader_t *header, - acachectl_t *array) -{ - unsigned int count; - unsigned int i; - unsigned char *raw; /* RDATASLAB */ - - /* - * The caller must be holding the corresponding node lock. - */ - - if (array == NULL) - return; - - raw = (unsigned char *)header + sizeof(*header); - count = raw[0] * 256 + raw[1]; - - /* - * Sanity check: since an additional cache entry has a reference to - * the original DB node (in the callback arg), there should be no - * acache entries when the node can be freed. - */ - for (i = 0; i < count; i++) - INSIST(array[i].entry == NULL && array[i].cbarg == NULL); - - isc_mem_put(mctx, array, count * sizeof(acachectl_t)); -} - static inline void free_noqname(isc_mem_t *mctx, struct noqname **noqname) { @@ -1612,8 +1594,12 @@ update_newheader(rdatasetheader_t *new, rdatasetheader_t *old) { new->node = (dns_rbtnode_t *)p; } if (CASESET(old)) { + uint16_t attr; + memmove(new->upper, old->upper, sizeof(old->upper)); - new->attributes |= RDATASET_ATTR_CASESET; + attr = old->attributes & (RDATASET_ATTR_CASESET | + RDATASET_ATTR_CASEFULLYLOWER); + new->attributes |= attr; } } @@ -1660,9 +1646,6 @@ free_rdataset(dns_rbtdb_t *rbtdb, isc_mem_t *mctx, rdatasetheader_t *rdataset) { if (rdataset->closest != NULL) free_noqname(mctx, &rdataset->closest); - free_acachearray(mctx, rdataset, rdataset->additional_auth); - free_acachearray(mctx, rdataset, rdataset->additional_glue); - if (NONEXISTENT(rdataset)) size = sizeof(*rdataset); else @@ -2754,6 +2737,8 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) { if (cleanup_version != NULL) { INSIST(EMPTY(cleanup_version->changed_list)); + free_gluetable(cleanup_version); + isc_rwlock_destroy(&cleanup_version->glue_rwlock); isc_rwlock_destroy(&cleanup_version->rwlock); isc_mem_put(rbtdb->common.mctx, cleanup_version, sizeof(*cleanup_version)); @@ -2780,7 +2765,7 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) { DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_ZONE, ISC_LOG_ERROR, "Unable to reinsert header to " - "re-signing heap: %s\n", + "re-signing heap: %s", dns_result_totext(result)); } decrement_reference(rbtdb, header->node, least_serial, @@ -6610,8 +6595,6 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, newheader->closest = NULL; newheader->count = init_count++; newheader->trust = rdataset->trust; - newheader->additional_auth = NULL; - newheader->additional_glue = NULL; newheader->last_used = now; newheader->node = rbtnode; if (rbtversion != NULL) { @@ -6798,8 +6781,6 @@ subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, newheader->noqname = NULL; newheader->closest = NULL; newheader->count = init_count++; - newheader->additional_auth = NULL; - newheader->additional_glue = NULL; newheader->last_used = 0; newheader->node = rbtnode; if ((rdataset->attributes & DNS_RDATASETATTR_RESIGN) != 0) { @@ -6873,8 +6854,6 @@ subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, * to additional info. We need to clear these fields * to avoid having duplicated references. */ - newheader->additional_auth = NULL; - newheader->additional_glue = NULL; rbtversion->records += dns_rdataslab_count((unsigned char *)newheader, sizeof(*newheader)); @@ -6901,8 +6880,6 @@ subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, newheader->noqname = NULL; newheader->closest = NULL; newheader->count = 0; - newheader->additional_auth = NULL; - newheader->additional_glue = NULL; newheader->node = rbtnode; newheader->resign = 0; newheader->resign_lsb = 0; @@ -6994,8 +6971,6 @@ deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, newheader->trust = 0; newheader->noqname = NULL; newheader->closest = NULL; - newheader->additional_auth = NULL; - newheader->additional_glue = NULL; if (rbtversion != NULL) newheader->serial = rbtversion->serial; else @@ -7192,8 +7167,6 @@ loading_addrdataset(void *arg, const dns_name_t *name, newheader->noqname = NULL; newheader->closest = NULL; newheader->count = init_count++; - newheader->additional_auth = NULL; - newheader->additional_glue = NULL; newheader->last_used = 0; newheader->node = node; setownercase(newheader, name); @@ -8429,6 +8402,8 @@ dns_rbtdb_create sizeof(rbtdb->current_version->salt)); result = isc_rwlock_init(&rbtdb->current_version->rwlock, 0, 0); if (result != ISC_R_SUCCESS) { + free_gluetable(rbtdb->current_version); + isc_rwlock_destroy(&rbtdb->current_version->glue_rwlock); isc_refcount_destroy(&rbtdb->current_version->references); isc_mem_put(mctx, rbtdb->current_version, sizeof(*rbtdb->current_version)); @@ -9450,371 +9425,25 @@ dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name) { return (dns_name_copy(origin, name, NULL)); } -/*% - * Additional cache routines. - */ -static isc_result_t -rdataset_getadditional(dns_rdataset_t *rdataset, dns_rdatasetadditional_t type, - dns_rdatatype_t qtype, dns_acache_t *acache, - dns_zone_t **zonep, dns_db_t **dbp, - dns_dbversion_t **versionp, dns_dbnode_t **nodep, - dns_name_t *fname, dns_message_t *msg, - isc_stdtime_t now) -{ - dns_rbtdb_t *rbtdb = rdataset->private1; - dns_rbtnode_t *rbtnode = rdataset->private2; - unsigned char *raw = rdataset->private3; /* RDATASLAB */ - unsigned int current_count = rdataset->privateuint4; - unsigned int count; - rdatasetheader_t *header; - nodelock_t *nodelock; - unsigned int total_count; - acachectl_t *acarray; - dns_acacheentry_t *entry; - isc_result_t result; - - UNUSED(qtype); /* we do not use this value at least for now */ - UNUSED(acache); - - header = (struct rdatasetheader *)(raw - sizeof(*header)); - - total_count = raw[0] * 256 + raw[1]; - INSIST(total_count > current_count); - count = total_count - current_count - 1; - - acarray = NULL; - - nodelock = &rbtdb->node_locks[rbtnode->locknum].lock; - NODE_LOCK(nodelock, isc_rwlocktype_read); - - switch (type) { - case dns_rdatasetadditional_fromauth: - acarray = header->additional_auth; - break; - case dns_rdatasetadditional_fromcache: - acarray = NULL; - break; - case dns_rdatasetadditional_fromglue: - acarray = header->additional_glue; - break; - default: - INSIST(0); - } - - if (acarray == NULL) { - if (type != dns_rdatasetadditional_fromcache) - dns_acache_countquerymiss(acache); - NODE_UNLOCK(nodelock, isc_rwlocktype_read); - return (ISC_R_NOTFOUND); - } - - if (acarray[count].entry == NULL) { - dns_acache_countquerymiss(acache); - NODE_UNLOCK(nodelock, isc_rwlocktype_read); - return (ISC_R_NOTFOUND); - } - - entry = NULL; - dns_acache_attachentry(acarray[count].entry, &entry); - - NODE_UNLOCK(nodelock, isc_rwlocktype_read); - - result = dns_acache_getentry(entry, zonep, dbp, versionp, - nodep, fname, msg, now); - - dns_acache_detachentry(&entry); - - return (result); -} - -static void -acache_callback(dns_acacheentry_t *entry, void **arg) { - dns_rbtdb_t *rbtdb; - dns_rbtnode_t *rbtnode; - nodelock_t *nodelock; - acachectl_t *acarray = NULL; - acache_cbarg_t *cbarg; - unsigned int count; - - REQUIRE(arg != NULL); - cbarg = *arg; - - /* - * The caller must hold the entry lock. - */ - - rbtdb = (dns_rbtdb_t *)cbarg->db; - rbtnode = (dns_rbtnode_t *)cbarg->node; - - nodelock = &rbtdb->node_locks[rbtnode->locknum].lock; - NODE_LOCK(nodelock, isc_rwlocktype_write); - - switch (cbarg->type) { - case dns_rdatasetadditional_fromauth: - acarray = cbarg->header->additional_auth; - break; - case dns_rdatasetadditional_fromglue: - acarray = cbarg->header->additional_glue; - break; - default: - INSIST(0); - } - - count = cbarg->count; - if (acarray != NULL && acarray[count].entry == entry) { - acarray[count].entry = NULL; - INSIST(acarray[count].cbarg == cbarg); - acarray[count].cbarg = NULL; - isc_mem_put(rbtdb->common.mctx, cbarg, sizeof(acache_cbarg_t)); - dns_acache_detachentry(&entry); - } - - NODE_UNLOCK(nodelock, isc_rwlocktype_write); - - dns_db_detachnode((dns_db_t *)rbtdb, (dns_dbnode_t **)(void*)&rbtnode); - dns_db_detach((dns_db_t **)(void*)&rbtdb); - - *arg = NULL; -} - -static void -acache_cancelentry(isc_mem_t *mctx, dns_acacheentry_t *entry, - acache_cbarg_t **cbargp) -{ - acache_cbarg_t *cbarg; - - REQUIRE(mctx != NULL); - REQUIRE(entry != NULL); - REQUIRE(cbargp != NULL && *cbargp != NULL); - - cbarg = *cbargp; - - if (dns_acache_cancelentry(entry)) { - dns_db_detachnode(cbarg->db, &cbarg->node); - dns_db_detach(&cbarg->db); - } - - isc_mem_put(mctx, cbarg, sizeof(acache_cbarg_t)); - - *cbargp = NULL; -} - -static isc_result_t -rdataset_setadditional(dns_rdataset_t *rdataset, dns_rdatasetadditional_t type, - dns_rdatatype_t qtype, dns_acache_t *acache, - dns_zone_t *zone, dns_db_t *db, - dns_dbversion_t *version, dns_dbnode_t *node, - dns_name_t *fname) -{ - dns_rbtdb_t *rbtdb = rdataset->private1; - dns_rbtnode_t *rbtnode = rdataset->private2; - unsigned char *raw = rdataset->private3; /* RDATASLAB */ - unsigned int current_count = rdataset->privateuint4; - rdatasetheader_t *header; - unsigned int total_count, count; - nodelock_t *nodelock; - isc_result_t result; - acachectl_t *acarray; - dns_acacheentry_t *newentry, *oldentry = NULL; - acache_cbarg_t *newcbarg, *oldcbarg = NULL; - - UNUSED(qtype); - - if (type == dns_rdatasetadditional_fromcache) - return (ISC_R_SUCCESS); - - header = (struct rdatasetheader *)(raw - sizeof(*header)); - - total_count = raw[0] * 256 + raw[1]; - INSIST(total_count > current_count); - count = total_count - current_count - 1; /* should be private data */ - - newcbarg = isc_mem_get(rbtdb->common.mctx, sizeof(*newcbarg)); - if (newcbarg == NULL) - return (ISC_R_NOMEMORY); - newcbarg->type = type; - newcbarg->count = count; - newcbarg->header = header; - newcbarg->db = NULL; - dns_db_attach((dns_db_t *)rbtdb, &newcbarg->db); - newcbarg->node = NULL; - dns_db_attachnode((dns_db_t *)rbtdb, (dns_dbnode_t *)rbtnode, - &newcbarg->node); - newentry = NULL; - result = dns_acache_createentry(acache, (dns_db_t *)rbtdb, - acache_callback, newcbarg, &newentry); - if (result != ISC_R_SUCCESS) - goto fail; - - /* Set cache data in the new entry. */ - result = dns_acache_setentry(acache, newentry, zone, db, - version, node, fname); - if (result != ISC_R_SUCCESS) - goto fail; - - nodelock = &rbtdb->node_locks[rbtnode->locknum].lock; - NODE_LOCK(nodelock, isc_rwlocktype_write); - - acarray = NULL; - switch (type) { - case dns_rdatasetadditional_fromauth: - acarray = header->additional_auth; - break; - case dns_rdatasetadditional_fromglue: - acarray = header->additional_glue; - break; - default: - INSIST(0); - } - - if (acarray == NULL) { - unsigned int i; - - acarray = isc_mem_get(rbtdb->common.mctx, total_count * - sizeof(acachectl_t)); - - if (acarray == NULL) { - NODE_UNLOCK(nodelock, isc_rwlocktype_write); - goto fail; - } - - for (i = 0; i < total_count; i++) { - acarray[i].entry = NULL; - acarray[i].cbarg = NULL; - } - } - switch (type) { - case dns_rdatasetadditional_fromauth: - header->additional_auth = acarray; - break; - case dns_rdatasetadditional_fromglue: - header->additional_glue = acarray; - break; - default: - INSIST(0); - } - - if (acarray[count].entry != NULL) { - /* - * Swap the entry. Delay cleaning-up the old entry since - * it would require a node lock. - */ - oldentry = acarray[count].entry; - INSIST(acarray[count].cbarg != NULL); - oldcbarg = acarray[count].cbarg; - } - acarray[count].entry = newentry; - acarray[count].cbarg = newcbarg; - - NODE_UNLOCK(nodelock, isc_rwlocktype_write); - - if (oldentry != NULL) { - acache_cancelentry(rbtdb->common.mctx, oldentry, &oldcbarg); - dns_acache_detachentry(&oldentry); - } - - return (ISC_R_SUCCESS); - - fail: - if (newcbarg != NULL) { - if (newentry != NULL) { - acache_cancelentry(rbtdb->common.mctx, newentry, - &newcbarg); - dns_acache_detachentry(&newentry); - } else { - dns_db_detachnode((dns_db_t *)rbtdb, &newcbarg->node); - dns_db_detach(&newcbarg->db); - isc_mem_put(rbtdb->common.mctx, newcbarg, - sizeof(*newcbarg)); - } - } - - return (result); -} - -static isc_result_t -rdataset_putadditional(dns_acache_t *acache, dns_rdataset_t *rdataset, - dns_rdatasetadditional_t type, dns_rdatatype_t qtype) -{ - dns_rbtdb_t *rbtdb = rdataset->private1; - dns_rbtnode_t *rbtnode = rdataset->private2; - unsigned char *raw = rdataset->private3; /* RDATASLAB */ - unsigned int current_count = rdataset->privateuint4; - rdatasetheader_t *header; - nodelock_t *nodelock; - unsigned int total_count, count; - acachectl_t *acarray; - dns_acacheentry_t *entry; - acache_cbarg_t *cbarg; - - UNUSED(qtype); /* we do not use this value at least for now */ - UNUSED(acache); - - if (type == dns_rdatasetadditional_fromcache) - return (ISC_R_SUCCESS); - - header = (struct rdatasetheader *)(raw - sizeof(*header)); - - total_count = raw[0] * 256 + raw[1]; - INSIST(total_count > current_count); - count = total_count - current_count - 1; - - acarray = NULL; - entry = NULL; - - nodelock = &rbtdb->node_locks[rbtnode->locknum].lock; - NODE_LOCK(nodelock, isc_rwlocktype_write); - - switch (type) { - case dns_rdatasetadditional_fromauth: - acarray = header->additional_auth; - break; - case dns_rdatasetadditional_fromglue: - acarray = header->additional_glue; - break; - default: - INSIST(0); - } - - if (acarray == NULL) { - NODE_UNLOCK(nodelock, isc_rwlocktype_write); - return (ISC_R_NOTFOUND); - } - - entry = acarray[count].entry; - if (entry == NULL) { - NODE_UNLOCK(nodelock, isc_rwlocktype_write); - return (ISC_R_NOTFOUND); - } - - acarray[count].entry = NULL; - cbarg = acarray[count].cbarg; - acarray[count].cbarg = NULL; - - NODE_UNLOCK(nodelock, isc_rwlocktype_write); - - if (entry != NULL) { - if (cbarg != NULL) - acache_cancelentry(rbtdb->common.mctx, entry, &cbarg); - dns_acache_detachentry(&entry); - } - - return (ISC_R_SUCCESS); -} - static void setownercase(rdatasetheader_t *header, const dns_name_t *name) { unsigned int i; + isc_boolean_t fully_lower; /* * We do not need to worry about label lengths as they are all * less than or equal to 63. */ memset(header->upper, 0, sizeof(header->upper)); + fully_lower = ISC_TRUE; for (i = 0; i < name->length; i++) - if (name->ndata[i] >= 0x41 && name->ndata[i] <= 0x5a) + if (name->ndata[i] >= 0x41 && name->ndata[i] <= 0x5a) { header->upper[i/8] |= 1 << (i%8); + fully_lower = ISC_FALSE; + } header->attributes |= RDATASET_ATTR_CASESET; + if (ISC_LIKELY(fully_lower)) + header->attributes |= RDATASET_ATTR_CASEFULLYLOWER; } static void @@ -9826,17 +9455,94 @@ rdataset_setownercase(dns_rdataset_t *rdataset, const dns_name_t *name) { setownercase(header, name); } +static const unsigned char charmask[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static unsigned char maptolower[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff +}; + static void rdataset_getownercase(const dns_rdataset_t *rdataset, dns_name_t *name) { const unsigned char *raw = rdataset->private3; /* RDATASLAB */ const rdatasetheader_t *header; - unsigned int i; + unsigned int i, j; + unsigned char bits; + unsigned char c, flip; header = (const struct rdatasetheader *)(raw - sizeof(*header)); if (!CASESET(header)) return; +#if 0 + /* + * This was the original code, and is implemented differently in + * the #else block that follows. + */ for (i = 0; i < name->length; i++) { /* * Set the case bit if it does not match the recorded bit. @@ -9848,6 +9554,587 @@ rdataset_getownercase(const dns_rdataset_t *rdataset, dns_name_t *name) { (header->upper[i/8] & (1 << (i%8))) == 0) name->ndata[i] |= 0x20; /* set the lower case bit */ } +#else + + if (ISC_LIKELY(CASEFULLYLOWER(header))) { + unsigned char *bp, *be; + bp = name->ndata; + be = bp + name->length; + + while (bp <= be - 4) { + c = bp[0]; + bp[0] = maptolower[c]; + c = bp[1]; + bp[1] = maptolower[c]; + c = bp[2]; + bp[2] = maptolower[c]; + c = bp[3]; + bp[3] = maptolower[c]; + bp += 4; + } + while (bp < be) { + c = *bp; + *bp++ = maptolower[c]; + } + return; + } + + i = 0; + for (j = 0; j < (name->length >> 3); j++) { + unsigned int k; + + bits = ~(header->upper[j]); + + for (k = 0; k < 8; k++) { + c = name->ndata[i]; + flip = (bits & 1) << 5; + flip ^= c; + flip &= charmask[c]; + name->ndata[i] ^= flip; + + i++; + bits >>= 1; + } + } + + if (ISC_UNLIKELY(i == name->length)) + return; + + bits = ~(header->upper[j]); + + for (; i < name->length; i++) { + c = name->ndata[i]; + flip = (bits & 1) << 5; + flip ^= c; + flip &= charmask[c]; + name->ndata[i] ^= flip; + + bits >>= 1; + } +#endif +} + +struct rbtdb_glue { + struct rbtdb_glue *next; + dns_fixedname_t fixedname; + dns_rdataset_t rdataset_a; + dns_rdataset_t sigrdataset_a; + dns_rdataset_t rdataset_aaaa; + dns_rdataset_t sigrdataset_aaaa; +}; + +typedef struct { + rbtdb_glue_t *glue_list; + dns_rbtdb_t *rbtdb; + rbtdb_version_t *rbtversion; +} rbtdb_glue_additionaldata_ctx_t; + +static void +free_gluelist(rbtdb_glue_t *glue_list, dns_rbtdb_t *rbtdb) { + rbtdb_glue_t *cur, *cur_next; + + if (glue_list == (void *) -1) + return; + + cur = glue_list; + while (cur != NULL) { + cur_next = cur->next; + + if (dns_rdataset_isassociated(&cur->rdataset_a)) + dns_rdataset_disassociate(&cur->rdataset_a); + if (dns_rdataset_isassociated(&cur->sigrdataset_a)) + dns_rdataset_disassociate(&cur->sigrdataset_a); + + if (dns_rdataset_isassociated(&cur->rdataset_aaaa)) + dns_rdataset_disassociate(&cur->rdataset_aaaa); + if (dns_rdataset_isassociated(&cur->sigrdataset_aaaa)) + dns_rdataset_disassociate(&cur->sigrdataset_aaaa); + + dns_rdataset_invalidate(&cur->rdataset_a); + dns_rdataset_invalidate(&cur->sigrdataset_a); + dns_rdataset_invalidate(&cur->rdataset_aaaa); + dns_rdataset_invalidate(&cur->sigrdataset_aaaa); + + isc_mem_put(rbtdb->common.mctx, cur, sizeof(*cur)); + cur = cur_next; + } +} + +static void +free_gluetable(rbtdb_version_t *version) { + dns_rbtdb_t *rbtdb; + size_t i; + + RWLOCK(&version->glue_rwlock, isc_rwlocktype_write); + + rbtdb = version->rbtdb; + + for (i = 0; i < version->glue_table_size; i++) { + rbtdb_glue_table_node_t *cur, *cur_next; + + cur = version->glue_table[i]; + while (cur != NULL) { + cur_next = cur->next; + /* dns_rbtnode_refdecrement(cur->node, NULL); */ + cur->node = NULL; + free_gluelist(cur->glue_list, rbtdb); + cur->glue_list = NULL; + isc_mem_put(rbtdb->common.mctx, cur, sizeof(*cur)); + cur = cur_next; + } + version->glue_table[i] = NULL; + } + + isc_mem_put(rbtdb->common.mctx, version->glue_table, + (sizeof(*version->glue_table) * + version->glue_table_size)); + + RWUNLOCK(&version->glue_rwlock, isc_rwlocktype_write); +} + +static isc_boolean_t +rehash_gluetable(rbtdb_version_t *version) { + size_t oldsize; + rbtdb_glue_table_node_t **oldtable; + rbtdb_glue_table_node_t *gluenode; + rbtdb_glue_table_node_t *nextgluenode; + uint32_t hash; + size_t i; + + if (ISC_LIKELY(version->glue_table_nodecount < + (version->glue_table_size * 3U))) + return (ISC_FALSE); + + oldsize = version->glue_table_size; + oldtable = version->glue_table; + do { + INSIST((version->glue_table_size * 2 + 1) > + version->glue_table_size); + version->glue_table_size = version->glue_table_size * 2 + 1; + } while (version->glue_table_nodecount >= + (version->glue_table_size * 3U)); + + version->glue_table = (rbtdb_glue_table_node_t **) + isc_mem_get(version->rbtdb->common.mctx, + (version->glue_table_size * + sizeof(*version->glue_table))); + if (ISC_UNLIKELY(version->glue_table == NULL)) { + version->glue_table = oldtable; + version->glue_table_size = oldsize; + return (ISC_FALSE); + } + + for (i = 0; i < version->glue_table_size; i++) + version->glue_table[i] = NULL; + + for (i = 0; i < oldsize; i++) { + for (gluenode = oldtable[i]; + gluenode != NULL; + gluenode = nextgluenode) + { + hash = isc_hash_function(&gluenode->node, + sizeof(gluenode->node), + ISC_TRUE, NULL) % + version->glue_table_size; + nextgluenode = gluenode->next; + gluenode->next = version->glue_table[hash]; + version->glue_table[hash] = gluenode; + } + } + + isc_mem_put(version->rbtdb->common.mctx, oldtable, + oldsize * sizeof(*version->glue_table)); + + isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, + DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3), + "rehash_gluetable(): " + "resized glue table from %"ISC_PRINT_QUADFORMAT"u to " + "%"ISC_PRINT_QUADFORMAT"u", + (isc_uint64_t) oldsize, + (isc_uint64_t) version->glue_table_size); + + return (ISC_TRUE); +} + +static isc_result_t +glue_nsdname_cb(void *arg, const dns_name_t *name, dns_rdatatype_t qtype) { + rbtdb_glue_additionaldata_ctx_t *ctx; + isc_result_t result; + dns_fixedname_t fixedname_a; + dns_name_t *name_a; + dns_rdataset_t rdataset_a, sigrdataset_a; + dns_rbtnode_t *node_a; + dns_fixedname_t fixedname_aaaa; + dns_name_t *name_aaaa; + dns_rdataset_t rdataset_aaaa, sigrdataset_aaaa; + dns_rbtnode_t *node_aaaa; + rbtdb_glue_t *glue; + dns_name_t *gluename; + + /* + * NS records want addresses in additional records. + */ + INSIST(qtype == dns_rdatatype_a); + + ctx = (rbtdb_glue_additionaldata_ctx_t *) arg; + result = ISC_R_FAILURE; + glue = NULL; + node_a = NULL; + node_aaaa = NULL; + + dns_fixedname_init(&fixedname_a); + name_a = dns_fixedname_name(&fixedname_a); + dns_rdataset_init(&rdataset_a); + dns_rdataset_init(&sigrdataset_a); + + dns_fixedname_init(&fixedname_aaaa); + name_aaaa = dns_fixedname_name(&fixedname_aaaa); + dns_rdataset_init(&rdataset_aaaa); + dns_rdataset_init(&sigrdataset_aaaa); + + result = zone_find((dns_db_t *) ctx->rbtdb, name, ctx->rbtversion, + dns_rdatatype_a, DNS_DBFIND_GLUEOK, 0, + (dns_dbnode_t **) &node_a, name_a, + &rdataset_a, &sigrdataset_a); + if (result == DNS_R_GLUE) { + glue = isc_mem_get(ctx->rbtdb->common.mctx, sizeof(*glue)); + if (glue == NULL) { + result = ISC_R_NOMEMORY; + goto out; + } + + dns_fixedname_init(&glue->fixedname); + gluename = dns_fixedname_name(&glue->fixedname); + dns_name_copy(name_a, gluename, NULL); + + dns_rdataset_init(&glue->rdataset_a); + dns_rdataset_init(&glue->sigrdataset_a); + dns_rdataset_init(&glue->rdataset_aaaa); + dns_rdataset_init(&glue->sigrdataset_aaaa); + + dns_rdataset_clone(&rdataset_a, &glue->rdataset_a); + if (dns_rdataset_isassociated(&sigrdataset_a)) { + dns_rdataset_clone(&sigrdataset_a, + &glue->sigrdataset_a); + } + } + + result = zone_find((dns_db_t *) ctx->rbtdb, name, ctx->rbtversion, + dns_rdatatype_aaaa, DNS_DBFIND_GLUEOK, 0, + (dns_dbnode_t **) &node_aaaa, name_aaaa, + &rdataset_aaaa, &sigrdataset_aaaa); + if (result == DNS_R_GLUE) { + if (glue == NULL) { + glue = isc_mem_get(ctx->rbtdb->common.mctx, + sizeof(*glue)); + if (glue == NULL) { + result = ISC_R_NOMEMORY; + goto out; + } + + dns_fixedname_init(&glue->fixedname); + gluename = dns_fixedname_name(&glue->fixedname); + dns_name_copy(name_aaaa, gluename, NULL); + + dns_rdataset_init(&glue->rdataset_a); + dns_rdataset_init(&glue->sigrdataset_a); + dns_rdataset_init(&glue->rdataset_aaaa); + dns_rdataset_init(&glue->sigrdataset_aaaa); + } else { + INSIST(node_a == node_aaaa); + INSIST(dns_name_equal(name_a, name_aaaa)); + } + + dns_rdataset_clone(&rdataset_aaaa, &glue->rdataset_aaaa); + if (dns_rdataset_isassociated(&sigrdataset_aaaa)) { + dns_rdataset_clone(&sigrdataset_aaaa, + &glue->sigrdataset_aaaa); + } + } + + if (glue != NULL) { + glue->next = ctx->glue_list; + ctx->glue_list = glue; + } + + result = ISC_R_SUCCESS; + +out: + if (dns_rdataset_isassociated(&rdataset_a)) + rdataset_disassociate(&rdataset_a); + if (dns_rdataset_isassociated(&sigrdataset_a)) + rdataset_disassociate(&sigrdataset_a); + + if (dns_rdataset_isassociated(&rdataset_aaaa)) + rdataset_disassociate(&rdataset_aaaa); + if (dns_rdataset_isassociated(&sigrdataset_aaaa)) + rdataset_disassociate(&sigrdataset_aaaa); + + if (node_a != NULL) + detachnode((dns_db_t *) ctx->rbtdb, (dns_dbnode_t *) &node_a); + if (node_aaaa != NULL) + detachnode((dns_db_t *) ctx->rbtdb, + (dns_dbnode_t *) &node_aaaa); + + return (result); +} + +static isc_result_t +rdataset_addglue(dns_rdataset_t *rdataset, + dns_dbversion_t *version, + unsigned int options, + dns_message_t *msg) +{ + dns_rbtdb_t *rbtdb = rdataset->private1; + dns_rbtnode_t *node = rdataset->private2; + rbtdb_version_t *rbtversion = version; + isc_uint32_t index; + rbtdb_glue_table_node_t *cur; + isc_boolean_t found; + isc_boolean_t restarted; + rbtdb_glue_t *ge; + rbtdb_glue_additionaldata_ctx_t ctx; + isc_result_t result; + + INSIST(rdataset->type == dns_rdatatype_ns); + INSIST(rbtdb == rbtversion->rbtdb); + INSIST(!IS_CACHE(rbtdb) && !IS_STUB(rbtdb)); + + found = ISC_FALSE; + restarted = ISC_FALSE; + result = ISC_R_FAILURE; + + /* + * The glue table cache that forms a part of the DB version + * structure is not explicitly bounded and there's no cache + * cleaning. The zone data size itself is an implicit bound. + * + * The key into the glue hashtable is the node pointer. This is + * because the glue hashtable is a property of the DB version, + * and the glue is keyed for the ownername/NS tuple. We don't + * bother with using an expensive dns_name_t comparison here as + * the node pointer is a fixed value that won't change for a DB + * version and can be compared directly. + */ + index = isc_hash_function(&node, sizeof(node), ISC_TRUE, NULL) % + rbtversion->glue_table_size; + +restart: + /* + * First, check if we have the additional entries already cached + * in the glue table. + */ + RWLOCK(&rbtversion->glue_rwlock, isc_rwlocktype_read); + + for (cur = rbtversion->glue_table[index]; cur != NULL; cur = cur->next) + if (cur->node == node) + break; + + if (cur == NULL) { + goto no_glue; + } + /* + * We found a cached result. Add it to the message and + * return. + */ + found = ISC_TRUE; + ge = cur->glue_list; + + /* + * (void *) -1 is a special value that means no glue is + * present in the zone. + */ + if (ge == (void *) -1) + goto no_glue; + + for (; ge != NULL; ge = ge->next) { + isc_buffer_t *buffer = NULL; + dns_name_t *name = NULL; + dns_rdataset_t *rdataset_a = NULL; + dns_rdataset_t *sigrdataset_a = NULL; + dns_rdataset_t *rdataset_aaaa = NULL; + dns_rdataset_t *sigrdataset_aaaa = NULL; + dns_name_t *gluename = dns_fixedname_name(&ge->fixedname); + + result = isc_buffer_allocate(msg->mctx, &buffer, 512); + if (ISC_UNLIKELY(result != ISC_R_SUCCESS)) { + goto no_glue; + } + + result = dns_message_gettempname(msg, &name); + if (ISC_UNLIKELY(result != ISC_R_SUCCESS)) { + isc_buffer_free(&buffer); + goto no_glue; + } + + dns_name_copy(gluename, name, buffer); + dns_message_takebuffer(msg, &buffer); + + if (dns_rdataset_isassociated(&ge->rdataset_a)) { + result = dns_message_gettemprdataset(msg, &rdataset_a); + if (ISC_UNLIKELY(result != ISC_R_SUCCESS)) { + dns_message_puttempname(msg, &name); + isc_buffer_free(&buffer); + goto no_glue; + } + } + + if (dns_rdataset_isassociated(&ge->sigrdataset_a)) { + result = dns_message_gettemprdataset(msg, + &sigrdataset_a); + if (ISC_UNLIKELY(result != ISC_R_SUCCESS)) { + if (rdataset_a != NULL) { + dns_message_puttemprdataset(msg, + &rdataset_a); + } + dns_message_puttempname(msg, &name); + isc_buffer_free(&buffer); + goto no_glue; + } + } + + if (ISC_LIKELY((options & DNS_RDATASETADDGLUE_FILTERAAAA) == 0)) + { + if (dns_rdataset_isassociated(&ge->rdataset_aaaa)) { + result = dns_message_gettemprdataset(msg, + &rdataset_aaaa); + if (ISC_UNLIKELY(result != ISC_R_SUCCESS)) { + dns_message_puttempname(msg, &name); + isc_buffer_free(&buffer); + if (rdataset_a != NULL) { + dns_message_puttemprdataset(msg, + &rdataset_a); + } + if (sigrdataset_a != NULL) { + dns_message_puttemprdataset(msg, + &sigrdataset_a); + } + goto no_glue; + } + } + + if (dns_rdataset_isassociated(&ge->sigrdataset_aaaa)) { + result = dns_message_gettemprdataset(msg, + &sigrdataset_aaaa); + if (ISC_UNLIKELY(result != ISC_R_SUCCESS)) { + dns_message_puttempname(msg, &name); + isc_buffer_free(&buffer); + if (rdataset_a != NULL) { + dns_message_puttemprdataset(msg, + &rdataset_a); + } + if (sigrdataset_a != NULL) + dns_message_puttemprdataset(msg, + &sigrdataset_a); + if (rdataset_aaaa != NULL) + dns_message_puttemprdataset(msg, + &rdataset_aaaa); + goto no_glue; + } + } + } + + if (ISC_LIKELY(dns_rdataset_isassociated(&ge->rdataset_a))) { + dns_rdataset_clone(&ge->rdataset_a, rdataset_a); + ISC_LIST_APPEND(name->list, rdataset_a, link); + } + + if (dns_rdataset_isassociated(&ge->sigrdataset_a)) { + dns_rdataset_clone(&ge->sigrdataset_a, sigrdataset_a); + ISC_LIST_APPEND(name->list, sigrdataset_a, link); + } + + if (ISC_LIKELY((options & DNS_RDATASETADDGLUE_FILTERAAAA) == 0)) + { + if (dns_rdataset_isassociated(&ge->rdataset_aaaa)) { + dns_rdataset_clone(&ge->rdataset_aaaa, + rdataset_aaaa); + ISC_LIST_APPEND(name->list, rdataset_aaaa, + link); + } + if (dns_rdataset_isassociated(&ge->sigrdataset_aaaa)) { + dns_rdataset_clone(&ge->sigrdataset_aaaa, + sigrdataset_aaaa); + ISC_LIST_APPEND(name->list, sigrdataset_aaaa, + link); + } + } + + dns_message_addname(msg, name, DNS_SECTION_ADDITIONAL); + } + +no_glue: + RWUNLOCK(&rbtversion->glue_rwlock, isc_rwlocktype_read); + + if (found) { + return (ISC_R_SUCCESS); + } + + if (restarted) { + return (ISC_R_FAILURE); + } + + /* + * No cached glue was found in the table. Cache it and restart + * this function. + * + * Due to the gap between the read lock and the write lock, it's + * possible that we may cache a duplicate glue table entry, but + * we don't care. + */ + + ctx.glue_list = NULL; + ctx.rbtdb = rbtdb; + ctx.rbtversion = rbtversion; + + RWLOCK(&rbtversion->glue_rwlock, isc_rwlocktype_write); + + if (ISC_UNLIKELY(rehash_gluetable(rbtversion))) { + index = isc_hash_function(&node, sizeof(node), + ISC_TRUE, NULL) % + rbtversion->glue_table_size; + } + + (void)dns_rdataset_additionaldata(rdataset, glue_nsdname_cb, &ctx); + + cur = isc_mem_get(rbtdb->common.mctx, sizeof(*cur)); + if (cur == NULL) { + result = ISC_R_NOMEMORY; + goto out; + } + + /* + * XXXMUKS: it looks like the dns_dbversion is not destroyed + * when named is terminated by a keyboard break. This doesn't + * cleanup the node reference and keeps the process dangling. + */ + /* dns_rbtnode_refincrement0(node, NULL); */ + cur->node = node; + + if (ctx.glue_list == NULL) { + /* + * No glue was found. Cache it so. + */ + cur->glue_list = (void *) -1; + } else { + cur->glue_list = ctx.glue_list; + } + + cur->next = rbtversion->glue_table[index]; + rbtversion->glue_table[index] = cur; + rbtversion->glue_table_nodecount++; + + result = ISC_R_SUCCESS; + + out: + RWUNLOCK(&rbtversion->glue_rwlock, isc_rwlocktype_write); + + if (result == ISC_R_SUCCESS) { + restarted = ISC_TRUE; + goto restart; + } + + return (result); } /*% diff --git a/lib/dns/rdatalist.c b/lib/dns/rdatalist.c index 5702427364..a14a233910 100644 --- a/lib/dns/rdatalist.c +++ b/lib/dns/rdatalist.c @@ -36,14 +36,12 @@ static dns_rdatasetmethods_t methods = { isc__rdatalist_getnoqname, isc__rdatalist_addclosest, isc__rdatalist_getclosest, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, + NULL, /* settrust */ + NULL, /* expire */ + NULL, /* clearprefetch */ isc__rdatalist_setownercase, - isc__rdatalist_getownercase + isc__rdatalist_getownercase, + NULL /* addglue */ }; void diff --git a/lib/dns/rdataset.c b/lib/dns/rdataset.c index bbc9c8bd86..0fc45acf12 100644 --- a/lib/dns/rdataset.c +++ b/lib/dns/rdataset.c @@ -6,8 +6,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* $Id$ */ - /*! \file */ #include @@ -190,18 +188,16 @@ static dns_rdatasetmethods_t question_methods = { question_current, question_clone, question_count, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL + NULL, /* addnoqname */ + NULL, /* getnoqname */ + NULL, /* addclosest */ + NULL, /* getclosest */ + NULL, /* settrust */ + NULL, /* expire */ + NULL, /* clearprefetch */ + NULL, /* setownercase */ + NULL, /* getownercase */ + NULL /* addglue */ }; void @@ -293,6 +289,7 @@ dns_rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) { #define MAX_SHUFFLE 32 #define WANT_FIXED(r) (((r)->attributes & DNS_RDATASETATTR_FIXEDORDER) != 0) #define WANT_RANDOM(r) (((r)->attributes & DNS_RDATASETATTR_RANDOMIZE) != 0) +#define WANT_CYCLIC(r) (((r)->attributes & DNS_RDATASETATTR_CYCLIC) != 0) struct towire_sort { int key; @@ -320,9 +317,11 @@ towiresorted(dns_rdataset_t *rdataset, const dns_name_t *owner_name, isc_buffer_t savedbuffer, rdlen, rrbuffer; unsigned int headlen; isc_boolean_t question = ISC_FALSE; - isc_boolean_t shuffle = ISC_FALSE; - dns_rdata_t *shuffled = NULL, shuffled_fixed[MAX_SHUFFLE]; - struct towire_sort *sorted = NULL, sorted_fixed[MAX_SHUFFLE]; + isc_boolean_t shuffle = ISC_FALSE, sort = ISC_FALSE; + dns_rdata_t orig_fixed[MAX_SHUFFLE]; + dns_rdata_t *orig = orig_fixed; + struct towire_sort new_fixed[MAX_SHUFFLE]; + struct towire_sort *new = new_fixed; dns_fixedname_t fixed; dns_name_t *name; @@ -363,53 +362,43 @@ towiresorted(dns_rdataset_t *rdataset, const dns_name_t *owner_name, } /* - * Do we want to shuffle this answer? + * Do we want to sort and/or shuffle this answer? */ - if (!question && count > 1 && - (!WANT_FIXED(rdataset) || order != NULL) && - rdataset->type != dns_rdatatype_rrsig) - shuffle = ISC_TRUE; - - if (shuffle && count > MAX_SHUFFLE) { - shuffled = isc_mem_get(cctx->mctx, count * sizeof(*shuffled)); - sorted = isc_mem_get(cctx->mctx, count * sizeof(*sorted)); - if (shuffled == NULL || sorted == NULL) - shuffle = ISC_FALSE; - } else { - shuffled = shuffled_fixed; - sorted = sorted_fixed; + if (!question && count > 1 && rdataset->type != dns_rdatatype_rrsig) { + if (order != NULL) { + sort = ISC_TRUE; + } + if (WANT_RANDOM(rdataset) || WANT_CYCLIC(rdataset)) { + shuffle = ISC_TRUE; + } } - if (shuffle) { + if ((shuffle || sort) && count > MAX_SHUFFLE) { + orig = isc_mem_get(cctx->mctx, count * sizeof(*orig)); + new = isc_mem_get(cctx->mctx, count * sizeof(*new)); + if (orig == NULL || new == NULL) + shuffle = sort = ISC_FALSE; + } + + if (shuffle || sort) { /* * First we get handles to all of the rdata. */ i = 0; do { INSIST(i < count); - dns_rdata_init(&shuffled[i]); - dns_rdataset_current(rdataset, &shuffled[i]); + dns_rdata_init(&orig[i]); + dns_rdataset_current(rdataset, &orig[i]); i++; result = dns_rdataset_next(rdataset); } while (result == ISC_R_SUCCESS); if (result != ISC_R_NOMORE) goto cleanup; INSIST(i == count); + } - /* - * Now we shuffle. - */ - if (WANT_FIXED(rdataset)) { - /* - * 'Fixed' order. - */ - INSIST(order != NULL); - for (i = 0; i < count; i++) { - sorted[i].key = (*order)(&shuffled[i], - order_arg); - sorted[i].rdata = &shuffled[i]; - } - } else if (WANT_RANDOM(rdataset)) { + if (shuffle) { + if (WANT_RANDOM(rdataset)) { /* * 'Random' order. */ @@ -418,19 +407,19 @@ towiresorted(dns_rdataset_t *rdataset, const dns_name_t *owner_name, isc_random_get(&val); choice = i + (val % (count - i)); - rdata = shuffled[i]; - shuffled[i] = shuffled[choice]; - shuffled[choice] = rdata; + rdata = orig[i]; + orig[i] = orig[choice]; + orig[choice] = rdata; if (order != NULL) - sorted[i].key = (*order)(&shuffled[i], + new[i].key = (*order)(&orig[i], order_arg); else - sorted[i].key = 0; /* Unused */ - sorted[i].rdata = &shuffled[i]; + new[i].key = 0; /* Unused */ + new[i].rdata = &orig[i]; } - } else { + } else if (WANT_CYCLIC(rdataset)) { /* - * "Cyclic" order. + * 'Cyclic' order. */ isc_uint32_t val; unsigned int j; @@ -441,23 +430,31 @@ towiresorted(dns_rdataset_t *rdataset, const dns_name_t *owner_name, j = val % count; for (i = 0; i < count; i++) { if (order != NULL) - sorted[i].key = (*order)(&shuffled[j], + new[i].key = (*order)(&orig[j], order_arg); else - sorted[i].key = 0; /* Unused */ - sorted[i].rdata = &shuffled[j]; + new[i].key = 0; /* Unused */ + new[i].rdata = &orig[j]; j++; if (j == count) j = 0; /* Wrap around. */ } } + } else if (sort) { + for (i = 0; i < count; i++) { + if (order != NULL) + new[i].key = (*order)(&orig[i], order_arg); + else + new[i].key = 0; /* Unused */ + new[i].rdata = &orig[i]; + } + } - /* - * Sorted order. - */ - if (order != NULL) - qsort(sorted, count, sizeof(sorted[0]), - towire_compare); + /* + * Sortlist order. + */ + if (sort) { + qsort(new, count, sizeof(new[0]), towire_compare); } savedbuffer = *target; @@ -502,9 +499,9 @@ towiresorted(dns_rdataset_t *rdataset, const dns_name_t *owner_name, /* * Copy out the rdata */ - if (shuffle) - rdata = *(sorted[i].rdata); - else { + if (shuffle || sort) { + rdata = *(new[i].rdata); + } else { dns_rdata_reset(&rdata); dns_rdataset_current(rdataset, &rdata); } @@ -519,7 +516,7 @@ towiresorted(dns_rdataset_t *rdataset, const dns_name_t *owner_name, added++; } - if (shuffle) { + if (shuffle || sort) { i++; if (i == count) result = ISC_R_NOMORE; @@ -552,10 +549,10 @@ towiresorted(dns_rdataset_t *rdataset, const dns_name_t *owner_name, *target = savedbuffer; cleanup: - if (sorted != NULL && sorted != sorted_fixed) - isc_mem_put(cctx->mctx, sorted, count * sizeof(*sorted)); - if (shuffled != NULL && shuffled != shuffled_fixed) - isc_mem_put(cctx->mctx, shuffled, count * sizeof(*shuffled)); + if (new != NULL && new != new_fixed) + isc_mem_put(cctx->mctx, new, count * sizeof(*new)); + if (orig != NULL && orig != orig_fixed) + isc_mem_put(cctx->mctx, orig, count * sizeof(*orig)); return (result); } @@ -680,83 +677,6 @@ dns_rdataset_getclosest(dns_rdataset_t *rdataset, dns_name_t *name, return((rdataset->methods->getclosest)(rdataset, name, neg, negsig)); } -/* - * Additional cache stuff - */ -isc_result_t -dns_rdataset_getadditional(dns_rdataset_t *rdataset, - dns_rdatasetadditional_t type, - dns_rdatatype_t qtype, - dns_acache_t *acache, - dns_zone_t **zonep, - dns_db_t **dbp, - dns_dbversion_t **versionp, - dns_dbnode_t **nodep, - dns_name_t *fname, - dns_message_t *msg, - isc_stdtime_t now) -{ - REQUIRE(DNS_RDATASET_VALID(rdataset)); - REQUIRE(rdataset->methods != NULL); - REQUIRE(zonep == NULL || *zonep == NULL); - REQUIRE(dbp != NULL && *dbp == NULL); - REQUIRE(versionp != NULL && *versionp == NULL); - REQUIRE(nodep != NULL && *nodep == NULL); - REQUIRE(fname != NULL); - REQUIRE(msg != NULL); - - if (acache != NULL && rdataset->methods->getadditional != NULL) { - return ((rdataset->methods->getadditional)(rdataset, type, - qtype, acache, - zonep, dbp, - versionp, nodep, - fname, msg, now)); - } - - return (ISC_R_FAILURE); -} - -isc_result_t -dns_rdataset_setadditional(dns_rdataset_t *rdataset, - dns_rdatasetadditional_t type, - dns_rdatatype_t qtype, - dns_acache_t *acache, - dns_zone_t *zone, - dns_db_t *db, - dns_dbversion_t *version, - dns_dbnode_t *node, - dns_name_t *fname) -{ - REQUIRE(DNS_RDATASET_VALID(rdataset)); - REQUIRE(rdataset->methods != NULL); - - if (acache != NULL && rdataset->methods->setadditional != NULL) { - return ((rdataset->methods->setadditional)(rdataset, type, - qtype, acache, zone, - db, version, - node, fname)); - } - - return (ISC_R_FAILURE); -} - -isc_result_t -dns_rdataset_putadditional(dns_acache_t *acache, - dns_rdataset_t *rdataset, - dns_rdatasetadditional_t type, - dns_rdatatype_t qtype) -{ - REQUIRE(DNS_RDATASET_VALID(rdataset)); - REQUIRE(rdataset->methods != NULL); - - if (acache != NULL && rdataset->methods->putadditional != NULL) { - return ((rdataset->methods->putadditional)(acache, rdataset, - type, qtype)); - } - - return (ISC_R_FAILURE); -} - void dns_rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust) { REQUIRE(DNS_RDATASET_VALID(rdataset)); @@ -830,3 +750,20 @@ dns_rdataset_trimttl(dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset, rdataset->ttl = ttl; sigrdataset->ttl = ttl; } + +isc_result_t +dns_rdataset_addglue(dns_rdataset_t *rdataset, + dns_dbversion_t *version, + unsigned int options, + dns_message_t *msg) +{ + REQUIRE(DNS_RDATASET_VALID(rdataset)); + REQUIRE(rdataset->methods != NULL); + REQUIRE(rdataset->type == dns_rdatatype_ns); + + if (rdataset->methods->addglue == NULL) + return (ISC_R_NOTIMPLEMENTED); + + return ((rdataset->methods->addglue)(rdataset, version, + options, msg)); +} diff --git a/lib/dns/rdataslab.c b/lib/dns/rdataslab.c index cdff86c0dc..ee5039ab03 100644 --- a/lib/dns/rdataslab.c +++ b/lib/dns/rdataslab.c @@ -449,18 +449,16 @@ static dns_rdatasetmethods_t rdataset_methods = { rdataset_current, rdataset_clone, rdataset_count, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL + NULL, /* addnoqname */ + NULL, /* getnoqname */ + NULL, /* addclosest */ + NULL, /* getclosest */ + NULL, /* settrust */ + NULL, /* expire */ + NULL, /* clearprefetch */ + NULL, /* setownercase */ + NULL, /* getownercase */ + NULL /* addglue */ }; void diff --git a/lib/dns/sdb.c b/lib/dns/sdb.c index 55cbf44554..053f1ac655 100644 --- a/lib/dns/sdb.c +++ b/lib/dns/sdb.c @@ -1415,16 +1415,14 @@ static dns_rdatasetmethods_t methods = { isc__rdatalist_count, isc__rdatalist_addnoqname, isc__rdatalist_getnoqname, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL + NULL, /* addclosest */ + NULL, /* getclosest */ + NULL, /* settrust */ + NULL, /* expire */ + NULL, /* clearprefetch */ + NULL, /* setownercase */ + NULL, /* getownercase */ + NULL /* addglue */ }; static void diff --git a/lib/dns/sdlz.c b/lib/dns/sdlz.c index b80c978a02..5627aaf332 100644 --- a/lib/dns/sdlz.c +++ b/lib/dns/sdlz.c @@ -1471,16 +1471,14 @@ static dns_rdatasetmethods_t rdataset_methods = { isc__rdatalist_count, isc__rdatalist_addnoqname, isc__rdatalist_getnoqname, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL + NULL, /* addclosest */ + NULL, /* getclosest */ + NULL, /* settrust */ + NULL, /* expire */ + NULL, /* clearprefetch */ + NULL, /* setownercase */ + NULL, /* getownercase */ + NULL /* addglue */ }; static void diff --git a/lib/dns/ssu_external.c b/lib/dns/ssu_external.c index 7c19f1619b..7908f4dc44 100644 --- a/lib/dns/ssu_external.c +++ b/lib/dns/ssu_external.c @@ -124,7 +124,7 @@ dns_ssu_external_match(const dns_name_t *identity, int fd; const char *sock_path; unsigned int req_len; - isc_region_t token_region; + isc_region_t token_region = {NULL, 0}; unsigned char *data; isc_buffer_t buf; isc_uint32_t token_len = 0; diff --git a/lib/dns/view.c b/lib/dns/view.c index 0e02ccad96..3c3f4aa502 100644 --- a/lib/dns/view.c +++ b/lib/dns/view.c @@ -24,7 +24,6 @@ #include #include -#include #include #include #include @@ -137,7 +136,6 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, goto cleanup_zt; } - view->acache = NULL; view->cache = NULL; view->cachedb = NULL; ISC_LIST_INIT(view->dlz_searched); @@ -180,8 +178,6 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, */ view->recursion = ISC_TRUE; view->auth_nxdomain = ISC_FALSE; /* Was true in BIND 8 */ - view->additionalfromcache = ISC_TRUE; - view->additionalfromauth = ISC_TRUE; view->enablednssec = ISC_TRUE; view->enablevalidation = ISC_TRUE; view->acceptexpired = ISC_FALSE; @@ -380,11 +376,6 @@ destroy(dns_view_t *view) { dns_adb_detach(&view->adb); if (view->resolver != NULL) dns_resolver_detach(&view->resolver); - if (view->acache != NULL) { - if (view->cachedb != NULL) - dns_acache_putdb(view->acache, view->cachedb); - dns_acache_detach(&view->acache); - } dns_rrl_view_destroy(view); if (view->rpzs != NULL) dns_rpz_detach_rpzs(&view->rpzs); @@ -585,8 +576,6 @@ view_flushanddetach(dns_view_t **viewp, isc_boolean_t flush) { dns_adb_shutdown(view->adb); if (!REQSHUTDOWN(view)) dns_requestmgr_shutdown(view->requestmgr); - if (view->acache != NULL) - dns_acache_shutdown(view->acache); if (view->zonetable != NULL) { if (view->flush) dns_zt_flushanddetach(&view->zonetable); @@ -851,17 +840,12 @@ dns_view_setcache2(dns_view_t *view, dns_cache_t *cache, isc_boolean_t shared) { view->cacheshared = shared; if (view->cache != NULL) { - if (view->acache != NULL) - dns_acache_putdb(view->acache, view->cachedb); dns_db_detach(&view->cachedb); dns_cache_detach(&view->cache); } dns_cache_attach(cache, &view->cache); dns_cache_attachdb(cache, &view->cachedb); INSIST(DNS_DB_VALID(view->cachedb)); - - if (view->acache != NULL) - dns_acache_setdb(view->acache, view->cachedb); } isc_boolean_t @@ -1637,12 +1621,8 @@ dns_view_flushcache2(dns_view_t *view, isc_boolean_t fixuponly) { if (result != ISC_R_SUCCESS) return (result); } - if (view->acache != NULL) - dns_acache_putdb(view->acache, view->cachedb); dns_db_detach(&view->cachedb); dns_cache_attachdb(view->cache, &view->cachedb); - if (view->acache != NULL) - dns_acache_setdb(view->acache, view->cachedb); if (view->resolver != NULL) dns_resolver_flushbadcache(view->resolver, NULL); if (view->failcache != NULL) diff --git a/lib/dns/win32/libdns.def.in b/lib/dns/win32/libdns.def.in index e7cbb6fa53..cade336172 100644 --- a/lib/dns/win32/libdns.def.in +++ b/lib/dns/win32/libdns.def.in @@ -3,21 +3,6 @@ LIBRARY libdns ; Exported Functions EXPORTS -dns_acache_attach -dns_acache_attachentry -dns_acache_cancelentry -dns_acache_countquerymiss -dns_acache_create -dns_acache_createentry -dns_acache_detach -dns_acache_detachentry -dns_acache_getentry -dns_acache_putdb -dns_acache_setcachesize -dns_acache_setcleaninginterval -dns_acache_setdb -dns_acache_setentry -dns_acache_shutdown dns_acl_any dns_acl_attach dns_acl_create @@ -818,6 +803,7 @@ dns_rdatalist_fromrdataset dns_rdatalist_init dns_rdatalist_tordataset dns_rdataset_addclosest +dns_rdataset_addglue dns_rdataset_additionaldata dns_rdataset_addnoqname dns_rdataset_clearprefetch @@ -827,7 +813,6 @@ dns_rdataset_current dns_rdataset_disassociate dns_rdataset_expire dns_rdataset_first -dns_rdataset_getadditional dns_rdataset_getclosest dns_rdataset_getnoqname dns_rdataset_getownercase @@ -836,8 +821,6 @@ dns_rdataset_invalidate dns_rdataset_isassociated dns_rdataset_makequestion dns_rdataset_next -dns_rdataset_putadditional -dns_rdataset_setadditional dns_rdataset_setownercase dns_rdataset_settrust dns_rdataset_totext @@ -1266,7 +1249,6 @@ dns_zone_replacedb dns_zone_rpz_enable dns_zone_rpz_enable_db dns_zone_set_parentcatz -dns_zone_setacache dns_zone_setadded dns_zone_setalsonotify dns_zone_setalsonotifydscpkeys diff --git a/lib/dns/win32/libdns.dsp.in b/lib/dns/win32/libdns.dsp.in index fa5d2b5b13..186a045f02 100644 --- a/lib/dns/win32/libdns.dsp.in +++ b/lib/dns/win32/libdns.dsp.in @@ -98,10 +98,6 @@ LINK32=link.exe # PROP Default_Filter "h;hpp;hxx;hm;inl" # Begin Source File -SOURCE=..\include\dns\acache.h -# End Source File -# Begin Source File - SOURCE=..\include\dns\acl.h # End Source File # Begin Source File @@ -504,10 +500,6 @@ SOURCE=..\include\dns\zt.h # PROP Default_Filter "c" # Begin Source File -SOURCE=..\acache.c -# End Source File -# Begin Source File - SOURCE=..\acl.c # End Source File # Begin Source File diff --git a/lib/dns/win32/libdns.mak.in b/lib/dns/win32/libdns.mak.in index 913dbebef0..d0d1744987 100644 --- a/lib/dns/win32/libdns.mak.in +++ b/lib/dns/win32/libdns.mak.in @@ -120,7 +120,6 @@ CLEAN :"libisc - @PLATFORM@ ReleaseCLEAN" !ELSE CLEAN : !ENDIF - -@erase "$(INTDIR)\acache.obj" -@erase "$(INTDIR)\acl.obj" -@erase "$(INTDIR)\adb.obj" -@erase "$(INTDIR)\badcache.obj" @@ -282,7 +281,6 @@ LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib $(LIBXML) ../../isc/win32/Releas DEF_FILE= \ ".\libdns.def" LINK32_OBJS= \ - "$(INTDIR)\acache.obj" \ "$(INTDIR)\acl.obj" \ "$(INTDIR)\adb.obj" \ "$(INTDIR)\badcache.obj" \ @@ -422,8 +420,6 @@ CLEAN :"libisc - @PLATFORM@ DebugCLEAN" !ELSE CLEAN : !ENDIF - -@erase "$(INTDIR)\acache.obj" - -@erase "$(INTDIR)\acache.sbr" -@erase "$(INTDIR)\acl.obj" -@erase "$(INTDIR)\acl.sbr" -@erase "$(INTDIR)\adb.obj" @@ -687,7 +683,6 @@ RSC=rc.exe BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\libdns.bsc" BSC32_SBRS= \ - "$(INTDIR)\acache.sbr" \ "$(INTDIR)\acl.sbr" \ "$(INTDIR)\adb.sbr" \ "$(INTDIR)\badcache.sbr" \ @@ -807,7 +802,6 @@ LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib $(LIBXML) ../../isc/win32/Debug/ DEF_FILE= \ ".\libdns.def" LINK32_OBJS= \ - "$(INTDIR)\acache.obj" \ "$(INTDIR)\acl.obj" \ "$(INTDIR)\adb.obj" \ "$(INTDIR)\badcache.obj" \ @@ -937,24 +931,6 @@ LINK32_OBJS= \ !IF "$(CFG)" == "libdns - @PLATFORM@ Release" || "$(CFG)" == "libdns - @PLATFORM@ Debug" -SOURCE=..\acache.c - -!IF "$(CFG)" == "libdns - @PLATFORM@ Release" - - -"$(INTDIR)\acache.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -!ELSEIF "$(CFG)" == "libdns - @PLATFORM@ Debug" - - -"$(INTDIR)\acache.obj" "$(INTDIR)\acache.sbr" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -!ENDIF - SOURCE=..\acl.c !IF "$(CFG)" == "libdns - @PLATFORM@ Release" diff --git a/lib/dns/win32/libdns.vcxproj.filters.in b/lib/dns/win32/libdns.vcxproj.filters.in index 363b9c35c1..e2244c56dd 100644 --- a/lib/dns/win32/libdns.vcxproj.filters.in +++ b/lib/dns/win32/libdns.vcxproj.filters.in @@ -1,4 +1,4 @@ - + @@ -30,9 +30,6 @@ Library Source Files - - Library Source Files - Library Source Files @@ -356,9 +353,6 @@ Library Header Files - - Library Header Files - Library Header Files diff --git a/lib/dns/win32/libdns.vcxproj.in b/lib/dns/win32/libdns.vcxproj.in index ca23b1d31f..1308f58f6f 100644 --- a/lib/dns/win32/libdns.vcxproj.in +++ b/lib/dns/win32/libdns.vcxproj.in @@ -1,4 +1,4 @@ - + @@ -109,7 +109,6 @@ - @@ -231,7 +230,6 @@ @IF PKCS11 @END PKCS11 - diff --git a/lib/dns/zone.c b/lib/dns/zone.c index f477efc765..d4c54d16a9 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -30,7 +30,6 @@ #include #include -#include #include #include #include @@ -302,7 +301,6 @@ struct dns_zone { isc_uint32_t sigvalidityinterval; isc_uint32_t sigresigninginterval; dns_view_t *view; - dns_acache_t *acache; dns_checkmxfunc_t checkmx; dns_checksrvfunc_t checksrv; dns_checknsfunc_t checkns; @@ -1016,7 +1014,6 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) { zone->sigvalidityinterval = 30 * 24 * 3600; zone->sigresigninginterval = 7 * 24 * 3600; zone->view = NULL; - zone->acache = NULL; zone->checkmx = NULL; zone->checksrv = NULL; zone->checkns = NULL; @@ -1170,8 +1167,6 @@ zone_free(dns_zone_t *zone) { dns_stats_detach(&zone->rcvquerystats); if (zone->db != NULL) zone_detachdb(zone); - if (zone->acache != NULL) - dns_acache_detach(&zone->acache); if (zone->rpzs != NULL) { REQUIRE(zone->rpz_num < zone->rpzs->p.num_zones); dns_rpz_detach_rpzs(&zone->rpzs); @@ -1518,36 +1513,6 @@ dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin) { return (result); } -void -dns_zone_setacache(dns_zone_t *zone, dns_acache_t *acache) { - REQUIRE(DNS_ZONE_VALID(zone)); - REQUIRE(acache != NULL); - - LOCK_ZONE(zone); - if (zone->acache != NULL) - dns_acache_detach(&zone->acache); - dns_acache_attach(acache, &zone->acache); - ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read); - if (zone->db != NULL) { - isc_result_t result; - - /* - * If the zone reuses an existing DB, the DB needs to be - * set in the acache explicitly. We can safely ignore the - * case where the DB is already set. If other error happens, - * the acache will not work effectively. - */ - result = dns_acache_setdb(acache, zone->db); - if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) { - UNEXPECTED_ERROR(__FILE__, __LINE__, - "dns_acache_setdb() failed: %s", - isc_result_totext(result)); - } - } - ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read); - UNLOCK_ZONE(zone); -} - static isc_result_t dns_zone_setstring(dns_zone_t *zone, char **field, const char *value) { char *copy; @@ -14662,15 +14627,6 @@ zone_attachdb(dns_zone_t *zone, dns_db_t *db) { REQUIRE(zone->db == NULL && db != NULL); dns_db_attach(db, &zone->db); - if (zone->acache != NULL) { - isc_result_t result; - result = dns_acache_setdb(zone->acache, db); - if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) { - UNEXPECTED_ERROR(__FILE__, __LINE__, - "dns_acache_setdb() failed: %s", - isc_result_totext(result)); - } - } } /* The caller must hold the dblock as a writer. */ @@ -14678,8 +14634,6 @@ static inline void zone_detachdb(dns_zone_t *zone) { REQUIRE(zone->db != NULL); - if (zone->acache != NULL) - (void)dns_acache_putdb(zone->acache, zone->db); dns_db_detach(&zone->db); } diff --git a/lib/isc/hash.c b/lib/isc/hash.c index a9c5992c58..c1d85b6d60 100644 --- a/lib/isc/hash.c +++ b/lib/isc/hash.c @@ -397,6 +397,7 @@ isc__hash_setvec(const isc_uint16_t *vec) { static isc_uint32_t fnv_offset_basis; static isc_once_t fnv_once = ISC_ONCE_INIT; +static isc_boolean_t fnv_initialized = ISC_FALSE; static void fnv_initialize(void) { @@ -408,11 +409,14 @@ fnv_initialize(void) { while (fnv_offset_basis == 0) { isc_random_get(&fnv_offset_basis); } + + fnv_initialized = ISC_TRUE; } const void * isc_hash_get_initializer(void) { - RUNTIME_CHECK(isc_once_do(&fnv_once, fnv_initialize) == ISC_R_SUCCESS); + if (ISC_UNLIKELY(!fnv_initialized)) + RUNTIME_CHECK(isc_once_do(&fnv_once, fnv_initialize) == ISC_R_SUCCESS); return (&fnv_offset_basis); } @@ -425,7 +429,8 @@ isc_hash_set_initializer(const void *initializer) { * Ensure that fnv_initialize() is not called after * isc_hash_set_initializer() is called. */ - RUNTIME_CHECK(isc_once_do(&fnv_once, fnv_initialize) == ISC_R_SUCCESS); + if (ISC_UNLIKELY(!fnv_initialized)) + RUNTIME_CHECK(isc_once_do(&fnv_once, fnv_initialize) == ISC_R_SUCCESS); fnv_offset_basis = *((const unsigned int *) initializer); } @@ -440,7 +445,9 @@ isc_hash_function(const void *data, size_t length, const unsigned char *be; REQUIRE(length == 0 || data != NULL); - RUNTIME_CHECK(isc_once_do(&fnv_once, fnv_initialize) == ISC_R_SUCCESS); + + if (ISC_UNLIKELY(!fnv_initialized)) + RUNTIME_CHECK(isc_once_do(&fnv_once, fnv_initialize) == ISC_R_SUCCESS); hval = ISC_UNLIKELY(previous_hashp != NULL) ? *previous_hashp : fnv_offset_basis; @@ -461,35 +468,35 @@ isc_hash_function(const void *data, size_t length, */ if (case_sensitive) { - while (bp < be - 4) { - hval ^= (isc_uint32_t) bp[0]; + while (bp <= be - 4) { + hval ^= bp[0]; hval *= 16777619; - hval ^= (isc_uint32_t) bp[1]; + hval ^= bp[1]; hval *= 16777619; - hval ^= (isc_uint32_t) bp[2]; + hval ^= bp[2]; hval *= 16777619; - hval ^= (isc_uint32_t) bp[3]; + hval ^= bp[3]; hval *= 16777619; bp += 4; } while (bp < be) { - hval ^= (isc_uint32_t) *bp++; + hval ^= *bp++; hval *= 16777619; } } else { - while (bp < be - 4) { - hval ^= (isc_uint32_t) maptolower[bp[0]]; + while (bp <= be - 4) { + hval ^= maptolower[bp[0]]; hval *= 16777619; - hval ^= (isc_uint32_t) maptolower[bp[1]]; + hval ^= maptolower[bp[1]]; hval *= 16777619; - hval ^= (isc_uint32_t) maptolower[bp[2]]; + hval ^= maptolower[bp[2]]; hval *= 16777619; - hval ^= (isc_uint32_t) maptolower[bp[3]]; + hval ^= maptolower[bp[3]]; hval *= 16777619; bp += 4; } while (bp < be) { - hval ^= (isc_uint32_t) maptolower[*bp++]; + hval ^= maptolower[*bp++]; hval *= 16777619; } } @@ -507,7 +514,9 @@ isc_hash_function_reverse(const void *data, size_t length, const unsigned char *be; REQUIRE(length == 0 || data != NULL); - RUNTIME_CHECK(isc_once_do(&fnv_once, fnv_initialize) == ISC_R_SUCCESS); + + if (ISC_UNLIKELY(!fnv_initialized)) + RUNTIME_CHECK(isc_once_do(&fnv_once, fnv_initialize) == ISC_R_SUCCESS); hval = ISC_UNLIKELY(previous_hashp != NULL) ? *previous_hashp : fnv_offset_basis; @@ -530,33 +539,33 @@ isc_hash_function_reverse(const void *data, size_t length, if (case_sensitive) { while (be >= bp + 4) { be -= 4; - hval ^= (isc_uint32_t) be[3]; + hval ^= be[3]; hval *= 16777619; - hval ^= (isc_uint32_t) be[2]; + hval ^= be[2]; hval *= 16777619; - hval ^= (isc_uint32_t) be[1]; + hval ^= be[1]; hval *= 16777619; - hval ^= (isc_uint32_t) be[0]; + hval ^= be[0]; hval *= 16777619; } while (--be >= bp) { - hval ^= (isc_uint32_t) *be; + hval ^= *be; hval *= 16777619; } } else { while (be >= bp + 4) { be -= 4; - hval ^= (isc_uint32_t) maptolower[be[3]]; + hval ^= maptolower[be[3]]; hval *= 16777619; - hval ^= (isc_uint32_t) maptolower[be[2]]; + hval ^= maptolower[be[2]]; hval *= 16777619; - hval ^= (isc_uint32_t) maptolower[be[1]]; + hval ^= maptolower[be[1]]; hval *= 16777619; - hval ^= (isc_uint32_t) maptolower[be[0]]; + hval ^= maptolower[be[0]]; hval *= 16777619; } while (--be >= bp) { - hval ^= (isc_uint32_t) maptolower[*be]; + hval ^= maptolower[*be]; hval *= 16777619; } } diff --git a/lib/isc/include/isc/buffer.h b/lib/isc/include/isc/buffer.h index e904a01161..c0aeec88f6 100644 --- a/lib/isc/include/isc/buffer.h +++ b/lib/isc/include/isc/buffer.h @@ -104,7 +104,7 @@ * To make many functions be inline macros (via \#define) define this. * If it is undefined, a function will be used. */ -/* #define ISC_BUFFER_USEINLINE */ +#define ISC_BUFFER_USEINLINE 1 ISC_LANG_BEGINDECLS @@ -877,8 +877,8 @@ ISC_LANG_ENDDECLS #define ISC__BUFFER_PUTMEM(_b, _base, _length) \ do { \ if (ISC_UNLIKELY((_b)->autore)) { \ - isc_buffer_t *tmpbuf = _b; \ - REQUIRE(isc_buffer_reserve(&tmpbuf, _length) \ + isc_buffer_t *_tmp = _b; \ + REQUIRE(isc_buffer_reserve(&_tmp, _length) \ == ISC_R_SUCCESS); \ } \ REQUIRE(isc_buffer_availablelength(_b) >= (unsigned int) _length); \ @@ -892,8 +892,8 @@ ISC_LANG_ENDDECLS unsigned char *_cp; \ _length = strlen(_source); \ if (ISC_UNLIKELY((_b)->autore)) { \ - isc_buffer_t *tmpbuf = _b; \ - REQUIRE(isc_buffer_reserve(&tmpbuf, _length) \ + isc_buffer_t *_tmp = _b; \ + REQUIRE(isc_buffer_reserve(&_tmp, _length) \ == ISC_R_SUCCESS); \ } \ REQUIRE(isc_buffer_availablelength(_b) >= (unsigned int) _length); \ @@ -905,67 +905,71 @@ ISC_LANG_ENDDECLS #define ISC__BUFFER_PUTUINT8(_b, _val) \ do { \ unsigned char *_cp; \ + /* evaluate (_val) only once */ \ isc_uint8_t _val2 = (_val); \ if (ISC_UNLIKELY((_b)->autore)) { \ - isc_buffer_t *tmpbuf = _b; \ - REQUIRE(isc_buffer_reserve(&tmpbuf, 1) \ + isc_buffer_t *_tmp = _b; \ + REQUIRE(isc_buffer_reserve(&_tmp, 1) \ == ISC_R_SUCCESS); \ } \ REQUIRE(isc_buffer_availablelength(_b) >= 1U); \ _cp = isc_buffer_used(_b); \ (_b)->used++; \ - _cp[0] = _val2 & 0x00ff; \ + _cp[0] = _val2; \ } while (0) #define ISC__BUFFER_PUTUINT16(_b, _val) \ do { \ unsigned char *_cp; \ + /* evaluate (_val) only once */ \ isc_uint16_t _val2 = (_val); \ if (ISC_UNLIKELY((_b)->autore)) { \ - isc_buffer_t *tmpbuf = _b; \ - REQUIRE(isc_buffer_reserve(&tmpbuf, 2) \ + isc_buffer_t *_tmp = _b; \ + REQUIRE(isc_buffer_reserve(&_tmp, 2) \ == ISC_R_SUCCESS); \ } \ REQUIRE(isc_buffer_availablelength(_b) >= 2U); \ _cp = isc_buffer_used(_b); \ (_b)->used += 2; \ - _cp[0] = (unsigned char)((_val2 & 0xff00U) >> 8); \ - _cp[1] = (unsigned char)(_val2 & 0x00ffU); \ + _cp[0] = _val2 >> 8; \ + _cp[1] = _val2; \ } while (0) #define ISC__BUFFER_PUTUINT24(_b, _val) \ do { \ unsigned char *_cp; \ + /* evaluate (_val) only once */ \ isc_uint32_t _val2 = (_val); \ if (ISC_UNLIKELY((_b)->autore)) { \ - isc_buffer_t *tmpbuf = _b; \ - REQUIRE(isc_buffer_reserve(&tmpbuf, 3) \ + isc_buffer_t *_tmp = _b; \ + REQUIRE(isc_buffer_reserve(&_tmp, 3) \ == ISC_R_SUCCESS); \ } \ REQUIRE(isc_buffer_availablelength(_b) >= 3U); \ _cp = isc_buffer_used(_b); \ (_b)->used += 3; \ - _cp[0] = (unsigned char)((_val2 & 0xff0000U) >> 16); \ - _cp[1] = (unsigned char)((_val2 & 0xff00U) >> 8); \ - _cp[2] = (unsigned char)(_val2 & 0x00ffU); \ + _cp[0] = _val2 >> 16; \ + _cp[1] = _val2 >> 8; \ + _cp[2] = _val2; \ } while (0) #define ISC__BUFFER_PUTUINT32(_b, _val) \ do { \ unsigned char *_cp; \ + /* evaluate (_val) only once */ \ isc_uint32_t _val2 = (_val); \ if (ISC_UNLIKELY((_b)->autore)) { \ - isc_buffer_t *tmpbuf = _b; \ - REQUIRE(isc_buffer_reserve(&tmpbuf, 4) \ + isc_buffer_t *_tmp = _b; \ + REQUIRE(isc_buffer_reserve(&_tmp, 4) \ == ISC_R_SUCCESS); \ } \ REQUIRE(isc_buffer_availablelength(_b) >= 4U); \ _cp = isc_buffer_used(_b); \ (_b)->used += 4; \ - _cp[0] = (unsigned char)((_val2 & 0xff000000) >> 24); \ - _cp[1] = (unsigned char)((_val2 & 0x00ff0000) >> 16); \ - _cp[2] = (unsigned char)((_val2 & 0x0000ff00) >> 8); \ - _cp[3] = (unsigned char)((_val2 & 0x000000ff)); \ + _cp[0] = _val2 >> 24; \ + _cp[1] = _val2 >> 16; \ + _cp[2] = _val2 >> 8; \ + _cp[3] = _val2; \ } while (0) #if defined(ISC_BUFFER_USEINLINE) diff --git a/lib/isc/include/isc/msgs.h b/lib/isc/include/isc/msgs.h index d8bedc4a47..2926ed141a 100644 --- a/lib/isc/include/isc/msgs.h +++ b/lib/isc/include/isc/msgs.h @@ -121,6 +121,7 @@ #define ISC_MSG_POSTLOCK 1207 /*%< "postlock" */ #define ISC_MSG_PREUNLOCK 1208 /*%< "preunlock" */ #define ISC_MSG_POSTUNLOCK 1209 /*%< "postunlock" */ +#define ISC_MSG_PRINTLOCK2 1210 /*%< "rwlock %p thread %lu ..." w/ atomic */ #define ISC_MSG_UNKNOWNFAMILY 1301 /*%< "unknown address family: %d" */ diff --git a/lib/isc/mem.c b/lib/isc/mem.c index 9f6ee258a5..bda751eccc 100644 --- a/lib/isc/mem.c +++ b/lib/isc/mem.c @@ -200,14 +200,19 @@ struct isc__mempool { #define DELETE_TRACE(a, b, c, d, e) #define ISC_MEMFUNC_SCOPE #else +#define TRACE_OR_RECORD (ISC_MEM_DEBUGTRACE|ISC_MEM_DEBUGRECORD) #define ADD_TRACE(a, b, c, d, e) \ do { \ - if ((isc_mem_debugging & (ISC_MEM_DEBUGTRACE | \ - ISC_MEM_DEBUGRECORD)) != 0 && \ + if ((isc_mem_debugging & TRACE_OR_RECORD) != 0 && \ b != NULL) \ add_trace_entry(a, b, c, d, e); \ } while (0) -#define DELETE_TRACE(a, b, c, d, e) delete_trace_entry(a, b, c, d, e) +#define DELETE_TRACE(a, b, c, d, e) \ + do { \ + if ((isc_mem_debugging & TRACE_OR_RECORD) != 0 && \ + b != NULL) \ + delete_trace_entry(a, b, c, d, e); \ + } while(0) static void print_active(isc__mem_t *ctx, FILE *out); @@ -1553,9 +1558,7 @@ isc___mem_allocate(isc_mem_t *ctx0, size_t size FLARG) { if (((ctx->flags & ISC_MEMFLAG_INTERNAL) == 0) && (si != NULL)) mem_getstats(ctx, si[-1].u.size); -#if ISC_MEM_TRACKLINES ADD_TRACE(ctx, si, si[-1].u.size, file, line); -#endif if (ctx->hi_water != 0U && ctx->inuse > ctx->hi_water && !ctx->is_overmem) { ctx->is_overmem = ISC_TRUE; @@ -2078,7 +2081,7 @@ isc___mempool_get(isc_mempool_t *mpctx0 FLARG) { UNLOCK(mpctx->lock); #if ISC_MEM_TRACKLINES - if (item != NULL) { + if (((isc_mem_debugging & TRACE_OR_RECORD) != 0) && item != NULL) { MCTXLOCK(mctx, &mctx->lock); ADD_TRACE(mctx, item, mpctx->size, file, line); MCTXUNLOCK(mctx, &mctx->lock); @@ -2107,9 +2110,11 @@ isc___mempool_put(isc_mempool_t *mpctx0, void *mem FLARG) { mpctx->allocated--; #if ISC_MEM_TRACKLINES - MCTXLOCK(mctx, &mctx->lock); - DELETE_TRACE(mctx, mem, mpctx->size, file, line); - MCTXUNLOCK(mctx, &mctx->lock); + if ((isc_mem_debugging & TRACE_OR_RECORD) != 0) { + MCTXLOCK(mctx, &mctx->lock); + DELETE_TRACE(mctx, mem, mpctx->size, file, line); + MCTXUNLOCK(mctx, &mctx->lock); + } #endif /* ISC_MEM_TRACKLINES */ /* @@ -2333,17 +2338,19 @@ isc_mem_checkdestroyed(FILE *file) { RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS); LOCK(&contextslock); - if (!ISC_LIST_EMPTY(contexts)) { + if (!ISC_LIST_EMPTY(contexts)) { #if ISC_MEM_TRACKLINES - isc__mem_t *ctx; + if ((isc_mem_debugging & TRACE_OR_RECORD) != 0) { + isc__mem_t *ctx; - for (ctx = ISC_LIST_HEAD(contexts); - ctx != NULL; - ctx = ISC_LIST_NEXT(ctx, link)) { - fprintf(file, "context: %p\n", ctx); - print_active(ctx, file); + for (ctx = ISC_LIST_HEAD(contexts); + ctx != NULL; + ctx = ISC_LIST_NEXT(ctx, link)) { + fprintf(file, "context: %p\n", ctx); + print_active(ctx, file); + } + fflush(file); } - fflush(file); #endif INSIST(0); } diff --git a/lib/isc/rwlock.c b/lib/isc/rwlock.c index 3caa865bc8..d8dd147514 100644 --- a/lib/isc/rwlock.c +++ b/lib/isc/rwlock.c @@ -50,6 +50,24 @@ isc__rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type); static void print_lock(const char *operation, isc_rwlock_t *rwl, isc_rwlocktype_t type) { +#if defined(ISC_PLATFORM_HAVEXADD) && defined(ISC_PLATFORM_HAVECMPXCHG) + fprintf(stderr, + isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK, + ISC_MSG_PRINTLOCK2, + "rwlock %p thread %lu %s(%s): " + "write_requests=%u, write_completions=%u, " + "cnt_and_flag=0x%x, readers_waiting=%u, " + "write_granted=%u, write_quota=%u\n"), + rwl, isc_thread_self(), operation, + (type == isc_rwlocktype_read ? + isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK, + ISC_MSG_READ, "read") : + isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK, + ISC_MSG_WRITE, "write")), + rwl->write_requests, rwl->write_completions, + rwl->cnt_and_flag, rwl->readers_waiting, + rwl->write_granted, rwl->write_quota); +#else fprintf(stderr, isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK, ISC_MSG_PRINTLOCK, @@ -66,10 +84,11 @@ print_lock(const char *operation, isc_rwlock_t *rwl, isc_rwlocktype_t type) { ISC_MSG_READING, "reading") : isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK, ISC_MSG_WRITING, "writing")), - rwl->active, rwl->granted, rwl->readers_waiting, - rwl->writers_waiting); -} + rwl->active, rwl->granted, + rwl->readers_waiting, rwl->writers_waiting); #endif +} +#endif /* ISC_RWLOCK_TRACE */ isc_result_t isc_rwlock_init(isc_rwlock_t *rwl, unsigned int read_quota, diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c index 63f5048efa..0b763af7c6 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -1816,10 +1816,14 @@ static cfg_type_t cfg_type_dns64 = { static cfg_clausedef_t view_clauses[] = { - { "acache-cleaning-interval", &cfg_type_uint32, 0 }, - { "acache-enable", &cfg_type_boolean, 0 }, - { "additional-from-auth", &cfg_type_boolean, 0 }, - { "additional-from-cache", &cfg_type_boolean, 0 }, + { "acache-cleaning-interval", &cfg_type_uint32, + CFG_CLAUSEFLAG_OBSOLETE }, + { "acache-enable", &cfg_type_boolean, + CFG_CLAUSEFLAG_OBSOLETE }, + { "additional-from-auth", &cfg_type_boolean, + CFG_CLAUSEFLAG_OBSOLETE }, + { "additional-from-cache", &cfg_type_boolean, + CFG_CLAUSEFLAG_OBSOLETE }, { "allow-new-zones", &cfg_type_boolean, 0 }, { "allow-query-cache", &cfg_type_bracketed_aml, 0 }, { "allow-query-cache-on", &cfg_type_bracketed_aml, 0 }, @@ -1880,7 +1884,8 @@ view_clauses[] = { { "lame-ttl", &cfg_type_ttlval, 0 }, { "nocookie-udp-size", &cfg_type_uint32, 0 }, { "nosit-udp-size", &cfg_type_uint32, CFG_CLAUSEFLAG_OBSOLETE }, - { "max-acache-size", &cfg_type_sizenodefault, 0 }, + { "max-acache-size", &cfg_type_sizenodefault, + CFG_CLAUSEFLAG_OBSOLETE }, { "max-cache-size", &cfg_type_sizeorpercent, 0 }, { "max-cache-ttl", &cfg_type_uint32, 0 }, { "max-clients-per-query", &cfg_type_uint32, 0 }, diff --git a/util/copyrights b/util/copyrights index 948fb639c4..b0ea026470 100644 --- a/util/copyrights +++ b/util/copyrights @@ -3508,7 +3508,6 @@ ./lib/dns/.gitignore X 2012,2013,2016 ./lib/dns/Atffile X 2011 ./lib/dns/Makefile.in MAKE 1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017 -./lib/dns/acache.c C 2004,2005,2006,2007,2008,2012,2013,2015,2016 ./lib/dns/acl.c C 1999,2000,2001,2002,2004,2005,2006,2007,2008,2009,2011,2013,2014,2016 ./lib/dns/adb.c C 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016 ./lib/dns/api X 1999,2000,2001,2006,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017 @@ -3553,7 +3552,6 @@ ./lib/dns/hmac_link.c C.NAI 1999,2000,2001,2002,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016 ./lib/dns/include/Makefile.in MAKE 1998,1999,2000,2001,2004,2007,2012,2016 ./lib/dns/include/dns/Makefile.in MAKE 1998,1999,2000,2001,2002,2003,2004,2007,2008,2009,2011,2012,2013,2014,2015,2016,2017 -./lib/dns/include/dns/acache.h C 2004,2006,2007,2013,2016 ./lib/dns/include/dns/acl.h C 1999,2000,2001,2002,2004,2005,2006,2007,2009,2011,2013,2014,2016 ./lib/dns/include/dns/adb.h C 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2011,2013,2014,2015,2016 ./lib/dns/include/dns/badcache.h C 2014,2016