From 98f947115a645290fdeb7c25a35786a7627ea4ad Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marek=20Vavrus=CC=8Ca?= Date: Sun, 11 Mar 2018 21:13:05 -0700 Subject: [PATCH] kres: add insert and sync interfaces to the cache metatype This adds metatype wrappers for kr_cache_insert_rr and kr_cache_sync for the cache metatype, and tests. --- daemon/lua/kres-gen.lua | 3 ++ daemon/lua/kres-gen.sh | 4 +++ daemon/lua/kres.lua | 55 ++++++++++++++++++++++++++++++++++++- tests/config/basic.test.lua | 10 ++++++- tests/config/cache.test.lua | 7 +++++ 5 files changed, 77 insertions(+), 2 deletions(-) diff --git a/daemon/lua/kres-gen.lua b/daemon/lua/kres-gen.lua index 268bac1da..ebdcdf1ca 100644 --- a/daemon/lua/kres-gen.lua +++ b/daemon/lua/kres-gen.lua @@ -251,6 +251,7 @@ void knot_rrset_init_empty(knot_rrset_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 *); +uint16_t knot_rrsig_type_covered(const knot_rdataset_t *, size_t); uint32_t knot_rrsig_sig_expiration(const knot_rdataset_t *, size_t); uint32_t knot_rrsig_sig_inception(const knot_rdataset_t *, size_t); const knot_dname_t *knot_pkt_qname(const knot_pkt_t *); @@ -299,4 +300,6 @@ _Bool kr_dnssec_key_ksk(const uint8_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_insert_rr(struct kr_cache *, const knot_rrset_t *, const knot_rrset_t *, uint8_t, uint32_t); +int kr_cache_sync(struct kr_cache *); ]] diff --git a/daemon/lua/kres-gen.sh b/daemon/lua/kres-gen.sh index 7a33ff4dd..4061f75a1 100755 --- a/daemon/lua/kres-gen.sh +++ b/daemon/lua/kres-gen.sh @@ -110,6 +110,7 @@ printf "\tchar _stub[];\n};\n" knot_rrset_ttl knot_rrset_txt_dump knot_rrset_txt_dump_data + knot_rrsig_type_covered knot_rrsig_sig_expiration knot_rrsig_sig_inception # Packet @@ -169,6 +170,9 @@ EOF kr_dnssec_key_revoked kr_dnssec_key_tag kr_dnssec_key_match +# Cache + kr_cache_insert_rr + kr_cache_sync EOF printf "]]\n" diff --git a/daemon/lua/kres.lua b/daemon/lua/kres.lua index 1af5370d0..5cdccaab6 100644 --- a/daemon/lua/kres.lua +++ b/daemon/lua/kres.lua @@ -51,6 +51,7 @@ struct sockaddr { void * malloc(size_t size); void free(void *ptr); int inet_pton(int af, const char *src, void *dst); +int gettimeofday(struct timeval *tv, struct timezone *tz); ]] require('kres-gen') @@ -226,6 +227,9 @@ setmetatable(const_type_str, { end }) +-- Metatype for timeval +local timeval_t = ffi.typeof('struct timeval') + -- Metatype for sockaddr local addr_buf = ffi.new('char[16]') local sockaddr_t = ffi.typeof('struct sockaddr') @@ -258,6 +262,7 @@ end -- 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_pt = ffi.typeof('knot_rrset_t *') local knot_rrset_t = ffi.typeof('knot_rrset_t') ffi.metatype( knot_rrset_t, { -- Create a new empty RR set object with an allocated owner and a destructor @@ -275,6 +280,13 @@ ffi.metatype( knot_rrset_t, { __index = { owner = function(rr) return dname2wire(rr._owner) end, ttl = function(rr) return tonumber(knot.knot_rrset_ttl(rr)) end, + class = function(rr, val) + assert(ffi.istype(knot_rrset_t, rr)) + if val then + rr.rclass = val + end + return tonumber(rr.rclass) + end, rdata = function(rr, i) local rdata = knot.knot_rdataset_at(rr.rrs, i) return ffi.string(knot.knot_rdata_data(rdata), knot.knot_rdata_rdlen(rdata)) @@ -322,6 +334,19 @@ ffi.metatype( knot_rrset_t, { if ret ~= 0 then return nil, knot_strerror(ret) end return true end, + -- Return type covered by this RRSIG + type_covered = function(rr, pos) + assert(ffi.istype(knot_rrset_t, rr)) + if rr.type ~= const_type.RRSIG then return end + return tonumber(knot.knot_rrsig_type_covered(rr.rrs, pos or 0)) + end, + -- Check whether a RRSIG is covering current RR set + is_covered_by = function(rr, rrsig) + assert(ffi.istype(knot_rrset_t, rr)) + assert(ffi.istype(knot_rrset_t, rrsig)) + assert(rrsig.type == const_type.RRSIG) + return (rr.type == rrsig:type_covered() and rr:owner() == rrsig:owner()) + end, }, }) @@ -462,7 +487,7 @@ ffi.metatype( knot_pkt_t, { local section = knot.knot_pkt_section(pkt, section_id) for i = 1, section.count do local rrset = knot.knot_pkt_rr(section, i - 1) - table.insert(records, rrset) + table.insert(records, ffi.cast(knot_rrset_pt, rrset)) end return records end, @@ -596,6 +621,34 @@ ffi.metatype(ranked_rr_array_t, { } }) +-- Cache metatype +local kr_cache_t = ffi.typeof('struct kr_cache') +ffi.metatype( kr_cache_t, { + __index = { + insert = function (self, rr, rrsig, rank, timestamp) + assert(self ~= nil) + assert(ffi.istype(knot_rrset_t, rr), 'rr must be a rrset type') + assert(not rrsig or ffi.istype(knot_rrset_t, rrsig), 'rrsig must be nil or of the rrset type') + -- Get current timestamp + if not timestamp then + local now = timeval_t() + C.gettimeofday(now, nil) + timestamp = tonumber(now.tv_sec) + end + -- Insert record into cache + local ret = C.kr_cache_insert_rr(self, rr, rrsig, tonumber(rank or 0), timestamp) + if ret ~= 0 then return nil, knot_strerror(ret) end + return true + end, + sync = function (self) + assert(self ~= nil) + local ret = C.kr_cache_sync(self) + if ret ~= 0 then return nil, knot_strerror(ret) end + return true + end, + }, +}) + -- Pretty-print a single RR (which is a table with .owner .ttl .type .rdata) -- Extension: append .comment if exists. local function rr2str(rr, style) diff --git a/tests/config/basic.test.lua b/tests/config/basic.test.lua index 7bb847533..5e771fbd0 100644 --- a/tests/config/basic.test.lua +++ b/tests/config/basic.test.lua @@ -40,13 +40,21 @@ local function test_rrset_functions() rr = kres.rrset(kres.str2dname('com.'), kres.type.A, kres.class.IN) ok(ffi.istype(kres.rrset, rr), 'created an empty RR') same(rr:owner(), '\3com\0', 'created RR has correct owner') - same(rr.rclass, kres.class.IN, 'created RR has correct class') + same(rr:class(), kres.class.IN, 'created RR has correct class') + same(rr:class(kres.class.CH), kres.class.CH, 'can set a different class') + same(rr:class(kres.class.IN), kres.class.IN, 'can restore a class') same(rr.type, kres.type.A, 'created RR has correct type') -- test adding rdata local rdata = '\1\2\3\4' ok(rr:add_rdata(rdata, #rdata, 66), 'adding RDATA works') -- test conversion to text same(rr:txt_dump(), 'com. 66 A 1.2.3.4\n', 'RR to text works') + -- create a dummy rrsig + local rrsig = kres.rrset(kres.str2dname('com.'), kres.type.RRSIG, kres.class.IN) + rrsig:add_rdata('\0\1', 2, 0) + -- check rrsig matching + same(rr.type, rrsig:type_covered(), 'rrsig type covered matches covered RR type') + ok(rr:is_covered_by(rrsig), 'rrsig is covering a record') end -- test dns library packet interface diff --git a/tests/config/cache.test.lua b/tests/config/cache.test.lua index 6cbe8ad32..39548a87d 100644 --- a/tests/config/cache.test.lua +++ b/tests/config/cache.test.lua @@ -37,6 +37,13 @@ local function test_context_cache() is(type(c), 'cdata', 'context has a cache object') local s = c.stats same({s.hit, s.miss, s.insert, s.delete}, {0, 0, 0, 0}, 'context cache stats works') + -- insert a record into cache + local rdata = '\1\2\3\4' + local rr = kres.rrset('\3com\0', kres.type.A, kres.class.IN) + rr:add_rdata(rdata, #rdata, 66) + ok(c:insert(rr, nil, 0, 0), 'cache insertion works') + ok(c:sync(), 'cache sync works') + same(s.insert, 1, 'cache insertion increments counters') end return { -- 2.47.2