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);
+int kr_nsrep_set(struct kr_query *, size_t, const struct sockaddr *);
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 *);
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 *);
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);
kr_straddr_subnet
kr_bitcmp
kr_family_len
+ kr_straddr_socket
kr_rrarray_add
# Trust anchors
kr_ta_get
nslist = function(qry, list)
assert(#list <= 4, 'maximum of 4 addresses can be evaluated for each query')
for i, ns in ipairs(list) do
- C.kr_nsrep_set(qry, i - 1, ffi.cast(ub_t, ns[1]), #ns[1], ns[2] or 53)
+ assert(C.kr_nsrep_set(qry, i - 1, ns) == 0);
end
-- If less than maximum NSs, insert guard to terminate the list
if #list < 4 then
- C.kr_nsrep_set(qry, #list, nil, 0, 0)
+ assert(C.kr_nsrep_set(qry, #list, nil) == 0);
end
end,
},
uv_signal_stop(handle);
}
+/** Split away port from the address. */
static const char *set_addr(char *addr, int *port)
{
char *p = strchr(addr, '#');
return kr_ok();
}
-int kr_nsrep_set(struct kr_query *qry, size_t index, uint8_t *addr, size_t addr_len, int port)
+int kr_nsrep_set(struct kr_query *qry, size_t index, const struct sockaddr *sock)
{
if (!qry) {
return kr_error(EINVAL);
qry->ns.score = KR_NS_UNKNOWN;
qry->ns.reputation = 0;
}
+
+ if (!sock) {
+ qry->ns.addr[index].ip.sa_family = AF_UNSPEC;
+ return kr_ok();
+ }
+
+ switch (sock->sa_family) {
+ case AF_INET:
+ qry->ns.addr[index].ip4 = *(const struct sockaddr_in *)sock;
+ break;
+ case AF_INET6:
+ qry->ns.addr[index].ip6 = *(const struct sockaddr_in6 *)sock;
+ break;
+ default:
+ qry->ns.addr[index].ip.sa_family = AF_UNSPEC;
+ return kr_error(EINVAL);
+ }
+
/* Retrieve RTT from cache */
- if (addr && addr_len > 0) {
- struct kr_context *ctx = qry->ns.ctx;
- unsigned *score = ctx
- ? lru_get_try(ctx->cache_rtt, (const char *)addr, addr_len)
- : NULL;
- if (score) {
- qry->ns.score = MIN(qry->ns.score, *score);
- }
+ struct kr_context *ctx = qry->ns.ctx;
+ unsigned *score = ctx
+ ? lru_get_try(ctx->cache_rtt, kr_inaddr(sock), kr_family_len(sock->sa_family))
+ : NULL;
+ if (score) {
+ qry->ns.score = MIN(qry->ns.score, *score);
}
- update_nsrep(&qry->ns, index, addr, addr_len, port);
+
return kr_ok();
}
* Set given NS address.
* @param qry updated query
* @param index index of the updated target
- * @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)
+ * @param sock socket address to use (sockaddr_in or sockaddr_in6 or NULL)
* @return 0 or an error code
*/
KR_EXPORT
-int kr_nsrep_set(struct kr_query *qry, size_t index, uint8_t *addr, size_t addr_len, int port);
+int kr_nsrep_set(struct kr_query *qry, size_t index, const struct sockaddr *sock);
/**
* Elect best nameserver/address pair from the nsset.
#include <libknot/rrtype/rrsig.h>
#include <libknot/rrset-dump.h>
#include <libknot/version.h>
+#include <uv.h>
#include "lib/defines.h"
#include "lib/utils.h"
}
}
+struct sockaddr * kr_straddr_socket(const char *addr, int port)
+{
+ switch (kr_straddr_family(addr)) {
+ case AF_INET: {
+ struct sockaddr_in *res = malloc(sizeof(*res));
+ if (uv_ip4_addr(addr, port, res) >= 0) {
+ return (struct sockaddr *)res;
+ } else {
+ free(res);
+ return NULL;
+ }
+ }
+ case AF_INET6: {
+ struct sockaddr_in6 *res = malloc(sizeof(*res));
+ if (uv_ip6_addr(addr, port, res) >= 0) {
+ return (struct sockaddr *)res;
+ } else {
+ free(res);
+ return NULL;
+ }
+ }
+ default:
+ return NULL;
+ }
+}
+
int kr_straddr_subnet(void *dst, const char *addr)
{
if (!dst || !addr) {
/** Return address length in given family. */
KR_EXPORT KR_CONST
int kr_family_len(int family);
+/** Create a sockaddr* from string+port representation (also accepts IPv6 link-local). */
+KR_EXPORT
+struct sockaddr * kr_straddr_socket(const char *addr, int port);
/** Parse address and return subnet length (bits).
* @warning 'dst' must be at least `sizeof(struct in6_addr)` long. */
KR_EXPORT
return addr, port
end
+local function parse_sock(target)
+ local addr, port = target:match '([^@]*)@?(.*)'
+ port = port and tonumber(port) or 53
+ sock = ffi.gc(ffi.C.kr_straddr_socket(addr, port), ffi.C.free);
+
+ if sock == nil then
+ error("target '"..target..'" is not a valid IP address')
+ end
+ return sock
+end
+
-- Mirror request elsewhere, and continue solving
local function mirror(target)
local addr, port = parse_target(target)
local list = {}
if type(target) == 'table' then
for _, v in pairs(target) do
- table.insert(list, {parse_target(v)})
+ table.insert(list, parse_sock(v))
assert(#list <= 4, 'at most 4 FORWARD targets are supported')
end
else
- table.insert(list, {parse_target(target)})
+ table.insert(list, parse_sock(target))
end
return function(state, req)
req = kres.request_t(req)