mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-29 05:28:00 +00:00
1526. [func] Implemented "additional section caching (or acache)",
an internal cache framework for additional section content to improve response performance. Several configuration options were provided to control the behavior.
This commit is contained in:
parent
0e93730a02
commit
d0eb2cc33c
6
CHANGES
6
CHANGES
@ -770,7 +770,11 @@
|
|||||||
1527. [cleanup] Reduce the number of gettimeofday() calls without
|
1527. [cleanup] Reduce the number of gettimeofday() calls without
|
||||||
losing necessary timer granularity.
|
losing necessary timer granularity.
|
||||||
|
|
||||||
1526. [placeholder]
|
1526. [func] Implemented "additional section caching (or acache)",
|
||||||
|
an internal cache framework for additional section
|
||||||
|
content to improve response performance. Several
|
||||||
|
configuration options were provided to control the
|
||||||
|
behavior.
|
||||||
|
|
||||||
1525. [bug] dns_cache_create() could trigger a REQUIRE
|
1525. [bug] dns_cache_create() could trigger a REQUIRE
|
||||||
failure in isc_mem_put() during error cleanup.
|
failure in isc_mem_put() during error cleanup.
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* PERFORMANCE OF THIS SOFTWARE.
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $Id: config.c,v 1.51 2004/10/05 02:47:50 marka Exp $ */
|
/* $Id: config.c,v 1.52 2004/12/21 10:45:15 jinmei Exp $ */
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
@ -125,6 +125,9 @@ options {\n\
|
|||||||
check-names master fail;\n\
|
check-names master fail;\n\
|
||||||
check-names slave warn;\n\
|
check-names slave warn;\n\
|
||||||
check-names response ignore;\n\
|
check-names response ignore;\n\
|
||||||
|
use-additional-cache true;\n\
|
||||||
|
acache-cleaning-interval 60;\n\
|
||||||
|
max-acache-size 0;\n\
|
||||||
dnssec-enable no; /* Make yes for 9.4. */ \n\
|
dnssec-enable no; /* Make yes for 9.4. */ \n\
|
||||||
"
|
"
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* PERFORMANCE OF THIS SOFTWARE.
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $Id: server.h,v 1.75 2004/10/11 05:30:19 marka Exp $ */
|
/* $Id: server.h,v 1.76 2004/12/21 10:45:15 jinmei Exp $ */
|
||||||
|
|
||||||
#ifndef NAMED_SERVER_H
|
#ifndef NAMED_SERVER_H
|
||||||
#define NAMED_SERVER_H 1
|
#define NAMED_SERVER_H 1
|
||||||
@ -94,7 +94,8 @@ struct ns_server {
|
|||||||
ns_controls_t * controls; /* Control channels */
|
ns_controls_t * controls; /* Control channels */
|
||||||
unsigned int dispatchgen;
|
unsigned int dispatchgen;
|
||||||
ns_dispatchlist_t dispatches;
|
ns_dispatchlist_t dispatches;
|
||||||
|
|
||||||
|
dns_acache_t *acache;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NS_SERVER_MAGIC ISC_MAGIC('S','V','E','R')
|
#define NS_SERVER_MAGIC ISC_MAGIC('S','V','E','R')
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* PERFORMANCE OF THIS SOFTWARE.
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $Id: query.c,v 1.261 2004/06/30 14:16:06 marka Exp $ */
|
/* $Id: query.c,v 1.262 2004/12/21 10:45:15 jinmei Exp $ */
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
@ -92,6 +92,11 @@
|
|||||||
#define DNS_GETDB_NOLOG 0x02U
|
#define DNS_GETDB_NOLOG 0x02U
|
||||||
#define DNS_GETDB_PARTIAL 0x04U
|
#define DNS_GETDB_PARTIAL 0x04U
|
||||||
|
|
||||||
|
typedef struct client_additionalctx {
|
||||||
|
ns_client_t *client;
|
||||||
|
dns_rdataset_t *rdataset;
|
||||||
|
} client_additionalctx_t;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype);
|
query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype);
|
||||||
|
|
||||||
@ -538,37 +543,18 @@ query_findversion(ns_client_t *client, dns_db_t *db,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline isc_result_t
|
static inline isc_result_t
|
||||||
query_getzonedb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype,
|
query_validatezonedb(ns_client_t *client, dns_name_t *name,
|
||||||
unsigned int options, dns_zone_t **zonep, dns_db_t **dbp,
|
dns_rdatatype_t qtype, unsigned int options,
|
||||||
dns_dbversion_t **versionp)
|
dns_zone_t *zone, dns_db_t *db,
|
||||||
|
dns_dbversion_t **versionp)
|
||||||
{
|
{
|
||||||
isc_result_t result;
|
isc_result_t result;
|
||||||
isc_boolean_t check_acl, new_zone;
|
isc_boolean_t check_acl, new_zone;
|
||||||
dns_acl_t *queryacl;
|
dns_acl_t *queryacl;
|
||||||
ns_dbversion_t *dbversion;
|
ns_dbversion_t *dbversion;
|
||||||
unsigned int ztoptions;
|
|
||||||
dns_zone_t *zone = NULL;
|
|
||||||
dns_db_t *db = NULL;
|
|
||||||
isc_boolean_t partial = ISC_FALSE;
|
|
||||||
|
|
||||||
REQUIRE(zonep != NULL && *zonep == NULL);
|
REQUIRE(zone != NULL);
|
||||||
REQUIRE(dbp != NULL && *dbp == NULL);
|
REQUIRE(db != NULL);
|
||||||
|
|
||||||
/*
|
|
||||||
* Find a zone database to answer the query.
|
|
||||||
*/
|
|
||||||
ztoptions = ((options & DNS_GETDB_NOEXACT) != 0) ?
|
|
||||||
DNS_ZTFIND_NOEXACT : 0;
|
|
||||||
|
|
||||||
result = dns_zt_find(client->view->zonetable, name, ztoptions, NULL,
|
|
||||||
&zone);
|
|
||||||
if (result == DNS_R_PARTIALMATCH)
|
|
||||||
partial = ISC_TRUE;
|
|
||||||
if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
|
|
||||||
result = dns_zone_getdb(zone, &db);
|
|
||||||
|
|
||||||
if (result != ISC_R_SUCCESS)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This limits our searching to the zone where the first name
|
* This limits our searching to the zone where the first name
|
||||||
@ -689,17 +675,63 @@ query_getzonedb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype,
|
|||||||
*/
|
*/
|
||||||
dbversion->queryok = ISC_TRUE;
|
dbversion->queryok = ISC_TRUE;
|
||||||
|
|
||||||
|
/* Transfer ownership, if necessary. */
|
||||||
|
if (versionp != NULL)
|
||||||
|
*versionp = dbversion->version;
|
||||||
|
|
||||||
|
return (ISC_R_SUCCESS);
|
||||||
|
|
||||||
|
refuse:
|
||||||
|
return (DNS_R_REFUSED);
|
||||||
|
|
||||||
|
fail:
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline isc_result_t
|
||||||
|
query_getzonedb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype,
|
||||||
|
unsigned int options, dns_zone_t **zonep, dns_db_t **dbp,
|
||||||
|
dns_dbversion_t **versionp)
|
||||||
|
{
|
||||||
|
isc_result_t result;
|
||||||
|
unsigned int ztoptions;
|
||||||
|
dns_zone_t *zone = NULL;
|
||||||
|
dns_db_t *db = NULL;
|
||||||
|
isc_boolean_t partial = ISC_FALSE;
|
||||||
|
|
||||||
|
REQUIRE(zonep != NULL && *zonep == NULL);
|
||||||
|
REQUIRE(dbp != NULL && *dbp == NULL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find a zone database to answer the query.
|
||||||
|
*/
|
||||||
|
ztoptions = ((options & DNS_GETDB_NOEXACT) != 0) ?
|
||||||
|
DNS_ZTFIND_NOEXACT : 0;
|
||||||
|
|
||||||
|
result = dns_zt_find(client->view->zonetable, name, ztoptions, NULL,
|
||||||
|
&zone);
|
||||||
|
if (result == DNS_R_PARTIALMATCH)
|
||||||
|
partial = ISC_TRUE;
|
||||||
|
if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
|
||||||
|
result = dns_zone_getdb(zone, &db);
|
||||||
|
|
||||||
|
if (result != ISC_R_SUCCESS)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
result = query_validatezonedb(client, name, qtype, options, zone, db,
|
||||||
|
versionp);
|
||||||
|
|
||||||
|
if (result != ISC_R_SUCCESS)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
/* Transfer ownership. */
|
/* Transfer ownership. */
|
||||||
*zonep = zone;
|
*zonep = zone;
|
||||||
*dbp = db;
|
*dbp = db;
|
||||||
*versionp = dbversion->version;
|
|
||||||
|
|
||||||
if (partial && (options & DNS_GETDB_PARTIAL) != 0)
|
if (partial && (options & DNS_GETDB_PARTIAL) != 0)
|
||||||
return (DNS_R_PARTIALMATCH);
|
return (DNS_R_PARTIALMATCH);
|
||||||
return (ISC_R_SUCCESS);
|
return (ISC_R_SUCCESS);
|
||||||
|
|
||||||
refuse:
|
|
||||||
result = DNS_R_REFUSED;
|
|
||||||
fail:
|
fail:
|
||||||
if (zone != NULL)
|
if (zone != NULL)
|
||||||
dns_zone_detach(&zone);
|
dns_zone_detach(&zone);
|
||||||
@ -1237,11 +1269,516 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
|
|||||||
return (eresult);
|
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, 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;
|
||||||
|
|
||||||
|
if (qtype != dns_rdatatype_a) {
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
client = additionalctx->client;
|
||||||
|
REQUIRE(NS_CLIENT_VALID(client));
|
||||||
|
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;
|
||||||
|
additionaltype = dns_rdatasetadditional_fromauth;
|
||||||
|
dns_name_init(&cfname, NULL);
|
||||||
|
|
||||||
|
CTRACE("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("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("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("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("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("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_find(db, name, version, type, client->query.dboptions,
|
||||||
|
client->now, &node, fname, 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_find(db, name, version, type, client->query.dboptions,
|
||||||
|
client->now, &node, fname, 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 poision 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("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("query_addadditional2: negative glue additional cache");
|
||||||
|
dns_db_closeversion(cdb, &cversion, ISC_FALSE);
|
||||||
|
dns_db_detach(&cdb);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cache hit. */
|
||||||
|
CTRACE("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_find(db, name, version, type,
|
||||||
|
client->query.dboptions | DNS_DBFIND_GLUEOK,
|
||||||
|
client->now, &node, fname, 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;
|
||||||
|
if (WANTDNSSEC(client)) {
|
||||||
|
sigrdataset = query_newrdataset(client);
|
||||||
|
if (sigrdataset == NULL)
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 (result == DNS_R_NCACHENXDOMAIN)
|
||||||
|
goto setcache;
|
||||||
|
if (result == DNS_R_NCACHENXRRSET) {
|
||||||
|
dns_rdataset_disassociate(rdataset);
|
||||||
|
/*
|
||||||
|
* Negative cache entries don't have sigrdatasets.
|
||||||
|
*/
|
||||||
|
INSIST(sigrdataset == NULL ||
|
||||||
|
! dns_rdataset_isassociated(sigrdataset));
|
||||||
|
}
|
||||||
|
if (result == ISC_R_SUCCESS) {
|
||||||
|
/* Remember the result as a cache */
|
||||||
|
ISC_LIST_APPEND(cfname.list, rdataset, link);
|
||||||
|
if (sigrdataset != NULL &&
|
||||||
|
dns_rdataset_isassociated(sigrdataset)) {
|
||||||
|
ISC_LIST_APPEND(cfname.list, sigrdataset,
|
||||||
|
link);
|
||||||
|
sigrdataset =
|
||||||
|
query_newrdataset(client);
|
||||||
|
if (sigrdataset == NULL)
|
||||||
|
needadditionalcache = ISC_FALSE;
|
||||||
|
}
|
||||||
|
rdataset = query_newrdataset(client);
|
||||||
|
if (rdataset == NULL) {
|
||||||
|
/* do not cache incomplete information */
|
||||||
|
goto foundcache;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find AAAA RRset with sig RRset */
|
||||||
|
result = dns_db_findrdataset(db, node, version,
|
||||||
|
dns_rdatatype_aaaa, 0,
|
||||||
|
client->now, rdataset,
|
||||||
|
sigrdataset);
|
||||||
|
/* The NXDOMAIN case should be covered above */
|
||||||
|
INSIST(result != DNS_R_NCACHENXDOMAIN);
|
||||||
|
if (result == DNS_R_NCACHENXRRSET) {
|
||||||
|
dns_rdataset_disassociate(rdataset);
|
||||||
|
/*
|
||||||
|
* Negative cache entries don't have sigrdatasets.
|
||||||
|
*/
|
||||||
|
INSIST(sigrdataset == NULL ||
|
||||||
|
! dns_rdataset_isassociated(sigrdataset));
|
||||||
|
}
|
||||||
|
if (result == ISC_R_SUCCESS) {
|
||||||
|
ISC_LIST_APPEND(cfname.list, rdataset, link);
|
||||||
|
rdataset = NULL;
|
||||||
|
if (sigrdataset != NULL &&
|
||||||
|
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 != 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_sig &&
|
||||||
|
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("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("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("query_addadditional2: done");
|
||||||
|
return (eresult);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
query_addrdataset(ns_client_t *client, dns_name_t *fname,
|
query_addrdataset(ns_client_t *client, dns_name_t *fname,
|
||||||
dns_rdataset_t *rdataset)
|
dns_rdataset_t *rdataset)
|
||||||
{
|
{
|
||||||
dns_rdatatype_t type = rdataset->type;
|
dns_rdatatype_t type = rdataset->type;
|
||||||
|
client_additionalctx_t additionalctx;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add 'rdataset' and any pertinent additional data to
|
* Add 'rdataset' and any pertinent additional data to
|
||||||
@ -1264,8 +1801,10 @@ query_addrdataset(ns_client_t *client, dns_name_t *fname,
|
|||||||
*
|
*
|
||||||
* We don't care if dns_rdataset_additionaldata() fails.
|
* We don't care if dns_rdataset_additionaldata() fails.
|
||||||
*/
|
*/
|
||||||
(void)dns_rdataset_additionaldata(rdataset,
|
additionalctx.client = client;
|
||||||
query_addadditional, client);
|
additionalctx.rdataset = rdataset;
|
||||||
|
(void)dns_rdataset_additionaldata(rdataset, query_addadditional2,
|
||||||
|
&additionalctx);
|
||||||
/*
|
/*
|
||||||
* RFC 2535 section 3.5 says that when NS, SOA, A, or AAAA records
|
* RFC 2535 section 3.5 says that when NS, SOA, A, or AAAA records
|
||||||
* are retrieved, any KEY RRs for the owner name should be added
|
* are retrieved, any KEY RRs for the owner name should be added
|
||||||
@ -1362,11 +1901,12 @@ query_addrrset(ns_client_t *client, dns_name_t **namep,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline isc_result_t
|
static inline isc_result_t
|
||||||
query_addsoa(ns_client_t *client, dns_db_t *db, isc_boolean_t zero_ttl) {
|
query_addsoa(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version,
|
||||||
dns_name_t *name, *fname;
|
isc_boolean_t zero_ttl)
|
||||||
|
{
|
||||||
|
dns_name_t *name;
|
||||||
dns_dbnode_t *node;
|
dns_dbnode_t *node;
|
||||||
isc_result_t result, eresult;
|
isc_result_t result, eresult;
|
||||||
dns_fixedname_t foundname;
|
|
||||||
dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
|
dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
|
||||||
dns_rdataset_t **sigrdatasetp = NULL;
|
dns_rdataset_t **sigrdatasetp = NULL;
|
||||||
|
|
||||||
@ -1378,8 +1918,6 @@ query_addsoa(ns_client_t *client, dns_db_t *db, isc_boolean_t zero_ttl) {
|
|||||||
name = NULL;
|
name = NULL;
|
||||||
rdataset = NULL;
|
rdataset = NULL;
|
||||||
node = NULL;
|
node = NULL;
|
||||||
dns_fixedname_init(&foundname);
|
|
||||||
fname = dns_fixedname_name(&foundname);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get resources and make 'name' be the database origin.
|
* Get resources and make 'name' be the database origin.
|
||||||
@ -1405,9 +1943,26 @@ query_addsoa(ns_client_t *client, dns_db_t *db, isc_boolean_t zero_ttl) {
|
|||||||
/*
|
/*
|
||||||
* Find the SOA.
|
* Find the SOA.
|
||||||
*/
|
*/
|
||||||
result = dns_db_find(db, name, NULL, dns_rdatatype_soa,
|
result = dns_db_getsoanode(db, &node);
|
||||||
client->query.dboptions, 0, &node,
|
if (result == ISC_R_SUCCESS) {
|
||||||
fname, rdataset, sigrdataset);
|
result = dns_db_findrdataset(db, node, version,
|
||||||
|
dns_rdatatype_soa,
|
||||||
|
0, client->now, rdataset,
|
||||||
|
sigrdataset);
|
||||||
|
} else {
|
||||||
|
dns_fixedname_t foundname;
|
||||||
|
dns_name_t *fname;
|
||||||
|
|
||||||
|
dns_fixedname_init(&foundname);
|
||||||
|
fname = dns_fixedname_name(&foundname);
|
||||||
|
|
||||||
|
result = dns_db_find(db, name, version, dns_rdatatype_soa,
|
||||||
|
client->query.dboptions, 0, &node,
|
||||||
|
fname, rdataset, sigrdataset);
|
||||||
|
|
||||||
|
if (result == ISC_R_SUCCESS)
|
||||||
|
(void)dns_db_setsoanode(db, node);
|
||||||
|
}
|
||||||
if (result != ISC_R_SUCCESS) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
/*
|
/*
|
||||||
* This is bad. We tried to get the SOA RR at the zone top
|
* This is bad. We tried to get the SOA RR at the zone top
|
||||||
@ -1463,7 +2018,7 @@ query_addsoa(ns_client_t *client, dns_db_t *db, isc_boolean_t zero_ttl) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline isc_result_t
|
static inline isc_result_t
|
||||||
query_addns(ns_client_t *client, dns_db_t *db) {
|
query_addns(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version) {
|
||||||
dns_name_t *name, *fname;
|
dns_name_t *name, *fname;
|
||||||
dns_dbnode_t *node;
|
dns_dbnode_t *node;
|
||||||
isc_result_t result, eresult;
|
isc_result_t result, eresult;
|
||||||
@ -1510,13 +2065,25 @@ query_addns(ns_client_t *client, dns_db_t *db) {
|
|||||||
/*
|
/*
|
||||||
* Find the NS rdataset.
|
* Find the NS rdataset.
|
||||||
*/
|
*/
|
||||||
CTRACE("query_addns: calling dns_db_find");
|
result = dns_db_getnsnode(db, &node);
|
||||||
result = dns_db_find(db, name, NULL, dns_rdatatype_ns,
|
if (result == ISC_R_SUCCESS) {
|
||||||
client->query.dboptions, 0, &node,
|
result = dns_db_findrdataset(db, node, version,
|
||||||
fname, rdataset, sigrdataset);
|
dns_rdatatype_ns,
|
||||||
CTRACE("query_addns: dns_db_find complete");
|
0, client->now, rdataset,
|
||||||
|
sigrdataset);
|
||||||
|
} else {
|
||||||
|
CTRACE("query_addns: calling dns_db_find");
|
||||||
|
result = dns_db_find(db, name, NULL, dns_rdatatype_ns,
|
||||||
|
client->query.dboptions, 0, &node,
|
||||||
|
fname, rdataset, sigrdataset);
|
||||||
|
CTRACE("query_addns: dns_db_find complete");
|
||||||
|
|
||||||
|
if (result == ISC_R_SUCCESS)
|
||||||
|
(void)dns_db_setnsnode(db, node);
|
||||||
|
}
|
||||||
if (result != ISC_R_SUCCESS) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
CTRACE("query_addns: dns_db_find failed");
|
CTRACE("query_addns: "
|
||||||
|
"dns_db_findrdataset or dns_db_find failed");
|
||||||
/*
|
/*
|
||||||
* This is bad. We tried to get the NS rdataset at the zone
|
* This is bad. We tried to get the NS rdataset at the zone
|
||||||
* top and it didn't work!
|
* top and it didn't work!
|
||||||
@ -2514,7 +3081,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
|
|||||||
|
|
||||||
if (is_zone)
|
if (is_zone)
|
||||||
authoritative = ISC_TRUE;
|
authoritative = ISC_TRUE;
|
||||||
|
|
||||||
if (event == NULL && client->query.restarts == 0) {
|
if (event == NULL && client->query.restarts == 0) {
|
||||||
if (is_zone) {
|
if (is_zone) {
|
||||||
dns_zone_attach(zone, &client->query.authzone);
|
dns_zone_attach(zone, &client->query.authzone);
|
||||||
@ -2838,7 +3405,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
|
|||||||
/*
|
/*
|
||||||
* Add SOA.
|
* Add SOA.
|
||||||
*/
|
*/
|
||||||
result = query_addsoa(client, db, ISC_FALSE);
|
result = query_addsoa(client, db, version, ISC_FALSE);
|
||||||
if (result != ISC_R_SUCCESS) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
QUERY_ERROR(result);
|
QUERY_ERROR(result);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@ -2879,9 +3446,9 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
|
|||||||
* resolver and not have it cached.
|
* resolver and not have it cached.
|
||||||
*/
|
*/
|
||||||
if (qtype == dns_rdatatype_soa)
|
if (qtype == dns_rdatatype_soa)
|
||||||
result = query_addsoa(client, db, ISC_TRUE);
|
result = query_addsoa(client, db, version, ISC_TRUE);
|
||||||
else
|
else
|
||||||
result = query_addsoa(client, db, ISC_FALSE);
|
result = query_addsoa(client, db, version, ISC_FALSE);
|
||||||
if (result != ISC_R_SUCCESS) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
QUERY_ERROR(result);
|
QUERY_ERROR(result);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@ -3205,7 +3772,8 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
|
|||||||
/*
|
/*
|
||||||
* Add SOA.
|
* Add SOA.
|
||||||
*/
|
*/
|
||||||
result = query_addsoa(client, db, ISC_FALSE);
|
result = query_addsoa(client, db, version,
|
||||||
|
ISC_FALSE);
|
||||||
if (result == ISC_R_SUCCESS)
|
if (result == ISC_R_SUCCESS)
|
||||||
result = ISC_R_NOMORE;
|
result = ISC_R_NOMORE;
|
||||||
} else {
|
} else {
|
||||||
@ -3257,7 +3825,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
|
|||||||
qtype == dns_rdatatype_any) &&
|
qtype == dns_rdatatype_any) &&
|
||||||
dns_name_equal(client->query.qname,
|
dns_name_equal(client->query.qname,
|
||||||
dns_db_origin(db))))
|
dns_db_origin(db))))
|
||||||
(void)query_addns(client, db);
|
(void)query_addns(client, db, version);
|
||||||
} else if (qtype != dns_rdatatype_ns) {
|
} else if (qtype != dns_rdatatype_ns) {
|
||||||
if (fname != NULL)
|
if (fname != NULL)
|
||||||
query_releasename(client, &fname);
|
query_releasename(client, &fname);
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* PERFORMANCE OF THIS SOFTWARE.
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $Id: server.c,v 1.433 2004/11/10 22:14:28 marka Exp $ */
|
/* $Id: server.c,v 1.434 2004/12/21 10:45:15 jinmei Exp $ */
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
@ -41,6 +41,7 @@
|
|||||||
|
|
||||||
#include <bind9/check.h>
|
#include <bind9/check.h>
|
||||||
|
|
||||||
|
#include <dns/acache.h>
|
||||||
#include <dns/adb.h>
|
#include <dns/adb.h>
|
||||||
#include <dns/cache.h>
|
#include <dns/cache.h>
|
||||||
#include <dns/db.h>
|
#include <dns/db.h>
|
||||||
@ -733,6 +734,7 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
|
|||||||
isc_result_t result;
|
isc_result_t result;
|
||||||
isc_uint32_t max_adb_size;
|
isc_uint32_t max_adb_size;
|
||||||
isc_uint32_t max_cache_size;
|
isc_uint32_t max_cache_size;
|
||||||
|
isc_uint32_t max_acache_size;
|
||||||
isc_uint32_t lame_ttl;
|
isc_uint32_t lame_ttl;
|
||||||
dns_tsig_keyring_t *ring;
|
dns_tsig_keyring_t *ring;
|
||||||
dns_view_t *pview = NULL; /* Production view */
|
dns_view_t *pview = NULL; /* Production view */
|
||||||
@ -776,6 +778,51 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
|
|||||||
CHECKM(ns_config_getport(config, &port), "port");
|
CHECKM(ns_config_getport(config, &port), "port");
|
||||||
dns_view_setdstport(view, port);
|
dns_view_setdstport(view, port);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create additional cache for this view and zones under the view
|
||||||
|
* unless explicitly disabled.
|
||||||
|
*/
|
||||||
|
obj = NULL;
|
||||||
|
ns_config_get(maps, "use-additional-cache", &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_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 = ISC_UINT32_MAX;
|
||||||
|
} else {
|
||||||
|
isc_resourcevalue_t value;
|
||||||
|
|
||||||
|
value = cfg_obj_asuint64(obj);
|
||||||
|
if (value > ISC_UINT32_MAX) {
|
||||||
|
cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR,
|
||||||
|
"'max-acache-size "
|
||||||
|
"%" ISC_PRINT_QUADFORMAT
|
||||||
|
"d' is too large",
|
||||||
|
value);
|
||||||
|
result = ISC_R_RANGE;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
max_acache_size = (isc_uint32_t)value;
|
||||||
|
}
|
||||||
|
dns_acache_setcachesize(view->acache, max_acache_size);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Configure the zones.
|
* Configure the zones.
|
||||||
*/
|
*/
|
||||||
@ -1737,6 +1784,8 @@ configure_zone(cfg_obj_t *config, cfg_obj_t *zconfig, cfg_obj_t *vconfig,
|
|||||||
* new view.
|
* new view.
|
||||||
*/
|
*/
|
||||||
dns_zone_setview(zone, view);
|
dns_zone_setview(zone, view);
|
||||||
|
if (view->acache != NULL)
|
||||||
|
dns_zone_setacache(zone, view->acache);
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* We cannot reuse an existing zone, we have
|
* We cannot reuse an existing zone, we have
|
||||||
@ -1745,6 +1794,8 @@ configure_zone(cfg_obj_t *config, cfg_obj_t *zconfig, cfg_obj_t *vconfig,
|
|||||||
CHECK(dns_zone_create(&zone, mctx));
|
CHECK(dns_zone_create(&zone, mctx));
|
||||||
CHECK(dns_zone_setorigin(zone, origin));
|
CHECK(dns_zone_setorigin(zone, origin));
|
||||||
dns_zone_setview(zone, view);
|
dns_zone_setview(zone, view);
|
||||||
|
if (view->acache != NULL)
|
||||||
|
dns_zone_setacache(zone, view->acache);
|
||||||
CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone));
|
CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.0//EN"
|
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.0//EN"
|
||||||
"http://www.oasis-open.org/docbook/xml/4.0/docbookx.dtd">
|
"http://www.oasis-open.org/docbook/xml/4.0/docbookx.dtd">
|
||||||
|
|
||||||
<!-- File: $Id: Bv9ARM-book.xml,v 1.259 2004/11/11 01:08:24 marka Exp $ -->
|
<!-- File: $Id: Bv9ARM-book.xml,v 1.260 2004/12/21 10:45:16 jinmei Exp $ -->
|
||||||
|
|
||||||
<book>
|
<book>
|
||||||
<title>BIND 9 Administrator Reference Manual</title>
|
<title>BIND 9 Administrator Reference Manual</title>
|
||||||
@ -392,7 +392,12 @@ signed zones, serving many thousands of queries per second.</para></sect1>
|
|||||||
cache and zones loaded off disk. The <command>max-cache-size</command>
|
cache and zones loaded off disk. The <command>max-cache-size</command>
|
||||||
option can be used to limit the amount of memory used by the cache,
|
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 <acronym>DNS</acronym>
|
at the expense of reducing cache hit rates and causing more <acronym>DNS</acronym>
|
||||||
traffic. It is still good practice to have enough memory to load
|
traffic.
|
||||||
|
Additionally, if additional section caching
|
||||||
|
(<xref linkend="acache"/>) is enabled,
|
||||||
|
the <command>max-acache-size</command> 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
|
all zone and cache data into memory — unfortunately, the best way
|
||||||
to determine this for a given installation is to watch the name server
|
to determine this for a given installation is to watch the name server
|
||||||
in operation. After a few weeks the server process should reach
|
in operation. After a few weeks the server process should reach
|
||||||
@ -2800,8 +2805,11 @@ statement in the <filename>named.conf</filename> file:</para>
|
|||||||
<optional> edns-udp-size <replaceable>number</replaceable>; </optional>
|
<optional> edns-udp-size <replaceable>number</replaceable>; </optional>
|
||||||
<optional> root-delegation-only <optional> exclude { <replaceable>namelist</replaceable> } </optional> ; </optional>
|
<optional> root-delegation-only <optional> exclude { <replaceable>namelist</replaceable> } </optional> ; </optional>
|
||||||
<optional> querylog <replaceable>yes_or_no</replaceable> ; </optional>
|
<optional> querylog <replaceable>yes_or_no</replaceable> ; </optional>
|
||||||
};
|
|
||||||
<optional> disable-algorithms <replaceable>domain</replaceable> { <replaceable>algorithm</replaceable>; <optional> <replaceable>algorithm</replaceable>; </optional> }; </optional>
|
<optional> disable-algorithms <replaceable>domain</replaceable> { <replaceable>algorithm</replaceable>; <optional> <replaceable>algorithm</replaceable>; </optional> }; </optional>
|
||||||
|
<optional> use-additional-cache <replaceable>yes_or_no</replaceable> ; </optional>
|
||||||
|
<optional> acache-cleaning-interval <replaceable>number</replaceable>; </optional>
|
||||||
|
<optional> max-acache-size <replaceable>size_spec</replaceable> ; </optional>
|
||||||
|
};
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</sect2>
|
</sect2>
|
||||||
|
|
||||||
@ -4346,6 +4354,99 @@ to be incremented, and may additionally cause the
|
|||||||
|
|
||||||
</sect3>
|
</sect3>
|
||||||
|
|
||||||
|
<sect3 id="acache">
|
||||||
|
<title>Additional Section Caching</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The additional section cache, also called <command>acache,</command>
|
||||||
|
is an internal cache to improve the response performance of BIND 9.
|
||||||
|
When the additional section caching is enabled, BIND 9 will
|
||||||
|
cache 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 relevant to the DNS caching server function.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The additional section caching does not make any difference on 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.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
In order to achieve the maximum performance improvement by acache,
|
||||||
|
it is recommended to set <command>additional-from-cache</command>
|
||||||
|
to <command>no</command>, since the current implementation of acache
|
||||||
|
does not make a short-cut of additional section information from a DNS
|
||||||
|
cache data.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
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 severe, the acache mechanism can be
|
||||||
|
disabled by setting <command>use-additional-cache</command> to
|
||||||
|
<command>no</command>.
|
||||||
|
It is also possible to specify the upper limit of memory consumption
|
||||||
|
for acache by <command>max-acache-size</command>.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The additional section caching also has a minor effect on the RRset
|
||||||
|
ordering in the additional section.
|
||||||
|
Without acache, the "cyclic" order is effective for the additional
|
||||||
|
section as well as the answer and authority sections.
|
||||||
|
However, the 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
|
||||||
|
configuration for <command>rrset-order</command>.
|
||||||
|
This should be minor, though, 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.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The following is a summary of options related to acache.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<variablelist>
|
||||||
|
|
||||||
|
<varlistentry><term><command>use-additional-cache</command></term>
|
||||||
|
<listitem><para>
|
||||||
|
If yes, the additional section caching is enabled.
|
||||||
|
The default value is yes.
|
||||||
|
</para>
|
||||||
|
</listitem></varlistentry>
|
||||||
|
|
||||||
|
<varlistentry><term><command>acache-cleaning-interval</command></term>
|
||||||
|
<listitem><para>
|
||||||
|
The server will remove stale cache entries, based on an LRU based
|
||||||
|
algorithm, every <command>acache-cleaning-interval</command> minutes.
|
||||||
|
The default is 60 minutes.
|
||||||
|
If set to 0, no periodic cleaning will occur.
|
||||||
|
</para>
|
||||||
|
</listitem></varlistentry>
|
||||||
|
|
||||||
|
<varlistentry><term><command>max-acache-size</command></term>
|
||||||
|
<listitem><para>
|
||||||
|
The maximum amount of memory to use for the server's acache, in bytes.
|
||||||
|
When the amount of data in the acache reaches this limit, the server
|
||||||
|
will cause more aggressive cleaning 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 <literal>unlimited</literal>, meaning that
|
||||||
|
entries are purged from acache only at the periodic cleaning time.
|
||||||
|
</para>
|
||||||
|
</listitem></varlistentry>
|
||||||
|
|
||||||
|
</variablelist>
|
||||||
|
|
||||||
|
</sect3>
|
||||||
|
|
||||||
</sect2>
|
</sect2>
|
||||||
|
|
||||||
<sect2 id="server_statement_grammar">
|
<sect2 id="server_statement_grammar">
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
# PERFORMANCE OF THIS SOFTWARE.
|
# PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
# $Id: Makefile.in,v 1.148 2004/12/09 01:40:59 marka Exp $
|
# $Id: Makefile.in,v 1.149 2004/12/21 10:45:16 jinmei Exp $
|
||||||
|
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
VPATH = @srcdir@
|
VPATH = @srcdir@
|
||||||
@ -49,7 +49,7 @@ DSTOBJS = dst_api.@O@ dst_lib.@O@ dst_parse.@O@ dst_result.@O@ \
|
|||||||
opensslrsa_link.@O@
|
opensslrsa_link.@O@
|
||||||
|
|
||||||
# Alphabetically
|
# Alphabetically
|
||||||
DNSOBJS = acl.@O@ adb.@O@ byaddr.@O@ \
|
DNSOBJS = acache.@O@ acl.@O@ adb.@O@ byaddr.@O@ \
|
||||||
cache.@O@ callbacks.@O@ compress.@O@ \
|
cache.@O@ callbacks.@O@ compress.@O@ \
|
||||||
db.@O@ dbiterator.@O@ dbtable.@O@ diff.@O@ dispatch.@O@ \
|
db.@O@ dbiterator.@O@ dbtable.@O@ diff.@O@ dispatch.@O@ \
|
||||||
dnssec.@O@ ds.@O@ forward.@O@ journal.@O@ keytable.@O@ \
|
dnssec.@O@ ds.@O@ forward.@O@ journal.@O@ keytable.@O@ \
|
||||||
@ -73,7 +73,7 @@ DSTSRCS = dst_api.c dst_lib.c dst_parse.c \
|
|||||||
openssl_link.c openssldh_link.c \
|
openssl_link.c openssldh_link.c \
|
||||||
openssldsa_link.c opensslrsa_link.c
|
openssldsa_link.c opensslrsa_link.c
|
||||||
|
|
||||||
DNSSRCS = acl.c adb.c byaddr.c \
|
DNSSRCS = acache.c acl.c adb.c byaddr.c \
|
||||||
cache.c callbacks.c compress.c \
|
cache.c callbacks.c compress.c \
|
||||||
db.c dbiterator.c dbtable.c diff.c dispatch.c \
|
db.c dbiterator.c dbtable.c diff.c dispatch.c \
|
||||||
dnssec.c ds.c forward.c journal.c keytable.c \
|
dnssec.c ds.c forward.c journal.c keytable.c \
|
||||||
|
1575
lib/dns/acache.c
Normal file
1575
lib/dns/acache.c
Normal file
File diff suppressed because it is too large
Load Diff
50
lib/dns/db.c
50
lib/dns/db.c
@ -15,7 +15,7 @@
|
|||||||
* PERFORMANCE OF THIS SOFTWARE.
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $Id: db.c,v 1.74 2004/03/05 05:09:18 marka Exp $ */
|
/* $Id: db.c,v 1.75 2004/12/21 10:45:16 jinmei Exp $ */
|
||||||
|
|
||||||
/***
|
/***
|
||||||
*** Imports
|
*** Imports
|
||||||
@ -791,3 +791,51 @@ dns_db_unregister(dns_dbimplementation_t **dbimp) {
|
|||||||
isc_mem_detach(&mctx);
|
isc_mem_detach(&mctx);
|
||||||
RWUNLOCK(&implock, isc_rwlocktype_write);
|
RWUNLOCK(&implock, isc_rwlocktype_write);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isc_result_t
|
||||||
|
dns_db_getsoanode(dns_db_t *db, dns_dbnode_t **nodep) {
|
||||||
|
REQUIRE(DNS_DB_VALID(db));
|
||||||
|
REQUIRE(dns_db_iszone(db) == ISC_TRUE);
|
||||||
|
REQUIRE(nodep != NULL && *nodep == NULL);
|
||||||
|
|
||||||
|
if (db->methods->getsoanode != NULL)
|
||||||
|
return ((db->methods->getsoanode)(db, nodep));
|
||||||
|
|
||||||
|
return (ISC_R_NOTFOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t
|
||||||
|
dns_db_setsoanode(dns_db_t *db, dns_dbnode_t *node) {
|
||||||
|
REQUIRE(DNS_DB_VALID(db));
|
||||||
|
REQUIRE(dns_db_iszone(db) == ISC_TRUE);
|
||||||
|
REQUIRE(node != NULL);
|
||||||
|
|
||||||
|
if (db->methods->setsoanode != NULL)
|
||||||
|
return ((db->methods->setsoanode)(db, node));
|
||||||
|
|
||||||
|
return (ISC_R_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t
|
||||||
|
dns_db_getnsnode(dns_db_t *db, dns_dbnode_t **nodep) {
|
||||||
|
REQUIRE(DNS_DB_VALID(db));
|
||||||
|
REQUIRE(dns_db_iszone(db) == ISC_TRUE);
|
||||||
|
REQUIRE(nodep != NULL && *nodep == NULL);
|
||||||
|
|
||||||
|
if (db->methods->getnsnode != NULL)
|
||||||
|
return ((db->methods->getnsnode)(db, nodep));
|
||||||
|
|
||||||
|
return (ISC_R_NOTFOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t
|
||||||
|
dns_db_setnsnode(dns_db_t *db, dns_dbnode_t *node) {
|
||||||
|
REQUIRE(DNS_DB_VALID(db));
|
||||||
|
REQUIRE(dns_db_iszone(db) == ISC_TRUE);
|
||||||
|
REQUIRE(node != NULL);
|
||||||
|
|
||||||
|
if (db->methods->setnsnode != NULL)
|
||||||
|
return ((db->methods->setnsnode)(db, node));
|
||||||
|
|
||||||
|
return (ISC_R_FAILURE);
|
||||||
|
}
|
||||||
|
440
lib/dns/include/dns/acache.h
Normal file
440
lib/dns/include/dns/acache.h
Normal file
@ -0,0 +1,440 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2003 Internet Software Consortium.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
|
||||||
|
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||||
|
* INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
|
||||||
|
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* $Id: acache.h,v 1.2 2004/12/21 10:45:18 jinmei 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 <isc/mutex.h>
|
||||||
|
#include <isc/lang.h>
|
||||||
|
#include <isc/refcount.h>
|
||||||
|
#include <isc/stdtime.h>
|
||||||
|
|
||||||
|
#include <dns/types.h>
|
||||||
|
|
||||||
|
/***
|
||||||
|
*** 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, isc_uint32_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
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ISC_LANG_ENDDECLS
|
||||||
|
|
||||||
|
#endif /* DNS_ACACHE_H */
|
@ -15,7 +15,7 @@
|
|||||||
* PERFORMANCE OF THIS SOFTWARE.
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $Id: db.h,v 1.77 2004/05/14 04:45:57 marka Exp $ */
|
/* $Id: db.h,v 1.78 2004/12/21 10:45:18 jinmei Exp $ */
|
||||||
|
|
||||||
#ifndef DNS_DB_H
|
#ifndef DNS_DB_H
|
||||||
#define DNS_DB_H 1
|
#define DNS_DB_H 1
|
||||||
@ -145,6 +145,10 @@ typedef struct dns_dbmethods {
|
|||||||
isc_boolean_t (*ispersistent)(dns_db_t *db);
|
isc_boolean_t (*ispersistent)(dns_db_t *db);
|
||||||
void (*overmem)(dns_db_t *db, isc_boolean_t overmem);
|
void (*overmem)(dns_db_t *db, isc_boolean_t overmem);
|
||||||
void (*settask)(dns_db_t *db, isc_task_t *);
|
void (*settask)(dns_db_t *db, isc_task_t *);
|
||||||
|
isc_result_t (*getsoanode)(dns_db_t *db, dns_dbnode_t **nodep);
|
||||||
|
isc_result_t (*setsoanode)(dns_db_t *db, dns_dbnode_t *nodep);
|
||||||
|
isc_result_t (*getnsnode)(dns_db_t *db, dns_dbnode_t **nodep);
|
||||||
|
isc_result_t (*setnsnode)(dns_db_t *db, dns_dbnode_t *nodep);
|
||||||
} dns_dbmethods_t;
|
} dns_dbmethods_t;
|
||||||
|
|
||||||
typedef isc_result_t
|
typedef isc_result_t
|
||||||
@ -1266,6 +1270,84 @@ dns_db_unregister(dns_dbimplementation_t **dbimp);
|
|||||||
* Any memory allocated in *dbimp will be freed.
|
* Any memory allocated in *dbimp will be freed.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
isc_result_t
|
||||||
|
dns_db_getsoanode(dns_db_t *db, dns_dbnode_t **nodep);
|
||||||
|
/*
|
||||||
|
* Get a cached SOA DB node corresponding to the DB's zone.
|
||||||
|
*
|
||||||
|
* Requires:
|
||||||
|
*
|
||||||
|
* 'db' is a valid zone database.
|
||||||
|
* 'nodep' != NULL && '*nodep' == NULL
|
||||||
|
*
|
||||||
|
* Ensures:
|
||||||
|
* On sucess, '*nodep' will point to a DB node for the SOA RR of 'db.'
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* ISC_R_SUCCESS
|
||||||
|
* ISC_R_NOTFOUND - an SOA RR node has not been cached in 'db' or SOA RR
|
||||||
|
* caching is not supported for 'db'
|
||||||
|
*/
|
||||||
|
|
||||||
|
isc_result_t
|
||||||
|
dns_db_setsoanode(dns_db_t *db, dns_dbnode_t *node);
|
||||||
|
/*
|
||||||
|
* Set an SOA DB node as cache corresponding to the DB's zone. If there is
|
||||||
|
* already a node set in the DB, it will be detached and replaced with the
|
||||||
|
* new one.
|
||||||
|
*
|
||||||
|
* Requires:
|
||||||
|
*
|
||||||
|
* 'db' is a valid zone database.
|
||||||
|
* 'node' is a valid DB node.
|
||||||
|
*
|
||||||
|
* Ensures:
|
||||||
|
* On sucess, '*nodep' will point to a DB node for the SOA RR of 'db.'
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* ISC_R_SUCCESS
|
||||||
|
* ISC_R_FAILURE - SOA RR caching is not supported for 'db'
|
||||||
|
*/
|
||||||
|
|
||||||
|
isc_result_t
|
||||||
|
dns_db_getnsnode(dns_db_t *db, dns_dbnode_t **nodep);
|
||||||
|
/*
|
||||||
|
* Get a cached NS DB node corresponding to the DB's zone.
|
||||||
|
*
|
||||||
|
* Requires:
|
||||||
|
*
|
||||||
|
* 'db' is a valid zone database.
|
||||||
|
* 'nodep' != NULL && '*nodep' == NULL
|
||||||
|
*
|
||||||
|
* Ensures:
|
||||||
|
* On sucess, '*nodep' will point to a DB node for the NS RR of 'db.'
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* ISC_R_SUCCESS
|
||||||
|
* ISC_R_NOTFOUND - an NS RR node has not been cached in 'db' or NS RR
|
||||||
|
* caching is not supported for 'db'
|
||||||
|
*/
|
||||||
|
|
||||||
|
isc_result_t
|
||||||
|
dns_db_setnsnode(dns_db_t *db, dns_dbnode_t *node);
|
||||||
|
/*
|
||||||
|
* Set an NS DB node as cache corresponding to the DB's zone. If there is
|
||||||
|
* already a node set in the DB, it will be detached and replaced with the
|
||||||
|
* new one.
|
||||||
|
*
|
||||||
|
* Requires:
|
||||||
|
*
|
||||||
|
* 'db' is a valid zone database.
|
||||||
|
* 'node' is a valid DB node.
|
||||||
|
*
|
||||||
|
* Ensures:
|
||||||
|
* On sucess, '*nodep' will point to a DB node for the NS RR of 'db.'
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* ISC_R_SUCCESS
|
||||||
|
* ISC_R_FAILURE - NS RR caching is not supported for 'db'
|
||||||
|
*/
|
||||||
|
|
||||||
ISC_LANG_ENDDECLS
|
ISC_LANG_ENDDECLS
|
||||||
|
|
||||||
#endif /* DNS_DB_H */
|
#endif /* DNS_DB_H */
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* PERFORMANCE OF THIS SOFTWARE.
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $Id: events.h,v 1.42 2004/03/05 05:09:42 marka Exp $ */
|
/* $Id: events.h,v 1.43 2004/12/21 10:45:19 jinmei Exp $ */
|
||||||
|
|
||||||
#ifndef DNS_EVENTS_H
|
#ifndef DNS_EVENTS_H
|
||||||
#define DNS_EVENTS_H 1
|
#define DNS_EVENTS_H 1
|
||||||
@ -63,6 +63,10 @@
|
|||||||
#define DNS_EVENT_DUMPQUANTUM (ISC_EVENTCLASS_DNS + 34)
|
#define DNS_EVENT_DUMPQUANTUM (ISC_EVENTCLASS_DNS + 34)
|
||||||
#define DNS_EVENT_IMPORTRECVDONE (ISC_EVENTCLASS_DNS + 35)
|
#define DNS_EVENT_IMPORTRECVDONE (ISC_EVENTCLASS_DNS + 35)
|
||||||
#define DNS_EVENT_FREESTORAGE (ISC_EVENTCLASS_DNS + 36)
|
#define DNS_EVENT_FREESTORAGE (ISC_EVENTCLASS_DNS + 36)
|
||||||
|
#define DNS_EVENT_VIEWACACHESHUTDOWN (ISC_EVENTCLASS_DNS + 37)
|
||||||
|
#define DNS_EVENT_ACACHECONTROL (ISC_EVENTCLASS_DNS + 38)
|
||||||
|
#define DNS_EVENT_ACACHECLEAN (ISC_EVENTCLASS_DNS + 39)
|
||||||
|
#define DNS_EVENT_ACACHEOVERMEM (ISC_EVENTCLASS_DNS + 40)
|
||||||
|
|
||||||
#define DNS_EVENT_FIRSTEVENT (ISC_EVENTCLASS_DNS + 0)
|
#define DNS_EVENT_FIRSTEVENT (ISC_EVENTCLASS_DNS + 0)
|
||||||
#define DNS_EVENT_LASTEVENT (ISC_EVENTCLASS_DNS + 65535)
|
#define DNS_EVENT_LASTEVENT (ISC_EVENTCLASS_DNS + 65535)
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* PERFORMANCE OF THIS SOFTWARE.
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $Id: log.h,v 1.33 2004/03/05 05:09:43 marka Exp $ */
|
/* $Id: log.h,v 1.34 2004/12/21 10:45:19 jinmei Exp $ */
|
||||||
|
|
||||||
/* Principal Authors: DCL */
|
/* Principal Authors: DCL */
|
||||||
|
|
||||||
@ -69,6 +69,7 @@ LIBDNS_EXTERNAL_DATA extern isc_logmodule_t dns_modules[];
|
|||||||
#define DNS_LOGMODULE_SDB (&dns_modules[22])
|
#define DNS_LOGMODULE_SDB (&dns_modules[22])
|
||||||
#define DNS_LOGMODULE_DIFF (&dns_modules[23])
|
#define DNS_LOGMODULE_DIFF (&dns_modules[23])
|
||||||
#define DNS_LOGMODULE_HINTS (&dns_modules[24])
|
#define DNS_LOGMODULE_HINTS (&dns_modules[24])
|
||||||
|
#define DNS_LOGMODULE_ACACHE (&dns_modules[25])
|
||||||
|
|
||||||
ISC_LANG_BEGINDECLS
|
ISC_LANG_BEGINDECLS
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* PERFORMANCE OF THIS SOFTWARE.
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $Id: rdataset.h,v 1.51 2004/03/05 05:09:45 marka Exp $ */
|
/* $Id: rdataset.h,v 1.52 2004/12/21 10:45:19 jinmei Exp $ */
|
||||||
|
|
||||||
#ifndef DNS_RDATASET_H
|
#ifndef DNS_RDATASET_H
|
||||||
#define DNS_RDATASET_H 1
|
#define DNS_RDATASET_H 1
|
||||||
@ -54,11 +54,18 @@
|
|||||||
|
|
||||||
#include <isc/lang.h>
|
#include <isc/lang.h>
|
||||||
#include <isc/magic.h>
|
#include <isc/magic.h>
|
||||||
|
#include <isc/stdtime.h>
|
||||||
|
|
||||||
#include <dns/types.h>
|
#include <dns/types.h>
|
||||||
|
|
||||||
ISC_LANG_BEGINDECLS
|
ISC_LANG_BEGINDECLS
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
dns_rdatasetadditional_fromauth,
|
||||||
|
dns_rdatasetadditional_fromcache,
|
||||||
|
dns_rdatasetadditional_fromglue
|
||||||
|
} dns_rdatasetadditional_t;
|
||||||
|
|
||||||
typedef struct dns_rdatasetmethods {
|
typedef struct dns_rdatasetmethods {
|
||||||
void (*disassociate)(dns_rdataset_t *rdataset);
|
void (*disassociate)(dns_rdataset_t *rdataset);
|
||||||
isc_result_t (*first)(dns_rdataset_t *rdataset);
|
isc_result_t (*first)(dns_rdataset_t *rdataset);
|
||||||
@ -74,6 +81,30 @@ typedef struct dns_rdatasetmethods {
|
|||||||
dns_name_t *name,
|
dns_name_t *name,
|
||||||
dns_rdataset_t *nsec,
|
dns_rdataset_t *nsec,
|
||||||
dns_rdataset_t *nsecsig);
|
dns_rdataset_t *nsecsig);
|
||||||
|
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);
|
||||||
} dns_rdatasetmethods_t;
|
} dns_rdatasetmethods_t;
|
||||||
|
|
||||||
#define DNS_RDATASET_MAGIC ISC_MAGIC('D','N','S','R')
|
#define DNS_RDATASET_MAGIC ISC_MAGIC('D','N','S','R')
|
||||||
@ -409,7 +440,6 @@ dns_rdataset_towirepartial(dns_rdataset_t *rdataset,
|
|||||||
* written.
|
* written.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
isc_result_t
|
isc_result_t
|
||||||
dns_rdataset_additionaldata(dns_rdataset_t *rdataset,
|
dns_rdataset_additionaldata(dns_rdataset_t *rdataset,
|
||||||
dns_additionaldatafunc_t add, void *arg);
|
dns_additionaldatafunc_t add, void *arg);
|
||||||
@ -463,6 +493,100 @@ dns_rdataset_addnoqname(dns_rdataset_t *rdataset, dns_name_t *name);
|
|||||||
* 'name' to be valid and have NSEC and RRSIG(NSEC) rdatasets.
|
* 'name' to be valid and have NSEC and RRSIG(NSEC) 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:
|
||||||
|
* 'rdataset' is a valid rdataset.
|
||||||
|
* 'acache' can be NULL, in which case this function will simply return
|
||||||
|
* ISC_R_FAILURE.
|
||||||
|
* For the other pointers, see dns_acache_getentry().
|
||||||
|
*
|
||||||
|
* Ensures:
|
||||||
|
* See dns_acache_getentry().
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* ISC_R_SUCCESS
|
||||||
|
* ISC_R_FAILURE - additional information caching is not supported.
|
||||||
|
* ISC_R_NOTFOUND - the corresponding DB node has not cached additional
|
||||||
|
* information for 'rdataset.'
|
||||||
|
*
|
||||||
|
* 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:
|
||||||
|
* 'rdataset' is a valid rdataset.
|
||||||
|
* 'acache' can be NULL, in which case this function will simply return
|
||||||
|
* ISC_R_FAILURE.
|
||||||
|
* For the other pointers, see dns_acache_setentry().
|
||||||
|
*
|
||||||
|
* Ensures:
|
||||||
|
* See dns_acache_setentry().
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* ISC_R_SUCCESS
|
||||||
|
* ISC_R_FAILURE - additional information caching is not supported.
|
||||||
|
* ISC_R_NOMEMORY
|
||||||
|
*
|
||||||
|
* 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:
|
||||||
|
* 'rdataset' is a valid rdataset.
|
||||||
|
* 'acache' can be NULL, in which case this function will simply return
|
||||||
|
* ISC_R_FAILURE.
|
||||||
|
*
|
||||||
|
* Ensures:
|
||||||
|
* See dns_acache_cancelentry().
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* ISC_R_SUCCESS
|
||||||
|
* ISC_R_FAILURE - additional information caching is not supported.
|
||||||
|
* ISC_R_NOTFOUND - the corresponding DB node has not cached additional
|
||||||
|
* information for 'rdataset.'
|
||||||
|
*/
|
||||||
|
|
||||||
ISC_LANG_ENDDECLS
|
ISC_LANG_ENDDECLS
|
||||||
|
|
||||||
#endif /* DNS_RDATASET_H */
|
#endif /* DNS_RDATASET_H */
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* PERFORMANCE OF THIS SOFTWARE.
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $Id: types.h,v 1.110 2004/03/30 02:13:44 marka Exp $ */
|
/* $Id: types.h,v 1.111 2004/12/21 10:45:19 jinmei Exp $ */
|
||||||
|
|
||||||
#ifndef DNS_TYPES_H
|
#ifndef DNS_TYPES_H
|
||||||
#define DNS_TYPES_H 1
|
#define DNS_TYPES_H 1
|
||||||
@ -30,6 +30,8 @@
|
|||||||
|
|
||||||
#include <isc/types.h>
|
#include <isc/types.h>
|
||||||
|
|
||||||
|
typedef struct dns_acache dns_acache_t;
|
||||||
|
typedef struct dns_acacheentry dns_acacheentry_t;
|
||||||
typedef struct dns_acl dns_acl_t;
|
typedef struct dns_acl dns_acl_t;
|
||||||
typedef struct dns_aclelement dns_aclelement_t;
|
typedef struct dns_aclelement dns_aclelement_t;
|
||||||
typedef struct dns_aclenv dns_aclenv_t;
|
typedef struct dns_aclenv dns_aclenv_t;
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* PERFORMANCE OF THIS SOFTWARE.
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $Id: view.h,v 1.91 2004/03/10 02:19:56 marka Exp $ */
|
/* $Id: view.h,v 1.92 2004/12/21 10:45:19 jinmei Exp $ */
|
||||||
|
|
||||||
#ifndef DNS_VIEW_H
|
#ifndef DNS_VIEW_H
|
||||||
#define DNS_VIEW_H 1
|
#define DNS_VIEW_H 1
|
||||||
@ -86,6 +86,7 @@ struct dns_view {
|
|||||||
dns_resolver_t * resolver;
|
dns_resolver_t * resolver;
|
||||||
dns_adb_t * adb;
|
dns_adb_t * adb;
|
||||||
dns_requestmgr_t * requestmgr;
|
dns_requestmgr_t * requestmgr;
|
||||||
|
dns_acache_t * acache;
|
||||||
dns_cache_t * cache;
|
dns_cache_t * cache;
|
||||||
dns_db_t * cachedb;
|
dns_db_t * cachedb;
|
||||||
dns_db_t * hints;
|
dns_db_t * hints;
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* PERFORMANCE OF THIS SOFTWARE.
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $Id: zone.h,v 1.127 2004/10/26 02:01:19 marka Exp $ */
|
/* $Id: zone.h,v 1.128 2004/12/21 10:45:19 jinmei Exp $ */
|
||||||
|
|
||||||
#ifndef DNS_ZONE_H
|
#ifndef DNS_ZONE_H
|
||||||
#define DNS_ZONE_H 1
|
#define DNS_ZONE_H 1
|
||||||
@ -1432,6 +1432,19 @@ dns_zone_checknames(dns_zone_t *zone, dns_name_t *name, dns_rdata_t *rdata);
|
|||||||
* DNS_R_BADNAME failed rdata checks.
|
* 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'
|
||||||
|
*/
|
||||||
|
|
||||||
ISC_LANG_ENDDECLS
|
ISC_LANG_ENDDECLS
|
||||||
|
|
||||||
#endif /* DNS_ZONE_H */
|
#endif /* DNS_ZONE_H */
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* PERFORMANCE OF THIS SOFTWARE.
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $Id: log.c,v 1.36 2004/03/05 05:09:20 marka Exp $ */
|
/* $Id: log.c,v 1.37 2004/12/21 10:45:16 jinmei Exp $ */
|
||||||
|
|
||||||
/* Principal Authors: DCL */
|
/* Principal Authors: DCL */
|
||||||
|
|
||||||
@ -74,6 +74,7 @@ LIBDNS_EXTERNAL_DATA isc_logmodule_t dns_modules[] = {
|
|||||||
{ "dns/sdb", 0 },
|
{ "dns/sdb", 0 },
|
||||||
{ "dns/diff", 0 },
|
{ "dns/diff", 0 },
|
||||||
{ "dns/hints", 0 },
|
{ "dns/hints", 0 },
|
||||||
|
{ "dns/acache", 0 },
|
||||||
{ NULL, 0 }
|
{ NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* PERFORMANCE OF THIS SOFTWARE.
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $Id: ncache.c,v 1.36 2004/03/05 05:09:21 marka Exp $ */
|
/* $Id: ncache.c,v 1.37 2004/12/21 10:45:17 jinmei Exp $ */
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
@ -473,6 +473,9 @@ static dns_rdatasetmethods_t rdataset_methods = {
|
|||||||
rdataset_clone,
|
rdataset_clone,
|
||||||
rdataset_count,
|
rdataset_count,
|
||||||
NULL,
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
533
lib/dns/rbtdb.c
533
lib/dns/rbtdb.c
@ -15,7 +15,7 @@
|
|||||||
* PERFORMANCE OF THIS SOFTWARE.
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $Id: rbtdb.c,v 1.200 2004/05/23 06:59:20 marka Exp $ */
|
/* $Id: rbtdb.c,v 1.201 2004/12/21 10:45:17 jinmei Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Principal Author: Bob Halley
|
* Principal Author: Bob Halley
|
||||||
@ -34,6 +34,7 @@
|
|||||||
#include <isc/task.h>
|
#include <isc/task.h>
|
||||||
#include <isc/util.h>
|
#include <isc/util.h>
|
||||||
|
|
||||||
|
#include <dns/acache.h>
|
||||||
#include <dns/db.h>
|
#include <dns/db.h>
|
||||||
#include <dns/dbiterator.h>
|
#include <dns/dbiterator.h>
|
||||||
#include <dns/events.h>
|
#include <dns/events.h>
|
||||||
@ -46,6 +47,8 @@
|
|||||||
#include <dns/rdatasetiter.h>
|
#include <dns/rdatasetiter.h>
|
||||||
#include <dns/rdataslab.h>
|
#include <dns/rdataslab.h>
|
||||||
#include <dns/result.h>
|
#include <dns/result.h>
|
||||||
|
#include <dns/view.h>
|
||||||
|
#include <dns/zone.h>
|
||||||
#include <dns/zonekey.h>
|
#include <dns/zonekey.h>
|
||||||
|
|
||||||
#ifdef DNS_RBTDB_VERSION64
|
#ifdef DNS_RBTDB_VERSION64
|
||||||
@ -103,6 +106,8 @@ struct noqname {
|
|||||||
void * nsecsig;
|
void * nsecsig;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct acachectl acachectl_t;
|
||||||
|
|
||||||
typedef struct rdatasetheader {
|
typedef struct rdatasetheader {
|
||||||
/*
|
/*
|
||||||
* Locked by the owning node's lock.
|
* Locked by the owning node's lock.
|
||||||
@ -140,6 +145,9 @@ typedef struct rdatasetheader {
|
|||||||
* should not be so crucial, no lock is set for the counter for
|
* should not be so crucial, no lock is set for the counter for
|
||||||
* performance reasons.
|
* performance reasons.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
acachectl_t *additional_auth;
|
||||||
|
acachectl_t *additional_glue;
|
||||||
} rdatasetheader_t;
|
} rdatasetheader_t;
|
||||||
|
|
||||||
#define RDATASET_ATTR_NONEXISTENT 0x0001
|
#define RDATASET_ATTR_NONEXISTENT 0x0001
|
||||||
@ -148,6 +156,19 @@ typedef struct rdatasetheader {
|
|||||||
#define RDATASET_ATTR_RETAIN 0x0008
|
#define RDATASET_ATTR_RETAIN 0x0008
|
||||||
#define RDATASET_ATTR_NXDOMAIN 0x0010
|
#define RDATASET_ATTR_NXDOMAIN 0x0010
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XXX
|
* XXX
|
||||||
* When the cache will pre-expire data (due to memory low or other
|
* When the cache will pre-expire data (due to memory low or other
|
||||||
@ -219,6 +240,8 @@ typedef struct {
|
|||||||
rbtdb_versionlist_t open_versions;
|
rbtdb_versionlist_t open_versions;
|
||||||
isc_boolean_t overmem;
|
isc_boolean_t overmem;
|
||||||
isc_task_t * task;
|
isc_task_t * task;
|
||||||
|
dns_dbnode_t *soanode;
|
||||||
|
dns_dbnode_t *nsnode;
|
||||||
/* Locked by tree_lock. */
|
/* Locked by tree_lock. */
|
||||||
dns_rbt_t * tree;
|
dns_rbt_t * tree;
|
||||||
isc_boolean_t secure;
|
isc_boolean_t secure;
|
||||||
@ -264,6 +287,30 @@ static isc_result_t rdataset_getnoqname(dns_rdataset_t *rdataset,
|
|||||||
dns_name_t *name,
|
dns_name_t *name,
|
||||||
dns_rdataset_t *nsec,
|
dns_rdataset_t *nsec,
|
||||||
dns_rdataset_t *nsecsig);
|
dns_rdataset_t *nsecsig);
|
||||||
|
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 dns_rdatasetmethods_t rdataset_methods = {
|
static dns_rdatasetmethods_t rdataset_methods = {
|
||||||
rdataset_disassociate,
|
rdataset_disassociate,
|
||||||
@ -273,7 +320,10 @@ static dns_rdatasetmethods_t rdataset_methods = {
|
|||||||
rdataset_clone,
|
rdataset_clone,
|
||||||
rdataset_count,
|
rdataset_count,
|
||||||
NULL,
|
NULL,
|
||||||
rdataset_getnoqname
|
rdataset_getnoqname,
|
||||||
|
rdataset_getadditional,
|
||||||
|
rdataset_setadditional,
|
||||||
|
rdataset_putadditional
|
||||||
};
|
};
|
||||||
|
|
||||||
static void rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp);
|
static void rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp);
|
||||||
@ -468,6 +518,11 @@ maybe_free_rbtdb(dns_rbtdb_t *rbtdb) {
|
|||||||
|
|
||||||
/* XXX check for open versions here */
|
/* XXX check for open versions here */
|
||||||
|
|
||||||
|
if (rbtdb->soanode != NULL)
|
||||||
|
dns_db_detachnode((dns_db_t *)rbtdb, &rbtdb->soanode);
|
||||||
|
if (rbtdb->nsnode != NULL)
|
||||||
|
dns_db_detachnode((dns_db_t *)rbtdb, &rbtdb->nsnode);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Even though there are no external direct references, there still
|
* Even though there are no external direct references, there still
|
||||||
* may be nodes in use.
|
* may be nodes in use.
|
||||||
@ -631,6 +686,35 @@ add_changed(dns_rbtdb_t *rbtdb, rbtdb_version_t *version,
|
|||||||
return (changed);
|
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;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
static inline void
|
||||||
free_noqname(isc_mem_t *mctx, struct noqname **noqname) {
|
free_noqname(isc_mem_t *mctx, struct noqname **noqname) {
|
||||||
|
|
||||||
@ -652,7 +736,10 @@ free_rdataset(isc_mem_t *mctx, rdatasetheader_t *rdataset) {
|
|||||||
|
|
||||||
if (rdataset->noqname != NULL)
|
if (rdataset->noqname != NULL)
|
||||||
free_noqname(mctx, &rdataset->noqname);
|
free_noqname(mctx, &rdataset->noqname);
|
||||||
|
|
||||||
|
free_acachearray(mctx, rdataset, rdataset->additional_auth);
|
||||||
|
free_acachearray(mctx, rdataset, rdataset->additional_glue);
|
||||||
|
|
||||||
if ((rdataset->attributes & RDATASET_ATTR_NONEXISTENT) != 0)
|
if ((rdataset->attributes & RDATASET_ATTR_NONEXISTENT) != 0)
|
||||||
size = sizeof(*rdataset);
|
size = sizeof(*rdataset);
|
||||||
else
|
else
|
||||||
@ -4265,6 +4352,8 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
|||||||
newheader->noqname = NULL;
|
newheader->noqname = NULL;
|
||||||
newheader->count = 0;
|
newheader->count = 0;
|
||||||
newheader->trust = rdataset->trust;
|
newheader->trust = rdataset->trust;
|
||||||
|
newheader->additional_auth = NULL;
|
||||||
|
newheader->additional_glue = NULL;
|
||||||
if (rbtversion != NULL) {
|
if (rbtversion != NULL) {
|
||||||
newheader->serial = rbtversion->serial;
|
newheader->serial = rbtversion->serial;
|
||||||
now = 0;
|
now = 0;
|
||||||
@ -4338,6 +4427,8 @@ subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
|||||||
newheader->trust = 0;
|
newheader->trust = 0;
|
||||||
newheader->noqname = NULL;
|
newheader->noqname = NULL;
|
||||||
newheader->count = 0;
|
newheader->count = 0;
|
||||||
|
newheader->additional_auth = NULL;
|
||||||
|
newheader->additional_glue = NULL;
|
||||||
|
|
||||||
LOCK(&rbtdb->node_locks[rbtnode->locknum].lock);
|
LOCK(&rbtdb->node_locks[rbtnode->locknum].lock);
|
||||||
|
|
||||||
@ -4390,6 +4481,13 @@ subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
|||||||
* header, not newheader.
|
* header, not newheader.
|
||||||
*/
|
*/
|
||||||
newheader->serial = rbtversion->serial;
|
newheader->serial = rbtversion->serial;
|
||||||
|
/*
|
||||||
|
* XXXJT: dns_rdataslab_subtract() copied the pointers
|
||||||
|
* to additional info. We need to clear these fields
|
||||||
|
* to avoid having duplicated references.
|
||||||
|
*/
|
||||||
|
newheader->additional_auth = NULL;
|
||||||
|
newheader->additional_glue = NULL;
|
||||||
} else if (result == DNS_R_NXRRSET) {
|
} else if (result == DNS_R_NXRRSET) {
|
||||||
/*
|
/*
|
||||||
* This subtraction would remove all of the rdata;
|
* This subtraction would remove all of the rdata;
|
||||||
@ -4409,6 +4507,8 @@ subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
|||||||
newheader->serial = rbtversion->serial;
|
newheader->serial = rbtversion->serial;
|
||||||
newheader->noqname = NULL;
|
newheader->noqname = NULL;
|
||||||
newheader->count = 0;
|
newheader->count = 0;
|
||||||
|
newheader->additional_auth = NULL;
|
||||||
|
newheader->additional_glue = NULL;
|
||||||
} else {
|
} else {
|
||||||
free_rdataset(rbtdb->common.mctx, newheader);
|
free_rdataset(rbtdb->common.mctx, newheader);
|
||||||
goto unlock;
|
goto unlock;
|
||||||
@ -4474,6 +4574,8 @@ deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
|||||||
newheader->attributes = RDATASET_ATTR_NONEXISTENT;
|
newheader->attributes = RDATASET_ATTR_NONEXISTENT;
|
||||||
newheader->trust = 0;
|
newheader->trust = 0;
|
||||||
newheader->noqname = NULL;
|
newheader->noqname = NULL;
|
||||||
|
newheader->additional_auth = NULL;
|
||||||
|
newheader->additional_glue = NULL;
|
||||||
if (rbtversion != NULL)
|
if (rbtversion != NULL)
|
||||||
newheader->serial = rbtversion->serial;
|
newheader->serial = rbtversion->serial;
|
||||||
else
|
else
|
||||||
@ -4556,6 +4658,8 @@ loading_addrdataset(void *arg, dns_name_t *name, dns_rdataset_t *rdataset) {
|
|||||||
newheader->serial = 1;
|
newheader->serial = 1;
|
||||||
newheader->noqname = NULL;
|
newheader->noqname = NULL;
|
||||||
newheader->count = 0;
|
newheader->count = 0;
|
||||||
|
newheader->additional_auth = NULL;
|
||||||
|
newheader->additional_glue = NULL;
|
||||||
|
|
||||||
result = add(rbtdb, node, rbtdb->current_version, newheader,
|
result = add(rbtdb, node, rbtdb->current_version, newheader,
|
||||||
DNS_DBADD_MERGE, ISC_TRUE, NULL, 0);
|
DNS_DBADD_MERGE, ISC_TRUE, NULL, 0);
|
||||||
@ -4755,6 +4859,74 @@ ispersistent(dns_db_t *db) {
|
|||||||
return (ISC_FALSE);
|
return (ISC_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static isc_result_t
|
||||||
|
getsoanode(dns_db_t *db, dns_dbnode_t **nodep) {
|
||||||
|
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
|
||||||
|
isc_result_t result = ISC_R_SUCCESS;
|
||||||
|
|
||||||
|
REQUIRE(VALID_RBTDB(rbtdb));
|
||||||
|
REQUIRE(nodep != NULL && *nodep == NULL);
|
||||||
|
|
||||||
|
LOCK(&rbtdb->lock);
|
||||||
|
if (rbtdb->soanode != NULL) {
|
||||||
|
attachnode(db, rbtdb->soanode, nodep);
|
||||||
|
} else
|
||||||
|
result = ISC_R_NOTFOUND;
|
||||||
|
UNLOCK(&rbtdb->lock);
|
||||||
|
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static isc_result_t
|
||||||
|
setsoanode(dns_db_t *db, dns_dbnode_t *node) {
|
||||||
|
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
|
||||||
|
|
||||||
|
REQUIRE(VALID_RBTDB(rbtdb));
|
||||||
|
REQUIRE(node != NULL);
|
||||||
|
|
||||||
|
LOCK(&rbtdb->lock);
|
||||||
|
if (rbtdb->soanode != NULL)
|
||||||
|
detachnode(db, &rbtdb->soanode);
|
||||||
|
attachnode(db, node, &rbtdb->soanode);
|
||||||
|
UNLOCK(&rbtdb->lock);
|
||||||
|
|
||||||
|
return (ISC_R_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static isc_result_t
|
||||||
|
getnsnode(dns_db_t *db, dns_dbnode_t **nodep) {
|
||||||
|
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
|
||||||
|
isc_result_t result = ISC_R_SUCCESS;
|
||||||
|
|
||||||
|
REQUIRE(VALID_RBTDB(rbtdb));
|
||||||
|
REQUIRE(nodep != NULL && *nodep == NULL);
|
||||||
|
|
||||||
|
LOCK(&rbtdb->lock);
|
||||||
|
if (rbtdb->nsnode != NULL) {
|
||||||
|
attachnode(db, rbtdb->nsnode, nodep);
|
||||||
|
} else
|
||||||
|
result = ISC_R_NOTFOUND;
|
||||||
|
UNLOCK(&rbtdb->lock);
|
||||||
|
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static isc_result_t
|
||||||
|
setnsnode(dns_db_t *db, dns_dbnode_t *node) {
|
||||||
|
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
|
||||||
|
|
||||||
|
REQUIRE(VALID_RBTDB(rbtdb));
|
||||||
|
REQUIRE(node != NULL);
|
||||||
|
|
||||||
|
LOCK(&rbtdb->lock);
|
||||||
|
if (rbtdb->nsnode != NULL)
|
||||||
|
detachnode(db, &rbtdb->nsnode);
|
||||||
|
attachnode(db, node, &rbtdb->nsnode);
|
||||||
|
UNLOCK(&rbtdb->lock);
|
||||||
|
|
||||||
|
return (ISC_R_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
static dns_dbmethods_t zone_methods = {
|
static dns_dbmethods_t zone_methods = {
|
||||||
attach,
|
attach,
|
||||||
detach,
|
detach,
|
||||||
@ -4782,7 +4954,11 @@ static dns_dbmethods_t zone_methods = {
|
|||||||
nodecount,
|
nodecount,
|
||||||
ispersistent,
|
ispersistent,
|
||||||
overmem,
|
overmem,
|
||||||
settask
|
settask,
|
||||||
|
getsoanode,
|
||||||
|
setsoanode,
|
||||||
|
getnsnode,
|
||||||
|
setnsnode
|
||||||
};
|
};
|
||||||
|
|
||||||
static dns_dbmethods_t cache_methods = {
|
static dns_dbmethods_t cache_methods = {
|
||||||
@ -4812,7 +4988,11 @@ static dns_dbmethods_t cache_methods = {
|
|||||||
nodecount,
|
nodecount,
|
||||||
ispersistent,
|
ispersistent,
|
||||||
overmem,
|
overmem,
|
||||||
settask
|
settask,
|
||||||
|
getsoanode,
|
||||||
|
setsoanode,
|
||||||
|
getnsnode,
|
||||||
|
setnsnode
|
||||||
};
|
};
|
||||||
|
|
||||||
isc_result_t
|
isc_result_t
|
||||||
@ -5704,3 +5884,346 @@ dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name) {
|
|||||||
|
|
||||||
return (dns_name_copy(origin, name, NULL));
|
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;
|
||||||
|
unsigned int current_count = rdataset->privateuint4;
|
||||||
|
unsigned int count;
|
||||||
|
rdatasetheader_t *header;
|
||||||
|
isc_mutex_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 = rdataset_count(rdataset);
|
||||||
|
INSIST(total_count > current_count);
|
||||||
|
count = total_count - current_count - 1;
|
||||||
|
|
||||||
|
acarray = NULL;
|
||||||
|
|
||||||
|
nodelock = &rbtdb->node_locks[rbtnode->locknum].lock;
|
||||||
|
LOCK(nodelock);
|
||||||
|
|
||||||
|
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) {
|
||||||
|
UNLOCK(nodelock);
|
||||||
|
return (ISC_R_NOTFOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (acarray[count].entry == NULL) {
|
||||||
|
UNLOCK(nodelock);
|
||||||
|
return (ISC_R_NOTFOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
entry = NULL;
|
||||||
|
dns_acache_attachentry(acarray[count].entry, &entry);
|
||||||
|
|
||||||
|
UNLOCK(nodelock);
|
||||||
|
|
||||||
|
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;
|
||||||
|
isc_mutex_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;
|
||||||
|
LOCK(nodelock);
|
||||||
|
|
||||||
|
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[count].entry == entry)
|
||||||
|
acarray[count].entry = NULL;
|
||||||
|
INSIST(acarray[count].cbarg != NULL);
|
||||||
|
isc_mem_put(rbtdb->common.mctx, acarray[count].cbarg,
|
||||||
|
sizeof(acache_cbarg_t));
|
||||||
|
acarray[count].cbarg = NULL;
|
||||||
|
|
||||||
|
dns_acache_detachentry(&entry);
|
||||||
|
|
||||||
|
UNLOCK(nodelock);
|
||||||
|
|
||||||
|
dns_db_detachnode((dns_db_t *)rbtdb, (dns_dbnode_t **)&rbtnode);
|
||||||
|
dns_db_detach((dns_db_t **)&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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
unsigned int current_count = rdataset->privateuint4;
|
||||||
|
rdatasetheader_t *header;
|
||||||
|
unsigned int total_count, count;
|
||||||
|
isc_mutex_t *nodelock;
|
||||||
|
isc_mem_t *mctx = rbtdb->common.mctx;
|
||||||
|
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 = rdataset_count(rdataset);
|
||||||
|
INSIST(total_count > current_count);
|
||||||
|
count = total_count - current_count - 1; /* should be private data */
|
||||||
|
|
||||||
|
newcbarg = isc_mem_get(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;
|
||||||
|
LOCK(nodelock);
|
||||||
|
|
||||||
|
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(mctx, total_count *
|
||||||
|
sizeof(acachectl_t));
|
||||||
|
|
||||||
|
if (acarray == NULL) {
|
||||||
|
UNLOCK(nodelock);
|
||||||
|
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;
|
||||||
|
|
||||||
|
UNLOCK(nodelock);
|
||||||
|
|
||||||
|
if (oldentry != NULL) {
|
||||||
|
if (oldcbarg != NULL)
|
||||||
|
acache_cancelentry(mctx, oldentry, &oldcbarg);
|
||||||
|
dns_acache_detachentry(&oldentry);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (ISC_R_SUCCESS);
|
||||||
|
|
||||||
|
fail:
|
||||||
|
if (newentry != NULL) {
|
||||||
|
if (newcbarg != NULL)
|
||||||
|
acache_cancelentry(mctx, newentry, &newcbarg);
|
||||||
|
dns_acache_detachentry(&newentry);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
unsigned int current_count = rdataset->privateuint4;
|
||||||
|
rdatasetheader_t *header;
|
||||||
|
isc_mutex_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 = rdataset_count(rdataset);
|
||||||
|
INSIST(total_count > current_count);
|
||||||
|
count = total_count - current_count - 1;
|
||||||
|
|
||||||
|
acarray = NULL;
|
||||||
|
entry = NULL;
|
||||||
|
|
||||||
|
nodelock = &rbtdb->node_locks[rbtnode->locknum].lock;
|
||||||
|
LOCK(nodelock);
|
||||||
|
|
||||||
|
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) {
|
||||||
|
UNLOCK(nodelock);
|
||||||
|
return (ISC_R_NOTFOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
entry = acarray[count].entry;
|
||||||
|
if (entry == NULL) {
|
||||||
|
UNLOCK(nodelock);
|
||||||
|
return (ISC_R_NOTFOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
acarray[count].entry = NULL;
|
||||||
|
cbarg = acarray[count].cbarg;
|
||||||
|
acarray[count].cbarg = NULL;
|
||||||
|
|
||||||
|
UNLOCK(nodelock);
|
||||||
|
|
||||||
|
if (entry != NULL) {
|
||||||
|
if(cbarg != NULL)
|
||||||
|
acache_cancelentry(rbtdb->common.mctx, entry, &cbarg);
|
||||||
|
dns_acache_detachentry(&entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (ISC_R_SUCCESS);
|
||||||
|
}
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* PERFORMANCE OF THIS SOFTWARE.
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $Id: rdatalist.c,v 1.28 2004/03/05 05:09:23 marka Exp $ */
|
/* $Id: rdatalist.c,v 1.29 2004/12/21 10:45:17 jinmei Exp $ */
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
@ -38,7 +38,10 @@ static dns_rdatasetmethods_t methods = {
|
|||||||
isc__rdatalist_clone,
|
isc__rdatalist_clone,
|
||||||
isc__rdatalist_count,
|
isc__rdatalist_count,
|
||||||
isc__rdatalist_addnoqname,
|
isc__rdatalist_addnoqname,
|
||||||
isc__rdatalist_getnoqname
|
isc__rdatalist_getnoqname,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* PERFORMANCE OF THIS SOFTWARE.
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $Id: rdataset.c,v 1.72 2004/03/05 05:09:23 marka Exp $ */
|
/* $Id: rdataset.c,v 1.73 2004/12/21 10:45:17 jinmei Exp $ */
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
@ -174,6 +174,9 @@ static dns_rdatasetmethods_t question_methods = {
|
|||||||
question_clone,
|
question_clone,
|
||||||
question_count,
|
question_count,
|
||||||
NULL,
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -624,3 +627,81 @@ dns_rdataset_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name,
|
|||||||
return (ISC_R_NOTIMPLEMENTED);
|
return (ISC_R_NOTIMPLEMENTED);
|
||||||
return((rdataset->methods->getnoqname)(rdataset, name, nsec, nsecsig));
|
return((rdataset->methods->getnoqname)(rdataset, name, nsec, nsecsig));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* PERFORMANCE OF THIS SOFTWARE.
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $Id: rdataslab.c,v 1.35 2004/03/05 05:09:23 marka Exp $ */
|
/* $Id: rdataslab.c,v 1.36 2004/12/21 10:45:17 jinmei Exp $ */
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
@ -241,6 +241,9 @@ static dns_rdatasetmethods_t rdataset_methods = {
|
|||||||
rdataset_clone,
|
rdataset_clone,
|
||||||
rdataset_count,
|
rdataset_count,
|
||||||
NULL,
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* PERFORMANCE OF THIS SOFTWARE.
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $Id: sdb.c,v 1.46 2004/07/22 03:58:07 marka Exp $ */
|
/* $Id: sdb.c,v 1.47 2004/12/21 10:45:18 jinmei Exp $ */
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
@ -1234,7 +1234,11 @@ static dns_dbmethods_t sdb_methods = {
|
|||||||
nodecount,
|
nodecount,
|
||||||
ispersistent,
|
ispersistent,
|
||||||
overmem,
|
overmem,
|
||||||
settask
|
settask,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
static isc_result_t
|
static isc_result_t
|
||||||
@ -1361,7 +1365,10 @@ static dns_rdatasetmethods_t methods = {
|
|||||||
rdataset_clone,
|
rdataset_clone,
|
||||||
isc__rdatalist_count,
|
isc__rdatalist_count,
|
||||||
isc__rdatalist_addnoqname,
|
isc__rdatalist_addnoqname,
|
||||||
isc__rdatalist_getnoqname
|
isc__rdatalist_getnoqname,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* PERFORMANCE OF THIS SOFTWARE.
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $Id: view.c,v 1.126 2004/03/10 02:19:56 marka Exp $ */
|
/* $Id: view.c,v 1.127 2004/12/21 10:45:18 jinmei Exp $ */
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
@ -24,6 +24,7 @@
|
|||||||
#include <isc/string.h> /* Required for HP/UX (and others?) */
|
#include <isc/string.h> /* Required for HP/UX (and others?) */
|
||||||
#include <isc/util.h>
|
#include <isc/util.h>
|
||||||
|
|
||||||
|
#include <dns/acache.h>
|
||||||
#include <dns/acl.h>
|
#include <dns/acl.h>
|
||||||
#include <dns/adb.h>
|
#include <dns/adb.h>
|
||||||
#include <dns/cache.h>
|
#include <dns/cache.h>
|
||||||
@ -120,6 +121,7 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
|
|||||||
goto cleanup_trustedkeys;
|
goto cleanup_trustedkeys;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
view->acache = NULL;
|
||||||
view->cache = NULL;
|
view->cache = NULL;
|
||||||
view->cachedb = NULL;
|
view->cachedb = NULL;
|
||||||
view->hints = NULL;
|
view->hints = NULL;
|
||||||
@ -253,6 +255,8 @@ destroy(dns_view_t *view) {
|
|||||||
dns_adb_detach(&view->adb);
|
dns_adb_detach(&view->adb);
|
||||||
if (view->resolver != NULL)
|
if (view->resolver != NULL)
|
||||||
dns_resolver_detach(&view->resolver);
|
dns_resolver_detach(&view->resolver);
|
||||||
|
if (view->acache != NULL)
|
||||||
|
dns_acache_detach(&view->acache);
|
||||||
if (view->requestmgr != NULL)
|
if (view->requestmgr != NULL)
|
||||||
dns_requestmgr_detach(&view->requestmgr);
|
dns_requestmgr_detach(&view->requestmgr);
|
||||||
if (view->task != NULL)
|
if (view->task != NULL)
|
||||||
@ -365,6 +369,8 @@ view_flushanddetach(dns_view_t **viewp, isc_boolean_t flush) {
|
|||||||
dns_adb_shutdown(view->adb);
|
dns_adb_shutdown(view->adb);
|
||||||
if (!REQSHUTDOWN(view))
|
if (!REQSHUTDOWN(view))
|
||||||
dns_requestmgr_shutdown(view->requestmgr);
|
dns_requestmgr_shutdown(view->requestmgr);
|
||||||
|
if (view->acache != NULL)
|
||||||
|
dns_acache_shutdown(view->acache);
|
||||||
if (view->flush)
|
if (view->flush)
|
||||||
dns_zt_flushanddetach(&view->zonetable);
|
dns_zt_flushanddetach(&view->zonetable);
|
||||||
else
|
else
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* PERFORMANCE OF THIS SOFTWARE.
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $Id: zone.c,v 1.425 2004/11/23 05:23:46 marka Exp $ */
|
/* $Id: zone.c,v 1.426 2004/12/21 10:45:18 jinmei Exp $ */
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
@ -31,6 +31,7 @@
|
|||||||
#include <isc/timer.h>
|
#include <isc/timer.h>
|
||||||
#include <isc/util.h>
|
#include <isc/util.h>
|
||||||
|
|
||||||
|
#include <dns/acache.h>
|
||||||
#include <dns/acl.h>
|
#include <dns/acl.h>
|
||||||
#include <dns/adb.h>
|
#include <dns/adb.h>
|
||||||
#include <dns/callbacks.h>
|
#include <dns/callbacks.h>
|
||||||
@ -206,6 +207,7 @@ struct dns_zone {
|
|||||||
dns_ssutable_t *ssutable;
|
dns_ssutable_t *ssutable;
|
||||||
isc_uint32_t sigvalidityinterval;
|
isc_uint32_t sigvalidityinterval;
|
||||||
dns_view_t *view;
|
dns_view_t *view;
|
||||||
|
dns_acache_t *acache;
|
||||||
/*
|
/*
|
||||||
* Zones in certain states such as "waiting for zone transfer"
|
* Zones in certain states such as "waiting for zone transfer"
|
||||||
* or "zone transfer in progress" are kept on per-state linked lists
|
* or "zone transfer in progress" are kept on per-state linked lists
|
||||||
@ -384,6 +386,8 @@ static void zone_iattach(dns_zone_t *source, dns_zone_t **target);
|
|||||||
static void zone_idetach(dns_zone_t **zonep);
|
static void zone_idetach(dns_zone_t **zonep);
|
||||||
static isc_result_t zone_replacedb(dns_zone_t *zone, dns_db_t *db,
|
static isc_result_t zone_replacedb(dns_zone_t *zone, dns_db_t *db,
|
||||||
isc_boolean_t dump);
|
isc_boolean_t dump);
|
||||||
|
static inline void zone_attachdb(dns_zone_t *zone, dns_db_t *db);
|
||||||
|
static inline void zone_detachdb(dns_zone_t *zone);
|
||||||
static isc_result_t default_journal(dns_zone_t *zone);
|
static isc_result_t default_journal(dns_zone_t *zone);
|
||||||
static void zone_xfrdone(dns_zone_t *zone, isc_result_t result);
|
static void zone_xfrdone(dns_zone_t *zone, isc_result_t result);
|
||||||
static isc_result_t zone_postload(dns_zone_t *zone, dns_db_t *db,
|
static isc_result_t zone_postload(dns_zone_t *zone, dns_db_t *db,
|
||||||
@ -572,6 +576,7 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
|
|||||||
zone->ssutable = NULL;
|
zone->ssutable = NULL;
|
||||||
zone->sigvalidityinterval = 30 * 24 * 3600;
|
zone->sigvalidityinterval = 30 * 24 * 3600;
|
||||||
zone->view = NULL;
|
zone->view = NULL;
|
||||||
|
zone->acache = NULL;
|
||||||
ISC_LINK_INIT(zone, statelink);
|
ISC_LINK_INIT(zone, statelink);
|
||||||
zone->statelist = NULL;
|
zone->statelist = NULL;
|
||||||
zone->counters = NULL;
|
zone->counters = NULL;
|
||||||
@ -636,7 +641,9 @@ zone_free(dns_zone_t *zone) {
|
|||||||
if (zone->counters != NULL)
|
if (zone->counters != NULL)
|
||||||
dns_stats_freecounters(zone->mctx, &zone->counters);
|
dns_stats_freecounters(zone->mctx, &zone->counters);
|
||||||
if (zone->db != NULL)
|
if (zone->db != NULL)
|
||||||
dns_db_detach(&zone->db);
|
zone_detachdb(zone);
|
||||||
|
if (zone->acache != NULL)
|
||||||
|
dns_acache_detach(&zone->acache);
|
||||||
zone_freedbargs(zone);
|
zone_freedbargs(zone);
|
||||||
RUNTIME_CHECK(dns_zone_setmasterswithkeys(zone, NULL, NULL, 0)
|
RUNTIME_CHECK(dns_zone_setmasterswithkeys(zone, NULL, NULL, 0)
|
||||||
== ISC_R_SUCCESS);
|
== ISC_R_SUCCESS);
|
||||||
@ -821,6 +828,33 @@ dns_zone_setorigin(dns_zone_t *zone, dns_name_t *origin) {
|
|||||||
return (result);
|
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);
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UNLOCK_ZONE(zone);
|
||||||
|
}
|
||||||
|
|
||||||
static isc_result_t
|
static isc_result_t
|
||||||
dns_zone_setstring(dns_zone_t *zone, char **field, const char *value) {
|
dns_zone_setstring(dns_zone_t *zone, char **field, const char *value) {
|
||||||
@ -1423,7 +1457,7 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
|
|||||||
if (result != ISC_R_SUCCESS)
|
if (result != ISC_R_SUCCESS)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
} else {
|
} else {
|
||||||
dns_db_attach(db, &zone->db);
|
zone_attachdb(zone, db);
|
||||||
DNS_ZONE_SETFLAG(zone,
|
DNS_ZONE_SETFLAG(zone,
|
||||||
DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
|
DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
|
||||||
}
|
}
|
||||||
@ -2641,7 +2675,7 @@ zone_unload(dns_zone_t *zone) {
|
|||||||
|
|
||||||
REQUIRE(LOCKED_ZONE(zone));
|
REQUIRE(LOCKED_ZONE(zone));
|
||||||
|
|
||||||
dns_db_detach(&zone->db);
|
zone_detachdb(zone);
|
||||||
DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADED);
|
DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADED);
|
||||||
DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
|
DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
|
||||||
}
|
}
|
||||||
@ -3400,7 +3434,7 @@ stub_callback(isc_task_t *task, isc_event_t *event) {
|
|||||||
dns_db_closeversion(stub->db, &stub->version, ISC_TRUE);
|
dns_db_closeversion(stub->db, &stub->version, ISC_TRUE);
|
||||||
LOCK_ZONE(zone);
|
LOCK_ZONE(zone);
|
||||||
if (zone->db == NULL)
|
if (zone->db == NULL)
|
||||||
dns_db_attach(stub->db, &zone->db);
|
zone_attachdb(zone, stub->db);
|
||||||
UNLOCK_ZONE(zone);
|
UNLOCK_ZONE(zone);
|
||||||
dns_db_detach(&stub->db);
|
dns_db_detach(&stub->db);
|
||||||
|
|
||||||
@ -5427,8 +5461,8 @@ zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
|
|||||||
"replacing zone database");
|
"replacing zone database");
|
||||||
|
|
||||||
if (zone->db != NULL)
|
if (zone->db != NULL)
|
||||||
dns_db_detach(&zone->db);
|
zone_detachdb(zone);
|
||||||
dns_db_attach(db, &zone->db);
|
zone_attachdb(zone, db);
|
||||||
dns_db_settask(zone->db, zone->task);
|
dns_db_settask(zone->db, zone->task);
|
||||||
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
|
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
|
||||||
return (ISC_R_SUCCESS);
|
return (ISC_R_SUCCESS);
|
||||||
@ -5438,6 +5472,31 @@ zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
|
|||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
|
zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
|
||||||
isc_time_t now;
|
isc_time_t now;
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* PERFORMANCE OF THIS SOFTWARE.
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $Id: namedconf.c,v 1.41 2004/11/11 01:08:24 marka Exp $ */
|
/* $Id: namedconf.c,v 1.42 2004/12/21 10:45:20 jinmei Exp $ */
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
@ -733,6 +733,9 @@ view_clauses[] = {
|
|||||||
{ "dnssec-must-be-secure", &cfg_type_mustbesecure,
|
{ "dnssec-must-be-secure", &cfg_type_mustbesecure,
|
||||||
CFG_CLAUSEFLAG_MULTI },
|
CFG_CLAUSEFLAG_MULTI },
|
||||||
{ "ixfr-from-differences", &cfg_type_ixfrdifftype, 0 },
|
{ "ixfr-from-differences", &cfg_type_ixfrdifftype, 0 },
|
||||||
|
{ "use-additional-cache", &cfg_type_boolean, 0 },
|
||||||
|
{ "acache-cleaning-interval", &cfg_type_uint32, 0 },
|
||||||
|
{ "max-acache-size", &cfg_type_sizenodefault, 0 },
|
||||||
{ NULL, NULL, 0 }
|
{ NULL, NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user