* existing rdataset of the same type. If not merging and the
* #DNS_DBADD_FORCE option is set, then the data will update the database
* without regard to trust levels. If not forcing the data, then the
- * rdataset will only be added if its trust level is >= the trust level of
- * any existing rdataset. Forcing is only meaningful for cache databases.
+ * rdataset will only be added if its trust level is >= the trust level
+ * of any existing active (not expired) rdataset of the same type.
+ * Forcing is only meaningful for cache databases.
* If #DNS_DBADD_EXACT is set then there must be no rdata in common between
* the old and new rdata sets. If #DNS_DBADD_EXACTTTL is set then both
* the old and new rdata sets must have the same ttl.
* changed, compare the old and new rdatasets; if they are equal,
* return #ISC_R_SUCCESS instead of #DNS_R_UNCHANGED.
*
+ * \li If the #DNS_DBADD_PREFETCH option is set, the rdataset is being
+ * added as the result of a prefetch. In a cache database this allows
+ * equal but less trusted data to refresh the TTL of existing address
+ * (A/AAAA) and DS records, which would otherwise be kept unchanged.
+ *
* \li The 'now' field is ignored if 'db' is a zone database. If 'db' is
* a cache database, then the added rdataset will expire no later than
* now + rdataset->ttl.
*
* Notes:
*
- * \li If 'type' is dns_rdatatype_any, then no rdatasets will exist in
- * 'version' (provided that the dns_db_deleterdataset() isn't followed
- * by one or more dns_db_addrdataset() calls).
+ * \li In a cache database, a negative cache entry is stored under the
+ * type it covers. Passing 'type' == dns_rdatatype_none with 'covers'
+ * set (the shape in which rdataset iterators return negative entries)
+ * deletes the cache entry for the covered type, whether it is positive
+ * or negative.
*
* Requires:
*
* read-write version, or the database has cache semantics
* and version is NULL.
*
- * \li 'type' is not a meta-RR type, except for dns_rdatatype_any, which is
- * allowed.
- *
- * \li If 'covers' != 0, 'type' must be SIG.
+ * \li If 'covers' != 0, 'type' must be RRSIG or dns_rdatatype_none.
*
* Returns:
*
* \li #ISC_R_SUCCESS
- * \li #DNS_R_UNCHANGED No rdatasets of 'type' existed
- * before the operation was attempted.
+ * \li #DNS_R_UNCHANGED No rdatasets of 'type' existed before
+ * the operation was attempted.
+ * \li #ISC_R_NOTIMPLEMENTED 'type' is dns_rdatatype_any; or the
+ * database has zone semantics and 'type'
+ * is RRSIG with 'covers' == 0.
*
* \li Other results are possible, depending upon the database
* implementation used.
static size_t
header_delete(qpcnode_t *node, dns_slabheader_t *header);
-static size_t
-rdataset_size(dns_slabheader_t *header) {
- if (EXISTS(header)) {
- return dns_rdataslab_size(header);
- }
-
- return sizeof(*header);
-}
-
static void
flush_node(qpcache_t *qpdb, qpcnode_t *node, isc_rwlocktype_t *nlocktypep,
isc_rwlocktype_t *tlocktypep, dns_expire_t reason DNS__DB_FLARG);
size_t purgesize =
2 * (sizeof(qpcnode_t) +
dns_name_size(&HEADERNODE(newheader)->name)) +
- rdataset_size(newheader) + QP_SAFETY_MARGIN;
+ dns_rdataslab_size(newheader) + QP_SAFETY_MARGIN;
expire_lru_headers(qpdb, newheader, idx, purgesize, nlocktypep,
tlocktypep DNS__DB_FLARG_PASS);
.attributes = hattributes,
};
- if (!EXISTS(header) || !STATCOUNT(header)) {
+ if (!STATCOUNT(header)) {
return;
}
return 0;
}
- size_t expired = rdataset_size(header);
+ size_t expired = dns_rdataslab_size(header);
qpcache_t *qpdb = node->qpdb;
cds_list_del_init(&header->headers_link);
rdataset->methods = &dns_rdataslab_rdatasetmethods;
rdataset->rdclass = qpdb->common.rdclass;
if (NEGATIVE(header)) {
+ /*
+ * Convert the internal represetation of a negative record
+ * to the rdataset representation (type=0, covers=type).
+ */
rdataset->type = dns_rdatatype_none;
rdataset->covers = DNS_TYPEPAIR_TYPE(header->typepair);
INSIST(DNS_TYPEPAIR_COVERS(header->typepair) ==
static bool
invalid_header(dns_slabheader_t *header, qpc_search_t *search) {
- return header == NULL || check_stale_header(header, search) ||
- !EXISTS(header);
+ return header == NULL || check_stale_header(header, search);
}
/*
return false;
}
- REQUIRE(EXISTS(sigheader));
if (sigheader->typepair == typepair) {
*foundp = sigheader;
*foundsigp = NULL;
return false;
}
- REQUIRE(EXISTS(header));
REQUIRE(!NEGATIVE(header) || sigheader == NULL);
if (header->typepair == typepair) {
static bool
iterator_active(qpcache_t *qpdb, qpc_rditer_t *iterator,
dns_slabheader_t *header) {
- if (!EXISTS(header)) {
- return false;
- }
-
/*
* If this header is still active then return it.
*/
NODE_RDLOCK(nlock, &nlocktype);
DNS_SLABHEADER_FOREACH(header, &qpnode->headers) {
- if (!EXISTS(header)) {
- continue;
- }
if (EXPIREDOK(iterator) ||
iterator_active(qpdb, iterator, header))
{
* separate pass first: evicting as we go and bailing out later would
* destroy lower-trust siblings before we found the secure header.
*/
- if (EXISTS(newheader) && NEGATIVE(newheader) &&
- rdtype == dns_rdatatype_any && trust < dns_trust_secure)
+ if (NEGATIVE(newheader) && rdtype == dns_rdatatype_any &&
+ trust < dns_trust_secure)
{
DNS_SLABHEADER_FOREACH(header, &qpnode->headers) {
if (ACTIVE(header, now) &&
}
DNS_SLABHEADER_FOREACH(header, &qpnode->headers) {
- if (EXISTS(newheader) && NEGATIVE(newheader)) {
+ if (NEGATIVE(newheader)) {
if (rdtype == dns_rdatatype_any) {
/*
* We're adding a negative cache entry which
}
}
}
- if (EXISTS(header) && EXISTS(newheader) && NEGATIVE(header) &&
- !NEGATIVE(newheader) && ACTIVE(header, now))
+ if (NEGATIVE(header) && !NEGATIVE(newheader) &&
+ ACTIVE(header, now))
{
/*
* There's an existing NXDOMAIN or negative
}
if (oldheader != NULL) {
- /*
- * Deleting an already non-existent rdataset has no effect.
- */
- if (!EXISTS(oldheader) && !EXISTS(newheader)) {
- return DNS_R_UNCHANGED;
- }
-
/*
* Trying to add an rdataset with lower trust to a cache
* DB has no effect, provided that the cache data isn't
* policy is here.
*/
dns_trust_t oldtrust = header_trust(oldheader);
- if (trust < oldtrust &&
- (ACTIVE(oldheader, now) || !EXISTS(oldheader)))
- {
+ if (trust < oldtrust && ACTIVE(oldheader, now)) {
qpcache_hit(qpdb, oldheader);
bindrdataset(qpdb, qpnode, oldheader, now, nlocktype,
tlocktype,
*/
if (ACTIVE(oldheader, now) &&
oldheader->typepair == DNS_TYPEPAIR(dns_rdatatype_ns) &&
- EXISTS(oldheader) && EXISTS(newheader) &&
newheader->trust < oldtrust &&
oldheader->expire < newheader->expire &&
dns_rdataslab_equalx(
*/
if (ACTIVE(oldheader, now) &&
oldheader->typepair == DNS_TYPEPAIR(dns_rdatatype_ns) &&
- EXISTS(oldheader) && EXISTS(newheader) &&
newheader->trust > oldtrust)
{
if (newheader->expire > oldheader->expire) {
oldheader->typepair == DNS_TYPEPAIR(dns_rdatatype_ds) ||
oldheader->typepair ==
DNS_SIGTYPEPAIR(dns_rdatatype_ds)) &&
- EXISTS(oldheader) && EXISTS(newheader) &&
newheader->trust < oldtrust &&
oldheader->expire < newheader->expire &&
dns_rdataslab_equal(oldheader, newheader))
INSIST(oldheader->related == related);
header_delete(qpnode, oldheader);
-
- } else if (!EXISTS(newheader)) {
- /*
- * The type already doesn't exist; no point trying
- * to delete it.
- */
- return DNS_R_UNCHANGED;
}
/*
*
* Delete the related rrsig in the cache.
*/
- if (EXISTS(newheader) && NEGATIVE(newheader) &&
- !dns_rdatatype_issig(rdtype) && related != NULL)
+ if (NEGATIVE(newheader) && !dns_rdatatype_issig(rdtype) &&
+ related != NULL)
{
header_delete(qpnode, related);
}
dns_rdatatype_t covers DNS__DB_FLARG) {
qpcache_t *qpdb = (qpcache_t *)db;
qpcnode_t *qpnode = (qpcnode_t *)node;
- isc_result_t result;
- dns_slabheader_t *newheader = NULL;
+ isc_result_t result = DNS_R_UNCHANGED;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
isc_rwlock_t *nlock = NULL;
- uint16_t attributes = DNS_SLABHEADERATTR_NONEXISTENT;
+ dns_typepair_t typepair;
REQUIRE(VALID_QPDB(qpdb));
REQUIRE(version == NULL);
return ISC_R_NOTIMPLEMENTED;
}
- /* Convert the negative type into positive type. */
+ /*
+ * Convert the rdataset representation of a negative record
+ * (type=0, covers=type) to the internal representation (the
+ * other way around).
+ */
if (type == dns_rdatatype_none && covers != dns_rdatatype_none) {
type = covers;
covers = dns_rdatatype_none;
- attributes |= DNS_SLABHEADERATTR_NEGATIVE;
}
- newheader = dns_slabheader_new(db->mctx, node);
- newheader->typepair = DNS_TYPEPAIR_VALUE(type, covers);
- setttl(newheader, 0);
- atomic_init(&newheader->attributes, attributes);
+ typepair = DNS_TYPEPAIR_VALUE(type, covers);
nlock = &qpdb->buckets[qpnode->locknum].lock;
NODE_WRLOCK(nlock, &nlocktype);
- result = add(qpdb, qpnode, newheader, DNS_DBADD_FORCE, NULL, 0,
- nlocktype, isc_rwlocktype_none DNS__DB_FLARG_PASS);
- if (result != ISC_R_SUCCESS) {
- dns_slabheader_detach(&newheader);
+ DNS_SLABHEADER_FOREACH(header, &qpnode->headers) {
+ if (header->typepair == typepair) {
+ header_delete(qpnode, header);
+ result = ISC_R_SUCCESS;
+ break;
+ }
}
NODE_UNLOCK(nlock, &nlocktype);