Commit bc3d2159 authored by Vladimír Čunát's avatar Vladimír Čunát

Merge !324: dns64: correct order of CNAME and AAAA in answer

parents 2f2b78c9 df52a663
Pipeline #7893 canceled with stages
in 75 minutes and 29 seconds
......@@ -5,6 +5,7 @@ Bugfixes
--------
- daemon: check existence of config file even if rundir isn't specified
- policy.FORWARD and STUB: use RTT tracking to choose servers (#125, #208)
- dns64: fix CNAME problems (#203) It still won't work with query policies.
Improvements
------------
......
......@@ -124,6 +124,7 @@ struct kr_request {
int has_tls;
knot_mm_t pool;
};
enum kr_rank {KR_RANK_INITIAL, KR_RANK_OMIT, KR_RANK_INDET, KR_RANK_BOGUS, KR_RANK_MISMATCH, KR_RANK_MISSING, KR_RANK_INSECURE = 8, KR_RANK_AUTH = 16, KR_RANK_SECURE = 32};
struct knot_rrset {
knot_dname_t *_owner;
uint16_t type;
......@@ -151,6 +152,8 @@ struct kr_query {
struct timeval timestamp;
struct kr_zonecut zone_cut;
struct kr_nsrep ns;
struct kr_layer_pickle *deferred;
uint32_t uid;
/* ^hidden stub^ */
char _stub[];
};
......@@ -199,7 +202,7 @@ int kr_straddr_subnet(void *, const char *);
int kr_bitcmp(const char *, const char *, int);
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 *);
int kr_ranked_rrarray_add(ranked_rr_array_t *, const knot_rrset_t *, uint8_t, _Bool, uint32_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 *);
......
......@@ -55,6 +55,7 @@ typedef void (*map_free_f)(void *baton, void *ptr);
kr_qarray_t
struct kr_rplan
struct kr_request
enum kr_rank
EOF
genResType() {
......@@ -69,7 +70,7 @@ genResType "struct knot_rrset" | sed 's/\<owner\>/_owner/'
genResType "struct kr_nsrep" | sed '/union/,$ d'
printf "\t/* beware: hidden stub */\n};\n"
genResType "struct kr_query" | sed '/struct kr_layer_pickle/,$ d'
genResType "struct kr_query" | sed '/uint32_t forward_flags/,$ d'
printf "\t/* ^hidden stub^ */\n\tchar _stub[];\n};\n"
genResType "struct kr_context" | sed '/struct kr_cache/,$ d'
......@@ -130,7 +131,7 @@ EOF
kr_bitcmp
kr_family_len
kr_straddr_socket
kr_rrarray_add
kr_ranked_rrarray_add
# Trust anchors
kr_ta_get
kr_ta_add
......
......@@ -135,6 +135,8 @@ 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, {
-- beware: `owner` and `rdata` are typed as a plain lua strings
-- and not the real types they represent.
__index = {
owner = function(rr) return ffi.string(rr._owner, knot.knot_dname_size(rr._owner)) end,
ttl = function(rr) return tonumber(knot.knot_rrset_ttl(rr)) end,
......@@ -317,7 +319,7 @@ local function rr2str(rr, style)
-- Construct a single-RR temporary set while minimizing copying.
local rrs = knot_rrset_t()
knot.knot_rrset_init_empty(rrs)
rrs._owner = ffi.cast('char *', rr.owner) -- explicit cast needed here
rrs._owner = ffi.cast('knot_dname_t *', rr.owner) -- explicit cast needed here
rrs.type = rr.type
rrs.rclass = kres.class.IN
knot.knot_rrset_add_rdata(rrs, rr.rdata, #rr.rdata, rr.ttl, nil)
......
......@@ -242,6 +242,7 @@ int kr_rrmap_add(map_t *stash, const knot_rrset_t *rr, uint8_t rank, knot_mm_t *
int kr_rrarray_add(rr_array_t *array, const knot_rrset_t *rr, knot_mm_t *pool);
/** @internal Add RRSet copy to ranked RR array. */
KR_EXPORT
int kr_ranked_rrarray_add(ranked_rr_array_t *array, const knot_rrset_t *rr,
uint8_t rank, bool to_wire, uint32_t qry_uid, knot_mm_t *pool);
......
......@@ -5,6 +5,8 @@ DNS64
The module for :rfc:`6147` DNS64 AAAA-from-A record synthesis, it is used to enable client-server communication between an IPv6-only client and an IPv4-only server. See the well written `introduction`_ in the PowerDNS documentation.
.. warning:: The module currently won't work well with query policies.
.. tip:: The A record sub-requests will be DNSSEC secured, but the synthetic AAAA records can't be. Make sure the last mile between stub and resolver is secure to avoid spoofing.
Example configuration
......@@ -18,5 +20,6 @@ Example configuration
dns64.config('fe80::21b:aabb:0:0')
.. _RPZ: https://dnsrpz.info/
.. _introduction: https://doc.powerdns.com/md/recursor/dns64
\ No newline at end of file
.. _introduction: https://doc.powerdns.com/md/recursor/dns64
......@@ -24,20 +24,40 @@ mod.layer = {
-- Synthetic AAAA from marked A responses
local answer = pkt:section(kres.section.ANSWER)
if bit.band(qry.flags, MARK_DNS64) ~= 0 then -- Marked request
for i = 1, #answer do
local rr = answer[i]
-- Synthesise AAAA from A
if rr.type == kres.type.A then
ffi.copy(addr_buf, mod.proxy, 16)
ffi.copy(addr_buf + 12, rr.rdata, 4)
req.answer:put(rr.owner, rr.ttl, rr.class, kres.type.AAAA, ffi.string(addr_buf, 16))
local section = ffi.C.knot_pkt_section(pkt, kres.section.ANSWER)
for i = 1, section.count do
local orig = ffi.C.knot_pkt_rr(section, i - 1)
if orig.type == kres.type.A then
local rrs = ffi.typeof('knot_rrset_t')()
ffi.C.knot_rrset_init_empty(rrs)
rrs._owner = ffi.cast('knot_dname_t *', orig:owner()) -- explicit cast needed here
rrs.type = kres.type.AAAA
rrs.rclass = orig.rclass
for k = 1, orig.rrs.rr_count do
local rdata = orig:rdata( k - 1 )
ffi.copy(addr_buf, mod.proxy, 16)
ffi.copy(addr_buf + 12, rdata, 4)
ffi.C.knot_rrset_add_rdata(rrs, ffi.string(addr_buf, 16), 16, orig:ttl(), req.pool)
end
-- All referred memory is copied within the function,
-- so it doesn't matter that lua GCs our variables.
ffi.C.kr_ranked_rrarray_add(
req.answ_selected,
rrs,
ffi.C.KR_RANK_OMIT,
true,
qry.uid,
req.pool)
end
end
else -- Observe AAAA NODATA responses
local is_nodata = (pkt:rcode() == kres.rcode.NOERROR) and (#answer == 0)
if pkt:qtype() == kres.type.AAAA and is_nodata and pkt:qname() == qry:name() and qry:final() then
local next = req:push(pkt:qname(), kres.type.A, kres.class.IN, 0, qry)
next.flags = bit.band(qry.flags, kres.query.DNSSEC_WANT) + kres.query.AWAIT_CUT + MARK_DNS64
local extraFlags = bit.bor(
bit.band(qry.flags, kres.query.DNSSEC_WANT),
bit.bor(MARK_DNS64, kres.query.AWAIT_CUT)
)
local next = req:push(pkt:qname(), kres.type.A, kres.class.IN, extraFlags, qry)
end
end
return state
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment