From: Vladimír Čunát Date: Thu, 15 Dec 2016 15:42:24 +0000 (+0100) Subject: allow generating most cdefs for lua X-Git-Tag: v1.2.0-rc1~52^2~6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=06b0d3d4bf6c;p=thirdparty%2Fknot-resolver.git allow generating most cdefs for lua Motivation: maintaining these by hand in kres.lua is tricky, as just inserting or reordering the structures can do anything and isn't detected in general. For example, `rr_array_t::at` has always "missed a star". A couple libknot structure fields have apparently changed name since the old definitions were written; in most cases I renamed them in *.lua. The file daemon/lua/kres-gen.lua will be regenerated only if explicitly deleted. That requires building with debug symbols and gdb on $PATH. --- diff --git a/daemon/daemon.mk b/daemon/daemon.mk index fcdbde5ba..be21698eb 100644 --- a/daemon/daemon.mk +++ b/daemon/daemon.mk @@ -8,7 +8,7 @@ kresd_SOURCES := \ daemon/tls.c \ daemon/main.c -kresd_DIST := daemon/lua/kres.lua daemon/lua/trust_anchors.lua +kresd_DIST := daemon/lua/kres.lua daemon/lua/kres-gen.lua daemon/lua/trust_anchors.lua # Embedded resources %.inc: %.lua @@ -44,7 +44,7 @@ endif # Targets date := $(shell date +%F) -daemon: $(kresd) +daemon: $(kresd) $(kresd_DIST) daemon-install: kresd-install bindings-install ifneq ($(SED),) $(SED) -e "s/@VERSION@/$(VERSION)/" -e "s/@DATE@/$(date)/" doc/kresd.8.in > doc/kresd.8 @@ -54,4 +54,9 @@ endif daemon-clean: kresd-clean @$(RM) daemon/lua/*.inc +daemon/lua/kres-gen.lua: | $(libkres) + @echo "WARNING: regenerating $@" + daemon/lua/kres-gen.sh > $@ +.DELETE_ON_ERROR: daemon/lua/kres-gen.lua + .PHONY: daemon daemon-install daemon-clean diff --git a/daemon/lua/kres-gen.lua b/daemon/lua/kres-gen.lua new file mode 100644 index 000000000..1a59b1878 --- /dev/null +++ b/daemon/lua/kres-gen.lua @@ -0,0 +1,195 @@ +--[[ This file is generated by ./kres-gen.sh ]] ffi.cdef[[ + + +typedef struct knot_dump_style knot_dump_style_t; +extern const knot_dump_style_t KNOT_DUMP_STYLE_DEFAULT; + + +typedef struct knot_mm { + void *ctx, *alloc, *free; +} knot_mm_t; + +typedef void *(*map_alloc_f)(void *, size_t); +typedef void (*map_free_f)(void *baton, void *ptr); + +typedef enum {KNOT_ANSWER, KNOT_AUTHORITY, KNOT_ADDITIONAL} knot_section_t; +typedef struct { + uint16_t pos; + uint16_t flags; + uint16_t compress_ptr[16]; +} knot_rrinfo_t; +typedef unsigned char knot_dname_t; +typedef unsigned char knot_rdata_t; +typedef struct knot_rdataset knot_rdataset_t; +struct knot_rdataset { + uint16_t rr_count; + knot_rdata_t *data; +} +; +typedef struct knot_rrset knot_rrset_t; +typedef struct { + struct knot_pkt *pkt; + uint16_t pos; + uint16_t count; +} knot_pktsection_t; +struct knot_pkt { + uint8_t *wire; + size_t size; + size_t max_size; + size_t parsed; + uint16_t reserved; + uint16_t qname_size; + uint16_t rrset_count; + uint16_t flags; + knot_rrset_t *opt_rr; + knot_rrset_t *tsig_rr; + struct { + uint8_t *pos; + size_t len; + } tsig_wire; + knot_section_t current; + knot_pktsection_t sections[3]; + size_t rrset_allocd; + knot_rrinfo_t *rr_info; + knot_rrset_t *rr; + knot_mm_t mm; +} +; +typedef struct knot_pkt knot_pkt_t; +typedef struct { + void *root; + map_alloc_f malloc; + map_free_f free; + void *baton; +} map_t; +typedef struct { + knot_rrset_t **at; + size_t len; + size_t cap; +} rr_array_t; +struct kr_zonecut { + knot_dname_t *name; + knot_rrset_t *key; + knot_rrset_t *trust_anchor; + struct kr_zonecut *parent; + map_t nsset; + knot_mm_t *pool; +} +; +typedef struct { + struct kr_query **at; + size_t len; + size_t cap; +} kr_qarray_t; +struct kr_rplan { + kr_qarray_t pending; + kr_qarray_t resolved; + struct kr_request *request; + knot_mm_t *pool; +} +; +struct kr_request { + struct kr_context *ctx; + knot_pkt_t *answer; + struct kr_query *current_query; + struct { + const knot_rrset_t *key; + const struct sockaddr *addr; + const struct sockaddr *dst_addr; + const knot_pkt_t *packet; + const knot_rrset_t *opt; + } qsource; + struct { + unsigned int rtt; + const struct sockaddr *addr; + } upstream; + uint32_t options; + int state; + rr_array_t authority; + rr_array_t additional; + struct kr_rplan rplan; + int has_tls; + knot_mm_t pool; +} +; +struct knot_rrset { + knot_dname_t *_owner; + uint16_t type; + uint16_t rclass; + knot_rdataset_t rrs; + void *additional; +} +; +struct kr_query { + struct kr_query *parent; + knot_dname_t *sname; + uint16_t stype; + uint16_t sclass; + uint16_t id; + uint32_t flags; + uint32_t secret; + uint16_t fails; + uint16_t reorder; + struct timeval timestamp; + struct kr_zonecut zone_cut; + char _stub[]; +}; +struct kr_context { + uint32_t options; + knot_rrset_t *opt_rr; + map_t trust_anchors; + map_t negative_anchors; + struct kr_zonecut root_hints; + 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;} +; +int knot_dname_size(const knot_dname_t *); +knot_dname_t *knot_dname_from_str(uint8_t *, const char *, size_t); +char *knot_dname_to_str(char *, const knot_dname_t *, size_t); +uint16_t knot_rdata_rdlen(const knot_rdata_t *); +uint8_t *knot_rdata_data(const knot_rdata_t *); +knot_rdata_t *knot_rdataset_at(const knot_rdataset_t *, size_t); +uint32_t knot_rrset_ttl(const knot_rrset_t *); +int knot_rrset_txt_dump_data(const knot_rrset_t *, const size_t, char *, const size_t, + const knot_dump_style_t *); +int knot_rrset_txt_dump(const knot_rrset_t *, char *, const size_t, const knot_dump_style_t *); +const knot_dname_t *knot_pkt_qname(const knot_pkt_t *); +uint16_t knot_pkt_qtype(const knot_pkt_t *); +uint16_t knot_pkt_qclass(const knot_pkt_t *); +int knot_pkt_begin(knot_pkt_t *, knot_section_t); +int knot_pkt_put_question(knot_pkt_t *, const knot_dname_t *, uint16_t, uint16_t); +const knot_rrset_t *knot_pkt_rr(const knot_pktsection_t *, uint16_t); +const knot_pktsection_t *knot_pkt_section(const knot_pkt_t *, knot_section_t); +struct kr_rplan *kr_resolve_plan(struct kr_request *); +knot_mm_t *kr_resolve_pool(struct kr_request *); +struct kr_query *kr_rplan_push(struct kr_rplan *, struct kr_query *, const knot_dname_t *, uint16_t, uint16_t); +int kr_rplan_pop(struct kr_rplan *, struct kr_query *); +struct kr_query *kr_rplan_resolved(struct kr_rplan *); +int kr_nsrep_set(struct kr_query *, size_t, uint8_t *, size_t, int); +unsigned int kr_rand_uint(unsigned int); +int kr_pkt_put(knot_pkt_t *, const knot_dname_t *, uint32_t, uint16_t, uint16_t, const uint8_t *, uint16_t); +int kr_pkt_recycle(knot_pkt_t *); +const char *kr_inaddr(const struct sockaddr *); +int kr_inaddr_family(const struct sockaddr *); +int kr_inaddr_len(const struct sockaddr *); +int kr_straddr_family(const char *); +int kr_straddr_subnet(void *, const char *); +int kr_bitcmp(const char *, const char *, int); +int kr_family_len(int); +int kr_rrarray_add(rr_array_t *, const knot_rrset_t *, knot_mm_t *); +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 *); +void kr_ta_clear(map_t *); +_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); +]] diff --git a/daemon/lua/kres-gen.sh b/daemon/lua/kres-gen.sh new file mode 100755 index 000000000..cfb847f63 --- /dev/null +++ b/daemon/lua/kres-gen.sh @@ -0,0 +1,127 @@ +#!/bin/sh -e + +echo "--[[ This file is generated by ./kres-gen.sh ]] ffi.cdef[[ +" + +## Various types (mainly), from libknot and libkres + +echo " +typedef struct knot_dump_style knot_dump_style_t; +extern const knot_dump_style_t KNOT_DUMP_STYLE_DEFAULT; +" + +# The generator doesn't work well with typedefs of functions. +echo " +typedef struct knot_mm { + void *ctx, *alloc, *free; +} knot_mm_t; + +typedef void *(*map_alloc_f)(void *, size_t); +typedef void (*map_free_f)(void *baton, void *ptr); +" + +./scripts/gen-cdefs.sh libkres types <<-EOF + knot_section_t + knot_rrinfo_t + knot_dname_t + knot_rdata_t + knot_rdataset_t + struct knot_rdataset + knot_rrset_t + knot_pktsection_t + struct knot_pkt + knot_pkt_t + # generics + map_t + # libkres + rr_array_t + #struct ranked_rr_array_entry # TODO: prepared for vld-refactoring + #ranked_rr_array_entry_t + #ranked_rr_array_t + struct kr_zonecut + kr_qarray_t + struct kr_rplan + struct kr_request +EOF + +genResType() { + echo "$1" | ./scripts/gen-cdefs.sh libkres types +} + +# No simple way to fixup this rename in ./kres.lua AFAIK. +genResType "struct knot_rrset" | sed 's/\/_owner/' + +## Some definitions would need too many deps, so shorten them. + +genResType "struct kr_query" | sed '/struct kr_nsrep/,$ d' +echo -e "\tchar _stub[];\n};" + +genResType "struct kr_context" | sed '/struct kr_cache/,$ d' +echo -e "\tchar _stub[];\n};" + +# Getting struct query_flag is a bit complex. +genResType "enum kr_query_flag" | sed -e 's/enum kr_query_flag/struct query_flag/' \ + -e 's/QUERY_NO_THROTTLE/& = 2/' `# a special case for consecutive integers` \ + -e 's@\ 0 then + if rr.rrs.rr_count > 0 then local ret if i ~= nil then ret = knot.knot_rrset_txt_dump_data(rr, i, rrset_buf, rrset_buflen, knot.KNOT_DUMP_STYLE_DEFAULT) @@ -398,7 +199,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) - for k = 1, rrset.rr.count do + for k = 1, rrset.rrs.rr_count do table.insert(records, rrset:get(k - 1)) end end diff --git a/lib/README.rst b/lib/README.rst index 198a667c1..3a49b1562 100644 --- a/lib/README.rst +++ b/lib/README.rst @@ -250,7 +250,7 @@ You primarily need to retrieve currently processed query. -- Print information about current query local current = req:current() print(kres.dname2str(current.owner)) - print(current.type, current.class, current.id, current.flags) + print(current.stype, current.sclass, current.id, current.flags) end In layers that either begin or finalize, you can walk the list of resolved queries. @@ -258,7 +258,7 @@ In layers that either begin or finalize, you can walk the list of resolved queri .. code-block:: lua local last = req:resolved() - print(last.type) + print(last.stype) As described in the layers, you can not only retrieve information about current query, but also push new ones or pop old ones. diff --git a/lib/lib.mk b/lib/lib.mk index 1e73cdf06..7af91e50b 100644 --- a/lib/lib.mk +++ b/lib/lib.mk @@ -67,7 +67,9 @@ endif lib/zonecut.c: lib/root-hints.inc lib/root-hints.inc: + @echo "WARNING: regenerating $@" scripts/gen-root-hints.sh > $@ +.DELETE_ON_ERROR: lib/root-hints.inc # Make library ifeq ($(BUILDMODE), static) diff --git a/lib/rplan.h b/lib/rplan.h index 5c65a711e..5b6415118 100644 --- a/lib/rplan.h +++ b/lib/rplan.h @@ -51,6 +51,7 @@ X(BADCOOKIE_AGAIN, 1 << 22) /**< Query again because bad cookie returned. */ \ X(CNAME, 1 << 23) /**< Query response contains CNAME in answer section. */ \ X(REORDER_RR, 1 << 24) /**< Reorder cached RRs. */ + /* 1 << 31 Used by ../modules/dns64/dns64.lua */ /** Query flags */ enum kr_query_flag { diff --git a/modules/policy/README.rst b/modules/policy/README.rst index 30fb72934..e41752e00 100644 --- a/modules/policy/README.rst +++ b/modules/policy/README.rst @@ -49,7 +49,7 @@ Example configuration end) -- Disallow ANY queries policy.add(function (req, query) - if query.type == kres.type.ANY then + if query.stype == kres.type.ANY then return policy.DROP end end) diff --git a/modules/policy/zonefile.lua b/modules/policy/zonefile.lua index 9d64b19b1..bf6d1463e 100644 --- a/modules/policy/zonefile.lua +++ b/modules/policy/zonefile.lua @@ -1,6 +1,6 @@ -- LuaJIT ffi bindings for zscanner, a DNS zone parser. -- Author: Marek Vavrusa --- +-- FIXME: generate local ffi = require('ffi') local libzscanner = ffi.load(libzscanner_SONAME) diff --git a/modules/predict/predict.lua b/modules/predict/predict.lua index 86f5d44ac..9cec7d235 100644 --- a/modules/predict/predict.lua +++ b/modules/predict/predict.lua @@ -54,7 +54,7 @@ local function enqueue(queries) local nr_queries = #queries for i = 1, nr_queries do local entry = queries[i] - local key = string.format('%s %s', entry.type, entry.name) + local key = string.format('%s %s', entry.stype, entry.name) if not predict.queue[key] then predict.queue[key] = 1 queued = queued + 1 @@ -86,7 +86,7 @@ function predict.sample(epoch_now) local nr_samples = #queries for i = 1, nr_samples do local entry = queries[i] - local key = string.format('%s %s', entry.type, entry.name) + local key = string.format('%s %s', entry.stype, entry.name) current[key] = 1 end predict.log[epoch_now] = current diff --git a/scripts/gen-cdefs.sh b/scripts/gen-cdefs.sh new file mode 100755 index 000000000..b7ee5bc0b --- /dev/null +++ b/scripts/gen-cdefs.sh @@ -0,0 +1,51 @@ +#!/bin/sh -e + +if [ "$2" != types ] && [ "$2" != functions ]; then + echo "Usage: $0 libkres (types|functions)" >&2 + echo " and input identifiers, one per line." >&2 + echo " You need debug symbols in the library." >&2 + exit 1 +fi + +if type -P gdb >/dev/null; then :; else + echo "Failed to find gdb" >&2 + exit 1 +fi + +library="$(PATH="$(pwd)/lib:$(pkg-config libknot --variable=libdir)" type -P "$1.so")" +if [ -z "$library" ]; then + echo "$1 not found. Note: only .so platforms work currently." >&2 + exit 1 +fi + +GDB="gdb -quiet -symbols=$library" + +grep -v '^#\|^$' | while read ident; do + output="$( + if [ "$2" == functions ]; then + $GDB --ex "info functions ^$ident\$" --ex quit \ + | sed '1,/^All functions/ d; /^File .*:$/ d' + continue + fi + # else types + case "$ident" in + struct\ *|union\ *|enum\ *) + $GDB --ex "ptype $ident" --ex quit \ + | sed '1d; 2s/type = /\n/' + echo ";" + ;; + *) + $GDB --ex "info types ^$ident\$" --ex quit \ + | sed -e '1,/^File .*:$/ d' -e '/^File .*:$/,$ d' + # we need to stop early to remove ^^ multiple matches + ;; + esac + )" + # abort on empty output + if [ -z "$(echo "$output" | tr -d \n)" ]; then + echo "Failed to find cdef of $ident" >&2 + exit 1 + fi + echo "$output" | grep -v '^$' +done + diff --git a/scripts/kresd-host.lua b/scripts/kresd-host.lua index 62ab3149b..0ca73a138 100755 --- a/scripts/kresd-host.lua +++ b/scripts/kresd-host.lua @@ -86,7 +86,7 @@ for i, qtype in ipairs(qtypes) do local section = pkt:rrsets(kres.section.ANSWER) for i = 1, #section do local rr = section[i] - for k = 1, rr.rr.count do + for k = 1, rr.rrs.rr_count do local rdata = rr:tostring(k - 1) local owner = kres.dname2str(rr:owner()) if qverbose then