Commit 79c03561 authored by Marek Vavruša's avatar Marek Vavruša

lib: updated for reworked requestor, memleaks, static hints layer

parent fd3cfa82
......@@ -16,19 +16,16 @@ limitations under the License.
#include "daemon/layer/query.h"
#include "lib/resolve.h"
/* State-less single resolution iteration step, not needed. */
static int reset(knot_process_t *ctx) { return NS_PROC_MORE; }
static int finish(knot_process_t *ctx) { return NS_PROC_NOOP; }
static int begin(knot_process_t *ctx, void *module_param)
static int begin(knot_layer_t *ctx, void *module_param)
{
ctx->data = module_param;
return NS_PROC_MORE;
}
static int input_query(knot_pkt_t *pkt, knot_process_t *ctx)
static int input_query(knot_layer_t *ctx, knot_pkt_t *pkt)
{
assert(pkt && ctx);
struct layer_param *param = ctx->data;
struct kr_layer_param *param = ctx->data;
/* Check if at least header is parsed. */
if (pkt->parsed < pkt->size) {
......@@ -62,23 +59,17 @@ static int input_query(knot_pkt_t *pkt, knot_process_t *ctx)
}
}
static int output(knot_pkt_t *pkt, knot_process_t *ctx)
{
/* \note Output is returned indirectly via resolution result. */
return NS_PROC_NOOP;
}
/*! \brief Module implementation. */
static const knot_process_module_t LAYER_QUERY_MODULE = {
static const knot_layer_api_t LAYER_QUERY_MODULE = {
&begin,
&reset,
&finish,
NULL,
NULL,
&input_query,
&output,
&knot_process_noop /* No error processing. */
NULL,
NULL
};
const knot_process_module_t *layer_query_module(void)
const knot_layer_api_t *layer_query_module(void)
{
return &LAYER_QUERY_MODULE;
}
......@@ -18,5 +18,5 @@ limitations under the License.
#include "lib/layer.h"
/* Processing module implementation. */
const knot_process_module_t *layer_query_module(void);
const knot_layer_api_t *layer_query_module(void);
#define LAYER_QUERY layer_query_module()
......@@ -6,13 +6,19 @@
#include "daemon/worker.h"
#include "daemon/layer/query.h"
static void worker_alloc(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf)
static void buf_alloc(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf)
{
struct worker_ctx *worker = handle->data;
buf->base = mm_alloc(worker->pool, suggested_size);
buf->len = suggested_size;
}
static void buf_free(uv_handle_t* handle, const uv_buf_t* buf)
{
struct worker_ctx *worker = handle->data;
mm_free(worker->pool, buf->base);
}
static void worker_send(uv_udp_t *handle, knot_pkt_t *answer, const struct sockaddr *addr)
{
uv_buf_t sendbuf = uv_buf_init((char *)answer->wire, answer->size);
......@@ -26,21 +32,23 @@ static void worker_recv(uv_udp_t *handle, ssize_t nread, const uv_buf_t *buf,
assert(ctx->pool);
if (nread < KNOT_WIRE_HEADER_SIZE) {
buf_free((uv_handle_t *)handle, buf);
return;
}
struct kr_result result;
/* Create query processing context. */
struct layer_param param;
struct kr_layer_param param;
param.ctx = &ctx->resolve;
param.result = &result;
/* Process query packet. */
knot_process_t proc = {0};
memcpy(&proc.mm, ctx->pool, sizeof(mm_ctx_t));
knot_process_begin(&proc, &param, LAYER_QUERY);
int state = knot_process_in((uint8_t *)buf->base, nread, &proc);
knot_layer_t proc;
memset(&proc, 0, sizeof(knot_layer_t));
proc.mm = ctx->pool;
knot_process_begin(&proc, LAYER_QUERY, &param);
int state = knot_process_in(&proc, (uint8_t *)buf->base, nread);
if (state & (NS_PROC_DONE|NS_PROC_FAIL)) {
worker_send(handle, result.ans, addr);
}
......@@ -49,6 +57,8 @@ static void worker_recv(uv_udp_t *handle, ssize_t nread, const uv_buf_t *buf,
knot_process_finish(&proc);
kr_result_deinit(&result);
kr_context_reset(&ctx->resolve);
buf_free((uv_handle_t *)handle, buf);
}
void worker_init(struct worker_ctx *worker, mm_ctx_t *mm)
......@@ -68,7 +78,7 @@ void worker_start(uv_udp_t *handle, struct worker_ctx *worker)
{
handle->data = worker;
uv_udp_recv_start(handle, &worker_alloc, &worker_recv);
uv_udp_recv_start(handle, &buf_alloc, &worker_recv);
}
void worker_stop(uv_udp_t *handle)
......
......@@ -4,31 +4,6 @@
#include <common/sockaddr.h>
#include "context.h"
/* \brief Root hint descriptor. */
struct hint_info {
const char *name;
const char *addr;
const char *zone;
};
/* Initialize with SBELT name servers. */
#define HINT_COUNT 13
static const struct hint_info SBELT[HINT_COUNT] = {
{ "a.root-servers.net.", "198.41.0.4", "." },
{ "b.root-servers.net.", "192.228.79.201", "." },
{ "c.root-servers.net.", "192.33.4.12", "." },
{ "d.root-servers.net.", "199.7.91.13", "." },
{ "e.root-servers.net.", "192.203.230.10", "." },
{ "f.root-servers.net.", "192.5.5.241", "." },
{ "g.root-servers.net.", "192.112.36.4", "." },
{ "h.root-servers.net.", "128.63.2.53", "." },
{ "i.root-servers.net.", "192.36.148.17", "." },
{ "j.root-servers.net.", "192.58.128.30", "." },
{ "k.root-servers.net.", "193.0.14.129", "." },
{ "l.root-servers.net.", "199.7.83.42", "." },
{ "m.root-servers.net.", "202.12.27.33", "." }
};
/* TODO: debug, remove */
#ifndef NDEBUG
static void print_slist(struct kr_context *ctx)
......@@ -116,16 +91,14 @@ int kr_context_init(struct kr_context *ctx, mm_ctx_t *mm)
memset(ctx, 0, sizeof(struct kr_context));
ctx->pool = mm;
init_list(&ctx->slist);
kr_context_reset(ctx);
kr_slist_init(ctx);
return 0;
}
int kr_context_reset(struct kr_context *ctx)
{
while(kr_slist_pop(ctx) == 0);
kr_slist_clear(ctx);
kr_slist_init(ctx);
return 0;
......@@ -133,7 +106,8 @@ int kr_context_reset(struct kr_context *ctx)
int kr_context_deinit(struct kr_context *ctx)
{
/* TODO: free slist, pending queries. */
kr_slist_clear(ctx);
return -1;
}
......@@ -165,14 +139,15 @@ int kr_result_deinit(struct kr_result *result)
int kr_slist_init(struct kr_context *ctx)
{
int ret = 0;
struct sockaddr_storage ss;
for (unsigned i = 0; i < HINT_COUNT; ++i) {
ret = sockaddr_set(&ss, AF_INET, SBELT[i].addr, 53);
assert(ret == 0);
kr_slist_add(ctx, knot_dname_from_str(SBELT[i].zone),
(struct sockaddr *)&ss);
}
init_list(&ctx->slist);
return 0;
}
int kr_slist_clear(struct kr_context *ctx)
{
while(kr_slist_pop(ctx) == 0)
;
return 0;
}
......@@ -220,6 +195,7 @@ int kr_slist_pop(struct kr_context *ctx)
return -1;
}
remove_ns(ctx->pool, top);
return 0;
......
......@@ -44,10 +44,10 @@ struct kr_result {
/*! \brief Name resolution context. */
struct kr_context
{
const knot_pkt_t *query;
const knot_dname_t *sname;
uint16_t stype;
uint16_t sclass;
uint16_t next_id;
list_t slist;
mm_ctx_t *pool;
unsigned state;
......@@ -62,6 +62,7 @@ int kr_result_init(struct kr_context *ctx, struct kr_result *result);
int kr_result_deinit(struct kr_result *result);
int kr_slist_init(struct kr_context *ctx);
int kr_slist_clear(struct kr_context *ctx);
int kr_slist_add(struct kr_context *ctx, const knot_dname_t *name, const struct sockaddr *addr);
struct kr_ns *kr_slist_top(struct kr_context *ctx);
int kr_slist_sort(struct kr_context *ctx);
......
......@@ -21,7 +21,7 @@ limitations under the License.
/*!
* \brief Processing module parameters.
*/
struct layer_param {
struct kr_layer_param {
struct kr_context *ctx;
struct kr_result *result;
};
\ No newline at end of file
......@@ -56,7 +56,7 @@ static int glue_record(knot_pkt_t *pkt, const knot_dname_t *dp, struct sockaddr
return 0;
}
static int evaluate_dp(const knot_rrset_t *dp, knot_pkt_t *pkt, struct layer_param *param)
static int evaluate_dp(const knot_rrset_t *dp, knot_pkt_t *pkt, struct kr_layer_param *param)
{
struct kr_context *resolve = param->ctx;
......@@ -75,7 +75,7 @@ static int evaluate_dp(const knot_rrset_t *dp, knot_pkt_t *pkt, struct layer_par
return 0;
}
static int resolve_nonauth(knot_pkt_t *pkt, struct layer_param *param)
static int resolve_nonauth(knot_pkt_t *pkt, struct kr_layer_param *param)
{
const knot_pktsection_t *ns = knot_pkt_section(pkt, KNOT_AUTHORITY);
for (unsigned i = 0; i < ns->count; ++i) {
......@@ -87,7 +87,7 @@ static int resolve_nonauth(knot_pkt_t *pkt, struct layer_param *param)
return NS_PROC_DONE;
}
static void follow_cname_chain(const knot_rrset_t *rr, struct layer_param *param)
static void follow_cname_chain(const knot_rrset_t *rr, struct kr_layer_param *param)
{
struct kr_context *resolve = param->ctx;
struct kr_result *result = param->result;
......@@ -103,7 +103,7 @@ static void follow_cname_chain(const knot_rrset_t *rr, struct layer_param *param
}
}
static int resolve_auth(knot_pkt_t *pkt, struct layer_param *param)
static int resolve_auth(knot_pkt_t *pkt, struct kr_layer_param *param)
{
struct kr_context *resolve = param->ctx;
struct kr_result *result = param->result;
......@@ -118,15 +118,23 @@ static int resolve_auth(knot_pkt_t *pkt, struct layer_param *param)
knot_pkt_begin(ans, KNOT_ANSWER);
const knot_pktsection_t *an = knot_pkt_section(pkt, KNOT_ANSWER);
for (unsigned i = 0; i < an->count; ++i) {
const knot_rrset_t *rr = &an->rr[i];
int ret = knot_pkt_put(ans, COMPR_HINT_NONE, rr, 0);
knot_rrset_t *rr = knot_rrset_copy(&an->rr[i], &ans->mm);
if (rr == NULL) {
return NS_PROC_FAIL;
}
int ret = knot_pkt_put(ans, COMPR_HINT_NONE, rr, KNOT_PF_FREE);
if (ret != 0) {
knot_rrset_free(&rr, &ans->mm);
knot_wire_set_tc(ans->wire);
return NS_PROC_FAIL;
}
/* Check canonical name. */
/* TODO: these may not come in order, queueing is needed. */
follow_cname_chain(rr, param);
/* Free just the allocated container. */
mm_free(&ans->mm, rr);
}
/* Follow canonical name as next SNAME. */
......@@ -147,7 +155,7 @@ static int resolve_auth(knot_pkt_t *pkt, struct layer_param *param)
}
/*! \brief Error handling, RFC1034 5.3.3, 4d. */
static int resolve_error(knot_pkt_t *pkt, struct layer_param *param)
static int resolve_error(knot_pkt_t *pkt, struct kr_layer_param *param)
{
return NS_PROC_FAIL;
}
......@@ -155,31 +163,53 @@ static int resolve_error(knot_pkt_t *pkt, struct layer_param *param)
/*! \brief Answer is paired to query. */
static bool is_answer_to_query(const knot_pkt_t *answer, struct kr_context *resolve)
{
return resolve->next_id == knot_wire_get_id(answer->wire) &&
return knot_wire_get_id(resolve->query->wire) == knot_wire_get_id(answer->wire) &&
resolve->sclass == knot_pkt_qclass(answer) &&
resolve->stype == knot_pkt_qtype(answer) &&
knot_dname_is_equal(resolve->sname, knot_pkt_qname(answer));
}
/* State-less single resolution iteration step, not needed. */
static int reset(knot_process_t *ctx) { return NS_PROC_MORE; }
static int finish(knot_process_t *ctx) { return NS_PROC_NOOP; }
static int reset(knot_layer_t *ctx) { return NS_PROC_FULL; }
static int finish(knot_layer_t *ctx) { return NS_PROC_NOOP; }
/* Set resolution context and parameters. */
static int begin(knot_process_t *ctx, void *module_param)
static int begin(knot_layer_t *ctx, void *module_param)
{
ctx->data = module_param;
return NS_PROC_FULL;
return reset(ctx);
}
static int prepare_query(knot_layer_t *ctx, knot_pkt_t *pkt)
{
assert(pkt && ctx);
struct kr_layer_param *param = ctx->data;
struct kr_context* resolve = param->ctx;
resolve->query = pkt;
knot_pkt_clear(pkt);
int ret = knot_pkt_put_question(pkt, resolve->sname, resolve->sclass, resolve->stype);
if (ret != KNOT_EOK) {
assert(0);
return NS_PROC_FAIL;
}
knot_wire_set_id(pkt->wire, knot_random_uint16_t());
/* Query complete, expect answer. */
return NS_PROC_MORE;
}
/*! \brief Resolve input query or continue resolution with followups.
*
* This roughly corresponds to RFC1034, 5.3.3 4a-d.
*/
static int resolve(knot_pkt_t *pkt, knot_process_t *ctx)
static int resolve(knot_layer_t *ctx, knot_pkt_t *pkt)
{
assert(pkt && ctx);
struct layer_param *param = ctx->data;
struct kr_layer_param *param = ctx->data;
/* Check for packet processing errors first. */
if (pkt->parsed < pkt->size) {
......@@ -208,34 +238,17 @@ static int resolve(knot_pkt_t *pkt, knot_process_t *ctx)
return resolve_auth(pkt, param);
}
static int issue(knot_pkt_t *pkt, knot_process_t *ctx)
{
assert(pkt && ctx);
struct layer_param *param = ctx->data;
struct kr_context *resolve = param->ctx;
struct kr_result *result = param->result;
knot_pkt_clear(pkt);
knot_pkt_put_question(pkt, resolve->sname, resolve->sclass, resolve->stype);
knot_wire_set_id(pkt->wire, knot_random_uint16_t());
resolve->next_id = knot_wire_get_id(pkt->wire);
result->nr_queries += 1;
return NS_PROC_MORE;
}
/*! \brief Module implementation. */
static const knot_process_module_t LAYER_ITERATE_MODULE = {
static const knot_layer_api_t LAYER_ITERATE_MODULE = {
&begin,
&reset,
&finish,
&resolve,
&issue,
&knot_process_noop /* No error processing. */
&prepare_query,
NULL
};
const knot_process_module_t *layer_iterate_module(void)
const knot_layer_api_t *layer_iterate_module(void)
{
return &LAYER_ITERATE_MODULE;
}
......@@ -18,5 +18,5 @@ limitations under the License.
#include "lib/layer.h"
/* Processing module implementation. */
const knot_process_module_t *layer_iterate_module(void);
const knot_layer_api_t *layer_iterate_module(void);
#define LAYER_ITERATE layer_iterate_module()
/* Copyright 2014 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "lib/layer/static.h"
/* \brief Root hint descriptor. */
struct hint_info {
const knot_dname_t *name;
const char *addr;
};
/* Initialize with SBELT name servers. */
#define U8(x) (const uint8_t *)(x)
#define HINT_COUNT 13
static const struct hint_info SBELT[HINT_COUNT] = {
{ U8("\x01""a""\x0c""root-servers""\x03""net"), "198.41.0.4" },
{ U8("\x01""b""\x0c""root-servers""\x03""net"), "192.228.79.201" },
{ U8("\x01""c""\x0c""root-servers""\x03""net"), "192.33.4.12" },
{ U8("\x01""d""\x0c""root-servers""\x03""net"), "199.7.91.13" },
{ U8("\x01""e""\x0c""root-servers""\x03""net"), "192.203.230.10" },
{ U8("\x01""f""\x0c""root-servers""\x03""net"), "192.5.5.241" },
{ U8("\x01""g""\x0c""root-servers""\x03""net"), "192.112.36.4" },
{ U8("\x01""h""\x0c""root-servers""\x03""net"), "128.63.2.53" },
{ U8("\x01""i""\x0c""root-servers""\x03""net"), "192.36.148.17" },
{ U8("\x01""j""\x0c""root-servers""\x03""net"), "192.58.128.30" },
{ U8("\x01""k""\x0c""root-servers""\x03""net"), "193.0.14.129" },
{ U8("\x01""l""\x0c""root-servers""\x03""net"), "199.7.83.42" },
{ U8("\x01""m""\x0c""root-servers""\x03""net"), "202.12.27.33" }
};
static int reset(knot_layer_t *ctx)
{
printf("loading sbelt\n");
return ctx->state;
}
static int begin(knot_layer_t *ctx, void *param)
{
ctx->data = param;
struct kr_context *resolve = ((struct kr_layer_param *)param)->ctx;
assert(resolve);
/* Initialize static root hints. */
struct sockaddr_storage ss;
for (unsigned i = 0; i < HINT_COUNT; ++i) {
sockaddr_set(&ss, AF_INET, SBELT[i].addr, 53);
kr_slist_add(resolve, U8(""), (struct sockaddr *)&ss);
}
return ctx->state;
}
/*! \brief Module implementation. */
static const knot_layer_api_t LAYER_STATIC_MODULE = {
&begin,
&reset,
NULL,
NULL,
NULL,
NULL
};
const knot_layer_api_t *layer_static_module(void)
{
return &LAYER_STATIC_MODULE;
}
/* Copyright 2014 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include "lib/layer.h"
/* Processing module implementation. */
const knot_layer_api_t *layer_static_module(void);
#define LAYER_STATIC layer_static_module()
......@@ -41,12 +41,44 @@ do { \
printf("[%s] at %s (soa %s) ", _qstr, _astr, _soastr); \
printf(s); \
printf("\n"); \
free(_qstr); \
free(_soastr); \
} while(0)
#else
static void print_result(struct kr_result *result) {}
#define print_step
#endif
static void iterate(struct knot_requestor *requestor, struct kr_context* ctx)
{
struct timeval timeout = { 5, 0 };
/* Sort preference list to the SNAME and pick a NS. */
kr_slist_sort(ctx);
struct kr_ns *ns = kr_slist_top(ctx);
if (ns == NULL) {
ctx->state = NS_PROC_FAIL;
return;
}
print_step("iterating");
/* Build query. */
knot_pkt_t *query = knot_pkt_new(NULL, KNOT_WIRE_MAX_PKTSIZE, requestor->mm);
/* Resolve. */
struct knot_request *tx = knot_request_make(requestor->mm,
(const struct sockaddr *)&ns->addr,
NULL, query, 0);
knot_requestor_enqueue(requestor, tx);
int ret = knot_requestor_exec(requestor, &timeout);
/* TODO: soft remove, retry later */
if (ret != 0) {
print_step("server failure %d", ret);
kr_slist_pop(ctx);
}
}
int kr_resolve(struct kr_context* ctx, struct kr_result* result,
const knot_dname_t *qname, uint16_t qclass, uint16_t qtype)
{
......@@ -54,42 +86,29 @@ int kr_resolve(struct kr_context* ctx, struct kr_result* result,
return -1;
}
/* Initialize context. */
ctx->sname = qname;
ctx->sclass = qclass;
ctx->stype = qtype;
ctx->state = NS_PROC_MORE;
ctx->query = NULL;
kr_result_init(ctx, result);
struct layer_param param;
struct kr_layer_param param;
param.ctx = ctx;
param.result = result;
/* TODO: how to load all the layers? no API support yet */
struct timeval timeout = { 5, 0 };
/* Initialize requestor and overlay. */
struct knot_requestor requestor;
knot_requestor_init(&requestor, LAYER_ITERATE, ctx->pool);
knot_requestor_init(&requestor, ctx->pool);
knot_requestor_overlay(&requestor, LAYER_STATIC, &param);
knot_requestor_overlay(&requestor, LAYER_ITERATE, &param);
while(ctx->state != NS_PROC_DONE) {
/* Sort preference list to the SNAME and pick a NS. */
kr_slist_sort(ctx);
struct kr_ns *ns = kr_slist_top(ctx);
print_step("iterating");
/* Resolve. */
struct knot_request *tx = knot_requestor_make(&requestor,
(const struct sockaddr *)&ns->addr,
NULL, NULL, 0);
knot_requestor_enqueue(&requestor, tx, &param);
int ret = knot_requestor_exec(&requestor, &timeout);
/* TODO: soft remove, retry later */
if (ret != 0) {
print_step("server failure %d", ret);
kr_slist_pop(ctx);
}
iterate(&requestor, ctx);
}
print_step(" ---> done");
/* Clean up. */
knot_requestor_clear(&requestor);
......
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