mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-29 13:38:26 +00:00
complete the qpzone database API implementation
finish importing the database API methods from RBTDB to qpzone: issecure, nodecount, getnsec3parameters, findnsec3node, setsigningtime, getsigningtime, getsize, setgluecachestats, locknode, unlocknode, and addglue.
This commit is contained in:
parent
f46455cfcb
commit
6e167724e7
644
lib/dns/qpzone.c
644
lib/dns/qpzone.c
@ -2327,15 +2327,250 @@ endload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) {
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static bool
|
||||
issecure(dns_db_t *db) {
|
||||
qpzonedb_t *qpdb = NULL;
|
||||
bool secure;
|
||||
|
||||
qpdb = (qpzonedb_t *)db;
|
||||
|
||||
REQUIRE(VALID_QPZONE(qpdb));
|
||||
|
||||
RWLOCK(&qpdb->lock, isc_rwlocktype_read);
|
||||
secure = qpdb->current_version->secure;
|
||||
RWUNLOCK(&qpdb->lock, isc_rwlocktype_read);
|
||||
|
||||
return (secure);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
findnodeintree(qpzonedb_t *qpdb, dns_qp_t *qp, const dns_name_t *name,
|
||||
bool create, bool nsec3, dns_dbnode_t **nodep DNS__DB_FLARG) {
|
||||
getnsec3parameters(dns_db_t *db, dns_dbversion_t *dbversion, dns_hash_t *hash,
|
||||
uint8_t *flags, uint16_t *iterations, unsigned char *salt,
|
||||
size_t *salt_length) {
|
||||
qpzonedb_t *qpdb = NULL;
|
||||
isc_result_t result = ISC_R_NOTFOUND;
|
||||
qpdb_version_t *version = dbversion;
|
||||
|
||||
qpdb = (qpzonedb_t *)db;
|
||||
|
||||
REQUIRE(VALID_QPZONE(qpdb));
|
||||
INSIST(version == NULL || version->qpdb == qpdb);
|
||||
|
||||
RWLOCK(&qpdb->lock, isc_rwlocktype_read);
|
||||
if (version == NULL) {
|
||||
version = qpdb->current_version;
|
||||
}
|
||||
|
||||
if (version->havensec3) {
|
||||
if (hash != NULL) {
|
||||
*hash = version->hash;
|
||||
}
|
||||
if (salt != NULL && salt_length != NULL) {
|
||||
REQUIRE(*salt_length >= version->salt_length);
|
||||
memmove(salt, version->salt, version->salt_length);
|
||||
}
|
||||
if (salt_length != NULL) {
|
||||
*salt_length = version->salt_length;
|
||||
}
|
||||
if (iterations != NULL) {
|
||||
*iterations = version->iterations;
|
||||
}
|
||||
if (flags != NULL) {
|
||||
*flags = version->flags;
|
||||
}
|
||||
result = ISC_R_SUCCESS;
|
||||
}
|
||||
RWUNLOCK(&qpdb->lock, isc_rwlocktype_read);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
getsize(dns_db_t *db, dns_dbversion_t *dbversion, uint64_t *records,
|
||||
uint64_t *xfrsize) {
|
||||
qpzonedb_t *qpdb = NULL;
|
||||
qpdb_version_t *version = dbversion;
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
|
||||
qpdb = (qpzonedb_t *)db;
|
||||
|
||||
REQUIRE(VALID_QPZONE(qpdb));
|
||||
INSIST(version == NULL || version->qpdb == qpdb);
|
||||
|
||||
RWLOCK(&qpdb->lock, isc_rwlocktype_read);
|
||||
if (version == NULL) {
|
||||
version = qpdb->current_version;
|
||||
}
|
||||
|
||||
RWLOCK(&version->rwlock, isc_rwlocktype_read);
|
||||
SET_IF_NOT_NULL(records, version->records);
|
||||
|
||||
SET_IF_NOT_NULL(xfrsize, version->xfrsize);
|
||||
RWUNLOCK(&version->rwlock, isc_rwlocktype_read);
|
||||
RWUNLOCK(&qpdb->lock, isc_rwlocktype_read);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
setsigningtime(dns_db_t *db, dns_rdataset_t *rdataset, isc_stdtime_t resign) {
|
||||
qpzonedb_t *qpdb = (qpzonedb_t *)db;
|
||||
dns_slabheader_t *header = NULL, oldheader;
|
||||
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
|
||||
|
||||
REQUIRE(VALID_QPZONE(qpdb));
|
||||
REQUIRE(rdataset != NULL);
|
||||
REQUIRE(rdataset->methods == &dns_rdataslab_rdatasetmethods);
|
||||
|
||||
header = dns_slabheader_fromrdataset(rdataset);
|
||||
|
||||
NODE_WRLOCK(&qpdb->node_locks[HEADERNODE(header)->locknum].lock,
|
||||
&nlocktype);
|
||||
|
||||
oldheader = *header;
|
||||
|
||||
/*
|
||||
* Only break the heap invariant (by adjusting resign and resign_lsb)
|
||||
* if we are going to be restoring it by calling isc_heap_increased
|
||||
* or isc_heap_decreased.
|
||||
*/
|
||||
if (resign != 0) {
|
||||
header->resign = (isc_stdtime_t)(dns_time64_from32(resign) >>
|
||||
1);
|
||||
header->resign_lsb = resign & 0x1;
|
||||
}
|
||||
if (header->heap_index != 0) {
|
||||
INSIST(RESIGN(header));
|
||||
if (resign == 0) {
|
||||
isc_heap_delete(
|
||||
qpdb->heaps[HEADERNODE(header)->locknum],
|
||||
header->heap_index);
|
||||
header->heap_index = 0;
|
||||
header->heap = NULL;
|
||||
} else if (resign_sooner(header, &oldheader)) {
|
||||
isc_heap_increased(
|
||||
qpdb->heaps[HEADERNODE(header)->locknum],
|
||||
header->heap_index);
|
||||
} else if (resign_sooner(&oldheader, header)) {
|
||||
isc_heap_decreased(
|
||||
qpdb->heaps[HEADERNODE(header)->locknum],
|
||||
header->heap_index);
|
||||
}
|
||||
} else if (resign != 0) {
|
||||
DNS_SLABHEADER_SETATTR(header, DNS_SLABHEADERATTR_RESIGN);
|
||||
resigninsert(qpdb, HEADERNODE(header)->locknum, header);
|
||||
}
|
||||
NODE_UNLOCK(&qpdb->node_locks[HEADERNODE(header)->locknum].lock,
|
||||
&nlocktype);
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
getsigningtime(dns_db_t *db, dns_rdataset_t *rdataset,
|
||||
dns_name_t *foundname DNS__DB_FLARG) {
|
||||
qpzonedb_t *qpdb = (qpzonedb_t *)db;
|
||||
dns_slabheader_t *header = NULL, *this = NULL;
|
||||
isc_result_t result = ISC_R_NOTFOUND;
|
||||
unsigned int locknum = 0;
|
||||
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
|
||||
|
||||
REQUIRE(VALID_QPZONE(qpdb));
|
||||
|
||||
for (int i = 0; i < qpdb->node_lock_count; i++) {
|
||||
NODE_RDLOCK(&qpdb->node_locks[i].lock, &nlocktype);
|
||||
|
||||
/*
|
||||
* Find for the earliest signing time among all of the
|
||||
* heaps, each of which is covered by a different bucket
|
||||
* lock.
|
||||
*/
|
||||
this = isc_heap_element(qpdb->heaps[i], 1);
|
||||
if (this == NULL) {
|
||||
/* Nothing found; unlock and try the next heap. */
|
||||
NODE_UNLOCK(&qpdb->node_locks[i].lock, &nlocktype);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (header == NULL) {
|
||||
/*
|
||||
* Found a signing time: retain the bucket lock and
|
||||
* preserve the lock number so we can unlock it
|
||||
* later.
|
||||
*/
|
||||
header = this;
|
||||
locknum = i;
|
||||
nlocktype = isc_rwlocktype_none;
|
||||
} else if (resign_sooner(this, header)) {
|
||||
/*
|
||||
* Found an earlier signing time; release the
|
||||
* previous bucket lock and retain this one instead.
|
||||
*/
|
||||
NODE_UNLOCK(&qpdb->node_locks[locknum].lock,
|
||||
&nlocktype);
|
||||
header = this;
|
||||
locknum = i;
|
||||
} else {
|
||||
/*
|
||||
* Earliest signing time in this heap isn't
|
||||
* an improvement; unlock and try the next heap.
|
||||
*/
|
||||
NODE_UNLOCK(&qpdb->node_locks[i].lock, &nlocktype);
|
||||
}
|
||||
}
|
||||
|
||||
if (header != NULL) {
|
||||
nlocktype = isc_rwlocktype_read;
|
||||
/*
|
||||
* Found something; pass back the answer and unlock
|
||||
* the bucket.
|
||||
*/
|
||||
bindrdataset(qpdb, HEADERNODE(header), header, 0,
|
||||
rdataset DNS__DB_FLARG_PASS);
|
||||
|
||||
if (foundname != NULL) {
|
||||
dns_name_copy(HEADERNODE(header)->name, foundname);
|
||||
}
|
||||
|
||||
NODE_UNLOCK(&qpdb->node_locks[locknum].lock, &nlocktype);
|
||||
|
||||
result = ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
setgluecachestats(dns_db_t *db, isc_stats_t *stats) {
|
||||
qpzonedb_t *qpdb = (qpzonedb_t *)db;
|
||||
|
||||
REQUIRE(VALID_QPZONE(qpdb));
|
||||
REQUIRE(!IS_STUB(qpdb));
|
||||
REQUIRE(stats != NULL);
|
||||
|
||||
isc_stats_attach(stats, &qpdb->gluecachestats);
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
findnodeintree(qpzonedb_t *qpdb, const dns_name_t *name, bool create,
|
||||
bool nsec3, dns_dbnode_t **nodep DNS__DB_FLARG) {
|
||||
isc_result_t result;
|
||||
qpdata_t *node = NULL;
|
||||
dns_qpmulti_t *dbtree = nsec3 ? qpdb->nsec3 : qpdb->tree;
|
||||
dns_qpread_t qpr = { 0 };
|
||||
dns_qp_t *qp = NULL;
|
||||
|
||||
if (create) {
|
||||
dns_qpmulti_write(dbtree, &qp);
|
||||
} else {
|
||||
dns_qpmulti_query(dbtree, &qpr);
|
||||
qp = (dns_qp_t *)&qpr;
|
||||
}
|
||||
|
||||
result = dns_qp_getname(qp, name, (void **)&node, NULL);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
if (!create) {
|
||||
dns_qpread_destroy(dbtree, &qpr);
|
||||
return (result);
|
||||
}
|
||||
|
||||
@ -2352,49 +2587,45 @@ findnodeintree(qpzonedb_t *qpdb, dns_qp_t *qp, const dns_name_t *name,
|
||||
wildcardmagic(qpdb, qp, name, true);
|
||||
}
|
||||
}
|
||||
} else if (result == ISC_R_EXISTS) {
|
||||
result = ISC_R_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
if (nsec3) {
|
||||
INSIST(node->nsec == DNS_DB_NSEC_NSEC3);
|
||||
INSIST(node->nsec == DNS_DB_NSEC_NSEC3 || !nsec3);
|
||||
}
|
||||
|
||||
newref(qpdb, node DNS__DB_FLARG_PASS);
|
||||
|
||||
if (create) {
|
||||
dns_qp_compact(qp, DNS_QPGC_MAYBE);
|
||||
dns_qpmulti_commit(dbtree, &qp);
|
||||
} else {
|
||||
dns_qpread_destroy(dbtree, &qpr);
|
||||
}
|
||||
|
||||
*nodep = (dns_dbnode_t *)node;
|
||||
return (result);
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
findnode(dns_db_t *db, const dns_name_t *name, bool create,
|
||||
dns_dbnode_t **nodep DNS__DB_FLARG) {
|
||||
qpzonedb_t *qpdb = (qpzonedb_t *)db;
|
||||
isc_result_t result;
|
||||
dns_qpread_t qpr = { 0 };
|
||||
dns_qp_t *qp = NULL;
|
||||
|
||||
REQUIRE(VALID_QPZONE(qpdb));
|
||||
|
||||
if (create) {
|
||||
dns_qpmulti_write(qpdb->tree, &qp);
|
||||
} else {
|
||||
dns_qpmulti_query(qpdb->tree, &qpr);
|
||||
qp = (dns_qp_t *)&qpr;
|
||||
}
|
||||
return (findnodeintree(qpdb, name, create, false,
|
||||
nodep DNS__DB_FLARG_PASS));
|
||||
}
|
||||
|
||||
result = findnodeintree(qpdb, qp, name, create, false,
|
||||
nodep DNS__DB_FLARG_PASS);
|
||||
static isc_result_t
|
||||
findnsec3node(dns_db_t *db, const dns_name_t *name, bool create,
|
||||
dns_dbnode_t **nodep DNS__DB_FLARG) {
|
||||
qpzonedb_t *qpdb = (qpzonedb_t *)db;
|
||||
|
||||
if (create) {
|
||||
dns_qp_compact(qp, DNS_QPGC_MAYBE);
|
||||
dns_qpmulti_commit(qpdb->tree, &qp);
|
||||
} else {
|
||||
dns_qpread_destroy(qpdb->tree, &qpr);
|
||||
}
|
||||
REQUIRE(VALID_QPZONE(qpdb));
|
||||
|
||||
return (result);
|
||||
return (findnodeintree(qpdb, name, create, true,
|
||||
nodep DNS__DB_FLARG_PASS));
|
||||
}
|
||||
|
||||
static bool
|
||||
@ -3795,6 +4026,32 @@ detachnode(dns_db_t *db, dns_dbnode_t **targetp DNS__DB_FLARG) {
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
nodecount(dns_db_t *db, dns_dbtree_t tree) {
|
||||
qpzonedb_t *qpdb = NULL;
|
||||
dns_qp_memusage_t mu;
|
||||
|
||||
qpdb = (qpzonedb_t *)db;
|
||||
|
||||
REQUIRE(VALID_QPZONE(qpdb));
|
||||
|
||||
switch (tree) {
|
||||
case dns_dbtree_main:
|
||||
mu = dns_qpmulti_memusage(qpdb->tree);
|
||||
break;
|
||||
case dns_dbtree_nsec:
|
||||
mu = dns_qpmulti_memusage(qpdb->nsec);
|
||||
break;
|
||||
case dns_dbtree_nsec3:
|
||||
mu = dns_qpmulti_memusage(qpdb->nsec3);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
return (mu.leaves);
|
||||
}
|
||||
|
||||
static void
|
||||
setloop(dns_db_t *db, isc_loop_t *loop) {
|
||||
qpzonedb_t *qpdb = NULL;
|
||||
@ -3830,6 +4087,22 @@ getoriginnode(dns_db_t *db, dns_dbnode_t **nodep DNS__DB_FLARG) {
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static void
|
||||
locknode(dns_db_t *db, dns_dbnode_t *dbnode, isc_rwlocktype_t type) {
|
||||
qpzonedb_t *qpdb = (qpzonedb_t *)db;
|
||||
qpdata_t *node = (qpdata_t *)dbnode;
|
||||
|
||||
RWLOCK(&qpdb->node_locks[node->locknum].lock, type);
|
||||
}
|
||||
|
||||
static void
|
||||
unlocknode(dns_db_t *db, dns_dbnode_t *dbnode, isc_rwlocktype_t type) {
|
||||
qpzonedb_t *qpdb = (qpzonedb_t *)db;
|
||||
qpdata_t *node = (qpdata_t *)dbnode;
|
||||
|
||||
RWUNLOCK(&qpdb->node_locks[node->locknum].lock, type);
|
||||
}
|
||||
|
||||
static void
|
||||
deletedata(dns_db_t *db ISC_ATTR_UNUSED, dns_dbnode_t *node ISC_ATTR_UNUSED,
|
||||
void *data) {
|
||||
@ -4931,6 +5204,303 @@ deleterdataset(dns_db_t *db, dns_dbnode_t *dbnode, dns_dbversion_t *dbversion,
|
||||
return (result);
|
||||
}
|
||||
|
||||
static dns_glue_t *
|
||||
new_gluelist(isc_mem_t *mctx, dns_name_t *name) {
|
||||
dns_glue_t *glue = isc_mem_get(mctx, sizeof(*glue));
|
||||
*glue = (dns_glue_t){ 0 };
|
||||
dns_name_t *gluename = dns_fixedname_initname(&glue->fixedname);
|
||||
|
||||
isc_mem_attach(mctx, &glue->mctx);
|
||||
dns_name_copy(name, gluename);
|
||||
|
||||
return (glue);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
glue_nsdname_cb(void *arg, const dns_name_t *name, dns_rdatatype_t qtype,
|
||||
dns_rdataset_t *unused DNS__DB_FLARG) {
|
||||
dns_glue_additionaldata_ctx_t *ctx = NULL;
|
||||
isc_result_t result;
|
||||
dns_fixedname_t fixedname_a;
|
||||
dns_name_t *name_a = NULL;
|
||||
dns_rdataset_t rdataset_a, sigrdataset_a;
|
||||
qpdata_t *node_a = NULL;
|
||||
dns_fixedname_t fixedname_aaaa;
|
||||
dns_name_t *name_aaaa = NULL;
|
||||
dns_rdataset_t rdataset_aaaa, sigrdataset_aaaa;
|
||||
qpdata_t *node_aaaa = NULL;
|
||||
dns_glue_t *glue = NULL;
|
||||
|
||||
UNUSED(unused);
|
||||
|
||||
/*
|
||||
* NS records want addresses in additional records.
|
||||
*/
|
||||
INSIST(qtype == dns_rdatatype_a);
|
||||
|
||||
ctx = (dns_glue_additionaldata_ctx_t *)arg;
|
||||
|
||||
name_a = dns_fixedname_initname(&fixedname_a);
|
||||
dns_rdataset_init(&rdataset_a);
|
||||
dns_rdataset_init(&sigrdataset_a);
|
||||
|
||||
name_aaaa = dns_fixedname_initname(&fixedname_aaaa);
|
||||
dns_rdataset_init(&rdataset_aaaa);
|
||||
dns_rdataset_init(&sigrdataset_aaaa);
|
||||
|
||||
result = find(ctx->db, name, ctx->version, dns_rdatatype_a,
|
||||
DNS_DBFIND_GLUEOK, 0, (dns_dbnode_t **)&node_a, name_a,
|
||||
&rdataset_a, &sigrdataset_a DNS__DB_FLARG_PASS);
|
||||
if (result == DNS_R_GLUE) {
|
||||
glue = new_gluelist(ctx->db->mctx, name_a);
|
||||
|
||||
dns_rdataset_init(&glue->rdataset_a);
|
||||
dns_rdataset_init(&glue->sigrdataset_a);
|
||||
dns_rdataset_init(&glue->rdataset_aaaa);
|
||||
dns_rdataset_init(&glue->sigrdataset_aaaa);
|
||||
|
||||
dns_rdataset_clone(&rdataset_a, &glue->rdataset_a);
|
||||
if (dns_rdataset_isassociated(&sigrdataset_a)) {
|
||||
dns_rdataset_clone(&sigrdataset_a,
|
||||
&glue->sigrdataset_a);
|
||||
}
|
||||
}
|
||||
|
||||
result = find(ctx->db, name, ctx->version, dns_rdatatype_aaaa,
|
||||
DNS_DBFIND_GLUEOK, 0, (dns_dbnode_t **)&node_aaaa,
|
||||
name_aaaa, &rdataset_aaaa,
|
||||
&sigrdataset_aaaa DNS__DB_FLARG_PASS);
|
||||
if (result == DNS_R_GLUE) {
|
||||
if (glue == NULL) {
|
||||
glue = new_gluelist(ctx->db->mctx, name_aaaa);
|
||||
|
||||
dns_rdataset_init(&glue->rdataset_a);
|
||||
dns_rdataset_init(&glue->sigrdataset_a);
|
||||
dns_rdataset_init(&glue->rdataset_aaaa);
|
||||
dns_rdataset_init(&glue->sigrdataset_aaaa);
|
||||
} else {
|
||||
INSIST(node_a == node_aaaa);
|
||||
INSIST(dns_name_equal(name_a, name_aaaa));
|
||||
}
|
||||
|
||||
dns_rdataset_clone(&rdataset_aaaa, &glue->rdataset_aaaa);
|
||||
if (dns_rdataset_isassociated(&sigrdataset_aaaa)) {
|
||||
dns_rdataset_clone(&sigrdataset_aaaa,
|
||||
&glue->sigrdataset_aaaa);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If the currently processed NS record is in-bailiwick, mark any glue
|
||||
* RRsets found for it with DNS_RDATASETATTR_REQUIRED. Note that for
|
||||
* simplicity, glue RRsets for all in-bailiwick NS records are marked
|
||||
* this way, even though dns_message_rendersection() only checks the
|
||||
* attributes for the first rdataset associated with the first name
|
||||
* added to the ADDITIONAL section.
|
||||
*/
|
||||
if (glue != NULL && dns_name_issubdomain(name, ctx->nodename)) {
|
||||
if (dns_rdataset_isassociated(&glue->rdataset_a)) {
|
||||
glue->rdataset_a.attributes |=
|
||||
DNS_RDATASETATTR_REQUIRED;
|
||||
}
|
||||
if (dns_rdataset_isassociated(&glue->rdataset_aaaa)) {
|
||||
glue->rdataset_aaaa.attributes |=
|
||||
DNS_RDATASETATTR_REQUIRED;
|
||||
}
|
||||
}
|
||||
|
||||
if (glue != NULL) {
|
||||
glue->next = ctx->glue_list;
|
||||
ctx->glue_list = glue;
|
||||
}
|
||||
|
||||
result = ISC_R_SUCCESS;
|
||||
|
||||
if (dns_rdataset_isassociated(&rdataset_a)) {
|
||||
dns_rdataset_disassociate(&rdataset_a);
|
||||
}
|
||||
if (dns_rdataset_isassociated(&sigrdataset_a)) {
|
||||
dns_rdataset_disassociate(&sigrdataset_a);
|
||||
}
|
||||
|
||||
if (dns_rdataset_isassociated(&rdataset_aaaa)) {
|
||||
dns_rdataset_disassociate(&rdataset_aaaa);
|
||||
}
|
||||
if (dns_rdataset_isassociated(&sigrdataset_aaaa)) {
|
||||
dns_rdataset_disassociate(&sigrdataset_aaaa);
|
||||
}
|
||||
|
||||
if (node_a != NULL) {
|
||||
dns__db_detachnode(ctx->db,
|
||||
(dns_dbnode_t *)&node_a DNS__DB_FLARG_PASS);
|
||||
}
|
||||
if (node_aaaa != NULL) {
|
||||
dns__db_detachnode(
|
||||
ctx->db, (dns_dbnode_t *)&node_aaaa DNS__DB_FLARG_PASS);
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
#define IS_REQUIRED_GLUE(r) (((r)->attributes & DNS_RDATASETATTR_REQUIRED) != 0)
|
||||
|
||||
static void
|
||||
addglue_to_message(dns_glue_t *ge, dns_message_t *msg) {
|
||||
for (; ge != NULL; ge = ge->next) {
|
||||
dns_name_t *name = NULL;
|
||||
dns_rdataset_t *rdataset_a = NULL;
|
||||
dns_rdataset_t *sigrdataset_a = NULL;
|
||||
dns_rdataset_t *rdataset_aaaa = NULL;
|
||||
dns_rdataset_t *sigrdataset_aaaa = NULL;
|
||||
dns_name_t *gluename = dns_fixedname_name(&ge->fixedname);
|
||||
bool prepend_name = false;
|
||||
|
||||
dns_message_gettempname(msg, &name);
|
||||
|
||||
dns_name_copy(gluename, name);
|
||||
|
||||
if (dns_rdataset_isassociated(&ge->rdataset_a)) {
|
||||
dns_message_gettemprdataset(msg, &rdataset_a);
|
||||
}
|
||||
|
||||
if (dns_rdataset_isassociated(&ge->sigrdataset_a)) {
|
||||
dns_message_gettemprdataset(msg, &sigrdataset_a);
|
||||
}
|
||||
|
||||
if (dns_rdataset_isassociated(&ge->rdataset_aaaa)) {
|
||||
dns_message_gettemprdataset(msg, &rdataset_aaaa);
|
||||
}
|
||||
|
||||
if (dns_rdataset_isassociated(&ge->sigrdataset_aaaa)) {
|
||||
dns_message_gettemprdataset(msg, &sigrdataset_aaaa);
|
||||
}
|
||||
|
||||
if (rdataset_a != NULL) {
|
||||
dns_rdataset_clone(&ge->rdataset_a, rdataset_a);
|
||||
ISC_LIST_APPEND(name->list, rdataset_a, link);
|
||||
if (IS_REQUIRED_GLUE(rdataset_a)) {
|
||||
prepend_name = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (sigrdataset_a != NULL) {
|
||||
dns_rdataset_clone(&ge->sigrdataset_a, sigrdataset_a);
|
||||
ISC_LIST_APPEND(name->list, sigrdataset_a, link);
|
||||
}
|
||||
|
||||
if (rdataset_aaaa != NULL) {
|
||||
dns_rdataset_clone(&ge->rdataset_aaaa, rdataset_aaaa);
|
||||
ISC_LIST_APPEND(name->list, rdataset_aaaa, link);
|
||||
if (IS_REQUIRED_GLUE(rdataset_aaaa)) {
|
||||
prepend_name = true;
|
||||
}
|
||||
}
|
||||
if (sigrdataset_aaaa != NULL) {
|
||||
dns_rdataset_clone(&ge->sigrdataset_aaaa,
|
||||
sigrdataset_aaaa);
|
||||
ISC_LIST_APPEND(name->list, sigrdataset_aaaa, link);
|
||||
}
|
||||
|
||||
dns_message_addname(msg, name, DNS_SECTION_ADDITIONAL);
|
||||
|
||||
/*
|
||||
* When looking for required glue, dns_message_rendersection()
|
||||
* only processes the first rdataset associated with the first
|
||||
* name added to the ADDITIONAL section. dns_message_addname()
|
||||
* performs an append on the list of names in a given section,
|
||||
* so if any glue record was marked as required, we need to
|
||||
* move the name it is associated with to the beginning of the
|
||||
* list for the ADDITIONAL section or else required glue might
|
||||
* not be rendered.
|
||||
*/
|
||||
if (prepend_name) {
|
||||
ISC_LIST_UNLINK(msg->sections[DNS_SECTION_ADDITIONAL],
|
||||
name, link);
|
||||
ISC_LIST_PREPEND(msg->sections[DNS_SECTION_ADDITIONAL],
|
||||
name, link);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static dns_glue_t *
|
||||
newglue(qpzonedb_t *qpdb, qpdb_version_t *version, qpdata_t *node,
|
||||
dns_rdataset_t *rdataset) {
|
||||
dns_fixedname_t nodename;
|
||||
dns_glue_additionaldata_ctx_t ctx = {
|
||||
.db = (dns_db_t *)qpdb,
|
||||
.version = (dns_dbversion_t *)version,
|
||||
.nodename = dns_fixedname_initname(&nodename),
|
||||
};
|
||||
|
||||
/*
|
||||
* Get the owner name of the NS RRset - it will be necessary for
|
||||
* identifying required glue in glue_nsdname_cb() (by
|
||||
* determining which NS records in the delegation are
|
||||
* in-bailiwick).
|
||||
*/
|
||||
dns_name_copy(node->name, ctx.nodename);
|
||||
|
||||
(void)dns_rdataset_additionaldata(rdataset, dns_rootname,
|
||||
glue_nsdname_cb, &ctx);
|
||||
|
||||
return (ctx.glue_list);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
addglue(dns_db_t *db, dns_dbversion_t *dbversion, dns_rdataset_t *rdataset,
|
||||
dns_message_t *msg) {
|
||||
qpzonedb_t *qpdb = (qpzonedb_t *)db;
|
||||
qpdb_version_t *version = dbversion;
|
||||
qpdata_t *node = (qpdata_t *)rdataset->slab.node;
|
||||
dns_slabheader_t *header = dns_slabheader_fromrdataset(rdataset);
|
||||
|
||||
REQUIRE(rdataset->type == dns_rdatatype_ns);
|
||||
REQUIRE(qpdb == (qpzonedb_t *)rdataset->slab.db);
|
||||
REQUIRE(qpdb == version->qpdb);
|
||||
REQUIRE(!IS_STUB(qpdb));
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
dns_glue_t *glue = rcu_dereference(header->glue_list);
|
||||
if (glue == NULL) {
|
||||
/* No cached glue was found in the table. Get new glue. */
|
||||
glue = newglue(qpdb, version, node, rdataset);
|
||||
|
||||
/* Cache the glue or (void *)-1 if no glue was found. */
|
||||
dns_glue_t *old_glue = rcu_cmpxchg_pointer(
|
||||
&header->glue_list, NULL, (glue) ? glue : (void *)-1);
|
||||
if (old_glue != NULL) {
|
||||
/* Somebody else was faster */
|
||||
freeglue(glue);
|
||||
glue = old_glue;
|
||||
} else if (glue != NULL) {
|
||||
cds_wfs_push(&version->glue_stack, &header->wfs_node);
|
||||
}
|
||||
}
|
||||
|
||||
/* We have a cached result. Add it to the message and return. */
|
||||
|
||||
if (qpdb->gluecachestats != NULL) {
|
||||
isc_stats_increment(
|
||||
qpdb->gluecachestats,
|
||||
(glue == (void *)-1)
|
||||
? dns_gluecachestatscounter_hits_absent
|
||||
: dns_gluecachestatscounter_hits_present);
|
||||
}
|
||||
|
||||
/*
|
||||
* (void *)-1 is a special value that means no glue is present in the
|
||||
* zone.
|
||||
*/
|
||||
if (glue != (void *)-1) {
|
||||
addglue_to_message(glue, msg);
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static dns_dbmethods_t qpdb_zonemethods = {
|
||||
.destroy = qpdb_destroy,
|
||||
.beginload = beginload,
|
||||
@ -4949,19 +5519,19 @@ static dns_dbmethods_t qpdb_zonemethods = {
|
||||
.addrdataset = addrdataset,
|
||||
.subtractrdataset = subtractrdataset,
|
||||
.deleterdataset = deleterdataset,
|
||||
.issecure = NULL,
|
||||
.nodecount = NULL,
|
||||
.issecure = issecure,
|
||||
.nodecount = nodecount,
|
||||
.setloop = setloop,
|
||||
.getoriginnode = getoriginnode,
|
||||
.getnsec3parameters = NULL,
|
||||
.findnsec3node = NULL,
|
||||
.setsigningtime = NULL,
|
||||
.getsigningtime = NULL,
|
||||
.getsize = NULL,
|
||||
.setgluecachestats = NULL,
|
||||
.locknode = NULL,
|
||||
.unlocknode = NULL,
|
||||
.addglue = NULL,
|
||||
.getnsec3parameters = getnsec3parameters,
|
||||
.findnsec3node = findnsec3node,
|
||||
.setsigningtime = setsigningtime,
|
||||
.getsigningtime = getsigningtime,
|
||||
.getsize = getsize,
|
||||
.setgluecachestats = setgluecachestats,
|
||||
.locknode = locknode,
|
||||
.unlocknode = unlocknode,
|
||||
.addglue = addglue,
|
||||
.deletedata = deletedata,
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user