]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
kres: add insert and sync interfaces to the cache metatype
authorMarek Vavruša <mvavrusa@cloudflare.com>
Mon, 12 Mar 2018 04:13:05 +0000 (21:13 -0700)
committerVladimír Čunát <vladimir.cunat@nic.cz>
Mon, 23 Apr 2018 12:34:40 +0000 (14:34 +0200)
This adds metatype wrappers for kr_cache_insert_rr and kr_cache_sync
for the cache metatype, and tests.

daemon/lua/kres-gen.lua
daemon/lua/kres-gen.sh
daemon/lua/kres.lua
tests/config/basic.test.lua
tests/config/cache.test.lua

index 268bac1da840f56dcca07214e07d33a691a9040c..ebdcdf1cae6437369f99f1da4d417fd28e399035 100644 (file)
@@ -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 *);
 ]]
index 7a33ff4ddd7b80f5d818c2bd252ce52418af826b..4061f75a17a6c13d8d5ee2a9b3bfc344e5f2239f 100755 (executable)
@@ -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"
index 1af5370d0f3fcdea2e17aaf66d8183d068679ed2..5cdccaab6514b11fc6529dcbe6442aabc4d47c5f 100644 (file)
@@ -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)
index 7bb847533a1f073d59a0f372baac5dfd271989bf..5e771fbd08cabd1d3139158db5b0d8a51cebe82c 100644 (file)
@@ -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
index 6cbe8ad329c3a4fb9b18c52f477f6e08421474db..39548a87d3e1a513c715c4910d52088addd70765 100644 (file)
@@ -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 {