return kr_ok();
}
-/**
- * @internal Composed key as { u8 tag, u8[1-255] name, u16 type }
- * The name is lowercased and label order is reverted for easy prefix search.
- * e.g. '\x03nic\x02cz\x00' is saved as '\0x00cz\x00nic\x00'
- */
-static size_t cache_key(uint8_t *buf, uint8_t tag, const knot_dname_t *name, uint16_t rrtype)
-{
- /* Convert to lookup format */
- int ret = kr_dname_lf(buf, name, NULL);
- if (ret != 0) {
- return 0;
- }
- /* Write tag + type */
- uint8_t name_len = buf[0];
- buf[0] = tag;
- memcpy(buf + sizeof(uint8_t) + name_len, &rrtype, sizeof(uint16_t));
- return name_len + KEY_HSIZE;
-}
-
-static struct kr_cache_entry *lookup(struct kr_cache *cache, uint8_t tag, const knot_dname_t *name, uint16_t type)
-{
- if (!name || !cache) {
- return NULL;
- }
-
- uint8_t keybuf[KEY_SIZE];
- size_t key_len = cache_key(keybuf, tag, name, type);
-
- /* Look up and return value */
- knot_db_val_t key = { keybuf, key_len };
- knot_db_val_t val = { NULL, 0 };
- int ret = cache_op(cache, read, &key, &val, 1);
- if (ret != 0) {
- return NULL;
- }
-
- return (struct kr_cache_entry *)val.data;
-}
-
-static int check_lifetime(struct kr_cache_entry *found, uint32_t *timestamp)
-{
- /* No time constraint */
- if (!timestamp) {
- return kr_ok();
- } else if (*timestamp <= found->timestamp) {
- /* John Connor record cached in the future. */
- *timestamp = 0;
- return kr_ok();
- } else {
- /* Check if the record is still valid. */
- uint32_t drift = *timestamp - found->timestamp;
- if (drift <= found->ttl) {
- *timestamp = drift;
- return kr_ok();
- }
- }
- return kr_error(ESTALE);
-}
-
-int kr_cache_peek(struct kr_cache *cache, uint8_t tag, const knot_dname_t *name, uint16_t type,
- struct kr_cache_entry **entry, uint32_t *timestamp)
-{
- if (!cache_isvalid(cache) || !name || !entry) {
- return kr_error(EINVAL);
- }
-
- struct kr_cache_entry *found = lookup(cache, tag, name, type);
- if (!found) {
- cache->stats.miss += 1;
- return kr_error(ENOENT);
- }
-
- /* Check entry lifetime */
- *entry = found;
- int ret = check_lifetime(found, timestamp);
- if (ret == 0) {
- cache->stats.hit += 1;
- } else {
- cache->stats.miss += 1;
- }
- return ret;
-}
-
-static void entry_write(struct kr_cache_entry *dst, struct kr_cache_entry *header, knot_db_val_t data)
-{
- memcpy(dst, header, sizeof(*header));
- if (data.data)
- memcpy(dst->data, data.data, data.len);
-}
-
-int kr_cache_insert(struct kr_cache *cache, uint8_t tag, const knot_dname_t *name, uint16_t type,
- struct kr_cache_entry *header, knot_db_val_t data)
-{
- if (!cache_isvalid(cache) || !name || !header) {
- return kr_error(EINVAL);
- }
-
- /* Enforce cache maximum TTL limits without TTL decay.
- * Minimum TTL is enforced in specific caches as it requires
- * rewriting of the records to avoid negative TTL when decayed. */
- header->ttl = MIN(header->ttl, cache->ttl_max);
-
- /* Prepare key/value for insertion. */
- uint8_t keybuf[KEY_SIZE];
- size_t key_len = cache_key(keybuf, tag, name, type);
- if (key_len == 0) {
- return kr_error(EILSEQ);
- }
- assert(data.len != 0);
- knot_db_val_t key = { keybuf, key_len };
- knot_db_val_t entry = { NULL, sizeof(*header) + data.len };
-
- /* LMDB can do late write and avoid copy */
- int ret = 0;
- cache->stats.insert += 1;
- if (cache->api == kr_cdb_lmdb()) {
- ret = cache_op(cache, write, &key, &entry, 1);
- if (ret != 0) {
- return ret;
- }
- entry_write(entry.data, header, data);
- } else {
- /* Other backends must prepare contiguous data first */
- auto_free char *buffer = malloc(entry.len);
- entry.data = buffer;
- entry_write(entry.data, header, data);
- ret = cache_op(cache, write, &key, &entry, 1);
- }
-
- return ret;
-}
-
-int kr_cache_remove(struct kr_cache *cache, uint8_t tag, const knot_dname_t *name, uint16_t type)
-{
- if (!cache_isvalid(cache) || !name ) {
- return kr_error(EINVAL);
- }
-
- uint8_t keybuf[KEY_SIZE];
- size_t key_len = cache_key(keybuf, tag, name, type);
- if (key_len == 0) {
- return kr_error(EILSEQ);
- }
- knot_db_val_t key = { keybuf, key_len };
- cache->stats.delete += 1;
- return cache_op(cache, remove, &key, 1);
-}
-
int kr_cache_clear(struct kr_cache *cache)
{
if (!cache_isvalid(cache)) {
return ret;
}
-int kr_cache_match(struct kr_cache *cache, uint8_t tag, const knot_dname_t *name, knot_db_val_t *val, int maxcount)
-{
- if (!cache_isvalid(cache) || !name ) {
- return kr_error(EINVAL);
- }
- if (!cache->api->match) {
- return kr_error(ENOSYS);
- }
-
- uint8_t keybuf[KEY_SIZE];
- size_t key_len = cache_key(keybuf, tag, name, 0);
- if (key_len == 0) {
- return kr_error(EILSEQ);
- }
-
- /* Trim type from the search key */
- knot_db_val_t key = { keybuf, key_len - 2 };
- return cache_op(cache, match, &key, val, maxcount);
-}
-
-int kr_cache_peek_rr(struct kr_cache *cache, knot_rrset_t *rr, uint8_t *rank, uint8_t *flags, uint32_t *timestamp)
-{
- if (!cache_isvalid(cache) || !rr || !timestamp) {
- return kr_error(EINVAL);
- }
-
- /* Check if the RRSet is in the cache. */
- struct kr_cache_entry *entry = NULL;
- int ret = kr_cache_peek(cache, KR_CACHE_RR, rr->owner, rr->type, &entry, timestamp);
- if (ret != 0) {
- return ret;
- }
- if (rank) {
- *rank = entry->rank;
- }
- if (flags) {
- *flags = entry->flags;
- }
- rr->rrs.rr_count = entry->count;
- rr->rrs.data = entry->data;
- return kr_ok();
-}
-
-int kr_cache_peek_rank(struct kr_cache *cache, uint8_t tag, const knot_dname_t *name, uint16_t type, uint32_t timestamp)
-{
- if (!cache_isvalid(cache) || !name) {
- return kr_error(EINVAL);
- }
- struct kr_cache_entry *found = lookup(cache, tag, name, type);
- if (!found) {
- return kr_error(ENOENT);
- }
- if (check_lifetime(found, ×tamp) != 0) {
- return kr_error(ESTALE);
- }
- return found->rank;
-}
-
-int kr_cache_materialize_x(knot_rrset_t *dst, const knot_rrset_t *src, uint32_t drift,
- uint reorder, knot_mm_t *mm)
-{
- if (!dst || !src || dst == src) {
- return kr_error(EINVAL);
- }
-
- /* Make RRSet copy */
- knot_rrset_init(dst, NULL, src->type, src->rclass);
- dst->owner = knot_dname_copy(src->owner, mm);
- if (!dst->owner) {
- return kr_error(ENOMEM);
- }
-
- /* Find valid records */
- knot_rdata_t **valid = malloc(sizeof(knot_rdata_t *) * src->rrs.rr_count);
- uint16_t valid_count = 0;
- knot_rdata_t *rd = src->rrs.data;
- for (uint16_t i = 0; i < src->rrs.rr_count; ++i) {
- if (knot_rdata_ttl(rd) >= drift) {
- valid[valid_count++] = rd;
- }
- rd = kr_rdataset_next(rd);
- }
-
- if (reorder && valid_count > 1) {
- /* Reorder the valid part; it's a reversed rotation,
- * done by two array reversals. */
- uint16_t shift = reorder % valid_count;
- for (uint16_t i = 0; i < shift / 2; ++i) {
- SWAP(valid[i], valid[shift - 1 - i]);
- }
- for (uint16_t i = 0; i < (valid_count - shift) / 2; ++i) {
- SWAP(valid[shift + i], valid[valid_count - 1 - i]);
- }
- }
-
- int err = knot_rdataset_gather(&dst->rrs, valid, valid_count, mm);
- free(valid);
- if (err) {
- knot_rrset_clear(dst, mm);
- return kr_error(err);
- }
-
- /* Fixup TTL by time passed */
- rd = dst->rrs.data;
- for (uint16_t i = 0; i < dst->rrs.rr_count; ++i) {
- knot_rdata_set_ttl(rd, knot_rdata_ttl(rd) - drift);
- rd = kr_rdataset_next(rd);
- }
-
- return kr_ok();
-}
-
-int kr_cache_insert_rr(struct kr_cache *cache, const knot_rrset_t *rr, uint8_t rank, uint8_t flags, uint32_t timestamp)
-{
- if (!cache_isvalid(cache) || !rr) {
- return kr_error(EINVAL);
- }
-
- /* Ignore empty records */
- if (knot_rrset_empty(rr)) {
- return kr_ok();
- }
-
- /* Prepare header to write */
- struct kr_cache_entry header = {
- .timestamp = timestamp,
- .ttl = 0,
- .rank = rank,
- .flags = flags,
- .count = rr->rrs.rr_count
- };
- knot_rdata_t *rd = rr->rrs.data;
- for (uint16_t i = 0; i < rr->rrs.rr_count; ++i) {
- if (knot_rdata_ttl(rd) > header.ttl) {
- header.ttl = knot_rdata_ttl(rd);
- }
- rd = kr_rdataset_next(rd);
- }
-
- knot_db_val_t data = { rr->rrs.data, knot_rdataset_size(&rr->rrs) };
- return kr_cache_insert(cache, KR_CACHE_RR, rr->owner, rr->type, &header, data);
-}
-
-int kr_cache_peek_rrsig(struct kr_cache *cache, knot_rrset_t *rr, uint8_t *rank, uint8_t *flags, uint32_t *timestamp)
-{
- if (!cache_isvalid(cache) || !rr || !timestamp) {
- return kr_error(EINVAL);
- }
-
- /* Check if the RRSet is in the cache. */
- struct kr_cache_entry *entry = NULL;
- int ret = kr_cache_peek(cache, KR_CACHE_SIG, rr->owner, rr->type, &entry, timestamp);
- if (ret != 0) {
- return ret;
- }
- assert(entry);
- if (rank) {
- *rank = entry->rank;
- }
- if (flags) {
- *flags = entry->flags;
- }
- rr->type = KNOT_RRTYPE_RRSIG;
- rr->rrs.rr_count = entry->count;
- rr->rrs.data = entry->data;
- return kr_ok();
-}
-
-int kr_cache_insert_rrsig(struct kr_cache *cache, const knot_rrset_t *rr, uint8_t rank, uint8_t flags, uint32_t timestamp)
-{
- if (!cache_isvalid(cache) || !rr) {
- return kr_error(EINVAL);
- }
-
- /* Ignore empty records */
- if (knot_rrset_empty(rr)) {
- return kr_ok();
- }
-
- /* Prepare header to write */
- struct kr_cache_entry header = {
- .timestamp = timestamp,
- .ttl = 0,
- .rank = rank,
- .flags = flags,
- .count = rr->rrs.rr_count
- };
- for (uint16_t i = 0; i < rr->rrs.rr_count; ++i) {
- knot_rdata_t *rd = knot_rdataset_at(&rr->rrs, i);
- if (knot_rdata_ttl(rd) > header.ttl) {
- header.ttl = knot_rdata_ttl(rd);
- }
- }
-
- uint16_t covered = knot_rrsig_type_covered(&rr->rrs, 0);
- knot_db_val_t data = { rr->rrs.data, knot_rdataset_size(&rr->rrs) };
- return kr_cache_insert(cache, KR_CACHE_SIG, rr->owner, covered, &header, data);
-}
#include "lib/dnssec/nsec.h"
#include "lib/dnssec/ta.h"
return cache->db != NULL;
}
-#if 0
-/**
- * Peek the cache for asset (name, type, tag)
- * @note The 'drift' is the time passed between the inception time and now (in seconds).
- * @param cache cache structure
- * @param tag asset tag
- * @param name asset name
- * @param type asset type
- * @param entry cache entry, will be set to valid pointer or NULL
- * @param timestamp current time (will be replaced with drift if successful)
- * @return 0 or an errcode
- */
-KR_EXPORT
-int kr_cache_peek(struct kr_cache *cache, uint8_t tag, const knot_dname_t *name, uint16_t type,
- struct kr_cache_entry **entry, uint32_t *timestamp);
-
-
-
-/**
- * Insert asset into cache, replacing any existing data.
- * @param cache cache structure
- * @param tag asset tag
- * @param name asset name
- * @param type asset type
- * @param header filled entry header (count, ttl and timestamp)
- * @param data inserted data
- * @return 0 or an errcode
- */
-KR_EXPORT
-int kr_cache_insert(struct kr_cache *cache, uint8_t tag, const knot_dname_t *name, uint16_t type,
- struct kr_cache_entry *header, knot_db_val_t data);
-
-/**
- * Remove asset from cache.
- * @param cache cache structure
- * @param tag asset tag
- * @param name asset name
- * @param type record type
- * @return 0 or an errcode
- */
-KR_EXPORT
-int kr_cache_remove(struct kr_cache *cache, uint8_t tag, const knot_dname_t *name, uint16_t type);
-
-#endif
/**
* Clear all items from the cache.
* @param cache cache structure
uint32_t new_ttl, knot_mm_t *pool);
-#if 0
-
-/**
- * Prefix scan on cached items.
- * @param cache cache structure
- * @param tag asset tag
- * @param name asset prefix key
- * @param vals array of values to store the result
- * @param valcnt maximum number of retrieved keys
- * @return number of retrieved keys or an error
- */
-KR_EXPORT
-int kr_cache_match(struct kr_cache *cache, uint8_t tag, const knot_dname_t *name, knot_db_val_t *vals, int valcnt);
-
-/**
- * Peek the cache for given key and retrieve it's rank.
- * @param cache cache structure
- * @param tag asset tag
- * @param name asset name
- * @param type record type
- * @param timestamp current time
- * @return rank (0 or positive), or an error (negative number)
- */
-KR_EXPORT
-int kr_cache_peek_rank(struct kr_cache *cache, uint8_t tag, const knot_dname_t *name, uint16_t type, uint32_t timestamp);
-
-/**
- * Peek the cache for given RRSet (name, type)
- * @note The 'drift' is the time passed between the cache time of the RRSet and now (in seconds).
- * @param cache cache structure
- * @param rr query RRSet (its rdataset may be changed depending on the result)
- * @param rank entry rank will be stored in this variable
- * @param flags entry flags
- * @param timestamp current time (will be replaced with drift if successful)
- * @return 0 or an errcode
- */
-KR_EXPORT
-int kr_cache_peek_rr(struct kr_cache *cache, knot_rrset_t *rr, uint8_t *rank, uint8_t *flags, uint32_t *timestamp);
-
-/**
- * Clone read-only RRSet and adjust TTLs.
- * @param dst destination for materialized RRSet
- * @param src read-only RRSet (its rdataset may be changed depending on the result)
- * @param drift time passed between cache time and now
- * @param reorder (pseudo)-random seed to reorder the data or zero
- * @param mm memory context
- * @return 0 or an errcode
- */
-KR_EXPORT
-int kr_cache_materialize(knot_rrset_t *dst, const knot_rrset_t *src, uint32_t drift,
- uint reorder, knot_mm_t *mm);
-
-/**
- * Insert RRSet into cache, replacing any existing data.
- * @param cache cache structure
- * @param rr inserted RRSet
- * @param rank rank of the data
- * @param flags additional flags for the data
- * @param timestamp current time
- * @return 0 or an errcode
- */
-KR_EXPORT
-int kr_cache_insert_rr(struct kr_cache *cache, const knot_rrset_t *rr, uint8_t rank, uint8_t flags, uint32_t timestamp);
-
-/**
- * Peek the cache for the given RRset signature (name, type)
- * @note The RRset type must not be RRSIG but instead it must equal the type covered field of the sought RRSIG.
- * @param cache cache structure
- * @param rr query RRSET (its rdataset and type may be changed depending on the result)
- * @param rank entry rank will be stored in this variable
- * @param flags entry additional flags
- * @param timestamp current time (will be replaced with drift if successful)
- * @return 0 or an errcode
- */
-KR_EXPORT
-int kr_cache_peek_rrsig(struct kr_cache *cache, knot_rrset_t *rr, uint8_t *rank, uint8_t *flags, uint32_t *timestamp);
-
-/**
- * Insert the selected RRSIG RRSet of the selected type covered into cache, replacing any existing data.
- * @note The RRSet must contain RRSIGS with only the specified type covered.
- * @param cache cache structure
- * @param rr inserted RRSIG RRSet
- * @param rank rank of the data
- * @param flags additional flags for the data
- * @param timestamp current time
- * @return 0 or an errcode
- */
-KR_EXPORT
-int kr_cache_insert_rrsig(struct kr_cache *cache, const knot_rrset_t *rr, uint8_t rank, uint8_t flags, uint32_t timestamp);
-
-#endif