Commit 64050a14 authored by Marek Vavrusa's avatar Marek Vavrusa

modules/daf: allow forwarding to custom port

example:

> daf.add 'forward 127.0.0.1@5353'
parent 842038c0
......@@ -290,7 +290,7 @@ struct kr_query *kr_rplan_push(struct kr_rplan *rplan, struct kr_query *parent,
struct kr_query *kr_rplan_resolved(struct kr_rplan *rplan);
struct kr_query *kr_rplan_next(struct kr_query *qry);
/* Nameservers */
int kr_nsrep_set(struct kr_query *qry, uint8_t *addr, size_t addr_len);
int kr_nsrep_set(struct kr_query *qry, uint8_t *addr, size_t addr_len, int port);
/* Query */
/* Utils */
unsigned kr_rand_uint(unsigned max);
......@@ -319,6 +319,9 @@ int kr_dnssec_key_match(const uint8_t *key_a_rdata, size_t key_a_rdlen,
const uint8_t *key_b_rdata, size_t key_b_rdlen);
]]
-- Constants
local query_flag = ffi.new('struct query_flag')
-- Metatype for sockaddr
local addr_buf = ffi.new('char[16]')
local sockaddr_t = ffi.typeof('struct sockaddr')
......@@ -352,7 +355,7 @@ ffi.metatype( knot_rrset_t, {
tostring = function(rr, i)
assert(ffi.istype(knot_rrset_t, rr))
if rr.rr.count > 0 then
local ret = -1
local ret
if i ~= nil then
ret = knot.knot_rrset_txt_dump_data(rr, i, rrset_buf, rrset_buflen, knot.KNOT_DUMP_STYLE_DEFAULT)
else
......@@ -417,18 +420,18 @@ local ub_t = ffi.typeof('unsigned char *')
local kr_query_t = ffi.typeof('struct kr_query')
ffi.metatype( kr_query_t, {
__index = {
name = function(qry, new_name) return ffi.string(qry.sname, knot.knot_dname_size(qry.sname)) end,
name = function(qry) return ffi.string(qry.sname, knot.knot_dname_size(qry.sname)) end,
hasflag = function(qry, flag)
return band(qry.flags, flag) ~= 0
end,
resolved = function(qry)
return qry:hasflag(kres.query.RESOLVED)
return qry:hasflag(query_flag.RESOLVED)
end,
final = function(qry)
return qry:resolved() and (qry.parent == nil)
end,
nslist = function(qry, ns)
if ns ~= nil then C.kr_nsrep_set(qry, ffi.cast(ub_t, ns), #ns) end
nslist = function(qry, ns, port)
if ns ~= nil then C.kr_nsrep_set(qry, ffi.cast(ub_t, ns), #ns, port) end
-- @todo: Return list of NS entries, not possible ATM because the NSLIST is union and missing typedef
end,
},
......@@ -444,7 +447,7 @@ ffi.metatype( kr_request_t, {
end,
resolved = function(req)
assert(req)
qry = C.kr_rplan_resolved(C.kr_resolve_plan(req))
local qry = C.kr_rplan_resolved(C.kr_resolve_plan(req))
if qry == nil then return nil end
return qry
......@@ -489,7 +492,7 @@ local kres = {
type = ffi.new('struct rr_type'),
section = ffi.new('struct pkt_section'),
rcode = ffi.new('struct pkt_rcode'),
query = ffi.new('struct query_flag'),
query = query_flag,
NOOP = 0, YIELD = 0, CONSUME = 1, PRODUCE = 2, DONE = 4, FAIL = 8,
-- Metatypes
pkt_t = function (udata) return ffi.cast('knot_pkt_t *', udata) end,
......
......@@ -30,14 +30,14 @@
#define FAVOUR_IPV6 20 /* 20ms bonus for v6 */
/** @internal Macro to set address structure. */
#define ADDR_SET(sa, family, addr, len) do {\
#define ADDR_SET(sa, family, addr, len, port) do {\
memcpy(&sa ## _addr, (addr), (len)); \
sa ## _family = (family); \
sa ## _port = htons(KR_DNS_PORT); \
sa ## _port = htons(port); \
} while (0)
/** Update nameserver representation with current name/address pair. */
static void update_nsrep(struct kr_nsrep *ns, size_t pos, uint8_t *addr, size_t addr_len)
static void update_nsrep(struct kr_nsrep *ns, size_t pos, uint8_t *addr, size_t addr_len, int port)
{
if (addr == NULL) {
ns->addr[pos].ip.sa_family = AF_UNSPEC;
......@@ -49,9 +49,9 @@ static void update_nsrep(struct kr_nsrep *ns, size_t pos, uint8_t *addr, size_t
switch(addr_len) {
case sizeof(struct in_addr):
ADDR_SET(ns->addr[pos].ip4.sin, AF_INET, addr, addr_len); break;
ADDR_SET(ns->addr[pos].ip4.sin, AF_INET, addr, addr_len, port); break;
case sizeof(struct in6_addr):
ADDR_SET(ns->addr[pos].ip6.sin6, AF_INET6, addr, addr_len); break;
ADDR_SET(ns->addr[pos].ip6.sin6, AF_INET6, addr, addr_len, port); break;
default: assert(0); break;
}
}
......@@ -69,7 +69,7 @@ static void update_nsrep_set(struct kr_nsrep *ns, const knot_dname_t *name, uint
if (addr[i]) {
void *addr_val = pack_obj_val(addr[i]);
size_t len = pack_obj_len(addr[i]);
update_nsrep(ns, i, addr_val, len);
update_nsrep(ns, i, addr_val, len, KR_DNS_PORT);
} else {
break;
}
......@@ -169,7 +169,7 @@ static int eval_nsrep(const char *k, void *v, void *baton)
return kr_ok();
}
int kr_nsrep_set(struct kr_query *qry, uint8_t *addr, size_t addr_len)
int kr_nsrep_set(struct kr_query *qry, uint8_t *addr, size_t addr_len, int port)
{
if (!qry || !addr) {
return kr_error(EINVAL);
......@@ -177,8 +177,8 @@ int kr_nsrep_set(struct kr_query *qry, uint8_t *addr, size_t addr_len)
qry->ns.name = (const uint8_t *)"";
qry->ns.score = KR_NS_UNKNOWN;
qry->ns.reputation = 0;
update_nsrep(&qry->ns, 0, addr, addr_len);
update_nsrep(&qry->ns, 1, NULL, 0);
update_nsrep(&qry->ns, 0, addr, addr_len, port);
update_nsrep(&qry->ns, 1, NULL, 0, 0);
return kr_ok();
}
......
......@@ -95,10 +95,11 @@ struct kr_nsrep
* @param qry updated query
* @param addr address bytes (struct in_addr or struct in6_addr)
* @param addr_len address bytes length (type will be derived from this)
* @param port address port (if <= 0, 53 will be used)
* @return 0 or an error code
*/
KR_EXPORT
int kr_nsrep_set(struct kr_query *qry, uint8_t *addr, size_t addr_len);
int kr_nsrep_set(struct kr_query *qry, uint8_t *addr, size_t addr_len, int port);
/**
* Elect best nameserver/address pair from the nsset.
......
......@@ -508,7 +508,6 @@ int kr_resolve_consume(struct kr_request *request, const struct sockaddr *src, k
/* Different processing for network error */
struct kr_query *qry = array_tail(rplan->pending);
bool tried_tcp = (qry->flags & QUERY_TCP);
if (!packet || packet->size == 0) {
if (tried_tcp)
......
......@@ -36,6 +36,10 @@ Firewall rules are declarative and consist of filters and actions. Filters have
-- Mirror queries matching given name to DNS logger
daf.add 'qname ~ %w+.example.com MIRROR 127.0.0.2'
daf.add 'qname ~ example-%d.com MIRROR 127.0.0.3@5353'
-- Forward queries from subnet
daf.add 'src = 127.0.0.1/8 forward 127.0.0.1@5353'
-- Truncate queries based on destination IPs
daf.add 'dst = 192.0.2.51 truncate'
......
local kres = require('kres')
local bit = require('bit')
-- Counter of unique rules
local nextid = 0
......@@ -53,13 +54,16 @@ end
-- Forward request, and solve as stub query
local function forward(target)
local dst_ip = kres.str2ip(target)
if dst_ip == nil then error("FORWARD target '"..target..'" is not a valid IP address') end
local addr, port = target:match '([^@]*)@?(.*)'
port = port and tonumber(port) or 53
addr = kres.str2ip(addr)
if addr == nil then error("FORWARD target '"..target..'" is not a valid IP address') end
return function(state, req)
req = kres.request_t(req)
local qry = req:current()
qry.flags = qry.flags + kres.query.STUB
qry:nslist(dst_ip)
-- Switch mode to stub resolver, do not track origin zone cut since it's not real authority NS
qry.flags = bit.band(bit.bor(qry.flags, kres.query.STUB), bit.bnot(kres.query.ALWAYS_CUT))
qry:nslist(addr, port)
return state
end
end
......
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