int has_tls;
knot_mm_t pool;
};
+typedef void knot_db_t;
+struct kr_cache {
+ knot_db_t *db;
+ const struct kr_cdb_api *api;
+ struct {
+ uint32_t hit;
+ uint32_t miss;
+ uint32_t insert;
+ uint32_t delete;
+ } stats;
+ uint32_t ttl_min;
+ uint32_t ttl_max;
+};
struct knot_rrset {
knot_dname_t *_owner;
uint16_t type;
map_t trust_anchors;
map_t negative_anchors;
struct kr_zonecut root_hints;
+ struct kr_cache cache;
char _stub[];
};
struct query_flag {static const int NO_MINIMIZE = 1; static const int NO_THROTTLE = 2; static const int NO_IPV6 = 4; static const int NO_IPV4 = 8; static const int TCP = 16; static const int RESOLVED = 32; static const int AWAIT_IPV4 = 64; static const int AWAIT_IPV6 = 128; static const int AWAIT_CUT = 256; static const int SAFEMODE = 512; static const int CACHED = 1024; static const int NO_CACHE = 2048; static const int EXPIRING = 4096; static const int ALLOW_LOCAL = 8192; static const int DNSSEC_WANT = 16384; static const int DNSSEC_BOGUS = 32768; static const int DNSSEC_INSECURE = 65536; static const int STUB = 131072; static const int ALWAYS_CUT = 262144; static const int DNSSEC_WEXPAND = 524288; static const int PERMISSIVE = 1048576; static const int STRICT = 2097152; static const int BADCOOKIE_AGAIN = 4194304; static const int CNAME = 8388608; static const int REORDER_RR = 16777216; static const int TRACE = 33554432; static const int NO_0X20 = 67108864; static const int DNSSEC_NODS = 134217728; static const int DNSSEC_OPTOUT = 268435456; static const int NONAUTH = 536870912;};
knot_rdata_t *knot_rdataset_at(const knot_rdataset_t *, size_t);
int knot_rrset_add_rdata(knot_rrset_t *, const uint8_t *, const uint16_t, const uint32_t, knot_mm_t *);
void knot_rrset_init_empty(knot_rrset_t *);
+knot_rrset_t *knot_rrset_new(const knot_dname_t *, uint16_t, uint16_t, knot_mm_t *);
+void knot_rrset_clear(knot_rrset_t *, knot_mm_t *);
uint32_t knot_rrset_ttl(const knot_rrset_t *);
int knot_rrset_txt_dump(const knot_rrset_t *, char **, size_t *, const knot_dump_style_t *);
int knot_rrset_txt_dump_data(const knot_rrset_t *, const size_t, char *, const size_t, const knot_dump_style_t *);
int kr_family_len(int);
struct sockaddr *kr_straddr_socket(const char *, int);
int kr_rrarray_add(rr_array_t *, const knot_rrset_t *, knot_mm_t *);
+void kr_rrset_print(const knot_rrset_t *, const char *);
knot_rrset_t *kr_ta_get(map_t *, const knot_dname_t *);
int kr_ta_add(map_t *, const knot_dname_t *, uint16_t, uint32_t, const uint8_t *, uint16_t);
int kr_ta_del(map_t *, const knot_dname_t *);
_Bool kr_dnssec_key_revoked(const uint8_t *);
int kr_dnssec_key_tag(uint16_t, const uint8_t *, size_t);
int kr_dnssec_key_match(const uint8_t *, size_t, const uint8_t *, size_t);
+int kr_cache_peek_rr(struct kr_cache *, knot_rrset_t *, uint8_t *, uint8_t *, uint32_t *);
]]
kr_qarray_t
struct kr_rplan
struct kr_request
+ knot_db_t
+ struct kr_cache
EOF
genResType() {
genResType "struct kr_query" | sed '/struct kr_layer_pickle/,$ d'
printf "\t/* ^hidden stub^ */\n\tchar _stub[];\n};\n"
-genResType "struct kr_context" | sed '/struct kr_cache/,$ d'
+genResType "struct kr_context" | sed '/cache_rtt/,$ d'
printf "\tchar _stub[];\n};\n"
# Getting struct query_flag is a bit complex.
knot_rdataset_at
knot_rrset_add_rdata
knot_rrset_init_empty
+ knot_rrset_new
+ knot_rrset_clear
knot_rrset_ttl
knot_rrset_txt_dump
knot_rrset_txt_dump_data
kr_family_len
kr_straddr_socket
kr_rrarray_add
+ kr_rrset_print
# Trust anchors
kr_ta_get
kr_ta_add
kr_dnssec_key_revoked
kr_dnssec_key_tag
kr_dnssec_key_match
+# Cache
+ kr_cache_peek_rr
EOF
printf "]]\n"
-- Metatype for RR set. Beware, the indexing is 0-based (rdata, get, tostring).
local rrset_buflen = (64 + 1) * 1024
local rrset_buf = ffi.new('char[?]', rrset_buflen)
+
local knot_rrset_t = ffi.typeof('knot_rrset_t')
ffi.metatype( knot_rrset_t, {
__index = {
return result
end
end,
+
+ tolist = function(rr)
+ if not rr then return {} end
+ assert(ffi.istype(knot_rrset_t, rr))
+ local res = {}
+ local i = 0
+ while i < #rr do
+ table.insert(res, rr:get(i))
+ i = i + 1
+ end
+ return res
+ end,
},
+ __len = function(rr) return rr.rrs.rr_count end,
})
-- Metatype for packet
return ret
end
+
-- Module API
kres = {
-- Constants
context = function () return ffi.cast('struct kr_context *', __engine) end,
}
+local function rrset_free(rrset)
+ if rrset then
+ --C.knot_rrset_clear(rrset, nil) FIXME: memory leak?
+ C.free(rrset)
+ end
+end
+
+-- Global!
+-- Get a cached RRset as knot_rrset_t, ignoring current time, its rank, etc.
+cache.peek_rr = function(name, rrtype)
+ local rrset = ffi.gc(
+ C.knot_rrset_new(kres.str2dname(name), rrtype or kres.type.A, kres.class.IN, nil),
+ rrset_free)
+ local err = C.kr_cache_peek_rr(kres.context().cache, rrset, nil, nil, nil)
+ if err == 0 then return rrset else return nil end
+end
+
return kres
return kr_error(ENOENT);
}
- /* Check entry lifetime */
+ /* Check entry lifetime, optionally. */
*entry = found;
- int ret = check_lifetime(found, timestamp);
+ int ret = timestamp ? check_lifetime(found, timestamp) : 0;
if (ret == 0) {
cache->stats.hit += 1;
} else {
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) {
+ if (!cache_isvalid(cache) || !rr) {
return kr_error(EINVAL);
}
* @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)
+ * @param timestamp current time (will be replaced with drift if successful).
+ * Pass NULL to avoid checking the TTL.
* @return 0 or an errcode
*/
KR_EXPORT