2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-29 13:38:26 +00:00

2349. [func] Provide incremental re-signing support for secure

dynamic zones. [RT #1091]
This commit is contained in:
Mark Andrews 2008-04-01 01:37:25 +00:00
parent 28b3569d62
commit a76b380643
29 changed files with 2781 additions and 304 deletions

View File

@ -1,3 +1,6 @@
2349. [func] Provide incremental re-signing support for secure
dynamic zones. [RT #1091]
2348. [func] Use the EVP interface to OpenSSL. Add PKCS#11 support.
Documentation is in the new README.pkcs11 file.
[RT #16844]

View File

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: query.c,v 1.303 2008/01/24 02:00:43 jinmei Exp $ */
/* $Id: query.c,v 1.304 2008/04/01 01:37:24 marka Exp $ */
/*! \file */
@ -1087,8 +1087,12 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
result = dns_db_find(db, name, version, type, client->query.dboptions,
client->now, &node, fname, rdataset,
sigrdataset);
if (result == ISC_R_SUCCESS)
if (result == ISC_R_SUCCESS) {
if (sigrdataset != NULL && !dns_db_issecure(db) &&
dns_rdataset_isassociated(sigrdataset))
dns_rdataset_disassociate(sigrdataset);
goto found;
}
if (dns_rdataset_isassociated(rdataset))
dns_rdataset_disassociate(rdataset);
@ -2025,7 +2029,7 @@ query_addsoa(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version,
eresult = DNS_R_SERVFAIL;
goto cleanup;
}
if (WANTDNSSEC(client)) {
if (WANTDNSSEC(client) && dns_db_issecure(db)) {
sigrdataset = query_newrdataset(client);
if (sigrdataset == NULL) {
eresult = DNS_R_SERVFAIL;
@ -2143,7 +2147,7 @@ query_addns(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version) {
eresult = DNS_R_SERVFAIL;
goto cleanup;
}
if (WANTDNSSEC(client)) {
if (WANTDNSSEC(client) && dns_db_issecure(db)) {
sigrdataset = query_newrdataset(client);
if (sigrdataset == NULL) {
CTRACE("query_addns: query_newrdataset failed");
@ -3534,7 +3538,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
QUERY_ERROR(DNS_R_SERVFAIL);
goto cleanup;
}
if (WANTDNSSEC(client)) {
if (WANTDNSSEC(client) && (!is_zone || dns_db_issecure(db))) {
sigrdataset = query_newrdataset(client);
if (sigrdataset == NULL) {
QUERY_ERROR(DNS_R_SERVFAIL);
@ -4173,7 +4177,16 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
result = dns_rdatasetiter_first(rdsiter);
while (result == ISC_R_SUCCESS) {
dns_rdatasetiter_current(rdsiter, rdataset);
if ((qtype == dns_rdatatype_any ||
if (is_zone && qtype == dns_rdatatype_any &&
!dns_db_issecure(db) &&
dns_rdatatype_isdnssec(rdataset->type)) {
/*
* The zone is transitioning from insecure
* to secure. Hide the dnssec records from
* ANY queries.
*/
dns_rdataset_disassociate(rdataset);
} else if ((qtype == dns_rdatatype_any ||
rdataset->type == qtype) && rdataset->type != 0) {
query_addrrset(client,
fname != NULL ? &fname : &tname,

View File

@ -15,12 +15,13 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: update.c,v 1.142 2008/02/07 03:12:15 marka Exp $ */
/* $Id: update.c,v 1.143 2008/04/01 01:37:24 marka Exp $ */
#include <config.h>
#include <isc/netaddr.h>
#include <isc/print.h>
#include <isc/serial.h>
#include <isc/string.h>
#include <isc/taskpool.h>
#include <isc/util.h>
@ -1063,9 +1064,17 @@ rr_equal_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) {
*
* RFC2136 does not mention NSEC or DNAME, but multiple NSECs or DNAMEs
* make little sense, so we replace those, too.
*
* Additionally replace RRSIG that have been generated by the same key
* for the same type. This simplifies refreshing a offline KSK by not
* requiring that the old RRSIG be deleted. It also simpifies key
* rollover by only requiring that the new RRSIG be added.
*/
static isc_boolean_t
replaces_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) {
dns_rdata_rrsig_t updatesig, dbsig;
isc_result_t result;
if (db_rr->type != update_rr->type)
return (ISC_FALSE);
if (db_rr->type == dns_rdatatype_cname)
@ -1076,6 +1085,20 @@ replaces_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) {
return (ISC_TRUE);
if (db_rr->type == dns_rdatatype_nsec)
return (ISC_TRUE);
if (db_rr->type == dns_rdatatype_rrsig) {
/*
* Replace existing RRSIG with the same keyid,
* covered and algorithm.
*/
result = dns_rdata_tostruct(db_rr, &dbsig, NULL);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
result = dns_rdata_tostruct(update_rr, &updatesig, NULL);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
if (dbsig.keyid == updatesig.keyid &&
dbsig.covered == updatesig.covered &&
dbsig.algorithm == updatesig.algorithm)
return (ISC_TRUE);
}
if (db_rr->type == dns_rdatatype_wks) {
/*
* Compare the address and protocol fields only. These
@ -1493,6 +1516,7 @@ next_active(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
dns_dbiterator_t *dbit = NULL;
isc_boolean_t has_nsec;
unsigned int wraps = 0;
isc_boolean_t secure = dns_db_issecure(db);
CHECK(dns_db_createiterator(db, ISC_FALSE, &dbit));
@ -1530,9 +1554,29 @@ next_active(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
* we must pause the iterator first.
*/
CHECK(dns_dbiterator_pause(dbit));
if (secure) {
CHECK(rrset_exists(db, ver, newname,
dns_rdatatype_nsec, 0, &has_nsec));
} else {
dns_fixedname_t ffound;
dns_name_t *found;
dns_fixedname_init(&ffound);
found = dns_fixedname_name(&ffound);
result = dns_db_find(db, newname, ver,
dns_rdatatype_soa,
DNS_DBFIND_NOWILD, 0, NULL, found,
NULL, NULL);
if (result == ISC_R_SUCCESS ||
result == DNS_R_EMPTYNAME ||
result == DNS_R_NXRRSET ||
result == DNS_R_CNAME ||
(result == DNS_R_DELEGATION &&
dns_name_equal(newname, found))) {
has_nsec = ISC_TRUE;
result = ISC_R_SUCCESS;
} else if (result != DNS_R_NXDOMAIN)
break;
}
} while (! has_nsec);
failure:
if (dbit != NULL)
@ -1541,6 +1585,35 @@ next_active(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
return (result);
}
static isc_boolean_t
has_opt_bit(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node) {
isc_result_t result;
dns_rdata_t rdata = DNS_RDATA_INIT;
dns_rdataset_t rdataset;
isc_boolean_t has_bit = ISC_FALSE;
dns_rdataset_init(&rdataset);
CHECK(dns_db_findrdataset(db, node, version, dns_rdatatype_nsec,
dns_rdatatype_none, 0, &rdataset, NULL));
CHECK(dns_rdataset_first(&rdataset));
dns_rdataset_current(&rdataset, &rdata);
has_bit = dns_nsec_typepresent(&rdata, dns_rdatatype_opt);
failure:
if (dns_rdataset_isassociated(&rdataset))
dns_rdataset_disassociate(&rdataset);
return (has_bit);
}
static void
set_bit(unsigned char *array, unsigned int index) {
unsigned int shift, mask;
shift = 7 - (index % 8);
mask = 1 << shift;
array[index / 8] |= mask;
}
/*%
* Add a NSEC record for "name", recording the change in "diff".
* The existing NSEC is removed.
@ -1572,6 +1645,24 @@ add_nsec(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
CHECK(dns_db_findnode(db, name, ISC_FALSE, &node));
dns_rdata_init(&rdata);
CHECK(dns_nsec_buildrdata(db, ver, node, target, buffer, &rdata));
/*
* Preserve the status of the OPT bit in the origin's NSEC record.
*/
if (dns_name_equal(dns_db_origin(db), name) &&
has_opt_bit(db, ver, node))
{
isc_region_t region;
dns_name_t next;
dns_name_init(&next, NULL);
dns_rdata_toregion(&rdata, &region);
dns_name_fromregion(&next, &region);
isc_region_consume(&region, next.length);
INSIST(region.length > (2 + dns_rdatatype_opt / 8) &&
region.base[0] == 0 &&
region.base[1] > dns_rdatatype_opt / 8);
set_bit(region.base + 2, dns_rdatatype_opt);
}
dns_db_detachnode(db, &node);
/*
@ -1715,7 +1806,7 @@ add_sigs(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
/* Update the database and journal with the RRSIG. */
/* XXX inefficient - will cause dataset merging */
CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, name,
CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN, name,
rdataset.ttl, &sig_rdata));
dns_rdata_reset(&sig_rdata);
added_sig = ISC_TRUE;
@ -1735,6 +1826,84 @@ add_sigs(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
return (result);
}
/*
* Delete expired RRsigs and any RRsigs we are about to re-sign.
* See also zone.c:del_sigs().
*/
static isc_result_t
del_keysigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
dns_diff_t *diff, dst_key_t **keys, unsigned int nkeys)
{
isc_result_t result;
dns_dbnode_t *node = NULL;
dns_rdataset_t rdataset;
dns_rdata_t rdata = DNS_RDATA_INIT;
unsigned int i;
dns_rdata_rrsig_t rrsig;
isc_boolean_t found;
fprintf(stderr, "del_keysigs\n");
dns_rdataset_init(&rdataset);
result = dns_db_findnode(db, name, ISC_FALSE, &node);
if (result == ISC_R_NOTFOUND)
return (ISC_R_SUCCESS);
if (result != ISC_R_SUCCESS)
goto failure;
result = dns_db_findrdataset(db, node, ver, dns_rdatatype_rrsig,
dns_rdatatype_dnskey, (isc_stdtime_t) 0,
&rdataset, NULL);
dns_db_detachnode(db, &node);
if (result == ISC_R_NOTFOUND)
return (ISC_R_SUCCESS);
if (result != ISC_R_SUCCESS)
goto failure;
for (result = dns_rdataset_first(&rdataset);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(&rdataset)) {
dns_rdataset_current(&rdataset, &rdata);
result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
found = ISC_FALSE;
for (i = 0; i < nkeys; i++) {
if (rrsig.keyid == dst_key_id(keys[i])) {
found = ISC_TRUE;
if (!dst_key_isprivate(keys[i])) {
/*
* The re-signing code in zone.c
* will mark this as offline.
* Just skip the record for now.
*/
break;
}
result = update_one_rr(db, ver, diff,
DNS_DIFFOP_DEL, name,
rdataset.ttl, &rdata);
break;
}
}
/*
* If there is not a matching DNSKEY then delete the RRSIG.
*/
if (!found)
result = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
name, rdataset.ttl, &rdata);
dns_rdata_reset(&rdata);
if (result != ISC_R_SUCCESS)
break;
}
dns_rdataset_disassociate(&rdataset);
if (result == ISC_R_NOMORE)
result = ISC_R_SUCCESS;
failure:
if (node != NULL)
dns_db_detachnode(db, &node);
return (result);
}
/*%
* Update RRSIG and NSEC records affected by an update. The original
* update, including the SOA serial update but exluding the RRSIG & NSEC
@ -1749,7 +1918,8 @@ add_sigs(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
static isc_result_t
update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
dns_dbversion_t *oldver, dns_dbversion_t *newver,
dns_diff_t *diff, isc_uint32_t sigvalidityinterval)
dns_diff_t *diff, isc_uint32_t sigvalidityinterval,
isc_boolean_t *deleted_zsk)
{
isc_result_t result;
dns_difftuple_t *t;
@ -1797,8 +1967,27 @@ update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
*/
check_ksk = ISC_TF((dns_zone_getoptions(zone) &
DNS_ZONEOPT_UPDATECHECKKSK) != 0);
if (check_ksk)
/*
* If we are not checking the ZSK flag then all DNSKEY's are
* already signing all RRsets so we don't need to trigger special
* changes.
*/
if (*deleted_zsk && (!check_ksk || !ksk_sanity(db, oldver)))
*deleted_zsk = ISC_FALSE;
if (check_ksk) {
check_ksk = ksk_sanity(db, newver);
if (!check_ksk && ksk_sanity(db, oldver))
update_log(client, zone, ISC_LOG_WARNING,
"disabling update-check-ksk");
}
/*
* If we have deleted a ZSK and we we still have some ZSK's
* we don't need to convert the KSK's to a ZSK's.
*/
if (*deleted_zsk && check_ksk)
*deleted_zsk = ISC_FALSE;
/*
* Get the NSEC's TTL from the SOA MINIMUM field.
@ -1845,7 +2034,14 @@ update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
* Delete all old RRSIGs covering this type, since they
* are all invalid when the signed RRset has changed.
* We may not be able to recreate all of them - tough.
* Special case changes to the zone's DNSKEY records
* to support offline KSKs.
*/
fprintf(stderr, "delete signatures %u\n", type);
if (type == dns_rdatatype_dnskey)
del_keysigs(db, newver, name, &sig_diff,
zone_keys, nkeys);
else
CHECK(delete_if(true_p, db, newver, name,
dns_rdatatype_rrsig, type,
NULL, &sig_diff));
@ -2349,6 +2545,52 @@ check_mx(ns_client_t *client, dns_zone_t *zone,
return (ok ? ISC_R_SUCCESS : DNS_R_REFUSED);
}
static isc_result_t
add_signing_records(dns_db_t *db, dns_name_t *name, dns_dbversion_t *ver,
dns_diff_t *diff)
{
isc_result_t result = ISC_R_SUCCESS;
dns_difftuple_t *tuple, *newtuple = NULL;
dns_rdata_dnskey_t dnskey;
dns_rdata_t rdata = DNS_RDATA_INIT;
unsigned char buf[4];
isc_region_t r;
isc_uint16_t keyid;
for (tuple = ISC_LIST_HEAD(diff->tuples);
tuple != NULL;
tuple = ISC_LIST_NEXT(tuple, link)) {
if (tuple->rdata.type != dns_rdatatype_dnskey ||
tuple->op != DNS_DIFFOP_ADD)
continue;
dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL);
if ((dnskey.flags &
(DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH))
!= DNS_KEYOWNER_ZONE)
continue;
dns_rdata_toregion(&tuple->rdata, &r);
keyid = dst_region_computeid(&r, dnskey.algorithm);
buf[0] = dnskey.algorithm;
buf[1] = (keyid & 0xff00) >> 8;
buf[2] = (keyid & 0xff);
buf[3] = 0;
rdata.data = buf;
rdata.length = sizeof(buf);
rdata.type = 0xFFFF; /* XXXMPA make user settable */
rdata.rdclass = tuple->rdata.rdclass;
CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, name,
0, &rdata, &newtuple));
CHECK(do_one_tuple(&newtuple, db, ver, diff));
INSIST(newtuple == NULL);
}
failure:
return (result);
}
static void
update_action(isc_task_t *task, isc_event_t *event) {
update_event_t *uev = (update_event_t *) event;
@ -2371,6 +2613,9 @@ update_action(isc_task_t *task, isc_event_t *event) {
dns_fixedname_t tmpnamefixed;
dns_name_t *tmpname = NULL;
unsigned int options;
isc_boolean_t deleted_zsk;
dns_difftuple_t *tuple;
dns_rdata_dnskey_t dnskey;
INSIST(event->ev_type == DNS_EVENT_UPDATE);
@ -2567,16 +2812,18 @@ update_action(isc_task_t *task, isc_event_t *event) {
* "Unlike traditional dynamic update, the client
* is forbidden from updating NSEC records."
*/
if (dns_db_issecure(db)) {
if (dns_db_isdnssec(db)) {
if (rdata.type == dns_rdatatype_nsec) {
FAILC(DNS_R_REFUSED,
"explicit NSEC updates are not allowed "
"in secure zones");
}
else if (rdata.type == dns_rdatatype_rrsig) {
else if (rdata.type == dns_rdatatype_rrsig &&
!dns_name_equal(name, zonename)) {
FAILC(DNS_R_REFUSED,
"explicit RRSIG updates are currently "
"not supported in secure zones");
"not supported in secure zones except "
"at the apex.");
}
}
@ -2852,6 +3099,7 @@ update_action(isc_task_t *task, isc_event_t *event) {
if (! ISC_LIST_EMPTY(diff.tuples)) {
char *journalfile;
dns_journal_t *journal;
isc_boolean_t has_dnskey;
/*
* Increment the SOA serial, but only if it was not
@ -2865,10 +3113,17 @@ update_action(isc_task_t *task, isc_event_t *event) {
CHECK(remove_orphaned_ds(db, ver, &diff));
if (dns_db_issecure(db)) {
CHECK(add_signing_records(db, zonename, ver, &diff));
CHECK(rrset_exists(db, ver, zonename, dns_rdatatype_dnskey,
0, &has_dnskey));
if (has_dnskey && dns_db_isdnssec(db)) {
isc_uint32_t interval;
interval = dns_zone_getsigvalidityinterval(zone);
result = update_signatures(client, zone, db, oldver,
ver, &diff,
dns_zone_getsigvalidityinterval(zone));
ver, &diff, interval,
&deleted_zsk);
if (result != ISC_R_SUCCESS) {
update_log(client, zone,
ISC_LOG_ERROR,
@ -2905,6 +3160,7 @@ update_action(isc_task_t *task, isc_event_t *event) {
*/
update_log(client, zone, LOGLEVEL_DEBUG,
"committing update transaction");
dns_db_closeversion(db, &ver, ISC_TRUE);
/*
@ -2916,6 +3172,35 @@ update_action(isc_task_t *task, isc_event_t *event) {
* Notify slaves of the change we just made.
*/
dns_zone_notify(zone);
for (tuple = ISC_LIST_HEAD(diff.tuples);
tuple != NULL;
tuple = ISC_LIST_NEXT(tuple, link)) {
isc_region_t r;
dns_secalg_t algorithm;
isc_uint16_t keyid;
if (tuple->rdata.type != dns_rdatatype_dnskey ||
tuple->op != DNS_DIFFOP_ADD)
continue;
dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL);
if ((dnskey.flags &
(DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH))
!= DNS_KEYOWNER_ZONE)
continue;
dns_rdata_toregion(&tuple->rdata, &r);
algorithm = dnskey.algorithm;
keyid = dst_region_computeid(&r, algorithm);
result = dns_zone_signwithkey(zone, algorithm, keyid);
if (result != ISC_R_SUCCESS) {
update_log(client, zone, ISC_LOG_ERROR,
"dns_zone_signwithkey failed: %s",
dns_result_totext(result));
}
}
} else {
update_log(client, zone, LOGLEVEL_DEBUG, "redundant request");
dns_db_closeversion(db, &ver, ISC_TRUE);

View File

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: nsupdate.c,v 1.157 2008/01/18 23:46:57 tbox Exp $ */
/* $Id: nsupdate.c,v 1.158 2008/04/01 01:37:24 marka Exp $ */
/*! \file */
@ -1032,7 +1032,7 @@ parse_rdata(char **cmdlinep, dns_rdataclass_t rdataclass,
check_result(result, "isc_lex_openbuffer");
result = isc_buffer_allocate(mctx, &buf, MAXWIRE);
check_result(result, "isc_buffer_allocate");
result = dns_rdata_fromtext(rdata, rdataclass, rdatatype, lex,
result = dns_rdata_fromtext(NULL, rdataclass, rdatatype, lex,
dns_rootname, 0, mctx, buf,
&callbacks);
isc_lex_destroy(&lex);

View File

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: check.c,v 1.89 2008/03/29 23:47:08 tbox Exp $ */
/* $Id: check.c,v 1.90 2008/04/01 01:37:24 marka Exp $ */
/*! \file */
@ -654,6 +654,7 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx) {
if (tresult != ISC_R_SUCCESS &&
result == ISC_R_SUCCESS)
result = tresult;
goto trust_anchor;
}
/*
* XXXMPA to be removed when multiple lookaside
@ -666,6 +667,7 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx) {
if (result == ISC_R_SUCCESS)
result = ISC_R_FAILURE;
}
trust_anchor:
dlv = cfg_obj_asstring(cfg_tuple_get(obj,
"trust-anchor"));
isc_buffer_init(&b, dlv, strlen(dlv));

View File

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: db.c,v 1.83 2007/06/18 23:47:40 tbox Exp $ */
/* $Id: db.c,v 1.84 2008/04/01 01:37:24 marka Exp $ */
/*! \file */
@ -228,6 +228,21 @@ dns_db_isstub(dns_db_t *db) {
return (ISC_FALSE);
}
isc_boolean_t
dns_db_isdnssec(dns_db_t *db) {
/*
* Is 'db' secure or partially secure?
*/
REQUIRE(DNS_DB_VALID(db));
REQUIRE((db->attributes & DNS_DBATTR_CACHE) == 0);
if (db->methods->isdnssec != NULL)
return ((db->methods->isdnssec)(db));
return ((db->methods->issecure)(db));
}
isc_boolean_t
dns_db_issecure(dns_db_t *db) {
@ -843,3 +858,27 @@ dns_db_getoriginnode(dns_db_t *db, dns_dbnode_t **nodep) {
return (ISC_R_NOTFOUND);
}
isc_result_t
dns_db_setsigningtime(dns_db_t *db, dns_rdataset_t *rdataset,
isc_stdtime_t resign)
{
if (db->methods->setsigningtime != NULL)
return ((db->methods->setsigningtime)(db, rdataset, resign));
return (ISC_R_NOTIMPLEMENTED);
}
isc_result_t
dns_db_getsigningtime(dns_db_t *db, dns_rdataset_t *rdataset, dns_name_t *name)
{
if (db->methods->getsigningtime != NULL)
return ((db->methods->getsigningtime)(db, rdataset, name));
return (ISC_R_NOTFOUND);
}
void
dns_db_resigned(dns_db_t *db, dns_rdataset_t *rdataset, dns_dbversion_t *version)
{
if (db->methods->resigned != NULL)
return ((db->methods->resigned)(db, rdataset, version));
}

View File

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: diff.c,v 1.14 2007/06/19 23:47:16 tbox Exp $ */
/* $Id: diff.c,v 1.15 2008/04/01 01:37:24 marka Exp $ */
/*! \file */
@ -35,6 +35,7 @@
#include <dns/rdataclass.h>
#include <dns/rdatalist.h>
#include <dns/rdataset.h>
#include <dns/rdatastruct.h>
#include <dns/rdatatype.h>
#include <dns/result.h>
@ -192,6 +193,52 @@ dns_diff_appendminimal(dns_diff_t *diff, dns_difftuple_t **tuplep)
ENSURE(*tuplep == NULL);
}
static isc_stdtime_t
setresign(dns_rdataset_t *modified, dns_diffop_t op) {
dns_rdata_t rdata = DNS_RDATA_INIT;
dns_rdata_rrsig_t sig;
isc_stdtime_t when;
unsigned int delta;
isc_result_t result;
result = dns_rdataset_first(modified);
INSIST(result == ISC_R_SUCCESS);
dns_rdataset_current(modified, &rdata);
(void)dns_rdata_tostruct(&rdata, &sig, NULL);
if ((rdata.flags & DNS_RDATA_OFFLINE) != 0) {
when = 0;
} else {
delta = (sig.timeexpire - sig.timesigned) * 3 / 4;
when = sig.timesigned + delta;
}
dns_rdata_reset(&rdata);
result = dns_rdataset_next(modified);
while (result == ISC_R_SUCCESS) {
dns_rdataset_current(modified, &rdata);
(void)dns_rdata_tostruct(&rdata, &sig, NULL);
if ((rdata.flags & DNS_RDATA_OFFLINE) != 0) {
goto next_rr;
}
delta = (sig.timeexpire - sig.timesigned)* 3 / 4;
switch (op) {
case DNS_DIFFOP_ADDRESIGN:
case DNS_DIFFOP_DELRESIGN:
if (when == 0 || sig.timesigned + delta < when)
when = sig.timesigned + delta;
break;
default:
INSIST(0);
}
next_rr:
dns_rdata_reset(&rdata);
result = dns_rdataset_next(modified);
}
INSIST(result == ISC_R_NOMORE);
fprintf(stderr, "setresign %u %u\n", modified->covers, when);
return (when);
}
static isc_result_t
diff_apply(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver,
isc_boolean_t warn)
@ -228,6 +275,9 @@ diff_apply(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver,
dns_diffop_t op;
dns_rdatalist_t rdl;
dns_rdataset_t rds;
dns_rdataset_t ardataset;
dns_rdataset_t *modified = NULL;
isc_boolean_t offline;
op = t->op;
type = t->rdata.type;
@ -255,6 +305,7 @@ diff_apply(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver,
ISC_LIST_INIT(rdl.rdata);
ISC_LINK_INIT(&rdl, link);
offline = ISC_FALSE;
while (t != NULL &&
dns_name_equal(&t->name, name) &&
t->op == op &&
@ -276,6 +327,10 @@ diff_apply(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver,
namebuf, typebuf, classbuf,
(unsigned long) t->ttl,
(unsigned long) rdl.ttl);
if (t->rdata.flags &DNS_RDATA_OFFLINE) {
fprintf(stderr, "diff_apply offline\n");
offline = ISC_TRUE;
}
ISC_LIST_APPEND(rdl.rdata, &t->rdata, link);
t = ISC_LIST_NEXT(t, link);
}
@ -285,27 +340,50 @@ diff_apply(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver,
*/
dns_rdataset_init(&rds);
CHECK(dns_rdatalist_tordataset(&rdl, &rds));
if (rds.type == dns_rdatatype_rrsig)
switch (op) {
case DNS_DIFFOP_ADDRESIGN:
case DNS_DIFFOP_DELRESIGN:
modified = &ardataset;
dns_rdataset_init(modified);
break;
default:
break;
}
rds.trust = dns_trust_ultimate;
/*
* Merge the rdataset into the database.
*/
if (op == DNS_DIFFOP_ADD) {
switch (op) {
case DNS_DIFFOP_ADD:
case DNS_DIFFOP_ADDRESIGN:
result = dns_db_addrdataset(db, node, ver,
0, &rds,
DNS_DBADD_MERGE|
DNS_DBADD_EXACT|
DNS_DBADD_EXACTTTL,
NULL);
} else if (op == DNS_DIFFOP_DEL) {
modified);
break;
case DNS_DIFFOP_DEL:
case DNS_DIFFOP_DELRESIGN:
result = dns_db_subtractrdataset(db, node, ver,
&rds,
DNS_DBSUB_EXACT,
NULL);
} else {
modified);
break;
default:
INSIST(0);
}
if (result == DNS_R_UNCHANGED) {
if (result == ISC_R_SUCCESS) {
if (modified != NULL) {
isc_stdtime_t resign;
resign = setresign(modified, op);
dns_db_setsigningtime(db, modified,
resign);
}
} else if (result == DNS_R_UNCHANGED) {
/*
* This will not happen when executing a
* dynamic update, because that code will
@ -318,14 +396,21 @@ diff_apply(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver,
isc_log_write(DIFF_COMMON_LOGARGS,
ISC_LOG_WARNING,
"update with no effect");
} else if (result == ISC_R_SUCCESS ||
result == DNS_R_NXRRSET) {
} else if (result == DNS_R_NXRRSET) {
/*
* OK.
*/
} else {
if (modified != NULL &&
dns_rdataset_isassociated(modified))
dns_rdataset_disassociate(modified);
CHECK(result);
}
if (modified != NULL &&
dns_rdataset_isassociated(modified))
dns_rdataset_disassociate(modified);
if (offline)
fprintf(stderr, "end offline\n");
}
dns_db_detachnode(db, &node);
}
@ -485,6 +570,7 @@ dns_diff_print(dns_diff_t *diff, FILE *file) {
dns_difftuple_t *t;
char *mem = NULL;
unsigned int size = 2048;
const char *op = NULL;
REQUIRE(DNS_DIFF_VALID(diff));
@ -536,15 +622,20 @@ dns_diff_print(dns_diff_t *diff, FILE *file) {
buf.used--;
isc_buffer_usedregion(&buf, &r);
switch (t->op) {
case DNS_DIFFOP_EXISTS: op = "exists"; break;
case DNS_DIFFOP_ADD: op = "add"; break;
case DNS_DIFFOP_DEL: op = "del"; break;
case DNS_DIFFOP_ADDRESIGN: op = "add re-sign"; break;
case DNS_DIFFOP_DELRESIGN: op = "del re-sign"; break;
}
if (file != NULL)
fprintf(file, "%s %.*s\n",
t->op == DNS_DIFFOP_ADD ? "add" : "del",
(int) r.length, (char *) r.base);
fprintf(file, "%s %.*s\n", op, (int) r.length,
(char *) r.base);
else
isc_log_write(DIFF_COMMON_LOGARGS, ISC_LOG_DEBUG(7),
"%s %.*s",
t->op == DNS_DIFFOP_ADD ? "add" : "del",
(int) r.length, (char *) r.base);
"%s %.*s", op, (int) r.length,
(char *) r.base);
}
result = ISC_R_SUCCESS;
cleanup:

View File

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: db.h,v 1.89 2007/06/18 23:47:42 tbox Exp $ */
/* $Id: db.h,v 1.90 2008/04/01 01:37:25 marka Exp $ */
#ifndef DNS_DB_H
#define DNS_DB_H 1
@ -148,6 +148,15 @@ typedef struct dns_dbmethods {
isc_result_t (*getoriginnode)(dns_db_t *db, dns_dbnode_t **nodep);
void (*transfernode)(dns_db_t *db, dns_dbnode_t **sourcep,
dns_dbnode_t **targetp);
isc_result_t (*setsigningtime)(dns_db_t *db,
dns_rdataset_t *rdataset,
isc_stdtime_t resign);
isc_result_t (*getsigningtime)(dns_db_t *db,
dns_rdataset_t *rdataset,
dns_name_t *name);
void (*resigned)(dns_db_t *db, dns_rdataset_t *rdataset,
dns_dbversion_t *version);
isc_boolean_t (*isdnssec)(dns_db_t *db);
} dns_dbmethods_t;
typedef isc_result_t
@ -357,6 +366,20 @@ dns_db_issecure(dns_db_t *db);
* \li #ISC_FALSE 'db' is not secure.
*/
isc_boolean_t
dns_db_isdnssec(dns_db_t *db);
/*%<
* Is 'db' secure or partially secure?
*
* Requires:
*
* \li 'db' is a valid database with zone semantics.
*
* Returns:
* \li #ISC_TRUE 'db' is secure or is partially.
* \li #ISC_FALSE 'db' is not secure.
*/
dns_name_t *
dns_db_origin(dns_db_t *db);
/*%<
@ -1317,6 +1340,54 @@ dns_db_getoriginnode(dns_db_t *db, dns_dbnode_t **nodep);
* \li #ISC_R_NOTFOUND - the DB implementation does not support this feature.
*/
isc_result_t
dns_db_setsigningtime(dns_db_t *db, dns_rdataset_t *rdataset,
isc_stdtime_t resign);
/*%<
* Sets the re-signing time associated with 'rdataset' to 'resign'.
*
* Requires:
* \li 'db' is a valid zone database.
* \li 'rdataset' to be associated with 'db'.
*
* Returns:
* \li #ISC_R_SUCCESS
* \li #ISC_R_NOMEMORY
* \li #ISC_R_NOTIMPLEMENTED - Not supported by this DB implementation.
*/
isc_result_t
dns_db_getsigningtime(dns_db_t *db, dns_rdataset_t *rdataset, dns_name_t *name);
/*%<
* Return the rdataset with the earliest signing time in the zone.
* Note: the rdataset is version agnostic.
*
* Requires:
* \li 'db' is a valid zone database.
* \li 'rdataset' to be initialized but not associated.
* \li 'name' to be NULL or have a buffer associated with it.
*
* Returns:
* \li #ISC_R_SUCCESS
* \li #ISC_R_NOTFOUND - No dataset exists.
*/
void
dns_db_resigned(dns_db_t *db, dns_rdataset_t *rdataset,
dns_dbversion_t *version);
/*%<
* Mark 'rdataset' as not being available to be returned by
* dns_db_getsigningtime(). If the changes associated with 'version'
* are committed this will be permanent. If the version is not committed
* this change will be rolled back when the version is closed.
*
* Requires:
* \li 'db' is a valid zone database.
* \li 'rdataset' to be associated with 'db'.
* \li 'version' to be open for writing.
*/
ISC_LANG_ENDDECLS
#endif /* DNS_DB_H */

View File

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: diff.h,v 1.12 2007/06/19 23:47:16 tbox Exp $ */
/* $Id: diff.h,v 1.13 2008/04/01 01:37:25 marka Exp $ */
#ifndef DNS_DIFF_H
#define DNS_DIFF_H 1
@ -59,12 +59,16 @@
* individual RRs of a "RRset exists (value dependent)"
* prerequisite set. In this case, op==DNS_DIFFOP_EXISTS,
* and the TTL is ignored.
*
* DNS_DIFFOP_*RESIGN will cause the 'resign' attribute to be recomputed.
*/
typedef enum {
DNS_DIFFOP_ADD, /*%< Add an RR. */
DNS_DIFFOP_DEL, /*%< Delete an RR. */
DNS_DIFFOP_EXISTS /*%< Assert RR existence. */
DNS_DIFFOP_ADD = 0, /*%< Add an RR. */
DNS_DIFFOP_DEL = 1, /*%< Delete an RR. */
DNS_DIFFOP_EXISTS = 2, /*%< Assert RR existence. */
DNS_DIFFOP_ADDRESIGN = 4, /*%< ADD + RESIGN. */
DNS_DIFFOP_DELRESIGN = 5, /*%< DEL + RESIGN. */
} dns_diffop_t;
typedef struct dns_difftuple dns_difftuple_t;

View File

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: journal.h,v 1.31 2007/06/19 23:47:16 tbox Exp $ */
/* $Id: journal.h,v 1.32 2008/04/01 01:37:25 marka Exp $ */
#ifndef DNS_JOURNAL_H
#define DNS_JOURNAL_H 1
@ -41,6 +41,11 @@
#include <dns/rdata.h>
#include <dns/types.h>
/***
*** Defines.
***/
#define DNS_JOURNALOPT_RESIGN 0x00000001
/***
*** Types
***/
@ -225,7 +230,8 @@ dns_journal_current_rr(dns_journal_t *j, dns_name_t **name, isc_uint32_t *ttl,
*/
isc_result_t
dns_journal_rollforward(isc_mem_t *mctx, dns_db_t *db, const char *filename);
dns_journal_rollforward(isc_mem_t *mctx, dns_db_t *db, unsigned int options,
const char *filename);
/*%<
* Roll forward (play back) the journal file "filename" into the
* database "db". This should be called when the server starts
@ -235,7 +241,7 @@ dns_journal_rollforward(isc_mem_t *mctx, dns_db_t *db, const char *filename);
*\li 'mctx' is a valid memory context.
*\li 'db' is a valid database which does not have a version
* open for writing.
* \li 'filename' is the name of the journal file belonging to 'db'.
*\li 'filename' is the name of the journal file belonging to 'db'.
*
* Returns:
*\li DNS_R_NOJOURNAL when journal does not exist.

View File

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: master.h,v 1.48 2007/06/19 23:47:17 tbox Exp $ */
/* $Id: master.h,v 1.49 2008/04/01 01:37:25 marka Exp $ */
#ifndef DNS_MASTER_H
#define DNS_MASTER_H 1
@ -55,6 +55,8 @@
#define DNS_MASTER_CHECKMX 0x00000800
#define DNS_MASTER_CHECKMXFAIL 0x00001000
#define DNS_MASTER_RESIGN 0x00002000
ISC_LANG_BEGINDECLS
/*

View File

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: masterdump.h,v 1.39 2007/06/19 23:47:17 tbox Exp $ */
/* $Id: masterdump.h,v 1.40 2008/04/01 01:37:25 marka Exp $ */
#ifndef DNS_MASTERDUMP_H
#define DNS_MASTERDUMP_H 1
@ -91,12 +91,15 @@ typedef struct dns_master_style dns_master_style_t;
/*% Print negative caching entries. */
#define DNS_STYLEFLAG_NCACHE 0x00800000U
/*% Never print the TTL */
/*% Never print the TTL. */
#define DNS_STYLEFLAG_NO_TTL 0x01000000U
/*% Never print the CLASS */
/*% Never print the CLASS. */
#define DNS_STYLEFLAG_NO_CLASS 0x02000000U
/*% Report re-signing time. */
#define DNS_STYLEFLAG_RESIGN 0x04000000U
ISC_LANG_BEGINDECLS
/***

View File

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: rdata.h,v 1.67 2007/06/19 23:47:17 tbox Exp $ */
/* $Id: rdata.h,v 1.68 2008/04/01 01:37:25 marka Exp $ */
#ifndef DNS_RDATA_H
#define DNS_RDATA_H 1
@ -124,7 +124,13 @@ struct dns_rdata {
#define DNS_RDATA_INIT { NULL, 0, 0, 0, 0, {(void*)(-1), (void *)(-1)}}
#define DNS_RDATA_UPDATE 0x0001 /*%< update pseudo record */
#define DNS_RDATA_UPDATE 0x0001 /*%< update pseudo record. */
#define DNS_RDATA_OFFLINE 0x0002 /*%< RRSIG has a offline key. */
#define DNS_RDATA_WARNMASK 0x001c /*%< RRSIG(DNSKEY) expired
warnings number mask. */
#define DNS_RDATA_WARNSHIFT 2 /*%< How many bits to shift
to find remaining
expired warning number. */
/*
* Flags affecting rdata formatting style. Flags 0xFFFF0000

View File

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: rdataset.h,v 1.62 2007/06/19 23:47:17 tbox Exp $ */
/* $Id: rdataset.h,v 1.63 2008/04/01 01:37:25 marka Exp $ */
#ifndef DNS_RDATASET_H
#define DNS_RDATASET_H 1
@ -140,6 +140,11 @@ struct dns_rdataset {
* increment the counter.
*/
isc_uint32_t count;
/*
* This RRSIG RRset should be re-generated around this time.
* Only valid if DNS_RDATASETATTR_RESIGN is set in attributes.
*/
isc_stdtime_t resign;
/*@{*/
/*%
* These are for use by the rdataset implementation, and MUST NOT
@ -152,6 +157,7 @@ struct dns_rdataset {
void * private5;
void * private6;
/*@}*/
};
/*!
@ -184,6 +190,7 @@ struct dns_rdataset {
#define DNS_RDATASETATTR_CHECKNAMES 0x00008000 /*%< Used by resolver. */
#define DNS_RDATASETATTR_REQUIREDGLUE 0x00010000
#define DNS_RDATASETATTR_LOADORDER 0x00020000
#define DNS_RDATASETATTR_RESIGN 0x00040000
/*%
* _OMITDNSSEC:

View File

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: rdataslab.h,v 1.31 2007/06/19 23:47:17 tbox Exp $ */
/* $Id: rdataslab.h,v 1.32 2008/04/01 01:37:25 marka Exp $ */
#ifndef DNS_RDATASLAB_H
#define DNS_RDATASLAB_H 1
@ -57,6 +57,13 @@ ISC_LANG_BEGINDECLS
#define DNS_RDATASLAB_FORCE 0x1
#define DNS_RDATASLAB_EXACT 0x2
#define DNS_RDATASLAB_OFFLINE 0x01 /* RRSIG is for offline DNSKEY */
#define DNS_RDATASLAB_WARNMASK 0x0E /*%< RRSIG(DNSKEY) expired
* warnings number mask. */
#define DNS_RDATASLAB_WARNSHIFT 1 /*%< How many bits to shift to find
* remaining expired warning number. */
/***
*** Functions
***/

View File

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: zone.h,v 1.155 2008/01/24 23:47:00 tbox Exp $ */
/* $Id: zone.h,v 1.156 2008/04/01 01:37:25 marka Exp $ */
#ifndef DNS_ZONE_H
#define DNS_ZONE_H 1
@ -879,12 +879,16 @@ isc_boolean_t
dns_zone_getupdatedisabled(dns_zone_t *zone);
/*%<
* Return update disabled.
* Transient unless called when running in isc_task_exclusive() mode.
*/
void
dns_zone_setupdatedisabled(dns_zone_t *zone, isc_boolean_t state);
/*%<
* Set update disabled.
* Should only be called only when running in isc_task_exclusive() mode.
* Failure to do so may result in updates being committed after the
* call has been made.
*/
isc_boolean_t
@ -1636,6 +1640,9 @@ dns_zone_setisself(dns_zone_t *zone, dns_isselffunc_t isself, void *arg);
* delivered to 'myview'.
*/
isc_result_t
dns_zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, uint16_t keyid);
#ifdef HAVE_LIBXML2
isc_result_t

View File

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: journal.c,v 1.99 2007/09/07 05:14:33 marka Exp $ */
/* $Id: journal.c,v 1.100 2008/04/01 01:37:24 marka Exp $ */
#include <config.h>
@ -709,8 +709,35 @@ ixfr_order(const void *av, const void *bv) {
dns_difftuple_t const *a = *ap;
dns_difftuple_t const *b = *bp;
int r;
int bop = 0, aop = 0;
r = (b->op == DNS_DIFFOP_DEL) - (a->op == DNS_DIFFOP_DEL);
switch (a->op) {
case DNS_DIFFOP_DEL:
case DNS_DIFFOP_DELRESIGN:
aop = 1;
break;
case DNS_DIFFOP_ADD:
case DNS_DIFFOP_ADDRESIGN:
aop = 0;
break;
default:
INSIST(0);
}
switch (b->op) {
case DNS_DIFFOP_DEL:
case DNS_DIFFOP_DELRESIGN:
bop = 1;
break;
case DNS_DIFFOP_ADD:
case DNS_DIFFOP_ADDRESIGN:
bop = 0;
break;
default:
INSIST(0);
}
r = bop - aop;
if (r != 0)
return (r);
@ -1191,7 +1218,7 @@ dns_journal_destroy(dns_journal_t **journalp) {
/* XXX Share code with incoming IXFR? */
static isc_result_t
roll_forward(dns_journal_t *j, dns_db_t *db) {
roll_forward(dns_journal_t *j, dns_db_t *db, unsigned int options) {
isc_buffer_t source; /* Transaction data from disk */
isc_buffer_t target; /* Ditto after _fromwire check */
isc_uint32_t db_serial; /* Database SOA serial */
@ -1202,6 +1229,7 @@ roll_forward(dns_journal_t *j, dns_db_t *db) {
dns_diff_t diff;
unsigned int n_soa = 0;
unsigned int n_put = 0;
dns_diffop_t op;
REQUIRE(DNS_JOURNAL_VALID(j));
REQUIRE(DNS_DB_VALID(db));
@ -1273,9 +1301,14 @@ roll_forward(dns_journal_t *j, dns_db_t *db) {
"initial SOA", j->filename);
FAIL(ISC_R_UNEXPECTED);
}
CHECK(dns_difftuple_create(diff.mctx, n_soa == 1 ?
DNS_DIFFOP_DEL : DNS_DIFFOP_ADD,
name, ttl, rdata, &tuple));
if ((options & DNS_JOURNALOPT_RESIGN) != 0)
op = (n_soa == 1) ? DNS_DIFFOP_DELRESIGN :
DNS_DIFFOP_ADDRESIGN;
else
op = (n_soa == 1) ? DNS_DIFFOP_DEL : DNS_DIFFOP_ADD;
CHECK(dns_difftuple_create(diff.mctx, op, name, ttl, rdata,
&tuple));
dns_diff_append(&diff, &tuple);
if (++n_put > 100) {
@ -1317,7 +1350,9 @@ roll_forward(dns_journal_t *j, dns_db_t *db) {
}
isc_result_t
dns_journal_rollforward(isc_mem_t *mctx, dns_db_t *db, const char *filename) {
dns_journal_rollforward(isc_mem_t *mctx, dns_db_t *db,
unsigned int options, const char *filename)
{
dns_journal_t *j;
isc_result_t result;
@ -1336,7 +1371,7 @@ dns_journal_rollforward(isc_mem_t *mctx, dns_db_t *db, const char *filename) {
if (JOURNAL_EMPTY(&j->header))
result = DNS_R_UPTODATE;
else
result = roll_forward(j, db);
result = roll_forward(j, db, options);
dns_journal_destroy(&j);

View File

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: master.c,v 1.169 2008/01/18 23:46:58 tbox Exp $ */
/* $Id: master.c,v 1.170 2008/04/01 01:37:24 marka Exp $ */
/*! \file */
@ -1738,8 +1738,7 @@ load_text(dns_loadctx_t *lctx) {
char namebuf[DNS_NAME_FORMATSIZE];
dns_name_format(ictx->current, namebuf,
sizeof(namebuf));
(*callbacks->error)(callbacks,
"%s:%lu: SOA "
(*callbacks->error)(callbacks, "%s:%lu: SOA "
"record not at top of zone (%s)",
source, line, namebuf);
result = DNS_R_NOTZONETOP;
@ -2700,6 +2699,29 @@ grow_rdata(int new_len, dns_rdata_t *old, int old_len,
return (new);
}
static isc_uint32_t
resign_fromlist(dns_rdatalist_t *this) {
dns_rdata_t *rdata;
dns_rdata_rrsig_t sig;
isc_uint32_t when, delta;
rdata = ISC_LIST_HEAD(this->rdata);
INSIST(rdata != NULL);
(void)dns_rdata_tostruct(rdata, &sig, NULL);
delta = (sig.timeexpire - sig.timesigned)* 3 / 4;
when = sig.timesigned + delta;
rdata = ISC_LIST_NEXT(rdata, link);
while (rdata != NULL) {
(void)dns_rdata_tostruct(rdata, &sig, NULL);
delta = (sig.timeexpire - sig.timesigned)* 3 / 4;
if (sig.timesigned + delta < when)
when = sig.timesigned + delta;
rdata = ISC_LIST_NEXT(rdata, link);
}
return (when);
}
/*
* Convert each element from a rdatalist_t to rdataset then call commit.
* Unlink each element as we go.
@ -2726,14 +2748,22 @@ commit(dns_rdatacallbacks_t *callbacks, dns_loadctx_t *lctx,
RUNTIME_CHECK(dns_rdatalist_tordataset(this, &dataset)
== ISC_R_SUCCESS);
dataset.trust = dns_trust_ultimate;
/*
* If this is a secure dynamic zone set the re-signing time.
*/
if (dataset.type == dns_rdatatype_rrsig &&
(lctx->options & DNS_MASTER_RESIGN) != 0) {
dataset.attributes |= DNS_RDATASETATTR_RESIGN;
dns_name_format(owner, namebuf, sizeof(namebuf));
dataset.resign = resign_fromlist(this);
}
result = ((*callbacks->add)(callbacks->add_private, owner,
&dataset));
if (result == ISC_R_NOMEMORY) {
(*error)(callbacks, "dns_master_load: %s",
dns_result_totext(result));
} else if (result != ISC_R_SUCCESS) {
dns_name_format(owner, namebuf,
sizeof(namebuf));
dns_name_format(owner, namebuf, sizeof(namebuf));
if (source != NULL) {
(*error)(callbacks, "%s: %s:%lu: %s: %s",
"dns_master_load", source, line,

View File

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: masterdump.c,v 1.89 2007/06/19 23:47:16 tbox Exp $ */
/* $Id: masterdump.c,v 1.90 2008/04/01 01:37:24 marka Exp $ */
/*! \file */
@ -108,7 +108,8 @@ dns_master_style_default = {
LIBDNS_EXTERNAL_DATA const dns_master_style_t
dns_master_style_full = {
DNS_STYLEFLAG_COMMENT,
DNS_STYLEFLAG_COMMENT |
DNS_STYLEFLAG_RESIGN,
46, 46, 46, 64, 120, 8
};
@ -840,6 +841,15 @@ dump_rdatasets_text(isc_mem_t *mctx, dns_name_t *name,
if ((ctx->style.flags & DNS_STYLEFLAG_OMIT_OWNER) != 0)
name = NULL;
}
if (ctx->style.flags & DNS_STYLEFLAG_RESIGN &&
rds->attributes & DNS_RDATASETATTR_RESIGN) {
isc_buffer_t b;
char buf[sizeof("YYYYMMDDHHMMSS")];
memset(buf, 0, sizeof(buf));
isc_buffer_init(&b, buf, sizeof(buf) - 1);
dns_time64_totext((isc_uint64_t)rds->resign, &b);
fprintf(f, "; resign=%s\n", buf);
}
dns_rdataset_disassociate(rds);
}

View File

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: rbtdb.c,v 1.252 2008/02/01 23:46:58 tbox Exp $ */
/* $Id: rbtdb.c,v 1.253 2008/04/01 01:37:24 marka Exp $ */
/*! \file */
@ -25,15 +25,16 @@
#include <config.h>
#include <isc/heap.h>
#include <isc/event.h>
#include <isc/heap.h>
#include <isc/mem.h>
#include <isc/mutex.h>
#include <isc/platform.h>
#include <isc/print.h>
#include <isc/mutex.h>
#include <isc/random.h>
#include <isc/refcount.h>
#include <isc/rwlock.h>
#include <isc/serial.h>
#include <isc/string.h>
#include <isc/task.h>
#include <isc/time.h>
@ -47,6 +48,7 @@
#include <dns/lib.h>
#include <dns/log.h>
#include <dns/masterdump.h>
#include <dns/nsec.h>
#include <dns/rbt.h>
#include <dns/rdata.h>
#include <dns/rdataset.h>
@ -261,6 +263,7 @@ typedef struct rdatasetheader {
/*%<
* Used for TTL-based cache cleaning.
*/
isc_stdtime_t resign;
} rdatasetheader_t;
typedef ISC_LIST(rdatasetheader_t) rdatasetheaderlist_t;
@ -271,6 +274,7 @@ typedef ISC_LIST(dns_rbtnode_t) rbtnodelist_t;
#define RDATASET_ATTR_IGNORE 0x0004
#define RDATASET_ATTR_RETAIN 0x0008
#define RDATASET_ATTR_NXDOMAIN 0x0010
#define RDATASET_ATTR_RESIGN 0x0020
#define RDATASET_ATTR_CACHE 0x1000 /* for debug */
#define RDATASET_ATTR_CANCELED 0x2000 /* for debug */
@ -307,6 +311,8 @@ struct acachectl {
(((header)->attributes & RDATASET_ATTR_RETAIN) != 0)
#define NXDOMAIN(header) \
(((header)->attributes & RDATASET_ATTR_NXDOMAIN) != 0)
#define RESIGN(header) \
(((header)->attributes & RDATASET_ATTR_RESIGN) != 0)
#define DEFAULT_NODE_LOCK_COUNT 7 /*%< Should be prime. */
#define DEFAULT_CACHE_NODE_LOCK_COUNT 1009 /*%< Should be prime. */
@ -340,6 +346,7 @@ typedef struct rbtdb_version {
isc_boolean_t writer;
isc_boolean_t commit_ok;
rbtdb_changedlist_t changed_list;
rdatasetheaderlist_t resigned_list;
ISC_LINK(struct rbtdb_version) link;
} rbtdb_version_t;
@ -372,6 +379,12 @@ struct cachestat {
};
#endif
typedef enum {
dns_db_insecure,
dns_db_partial,
dns_db_secure
} dns_db_secure_t;
typedef struct {
/* Unlocked. */
dns_db_t common;
@ -419,7 +432,7 @@ typedef struct {
/* Locked by tree_lock. */
dns_rbt_t * tree;
isc_boolean_t secure;
dns_db_secure_t secure;
/* Unlocked */
unsigned int quantum;
@ -498,6 +511,8 @@ static void update_header(dns_rbtdb_t *rbtdb, rdatasetheader_t *header,
isc_stdtime_t now);
static void check_stale_cache(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode,
isc_stdtime_t now, isc_boolean_t tree_locked);
static isc_result_t resign_insert(dns_rbtdb_t *rbtdb, int idx,
rdatasetheader_t *newheader);
static dns_rdatasetmethods_t rdataset_methods = {
rdataset_disassociate,
@ -653,6 +668,9 @@ set_ttl(dns_rbtdb_t *rbtdb, rdatasetheader_t *header, dns_ttl_t newttl) {
oldttl = header->rdh_ttl;
header->rdh_ttl = newttl;
if (!IS_CACHE(rbtdb))
return;
/*
* It's possible the rbtdb is not a cache. If this is the case,
* we will not have a heap, and we move on. If we do, though,
@ -672,7 +690,7 @@ set_ttl(dns_rbtdb_t *rbtdb, rdatasetheader_t *header, dns_ttl_t newttl) {
}
/*%
* This function allows the heap code to rank the priority of each
* These functions allows the heap code to rank the priority of each
* element. It returns ISC_TRUE if v1 happens "sooner" than v2.
*/
static isc_boolean_t
@ -685,11 +703,21 @@ ttl_sooner(void *v1, void *v2) {
return (ISC_FALSE);
}
static isc_boolean_t
resign_sooner(void *v1, void *v2) {
rdatasetheader_t *h1 = v1;
rdatasetheader_t *h2 = v2;
if (h1->resign < h2->resign)
return (ISC_TRUE);
return (ISC_FALSE);
}
/*%
* This function sets the heap index into the header.
*/
static void
ttl_set_index(void *what, unsigned int index) {
set_index(void *what, unsigned int index) {
rdatasetheader_t *h = what;
h->heap_index = index;
@ -828,7 +856,7 @@ free_rbtdb(dns_rbtdb_t *rbtdb, isc_boolean_t log, isc_event_t *event) {
}
/*
* Clean up LRU cache objects.
* Clean up LRU / re-signing order lists.
*/
if (rbtdb->rdatasets != NULL) {
for (i = 0; i < rbtdb->node_lock_count; i++)
@ -847,7 +875,7 @@ free_rbtdb(dns_rbtdb_t *rbtdb, isc_boolean_t log, isc_event_t *event) {
rbtdb->node_lock_count * sizeof(rbtnodelist_t));
}
/*
* Clean up TTL heap cache objects.
* Clean up heap objects.
*/
if (rbtdb->heaps != NULL) {
for (i = 0; i < rbtdb->node_lock_count; i++)
@ -1005,6 +1033,7 @@ allocate_version(isc_mem_t *mctx, rbtdb_serial_t serial,
version->writer = writer;
version->commit_ok = ISC_FALSE;
ISC_LIST_INIT(version->changed_list);
ISC_LIST_INIT(version->resigned_list);
ISC_LINK_INIT(version, link);
return (version);
@ -1165,6 +1194,7 @@ static inline void
free_rdataset(dns_rbtdb_t *rbtdb, isc_mem_t *mctx, rdatasetheader_t *rdataset)
{
unsigned int size;
int idx;
#ifdef LRU_DEBUG
/*
@ -1229,15 +1259,12 @@ free_rdataset(dns_rbtdb_t *rbtdb, isc_mem_t *mctx, rdatasetheader_t *rdataset)
}
#endif
if (IS_CACHE(rbtdb) && ISC_LINK_LINKED(rdataset, lru_link)) {
int idx = rdataset->node->locknum;
idx = rdataset->node->locknum;
if (ISC_LINK_LINKED(rdataset, lru_link))
ISC_LIST_UNLINK(rbtdb->rdatasets[idx], rdataset, lru_link);
if (rdataset->heap_index != 0) {
isc_heap_delete(rbtdb->heaps[idx],
rdataset->heap_index);
}
if (rdataset->heap_index != 0)
isc_heap_delete(rbtdb->heaps[idx], rdataset->heap_index);
rdataset->heap_index = 0;
}
if (rdataset->noqname != NULL)
free_noqname(mctx, &rdataset->noqname);
@ -1703,12 +1730,14 @@ cleanup_nondirty(rbtdb_version_t *version, rbtdb_changedlist_t *cleanup_list) {
}
}
static isc_boolean_t
static dns_db_secure_t
iszonesecure(dns_db_t *db, dns_dbnode_t *origin) {
dns_rdataset_t keyset;
dns_rdataset_t nsecset, signsecset;
dns_rdata_t rdata = DNS_RDATA_INIT;
isc_boolean_t haszonekey = ISC_FALSE;
isc_boolean_t hasnsec = ISC_FALSE;
isc_boolean_t hasoptbit = ISC_FALSE;
isc_result_t result;
dns_rdataset_init(&keyset);
@ -1728,7 +1757,7 @@ iszonesecure(dns_db_t *db, dns_dbnode_t *origin) {
dns_rdataset_disassociate(&keyset);
}
if (!haszonekey)
return (ISC_FALSE);
return (dns_db_insecure);
dns_rdataset_init(&nsecset);
dns_rdataset_init(&signsecset);
@ -1737,11 +1766,20 @@ iszonesecure(dns_db_t *db, dns_dbnode_t *origin) {
if (result == ISC_R_SUCCESS) {
if (dns_rdataset_isassociated(&signsecset)) {
hasnsec = ISC_TRUE;
result = dns_rdataset_first(&nsecset);
if (result == ISC_R_SUCCESS) {
dns_rdataset_current(&nsecset, &rdata);
hasoptbit = dns_nsec_typepresent(&rdata,
dns_rdatatype_opt);
}
dns_rdataset_disassociate(&signsecset);
}
dns_rdataset_disassociate(&nsecset);
}
return (hasnsec);
if (hasnsec && hasoptbit)
return (dns_db_partial);
return (hasnsec ? dns_db_secure : dns_db_insecure);
}
static void
@ -1750,10 +1788,12 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) {
rbtdb_version_t *version, *cleanup_version, *least_greater;
isc_boolean_t rollback = ISC_FALSE;
rbtdb_changedlist_t cleanup_list;
rdatasetheaderlist_t resigned_list;
rbtdb_changed_t *changed, *next_changed;
rbtdb_serial_t serial, least_serial;
dns_rbtnode_t *rbtnode;
unsigned int refs;
rdatasetheader_t *header;
isc_boolean_t writer;
REQUIRE(VALID_RBTDB(rbtdb));
@ -1761,6 +1801,7 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) {
cleanup_version = NULL;
ISC_LIST_INIT(cleanup_list);
ISC_LIST_INIT(resigned_list);
isc_refcount_decrement(&version->references, &refs);
if (refs > 0) { /* typical and easy case first */
@ -1850,12 +1891,16 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) {
INSIST(cur_ref == 1);
PREPEND(rbtdb->open_versions,
rbtdb->current_version, link);
resigned_list = version->resigned_list;
ISC_LIST_INIT(version->resigned_list);
} else {
/*
* We're rolling back this transaction.
*/
cleanup_list = version->changed_list;
ISC_LIST_INIT(version->changed_list);
resigned_list = version->resigned_list;
ISC_LIST_INIT(version->resigned_list);
rollback = ISC_TRUE;
cleanup_version = version;
rbtdb->future_version = NULL;
@ -1916,6 +1961,25 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) {
sizeof(*cleanup_version));
}
/*
* Commit/rollback re-signed headers.
*/
for (header = HEAD(resigned_list);
header != NULL;
header = HEAD(resigned_list)) {
ISC_LIST_UNLINK(resigned_list, header, lru_link);
if (rollback) {
nodelock_t *lock;
lock = &rbtdb->node_locks[header->node->locknum].lock;
NODE_LOCK(lock, isc_rwlocktype_write);
resign_insert(rbtdb, header->node->locknum, header);
NODE_UNLOCK(lock, isc_rwlocktype_write);
}
decrement_reference(rbtdb, header->node, least_serial,
isc_rwlocktype_write,
isc_rwlocktype_none);
}
if (!EMPTY(cleanup_list)) {
/*
* We acquire a tree write lock here in order to make sure
@ -2306,6 +2370,14 @@ bind_rdataset(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
rdataset->private6 = header->noqname;
if (rdataset->private6 != NULL)
rdataset->attributes |= DNS_RDATASETATTR_NOQNAME;
/*
* Copy out re-signing information.
*/
if (RESIGN(header)) {
rdataset->attributes |= DNS_RDATASETATTR_RESIGN;
rdataset->resign = header->resign;
} else
rdataset->resign = 0;
}
static inline isc_result_t
@ -2993,12 +3065,12 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
* If we're here, then the name does not exist, is not
* beneath a zonecut, and there's no matching wildcard.
*/
if (search.rbtdb->secure ||
if (search.rbtdb->secure == dns_db_secure ||
(search.options & DNS_DBFIND_FORCENSEC) != 0)
{
result = find_closest_nsec(&search, nodep, foundname,
rdataset, sigrdataset,
search.rbtdb->secure);
ISC_TRUE);
if (result == ISC_R_SUCCESS)
result = active ? DNS_R_EMPTYNAME :
DNS_R_NXDOMAIN;
@ -3222,7 +3294,7 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
* The desired type doesn't exist.
*/
result = DNS_R_NXRRSET;
if (search.rbtdb->secure &&
if (search.rbtdb->secure == dns_db_secure &&
(nsecheader == NULL || nsecsig == NULL)) {
/*
* The zone is secure but there's no NSEC,
@ -3237,7 +3309,8 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
NODE_UNLOCK(lock, isc_rwlocktype_read);
result = find_closest_nsec(&search, nodep, foundname,
rdataset, sigrdataset,
search.rbtdb->secure);
search.rbtdb->secure ==
dns_db_secure);
if (result == ISC_R_SUCCESS)
result = DNS_R_EMPTYWILD;
goto tree_exit;
@ -3256,7 +3329,7 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
new_reference(search.rbtdb, node);
*nodep = node;
}
if (search.rbtdb->secure ||
if (search.rbtdb->secure == dns_db_secure ||
(search.options & DNS_DBFIND_FORCENSEC) != 0)
{
bind_rdataset(search.rbtdb, node, nsecheader,
@ -4545,11 +4618,13 @@ printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) {
first = ISC_FALSE;
fprintf(out,
"\tserial = %lu, ttl = %u, "
"trust = %u, attributes = %u\n",
"trust = %u, attributes = %u, "
"resign = %u\n",
(unsigned long)current->serial,
current->rdh_ttl,
current->trust,
current->attributes);
current->attributes,
current->resign);
current = current->down;
} while (current != NULL);
}
@ -4941,6 +5016,16 @@ cachestat_update(dns_rbtdb_t *rbtdb, rdatasetheader_t *header) {
}
#endif
static isc_result_t
resign_insert(dns_rbtdb_t *rbtdb, int idx, rdatasetheader_t *newheader) {
isc_result_t result;
INSIST(newheader->heap_index == 0);
INSIST(!ISC_LINK_LINKED(newheader, lru_link));
result = isc_heap_insert(rbtdb->heaps[idx], newheader);
return (result);
}
static isc_result_t
add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
rdatasetheader_t *newheader, unsigned int options, isc_boolean_t loading,
@ -4956,6 +5041,7 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
dns_rdatatype_t rdtype, covers;
rbtdb_rdatatype_t negtype;
dns_trust_t trust;
int idx;
/*
* Add an rdatasetheader_t to a node.
@ -5158,6 +5244,10 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
free_rdataset(rbtdb, rbtdb->common.mctx,
newheader);
newheader = (rdatasetheader_t *)merged;
if (loading && RESIGN(newheader) &&
RESIGN(header) &&
header->resign < newheader->resign)
newheader->resign = header->resign;
} else {
free_rdataset(rbtdb, rbtdb->common.mctx,
newheader);
@ -5250,12 +5340,10 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
set_ttl(rbtdb, header, 0);
header->attributes |= RDATASET_ATTR_STALE;
}
idx = newheader->node->locknum;
if (IS_CACHE(rbtdb)) {
int idx = newheader->node->locknum;
ISC_LIST_PREPEND(rbtdb->rdatasets[idx],
newheader, lru_link);
/*
* XXXMLG We don't check the return value
* here. If it fails, we will not do TTL
@ -5264,10 +5352,11 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
* will not leak... for long.
*/
isc_heap_insert(rbtdb->heaps[idx], newheader);
}
#ifdef LRU_DEBUG
cachestat_update(rbtdb, newheader);
#endif
} else if (RESIGN(newheader))
resign_insert(rbtdb, idx, newheader);
}
} else {
/*
@ -5313,15 +5402,17 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
newheader->down = NULL;
rbtnode->data = newheader;
}
idx = newheader->node->locknum;
if (IS_CACHE(rbtdb)) {
int idx = newheader->node->locknum;
ISC_LIST_PREPEND(rbtdb->rdatasets[idx],
newheader, lru_link);
isc_heap_insert(rbtdb->heaps[idx], newheader);
}
#ifdef LRU_DEBUG
cachestat_update(rbtdb, newheader);
#endif
} else if (RESIGN(newheader)) {
resign_insert(rbtdb, idx, newheader);
}
}
/*
@ -5446,8 +5537,14 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
if (rbtversion != NULL) {
newheader->serial = rbtversion->serial;
now = 0;
if ((rdataset->attributes & DNS_RDATASETATTR_RESIGN) != 0) {
newheader->attributes |= RDATASET_ATTR_RESIGN;
newheader->resign = rdataset->resign;
} else
newheader->resign = 0;
} else {
newheader->serial = 1;
newheader->resign = 0;
if ((rdataset->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
newheader->attributes |= RDATASET_ATTR_NXDOMAIN;
if ((rdataset->attributes & DNS_RDATASETATTR_NOQNAME) != 0) {
@ -5595,6 +5692,11 @@ subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
newheader->additional_glue = NULL;
newheader->last_used = 0;
newheader->node = rbtnode;
if ((rdataset->attributes & DNS_RDATASETATTR_RESIGN) != 0) {
newheader->attributes |= RDATASET_ATTR_RESIGN;
newheader->resign = rdataset->resign;
} else
newheader->resign = 0;
NODE_LOCK(&rbtdb->node_locks[rbtnode->locknum].lock,
isc_rwlocktype_write);
@ -5644,6 +5746,7 @@ subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
if (result == ISC_R_SUCCESS) {
free_rdataset(rbtdb, rbtdb->common.mctx, newheader);
newheader = (rdatasetheader_t *)subresult;
init_rdataset(rbtdb, newheader);
/*
* We have to set the serial since the rdataslab
* subtraction routine copies the reserved portion of
@ -5849,9 +5952,13 @@ loading_addrdataset(void *arg, dns_name_t *name, dns_rdataset_t *rdataset) {
newheader->count = init_count++;
newheader->additional_auth = NULL;
newheader->additional_glue = NULL;
/* won't be used, but initialize anyway */
newheader->last_used = 0;
newheader->node = node;
if ((rdataset->attributes & DNS_RDATASETATTR_RESIGN) != 0) {
newheader->attributes |= RDATASET_ATTR_RESIGN;
newheader->resign = rdataset->resign;
} else
newheader->resign = 0;
result = add(rbtdb, node, rbtdb->current_version, newheader,
DNS_DBADD_MERGE, ISC_TRUE, NULL, 0);
@ -5966,12 +6073,28 @@ issecure(dns_db_t *db) {
REQUIRE(VALID_RBTDB(rbtdb));
RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
secure = rbtdb->secure;
secure = ISC_TF(rbtdb->secure == dns_db_secure);
RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
return (secure);
}
static isc_boolean_t
isdnssec(dns_db_t *db) {
dns_rbtdb_t *rbtdb;
isc_boolean_t dnssec;
rbtdb = (dns_rbtdb_t *)db;
REQUIRE(VALID_RBTDB(rbtdb));
RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
dnssec = ISC_TF(rbtdb->secure != dns_db_insecure);
RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
return (dnssec);
}
static unsigned int
nodecount(dns_db_t *db) {
dns_rbtdb_t *rbtdb;
@ -6035,6 +6158,125 @@ getoriginnode(dns_db_t *db, dns_dbnode_t **nodep) {
return (result);
}
static isc_result_t
setsigningtime(dns_db_t *db, dns_rdataset_t *rdataset, isc_stdtime_t resign) {
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
isc_stdtime_t oldresign;
isc_result_t result = ISC_R_SUCCESS;
rdatasetheader_t *header;
REQUIRE(VALID_RBTDB(rbtdb));
REQUIRE(!IS_CACHE(rbtdb));
REQUIRE(rdataset != NULL);
header = rdataset->private3;
header--;
NODE_LOCK(&rbtdb->node_locks[header->node->locknum].lock,
isc_rwlocktype_write);
oldresign = header->resign;
header->resign = resign;
if (header->heap_index != 0) {
INSIST(RESIGN(header));
if (resign == 0) {
isc_heap_delete(rbtdb->heaps[header->node->locknum],
header->heap_index);
header->heap_index = 0;
} else if (resign < oldresign)
isc_heap_increased(rbtdb->heaps[header->node->locknum],
header->heap_index);
else
isc_heap_decreased(rbtdb->heaps[header->node->locknum],
header->heap_index);
} else if (resign && header->heap_index == 0) {
header->attributes |= RDATASET_ATTR_RESIGN;
result = resign_insert(rbtdb, header->node->locknum, header);
}
NODE_UNLOCK(&rbtdb->node_locks[header->node->locknum].lock,
isc_rwlocktype_write);
return (result);
}
static isc_result_t
getsigningtime(dns_db_t *db, dns_rdataset_t *rdataset,
dns_name_t *foundname)
{
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
rdatasetheader_t *header = NULL, *this;
unsigned int i;
isc_result_t result = ISC_R_NOTFOUND;
REQUIRE(VALID_RBTDB(rbtdb));
RBTDB_LOCK(&rbtdb->lock, isc_rwlocktype_read);
for (i = 0; i < rbtdb->node_lock_count; i++) {
this = isc_heap_element(rbtdb->heaps[i], 1);
if (this == NULL)
continue;
if (header == NULL)
header = this;
else if (isc_serial_lt(this->resign, header->resign))
header = this;
}
if (header == NULL)
goto unlock;
NODE_LOCK(&rbtdb->node_locks[header->node->locknum].lock,
isc_rwlocktype_read);
bind_rdataset(rbtdb, header->node, header, 0, rdataset);
if (foundname != NULL)
dns_rbt_fullnamefromnode(header->node, foundname);
NODE_UNLOCK(&rbtdb->node_locks[header->node->locknum].lock,
isc_rwlocktype_read);
result = ISC_R_SUCCESS;
unlock:
RBTDB_UNLOCK(&rbtdb->lock, isc_rwlocktype_read);
return (result);
}
static void
resigned(dns_db_t *db, dns_rdataset_t *rdataset, dns_dbversion_t *version)
{
rbtdb_version_t *rbtversion = (rbtdb_version_t *)version;
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
dns_rbtnode_t *node;
rdatasetheader_t *header;
REQUIRE(VALID_RBTDB(rbtdb));
REQUIRE(rdataset != NULL);
REQUIRE(rbtdb->future_version == rbtversion);
REQUIRE(rbtversion->writer);
node = rdataset->private2;
header = rdataset->private3;
header--;
RBTDB_LOCK(&rbtdb->lock, isc_rwlocktype_read);
NODE_LOCK(&rbtdb->node_locks[node->locknum].lock,
isc_rwlocktype_write);
/*
* Delete from heap and save to re-signed list so that it can
* be restored if we backout of this change.
*/
new_reference(rbtdb, node);
isc_heap_delete(rbtdb->heaps[node->locknum], header->heap_index);
header->heap_index = 0;
ISC_LIST_APPEND(rbtversion->resigned_list, header, lru_link);
NODE_UNLOCK(&rbtdb->node_locks[node->locknum].lock,
isc_rwlocktype_write);
RBTDB_UNLOCK(&rbtdb->lock, isc_rwlocktype_read);
}
static dns_dbmethods_t zone_methods = {
attach,
detach,
@ -6065,6 +6307,10 @@ static dns_dbmethods_t zone_methods = {
settask,
getoriginnode,
NULL,
setsigningtime,
getsigningtime,
resigned,
isdnssec,
};
static dns_dbmethods_t cache_methods = {
@ -6096,7 +6342,11 @@ static dns_dbmethods_t cache_methods = {
overmem,
settask,
getoriginnode,
NULL
NULL,
NULL,
NULL,
NULL,
isdnssec
};
isc_result_t
@ -6168,6 +6418,9 @@ dns_rbtdb_create
}
for (i = 0; i < (int)rbtdb->node_lock_count; i++)
ISC_LIST_INIT(rbtdb->rdatasets[i]);
} else {
rbtdb->rdatasets = NULL;
}
/*
* Create the heaps.
@ -6180,17 +6433,18 @@ dns_rbtdb_create
}
for (i = 0; i < (int)rbtdb->node_lock_count; i++)
rbtdb->heaps[i] = NULL;
for (i = 0; i < (int)rbtdb->node_lock_count; i++) {
result = isc_heap_create(mctx, ttl_sooner,
ttl_set_index, 0,
if (IS_CACHE(rbtdb))
result = isc_heap_create(mctx, ttl_sooner, set_index,
0, &rbtdb->heaps[i]);
else
result = isc_heap_create(mctx, resign_sooner,
set_index, 0,
&rbtdb->heaps[i]);
if (result != ISC_R_SUCCESS)
goto cleanup_heaps;
}
} else {
rbtdb->rdatasets = NULL;
rbtdb->heaps = NULL;
}
rbtdb->deadnodes = isc_mem_get(mctx, rbtdb->node_lock_count *
sizeof(rbtnodelist_t));
@ -6297,7 +6551,7 @@ dns_rbtdb_create
return (result);
}
rbtdb->attributes = 0;
rbtdb->secure = ISC_FALSE;
rbtdb->secure = dns_db_insecure;
rbtdb->overmem = ISC_FALSE;
rbtdb->task = NULL;
@ -6446,7 +6700,9 @@ rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
#if DNS_RDATASET_FIXED
unsigned int offset;
#endif
unsigned int length;
isc_region_t r;
unsigned int flags = 0;
REQUIRE(raw != NULL);
@ -6462,15 +6718,25 @@ rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
raw += offset;
}
#endif
r.length = raw[0] * 256 + raw[1];
length = raw[0] * 256 + raw[1];
#if DNS_RDATASET_FIXED
raw += 4;
#else
raw += 2;
#endif
if (rdataset->type == dns_rdatatype_rrsig) {
flags = ((*raw & DNS_RDATASLAB_WARNMASK)
>> DNS_RDATASLAB_WARNSHIFT)
<< DNS_RDATA_WARNSHIFT;
if (*raw & DNS_RDATASLAB_OFFLINE)
flags |= DNS_RDATA_OFFLINE;
length--;
raw++;
}
r.length = length;
r.base = raw;
dns_rdata_fromregion(rdata, rdataset->rdclass, rdataset->type, &r);
rdata->flags |= flags;
}
static void
@ -7539,6 +7805,8 @@ static void
update_header(dns_rbtdb_t *rbtdb, rdatasetheader_t *header,
isc_stdtime_t now)
{
INSIST(IS_CACHE(rbtdb));
/* To be checked: can we really assume this? XXXMLG */
INSIST(ISC_LINK_LINKED(header, lru_link));

View File

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: rdata.c,v 1.196 2007/06/19 23:47:16 tbox Exp $ */
/* $Id: rdata.c,v 1.197 2008/04/01 01:37:25 marka Exp $ */
/*! \file */
@ -269,7 +269,7 @@ dns_rdata_init(dns_rdata_t *rdata) {
/* ISC_LIST_INIT(rdata->list); */
}
#if 0
#if 1
#define DNS_RDATA_INITIALIZED(rdata) \
((rdata)->data == NULL && (rdata)->length == 0 && \
(rdata)->rdclass == 0 && (rdata)->type == 0 && (rdata)->flags == 0 && \
@ -282,8 +282,9 @@ dns_rdata_init(dns_rdata_t *rdata) {
#define DNS_RDATA_INITIALIZED(rdata) ISC_TRUE
#endif
#endif
#define DNS_RDATA_VALIDFLAGS(rdata) \
(((rdata)->flags & ~DNS_RDATA_UPDATE) == 0)
(((rdata)->flags & ~(DNS_RDATA_UPDATE|DNS_RDATA_OFFLINE)) == 0)
void
dns_rdata_reset(dns_rdata_t *rdata) {

View File

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: rdataset.c,v 1.79 2007/06/19 23:47:16 tbox Exp $ */
/* $Id: rdataset.c,v 1.80 2008/04/01 01:37:25 marka Exp $ */
/*! \file */
@ -59,6 +59,7 @@ dns_rdataset_init(dns_rdataset_t *rdataset) {
rdataset->privateuint4 = 0;
rdataset->private5 = NULL;
rdataset->private6 = NULL;
rdataset->resign = 0;
}
void

View File

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: rdataslab.c,v 1.43 2007/06/18 23:47:41 tbox Exp $ */
/* $Id: rdataslab.c,v 1.44 2008/04/01 01:37:25 marka Exp $ */
/*! \file */
@ -47,6 +47,7 @@
* data records
* data length (2 bytes)
* order (2 bytes)
* meta data (1 byte for RRSIG's)
* data (data length bytes)
*
* If DNS_RDATASET_FIXED is defined to be zero (0) the format of a
@ -141,6 +142,7 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
#if DNS_RDATASET_FIXED
unsigned int *offsettable;
#endif
unsigned int length;
buflen = reservelen + 2;
@ -169,6 +171,8 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
#if DNS_RDATASET_FIXED
x[i].order = i;
#endif
if (x[i].rdata.flags & DNS_RDATA_OFFLINE)
fprintf(stderr, "OFFLINE\n");
result = dns_rdataset_next(rdataset);
}
if (result != ISC_R_NOMORE)
@ -209,12 +213,18 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
x[i].order = x[i-1].order;
#endif
nitems--;
} else
} else {
#if DNS_RDATASET_FIXED
buflen += (8 + x[i-1].rdata.length);
#else
buflen += (2 + x[i-1].rdata.length);
#endif
/*
* Provide space to store the per RR meta data.
*/
if (rdataset->type == dns_rdatatype_rrsig)
buflen++;
}
}
/*
* Don't forget the last item!
@ -224,6 +234,11 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
#else
buflen += (2 + x[i-1].rdata.length);
#endif
/*
* Provide space to store the per RR meta data.
*/
if (rdataset->type == dns_rdatatype_rrsig)
buflen++;
/*
* Ensure that singleton types are actually singletons.
@ -280,11 +295,26 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
#if DNS_RDATASET_FIXED
offsettable[x[i].order] = rawbuf - offsetbase;
#endif
*rawbuf++ = (x[i].rdata.length & 0xff00) >> 8;
*rawbuf++ = (x[i].rdata.length & 0x00ff);
length = x[i].rdata.length;
if (rdataset->type == dns_rdatatype_rrsig)
length++;
*rawbuf++ = (length & 0xff00) >> 8;
*rawbuf++ = (length & 0x00ff);
#if DNS_RDATASET_FIXED
rawbuf += 2; /* filled in later */
#endif
/*
* Store the per RR meta data.
*/
if (rdataset->type == dns_rdatatype_rrsig) {
*rawbuf = ((x[i].rdata.flags & DNS_RDATA_WARNMASK)
>> DNS_RDATA_WARNSHIFT)
<< DNS_RDATASLAB_WARNSHIFT;
*rawbuf++ |= (x[i].rdata.flags & DNS_RDATA_OFFLINE) ?
DNS_RDATASLAB_OFFLINE : 0;
if (x[i].rdata.flags & DNS_RDATA_OFFLINE)
fprintf(stderr, "set DNS_RDATASLAB_OFFLINE\n");
}
memcpy(rawbuf, x[i].rdata.data, x[i].rdata.length);
rawbuf += x[i].rdata.length;
}
@ -360,17 +390,30 @@ static void
rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
unsigned char *raw = rdataset->private5;
isc_region_t r;
unsigned int length;
unsigned int flags = 0;
REQUIRE(raw != NULL);
r.length = raw[0] * 256 + raw[1];
length = raw[0] * 256 + raw[1];
#if DNS_RDATASET_FIXED
raw += 4;
#else
raw += 2;
#endif
if (rdataset->type == dns_rdatatype_rrsig) {
flags = ((*raw & DNS_RDATASLAB_WARNMASK)
>> DNS_RDATASLAB_WARNSHIFT)
<< DNS_RDATA_WARNSHIFT;
if (*raw & DNS_RDATASLAB_OFFLINE)
flags |= DNS_RDATA_OFFLINE;
length--;
raw++;
}
r.length = length;
r.base = raw;
dns_rdata_fromregion(rdata, rdataset->rdclass, rdataset->type, &r);
rdata->flags |= flags;
}
static void
@ -474,15 +517,29 @@ rdata_from_slab(unsigned char **current,
{
unsigned char *tcurrent = *current;
isc_region_t region;
unsigned int length;
isc_boolean_t offline = ISC_FALSE;
region.length = *tcurrent++ * 256;
region.length += *tcurrent++;
length = *tcurrent++ * 256;
length += *tcurrent++;
if (type == dns_rdatatype_rrsig) {
if ((*tcurrent & DNS_RDATASLAB_OFFLINE) != 0)
offline = ISC_TRUE;
length--;
tcurrent++;
}
region.length = length;
#if DNS_RDATASET_FIXED
tcurrent += 2;
#endif
region.base = tcurrent;
tcurrent += region.length;
dns_rdata_fromregion(rdata, rdclass, type, &region);
if (offline) {
rdata->flags |= DNS_RDATA_OFFLINE;
fprintf(stderr, "rdata_from_slab: DNS_RDATA_OFFLINE\n");
}
*current = tcurrent;
}
@ -528,9 +585,8 @@ dns_rdataslab_merge(unsigned char *oslab, unsigned char *nslab,
dns_rdataclass_t rdclass, dns_rdatatype_t type,
unsigned int flags, unsigned char **tslabp)
{
unsigned char *ocurrent, *ostart, *ncurrent, *tstart, *tcurrent;
unsigned char *ocurrent, *ostart, *ncurrent, *tstart, *tcurrent, *data;
unsigned int ocount, ncount, count, olength, tlength, tcount, length;
isc_region_t nregion;
dns_rdata_t ordata = DNS_RDATA_INIT;
dns_rdata_t nrdata = DNS_RDATA_INIT;
isc_boolean_t added_something = ISC_FALSE;
@ -603,29 +659,24 @@ dns_rdataslab_merge(unsigned char *oslab, unsigned char *nslab,
* the old slab.
*/
do {
nregion.length = *ncurrent++ * 256;
nregion.length += *ncurrent++;
#if DNS_RDATASET_FIXED
ncurrent += 2; /* Skip order. */
#endif
nregion.base = ncurrent;
dns_rdata_init(&nrdata);
dns_rdata_fromregion(&nrdata, rdclass, type, &nregion);
rdata_from_slab(&ncurrent, rdclass, type, &nrdata);
if (!rdata_in_slab(oslab, reservelen, rdclass, type, &nrdata))
{
/*
* This rdata isn't in the old slab.
*/
#if DNS_RDATASET_FIXED
tlength += nregion.length + 8;
tlength += nrdata.length + 8;
#else
tlength += nregion.length + 2;
tlength += nrdata.length + 2;
#endif
if (type == dns_rdatatype_rrsig)
tlength++;
tcount++;
nncount++;
added_something = ISC_TRUE;
}
ncurrent += nregion.length;
ncount--;
} while (ncount > 0);
ncount = nncount;
@ -726,12 +777,17 @@ dns_rdataslab_merge(unsigned char *oslab, unsigned char *nslab,
offsettable[oorder] = tcurrent - offsetbase;
#endif
length = ordata.length;
data = ordata.data;
if (type == dns_rdatatype_rrsig) {
length++;
data--;
}
*tcurrent++ = (length & 0xff00) >> 8;
*tcurrent++ = (length & 0x00ff);
#if DNS_RDATASET_FIXED
tcurrent += 2; /* fill in later */
#endif
memcpy(tcurrent, ordata.data, length);
memcpy(tcurrent, data, length);
tcurrent += length;
oadded++;
if (oadded < ocount) {
@ -748,12 +804,17 @@ dns_rdataslab_merge(unsigned char *oslab, unsigned char *nslab,
offsettable[ocount + norder] = tcurrent - offsetbase;
#endif
length = nrdata.length;
data = nrdata.data;
if (type == dns_rdatatype_rrsig) {
length++;
data--;
}
*tcurrent++ = (length & 0xff00) >> 8;
*tcurrent++ = (length & 0x00ff);
#if DNS_RDATASET_FIXED
tcurrent += 2; /* fill in later */
#endif
memcpy(tcurrent, nrdata.data, length);
memcpy(tcurrent, data, length);
tcurrent += length;
nadded++;
if (nadded < ncount) {

View File

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: rootns.c,v 1.34 2008/02/05 23:47:08 tbox Exp $ */
/* $Id: rootns.c,v 1.35 2008/04/01 01:37:25 marka Exp $ */
/*! \file */
@ -97,6 +97,7 @@ in_rootns(dns_rdataset_t *rootns, dns_name_t *name) {
if (dns_name_compare(name, &ns.name) == 0)
return (ISC_R_SUCCESS);
result = dns_rdataset_next(rootns);
dns_rdata_reset(&rdata);
}
if (result == ISC_R_NOMORE)
result = ISC_R_NOTFOUND;
@ -338,6 +339,7 @@ check_address_records(dns_view_t *view, dns_db_t *hints, dns_db_t *db,
(rresult == ISC_R_SUCCESS || rresult == DNS_R_GLUE)) {
result = dns_rdataset_first(&rootrrset);
while (result == ISC_R_SUCCESS) {
dns_rdata_reset(&rdata);
dns_rdataset_current(&rootrrset, &rdata);
if (!inrrset(&hintrrset, &rdata))
report(view, name, ISC_TRUE, &rdata);
@ -345,6 +347,7 @@ check_address_records(dns_view_t *view, dns_db_t *hints, dns_db_t *db,
}
result = dns_rdataset_first(&hintrrset);
while (result == ISC_R_SUCCESS) {
dns_rdata_reset(&rdata);
dns_rdataset_current(&hintrrset, &rdata);
if (!inrrset(&rootrrset, &rdata))
report(view, name, ISC_FALSE, &rdata);
@ -355,6 +358,7 @@ check_address_records(dns_view_t *view, dns_db_t *hints, dns_db_t *db,
(rresult == ISC_R_SUCCESS || rresult == DNS_R_GLUE)) {
result = dns_rdataset_first(&rootrrset);
while (result == ISC_R_SUCCESS) {
dns_rdata_reset(&rdata);
dns_rdataset_current(&rootrrset, &rdata);
report(view, name, ISC_TRUE, &rdata);
result = dns_rdataset_next(&rootrrset);
@ -377,6 +381,7 @@ check_address_records(dns_view_t *view, dns_db_t *hints, dns_db_t *db,
(rresult == ISC_R_SUCCESS || rresult == DNS_R_GLUE)) {
result = dns_rdataset_first(&rootrrset);
while (result == ISC_R_SUCCESS) {
dns_rdata_reset(&rdata);
dns_rdataset_current(&rootrrset, &rdata);
if (!inrrset(&hintrrset, &rdata))
report(view, name, ISC_TRUE, &rdata);
@ -385,6 +390,7 @@ check_address_records(dns_view_t *view, dns_db_t *hints, dns_db_t *db,
}
result = dns_rdataset_first(&hintrrset);
while (result == ISC_R_SUCCESS) {
dns_rdata_reset(&rdata);
dns_rdataset_current(&hintrrset, &rdata);
if (!inrrset(&rootrrset, &rdata))
report(view, name, ISC_FALSE, &rdata);
@ -396,6 +402,7 @@ check_address_records(dns_view_t *view, dns_db_t *hints, dns_db_t *db,
(rresult == ISC_R_SUCCESS || rresult == DNS_R_GLUE)) {
result = dns_rdataset_first(&rootrrset);
while (result == ISC_R_SUCCESS) {
dns_rdata_reset(&rdata);
dns_rdataset_current(&rootrrset, &rdata);
report(view, name, ISC_TRUE, &rdata);
dns_rdata_reset(&rdata);

View File

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: sdb.c,v 1.62 2008/01/18 23:46:58 tbox Exp $ */
/* $Id: sdb.c,v 1.63 2008/04/01 01:37:25 marka Exp $ */
/*! \file */
@ -1247,6 +1247,10 @@ static dns_dbmethods_t sdb_methods = {
overmem,
settask,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
};

View File

@ -50,7 +50,7 @@
* USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: sdlz.c,v 1.14 2007/08/27 03:32:27 marka Exp $ */
/* $Id: sdlz.c,v 1.15 2008/04/01 01:37:25 marka Exp $ */
/*! \file */
@ -1051,6 +1051,10 @@ static dns_dbmethods_t sdlzdb_methods = {
overmem,
settask,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
};

View File

@ -16,7 +16,7 @@
*/
/*
* $Id: tsig.c,v 1.133 2008/01/18 23:46:58 tbox Exp $
* $Id: tsig.c,v 1.134 2008/04/01 01:37:25 marka Exp $
*/
/*! \file */
#include <config.h>
@ -445,7 +445,7 @@ cleanup_ring(dns_tsig_keyring_t *ring)
dns_rbtnodechain_current(&chain, &foundname, origin, &node);
tkey = node->data;
if (tkey != NULL) {
tsig_log(tkey, 2, "tsig expire: generated=%d, refs=%d, expire=%d)", tkey->generated, isc_refcount_current(&tkey->refs), now - tkey->expire);
tsig_log(tkey, 2, "tsig expire: generated=%d, refs=%d, expire=%d", tkey->generated, isc_refcount_current(&tkey->refs), now - tkey->expire);
if (tkey->generated
&& isc_refcount_current(&tkey->refs) == 1
&& tkey->inception != tkey->expire

File diff suppressed because it is too large Load Diff

View File

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: mem.c,v 1.143 2008/03/31 23:47:11 tbox Exp $ */
/* $Id: mem.c,v 1.144 2008/04/01 01:37:25 marka Exp $ */
/*! \file */
@ -112,7 +112,7 @@ typedef ISC_LIST(debuglink_t) debuglist_t;
static ISC_LIST(isc_mem_t) contexts;
static isc_once_t once = ISC_ONCE_INIT;
static isc_mutex_t lock;
static isc_mutex_t contextlock;
/*%
* Total size of lost memory due to a bug of external library.
@ -124,7 +124,7 @@ struct isc_mem {
unsigned int magic;
isc_ondestroy_t ondestroy;
unsigned int flags;
isc_mutex_t lock;
isc_mutex_t memlock;
isc_memalloc_t memalloc;
isc_memfree_t memfree;
void * arg;
@ -702,7 +702,7 @@ default_memfree(void *arg, void *ptr) {
static void
initialize_action(void) {
RUNTIME_CHECK(isc_mutex_init(&lock) == ISC_R_SUCCESS);
RUNTIME_CHECK(isc_mutex_init(&contextlock) == ISC_R_SUCCESS);
ISC_LIST_INIT(contexts);
totallost = 0;
}
@ -742,7 +742,7 @@ isc_mem_createx2(size_t init_max_size, size_t target_size,
return (ISC_R_NOMEMORY);
if ((flags & ISC_MEMFLAG_NOLOCK) == 0) {
result = isc_mutex_init(&ctx->lock);
result = isc_mutex_init(&ctx->memlock);
if (result != ISC_R_SUCCESS) {
(memfree)(arg, ctx);
return (result);
@ -827,9 +827,9 @@ isc_mem_createx2(size_t init_max_size, size_t target_size,
ctx->memalloc_failures = 0;
LOCK(&lock);
LOCK(&contextlock);
ISC_LIST_INITANDAPPEND(contexts, ctx, link);
UNLOCK(&lock);
UNLOCK(&contextlock);
*ctxp = ctx;
return (ISC_R_SUCCESS);
@ -845,7 +845,7 @@ isc_mem_createx2(size_t init_max_size, size_t target_size,
(ctx->memfree)(ctx->arg, ctx->debuglist);
#endif /* ISC_MEM_TRACKLINES */
if ((ctx->flags & ISC_MEMFLAG_NOLOCK) == 0)
DESTROYLOCK(&ctx->lock);
DESTROYLOCK(&ctx->memlock);
(memfree)(arg, ctx);
}
@ -877,10 +877,10 @@ destroy(isc_mem_t *ctx) {
ctx->magic = 0;
LOCK(&lock);
LOCK(&contextlock);
ISC_LIST_UNLINK(contexts, ctx, link);
totallost += ctx->inuse;
UNLOCK(&lock);
UNLOCK(&contextlock);
INSIST(ISC_LIST_EMPTY(ctx->pools));
@ -932,7 +932,7 @@ destroy(isc_mem_t *ctx) {
ondest = ctx->ondestroy;
if ((ctx->flags & ISC_MEMFLAG_NOLOCK) == 0)
DESTROYLOCK(&ctx->lock);
DESTROYLOCK(&ctx->memlock);
(ctx->memfree)(ctx->arg, ctx);
isc_ondestroy_notify(&ondest, ctx);
@ -943,9 +943,9 @@ isc_mem_attach(isc_mem_t *source, isc_mem_t **targetp) {
REQUIRE(VALID_CONTEXT(source));
REQUIRE(targetp != NULL && *targetp == NULL);
MCTXLOCK(source, &source->lock);
MCTXLOCK(source, &source->memlock);
source->references++;
MCTXUNLOCK(source, &source->lock);
MCTXUNLOCK(source, &source->memlock);
*targetp = source;
}
@ -959,12 +959,12 @@ isc_mem_detach(isc_mem_t **ctxp) {
ctx = *ctxp;
REQUIRE(VALID_CONTEXT(ctx));
MCTXLOCK(ctx, &ctx->lock);
MCTXLOCK(ctx, &ctx->memlock);
INSIST(ctx->references > 0);
ctx->references--;
if (ctx->references == 0)
want_destroy = ISC_TRUE;
MCTXUNLOCK(ctx, &ctx->lock);
MCTXUNLOCK(ctx, &ctx->memlock);
if (want_destroy)
destroy(ctx);
@ -1010,11 +1010,11 @@ isc__mem_putanddetach(isc_mem_t **ctxp, void *ptr, size_t size FLARG) {
}
isc__mem_free(ctx, ptr FLARG_PASS);
MCTXLOCK(ctx, &ctx->lock);
MCTXLOCK(ctx, &ctx->memlock);
ctx->references--;
if (ctx->references == 0)
want_destroy = ISC_TRUE;
MCTXUNLOCK(ctx, &ctx->lock);
MCTXUNLOCK(ctx, &ctx->memlock);
if (want_destroy)
destroy(ctx);
@ -1022,11 +1022,11 @@ isc__mem_putanddetach(isc_mem_t **ctxp, void *ptr, size_t size FLARG) {
}
if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
MCTXLOCK(ctx, &ctx->lock);
MCTXLOCK(ctx, &ctx->memlock);
mem_putunlocked(ctx, ptr, size);
} else {
mem_put(ctx, ptr, size);
MCTXLOCK(ctx, &ctx->lock);
MCTXLOCK(ctx, &ctx->memlock);
mem_putstats(ctx, ptr, size);
}
@ -1036,7 +1036,7 @@ isc__mem_putanddetach(isc_mem_t **ctxp, void *ptr, size_t size FLARG) {
if (ctx->references == 0)
want_destroy = ISC_TRUE;
MCTXUNLOCK(ctx, &ctx->lock);
MCTXUNLOCK(ctx, &ctx->memlock);
if (want_destroy)
destroy(ctx);
@ -1055,14 +1055,14 @@ isc_mem_destroy(isc_mem_t **ctxp) {
ctx = *ctxp;
REQUIRE(VALID_CONTEXT(ctx));
MCTXLOCK(ctx, &ctx->lock);
MCTXLOCK(ctx, &ctx->memlock);
#if ISC_MEM_TRACKLINES
if (ctx->references != 1)
print_active(ctx, stderr);
#endif
REQUIRE(ctx->references == 1);
ctx->references--;
MCTXUNLOCK(ctx, &ctx->lock);
MCTXUNLOCK(ctx, &ctx->memlock);
destroy(ctx);
@ -1073,9 +1073,9 @@ isc_result_t
isc_mem_ondestroy(isc_mem_t *ctx, isc_task_t *task, isc_event_t **event) {
isc_result_t res;
MCTXLOCK(ctx, &ctx->lock);
MCTXLOCK(ctx, &ctx->memlock);
res = isc_ondestroy_register(&ctx->ondestroy, task, event);
MCTXUNLOCK(ctx, &ctx->lock);
MCTXUNLOCK(ctx, &ctx->memlock);
return (res);
}
@ -1092,11 +1092,11 @@ isc__mem_get(isc_mem_t *ctx, size_t size FLARG) {
return (isc__mem_allocate(ctx, size FLARG_PASS));
if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
MCTXLOCK(ctx, &ctx->lock);
MCTXLOCK(ctx, &ctx->memlock);
ptr = mem_getunlocked(ctx, size);
} else {
ptr = mem_get(ctx, size);
MCTXLOCK(ctx, &ctx->lock);
MCTXLOCK(ctx, &ctx->memlock);
if (ptr != NULL)
mem_getstats(ctx, size);
}
@ -1113,7 +1113,7 @@ isc__mem_get(isc_mem_t *ctx, size_t size FLARG) {
fprintf(stderr, "maxinuse = %lu\n",
(unsigned long)ctx->inuse);
}
MCTXUNLOCK(ctx, &ctx->lock);
MCTXUNLOCK(ctx, &ctx->memlock);
if (call_water)
(ctx->water)(ctx->water_arg, ISC_MEM_HIWATER);
@ -1144,11 +1144,11 @@ isc__mem_put(isc_mem_t *ctx, void *ptr, size_t size FLARG)
}
if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
MCTXLOCK(ctx, &ctx->lock);
MCTXLOCK(ctx, &ctx->memlock);
mem_putunlocked(ctx, ptr, size);
} else {
mem_put(ctx, ptr, size);
MCTXLOCK(ctx, &ctx->lock);
MCTXLOCK(ctx, &ctx->memlock);
mem_putstats(ctx, ptr, size);
}
@ -1164,7 +1164,7 @@ isc__mem_put(isc_mem_t *ctx, void *ptr, size_t size FLARG)
if (ctx->water != NULL)
call_water = ISC_TRUE;
}
MCTXUNLOCK(ctx, &ctx->lock);
MCTXUNLOCK(ctx, &ctx->memlock);
if (call_water)
(ctx->water)(ctx->water_arg, ISC_MEM_LOWATER);
@ -1174,12 +1174,12 @@ void
isc_mem_waterack(isc_mem_t *ctx, int flag) {
REQUIRE(VALID_CONTEXT(ctx));
MCTXLOCK(ctx, &ctx->lock);
MCTXLOCK(ctx, &ctx->memlock);
if (flag == ISC_MEM_LOWATER)
ctx->hi_called = ISC_FALSE;
else if (flag == ISC_MEM_HIWATER)
ctx->hi_called = ISC_TRUE;
MCTXUNLOCK(ctx, &ctx->lock);
MCTXUNLOCK(ctx, &ctx->memlock);
}
#if ISC_MEM_TRACKLINES
@ -1233,7 +1233,7 @@ isc_mem_stats(isc_mem_t *ctx, FILE *out) {
const isc_mempool_t *pool;
REQUIRE(VALID_CONTEXT(ctx));
MCTXLOCK(ctx, &ctx->lock);
MCTXLOCK(ctx, &ctx->memlock);
for (i = 0; i <= ctx->max_size; i++) {
s = &ctx->stats[i];
@ -1254,7 +1254,7 @@ isc_mem_stats(isc_mem_t *ctx, FILE *out) {
* Note that since a pool can be locked now, these stats might be
* somewhat off if the pool is in active use at the time the stats
* are dumped. The link fields are protected by the isc_mem_t's
* lock, however, so walking this list and extracting integers from
* contextlock, however, so walking this list and extracting integers from
* stats fields is always safe.
*/
pool = ISC_LIST_HEAD(ctx->pools);
@ -1294,7 +1294,7 @@ isc_mem_stats(isc_mem_t *ctx, FILE *out) {
print_active(ctx, out);
#endif
MCTXUNLOCK(ctx, &ctx->lock);
MCTXUNLOCK(ctx, &ctx->memlock);
}
/*
@ -1333,11 +1333,11 @@ isc__mem_allocate(isc_mem_t *ctx, size_t size FLARG) {
REQUIRE(VALID_CONTEXT(ctx));
if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
MCTXLOCK(ctx, &ctx->lock);
MCTXLOCK(ctx, &ctx->memlock);
si = isc__mem_allocateunlocked(ctx, size);
} else {
si = isc__mem_allocateunlocked(ctx, size);
MCTXLOCK(ctx, &ctx->lock);
MCTXLOCK(ctx, &ctx->memlock);
if (si != NULL)
mem_getstats(ctx, si[-1].u.size);
}
@ -1357,7 +1357,7 @@ isc__mem_allocate(isc_mem_t *ctx, size_t size FLARG) {
fprintf(stderr, "maxinuse = %lu\n",
(unsigned long)ctx->inuse);
}
MCTXUNLOCK(ctx, &ctx->lock);
MCTXUNLOCK(ctx, &ctx->memlock);
if (call_water)
(ctx->water)(ctx->water_arg, ISC_MEM_HIWATER);
@ -1384,11 +1384,11 @@ isc__mem_free(isc_mem_t *ctx, void *ptr FLARG) {
}
if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
MCTXLOCK(ctx, &ctx->lock);
MCTXLOCK(ctx, &ctx->memlock);
mem_putunlocked(ctx, si, size);
} else {
mem_put(ctx, si, size);
MCTXLOCK(ctx, &ctx->lock);
MCTXLOCK(ctx, &ctx->memlock);
mem_putstats(ctx, si, size);
}
@ -1406,7 +1406,7 @@ isc__mem_free(isc_mem_t *ctx, void *ptr FLARG) {
if (ctx->water != NULL)
call_water = ISC_TRUE;
}
MCTXUNLOCK(ctx, &ctx->lock);
MCTXUNLOCK(ctx, &ctx->memlock);
if (call_water)
(ctx->water)(ctx->water_arg, ISC_MEM_LOWATER);
@ -1438,11 +1438,11 @@ isc__mem_strdup(isc_mem_t *mctx, const char *s FLARG) {
void
isc_mem_setdestroycheck(isc_mem_t *ctx, isc_boolean_t flag) {
REQUIRE(VALID_CONTEXT(ctx));
MCTXLOCK(ctx, &ctx->lock);
MCTXLOCK(ctx, &ctx->memlock);
ctx->checkfree = flag;
MCTXUNLOCK(ctx, &ctx->lock);
MCTXUNLOCK(ctx, &ctx->memlock);
}
/*
@ -1452,11 +1452,11 @@ isc_mem_setdestroycheck(isc_mem_t *ctx, isc_boolean_t flag) {
void
isc_mem_setquota(isc_mem_t *ctx, size_t quota) {
REQUIRE(VALID_CONTEXT(ctx));
MCTXLOCK(ctx, &ctx->lock);
MCTXLOCK(ctx, &ctx->memlock);
ctx->quota = quota;
MCTXUNLOCK(ctx, &ctx->lock);
MCTXUNLOCK(ctx, &ctx->memlock);
}
size_t
@ -1464,11 +1464,11 @@ isc_mem_getquota(isc_mem_t *ctx) {
size_t quota;
REQUIRE(VALID_CONTEXT(ctx));
MCTXLOCK(ctx, &ctx->lock);
MCTXLOCK(ctx, &ctx->memlock);
quota = ctx->quota;
MCTXUNLOCK(ctx, &ctx->lock);
MCTXUNLOCK(ctx, &ctx->memlock);
return (quota);
}
@ -1478,11 +1478,11 @@ isc_mem_inuse(isc_mem_t *ctx) {
size_t inuse;
REQUIRE(VALID_CONTEXT(ctx));
MCTXLOCK(ctx, &ctx->lock);
MCTXLOCK(ctx, &ctx->memlock);
inuse = ctx->inuse;
MCTXUNLOCK(ctx, &ctx->lock);
MCTXUNLOCK(ctx, &ctx->memlock);
return (inuse);
}
@ -1498,7 +1498,7 @@ isc_mem_setwater(isc_mem_t *ctx, isc_mem_water_t water, void *water_arg,
REQUIRE(VALID_CONTEXT(ctx));
REQUIRE(hiwater >= lowater);
MCTXLOCK(ctx, &ctx->lock);
MCTXLOCK(ctx, &ctx->memlock);
oldwater = ctx->water;
oldwater_arg = ctx->water_arg;
if (water == NULL) {
@ -1519,7 +1519,7 @@ isc_mem_setwater(isc_mem_t *ctx, isc_mem_water_t water, void *water_arg,
ctx->lo_water = lowater;
ctx->hi_called = ISC_FALSE;
}
MCTXUNLOCK(ctx, &ctx->lock);
MCTXUNLOCK(ctx, &ctx->memlock);
if (callwater && oldwater != NULL)
(oldwater)(oldwater_arg, ISC_MEM_LOWATER);
@ -1529,11 +1529,11 @@ void
isc_mem_setname(isc_mem_t *ctx, const char *name, void *tag) {
REQUIRE(VALID_CONTEXT(ctx));
LOCK(&ctx->lock);
LOCK(&ctx->memlock);
memset(ctx->name, 0, sizeof(ctx->name));
strncpy(ctx->name, name, sizeof(ctx->name) - 1);
ctx->tag = tag;
UNLOCK(&ctx->lock);
UNLOCK(&ctx->memlock);
}
const char *
@ -1587,10 +1587,10 @@ isc_mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp) {
*mpctxp = mpctx;
MCTXLOCK(mctx, &mctx->lock);
MCTXLOCK(mctx, &mctx->memlock);
ISC_LIST_INITANDAPPEND(mctx->pools, mpctx, link);
mctx->poolcnt++;
MCTXUNLOCK(mctx, &mctx->lock);
MCTXUNLOCK(mctx, &mctx->memlock);
return (ISC_R_SUCCESS);
}
@ -1643,7 +1643,7 @@ isc_mempool_destroy(isc_mempool_t **mpctxp) {
/*
* Return any items on the free list
*/
MCTXLOCK(mctx, &mctx->lock);
MCTXLOCK(mctx, &mctx->memlock);
while (mpctx->items != NULL) {
INSIST(mpctx->freecount > 0);
mpctx->freecount--;
@ -1657,15 +1657,15 @@ isc_mempool_destroy(isc_mempool_t **mpctxp) {
mem_putstats(mctx, item, mpctx->size);
}
}
MCTXUNLOCK(mctx, &mctx->lock);
MCTXUNLOCK(mctx, &mctx->memlock);
/*
* Remove our linked list entry from the memory context.
*/
MCTXLOCK(mctx, &mctx->lock);
MCTXLOCK(mctx, &mctx->memlock);
ISC_LIST_UNLINK(mctx->pools, mpctx, link);
mctx->poolcnt--;
MCTXUNLOCK(mctx, &mctx->lock);
MCTXUNLOCK(mctx, &mctx->memlock);
mpctx->magic = 0;
@ -1724,7 +1724,7 @@ isc__mempool_get(isc_mempool_t *mpctx FLARG) {
* We need to dip into the well. Lock the memory context here and
* fill up our free list.
*/
MCTXLOCK(mctx, &mctx->lock);
MCTXLOCK(mctx, &mctx->memlock);
for (i = 0; i < mpctx->fillcount; i++) {
if ((mctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
item = mem_getunlocked(mctx, mpctx->size);
@ -1739,7 +1739,7 @@ isc__mempool_get(isc_mempool_t *mpctx FLARG) {
mpctx->items = item;
mpctx->freecount++;
}
MCTXUNLOCK(mctx, &mctx->lock);
MCTXUNLOCK(mctx, &mctx->memlock);
/*
* If we didn't get any items, return NULL.
@ -1759,9 +1759,9 @@ isc__mempool_get(isc_mempool_t *mpctx FLARG) {
#if ISC_MEM_TRACKLINES
if (item != NULL) {
MCTXLOCK(mctx, &mctx->lock);
MCTXLOCK(mctx, &mctx->memlock);
ADD_TRACE(mctx, item, mpctx->size, file, line);
MCTXUNLOCK(mctx, &mctx->lock);
MCTXUNLOCK(mctx, &mctx->memlock);
}
#endif /* ISC_MEM_TRACKLINES */
@ -1785,9 +1785,9 @@ isc__mempool_put(isc_mempool_t *mpctx, void *mem FLARG) {
mpctx->allocated--;
#if ISC_MEM_TRACKLINES
MCTXLOCK(mctx, &mctx->lock);
MCTXLOCK(mctx, &mctx->memlock);
DELETE_TRACE(mctx, mem, mpctx->size, file, line);
MCTXUNLOCK(mctx, &mctx->lock);
MCTXUNLOCK(mctx, &mctx->memlock);
#endif /* ISC_MEM_TRACKLINES */
/*
@ -1795,14 +1795,14 @@ isc__mempool_put(isc_mempool_t *mpctx, void *mem FLARG) {
*/
if (mpctx->freecount >= mpctx->freemax) {
if ((mctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
MCTXLOCK(mctx, &mctx->lock);
MCTXLOCK(mctx, &mctx->memlock);
mem_putunlocked(mctx, mem, mpctx->size);
MCTXUNLOCK(mctx, &mctx->lock);
MCTXUNLOCK(mctx, &mctx->memlock);
} else {
mem_put(mctx, mem, mpctx->size);
MCTXLOCK(mctx, &mctx->lock);
MCTXLOCK(mctx, &mctx->memlock);
mem_putstats(mctx, mem, mpctx->size);
MCTXUNLOCK(mctx, &mctx->lock);
MCTXUNLOCK(mctx, &mctx->memlock);
}
if (mpctx->lock != NULL)
UNLOCK(mpctx->lock);
@ -1975,14 +1975,14 @@ isc_mem_printallactive(FILE *file) {
RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
LOCK(&lock);
LOCK(&contextlock);
for (ctx = ISC_LIST_HEAD(contexts);
ctx != NULL;
ctx = ISC_LIST_NEXT(ctx, link)) {
fprintf(file, "context: %p\n", ctx);
print_active(ctx, file);
}
UNLOCK(&lock);
UNLOCK(&contextlock);
#endif
}
@ -1991,7 +1991,7 @@ isc_mem_checkdestroyed(FILE *file) {
RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
LOCK(&lock);
LOCK(&contextlock);
if (!ISC_LIST_EMPTY(contexts)) {
#if ISC_MEM_TRACKLINES
isc_mem_t *ctx;
@ -2006,7 +2006,7 @@ isc_mem_checkdestroyed(FILE *file) {
#endif
INSIST(0);
}
UNLOCK(&lock);
UNLOCK(&contextlock);
}
unsigned int
@ -2014,9 +2014,9 @@ isc_mem_references(isc_mem_t *ctx) {
unsigned int references;
REQUIRE(VALID_CONTEXT(ctx));
MCTXLOCK(ctx, &ctx->lock);
MCTXLOCK(ctx, &ctx->memlock);
references = ctx->references;
MCTXUNLOCK(ctx, &ctx->lock);
MCTXUNLOCK(ctx, &ctx->memlock);
return (references);
}
@ -2047,7 +2047,7 @@ renderctx(isc_mem_t *ctx, summarystat_t *summary, xmlTextWriterPtr writer) {
}
REQUIRE(VALID_CONTEXT(ctx));
MCTXLOCK(ctx, &ctx->lock);
MCTXLOCK(ctx, &ctx->memlock);
summary->contextsize += sizeof(*ctx) +
(ctx->max_size + 1) * sizeof(struct stats) +
@ -2110,7 +2110,7 @@ renderctx(isc_mem_t *ctx, summarystat_t *summary, xmlTextWriterPtr writer) {
(isc_uint64_t)ctx->lo_water);
xmlTextWriterEndElement(writer); /* lowater */
MCTXUNLOCK(ctx, &ctx->lock);
MCTXUNLOCK(ctx, &ctx->memlock);
xmlTextWriterEndElement(writer); /* context */
}
@ -2127,14 +2127,14 @@ isc_mem_renderxml(xmlTextWriterPtr writer) {
RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
LOCK(&lock);
LOCK(&contextlock);
lost = totallost;
for (ctx = ISC_LIST_HEAD(contexts);
ctx != NULL;
ctx = ISC_LIST_NEXT(ctx, link)) {
renderctx(ctx, &summary, writer);
}
UNLOCK(&lock);
UNLOCK(&contextlock);
xmlTextWriterEndElement(writer); /* contexts */