Commit fd3cfa82 authored by Marek Vavruša's avatar Marek Vavruša

daemon: simple resolver daemon implementation

parent a2f4e48e
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = lib tests
SUBDIRS = lib tests daemon
......@@ -42,6 +42,7 @@ AC_SEARCH_LIBS([knot_rrset_clear], [knot])
# Config files
AC_CONFIG_FILES([Makefile
lib/Makefile
daemon/Makefile
tests/Makefile
])
......
AM_CPPFLAGS = \
-include $(top_builddir)/config.h \
-I$(top_srcdir)/lib
sbin_PROGRAMS = kresolved
kresolved_SOURCES = \
layer/query.h \
layer/query.c \
worker.h \
worker.c \
main.c
# sbin programs
kresolved_LDADD = $(top_builddir)/lib/libknotresolve.la \
$(KNOT_LIBS) \
$(libuv_LIBS)
/* 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 "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)
{
ctx->data = module_param;
return NS_PROC_MORE;
}
static int input_query(knot_pkt_t *pkt, knot_process_t *ctx)
{
assert(pkt && ctx);
struct layer_param *param = ctx->data;
/* Check if at least header is parsed. */
if (pkt->parsed < pkt->size) {
knot_pkt_free(&pkt);
return NS_PROC_FAIL;
}
/* Accept only queries. */
if (knot_wire_get_qr(pkt->wire)) {
knot_pkt_free(&pkt);
return NS_PROC_NOOP; /* Ignore. */
}
/* Prepare for query processing. */
int ret = kr_resolve(param->ctx, param->result,
knot_pkt_qname(pkt),
knot_pkt_qclass(pkt),
knot_pkt_qtype(pkt));
/* Set correct message ID. */
knot_pkt_t *answer = param->result->ans;
knot_wire_set_id(answer->wire, knot_wire_get_id(pkt->wire));
/* Free query and finish. */
knot_pkt_free(&pkt);
if (ret != 0) {
return NS_PROC_FAIL;
} else {
return NS_PROC_DONE;
}
}
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 = {
&begin,
&reset,
&finish,
&input_query,
&output,
&knot_process_noop /* No error processing. */
};
const knot_process_module_t *layer_query_module(void)
{
return &LAYER_QUERY_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_process_module_t *layer_query_module(void);
#define LAYER_QUERY layer_query_module()
#include <uv.h>
#include "lib/resolve.h"
#include "worker.h"
int main(void)
{
mm_ctx_t mm;
mm_ctx_init(&mm);
uv_loop_t *loop = uv_default_loop();
/* Bind to sockets. */
/* TODO: list of sockets, configurable loops. */
uv_udp_t udp_sock;
memset(&udp_sock, 0, sizeof(uv_udp_t));
struct sockaddr_in anyaddr;
uv_ip4_addr("0.0.0.0", 3535, &anyaddr);
uv_udp_init(loop, &udp_sock);
uv_udp_bind(&udp_sock, (struct sockaddr *)&anyaddr, 0);
/* Start a worker. */
struct worker_ctx worker;
worker_init(&worker, &mm);
worker_start(&udp_sock, &worker);
/* Run the event loop. */
int ret = uv_run(loop, UV_RUN_DEFAULT);
/* Cleanup. */
worker_stop(&udp_sock);
worker_deinit(&worker);
return ret;
}
#include <uv.h>
#include <libknot/packet/pkt.h>
#include <libknot/packet/net.h>
#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)
{
struct worker_ctx *worker = handle->data;
buf->base = mm_alloc(worker->pool, suggested_size);
buf->len = suggested_size;
}
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);
uv_udp_try_send(handle, &sendbuf, 1, addr);
}
static void worker_recv(uv_udp_t *handle, ssize_t nread, const uv_buf_t *buf,
const struct sockaddr *addr, unsigned flags)
{
struct worker_ctx *ctx = handle->data;
assert(ctx->pool);
if (nread < KNOT_WIRE_HEADER_SIZE) {
return;
}
struct kr_result result;
/* Create query processing context. */
struct 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);
if (state & (NS_PROC_DONE|NS_PROC_FAIL)) {
worker_send(handle, result.ans, addr);
}
/* Cleanup. */
knot_process_finish(&proc);
kr_result_deinit(&result);
kr_context_reset(&ctx->resolve);
}
void worker_init(struct worker_ctx *worker, mm_ctx_t *mm)
{
memset(worker, 0, sizeof(struct worker_ctx));
worker->pool = mm;
kr_context_init(&worker->resolve, mm);
}
void worker_deinit(struct worker_ctx *worker)
{
kr_context_deinit(&worker->resolve);
}
void worker_start(uv_udp_t *handle, struct worker_ctx *worker)
{
handle->data = worker;
uv_udp_recv_start(handle, &worker_alloc, &worker_recv);
}
void worker_stop(uv_udp_t *handle)
{
uv_udp_recv_stop(handle);
}
/* 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 <uv.h>
#include <libknot/mempattern.h>
#include "lib/resolve.h"
struct worker_ctx {
struct kr_context resolve;
mm_ctx_t *pool;
};
void worker_init(struct worker_ctx *worker, mm_ctx_t *mm);
void worker_deinit(struct worker_ctx *worker);
void worker_start(uv_udp_t *req, struct worker_ctx *worker);
void worker_stop(uv_udp_t *req);
daemon/layer/query.c
daemon/layer/query.h
daemon/main.c
daemon/worker.c
daemon/worker.h
include/kgetdns.h
lib/layer/iterate.c
lib/layer/iterate.h
......@@ -5,8 +10,8 @@ lib/layer/static.c
lib/layer/static.h
lib/context.c
lib/context.h
lib/layer.h
lib/resolve.c
lib/resolve.h
tests/context.c
tests/resolve.c
lib/layer.h
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