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 *);
_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 *);
]]
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')
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')
-- 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
__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))
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,
},
})
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,
}
})
+-- 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)
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
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 {