From fd3cfa822b54252c533b8f75d2ee335673717740 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Vavru=C5=A1a?= <marek.vavrusa@nic.cz> Date: Fri, 8 Aug 2014 13:53:10 +0200 Subject: [PATCH] daemon: simple resolver daemon implementation --- Makefile.am | 2 +- configure.ac | 1 + daemon/Makefile.am | 17 +++++++++ daemon/layer/query.c | 84 ++++++++++++++++++++++++++++++++++++++++++++ daemon/layer/query.h | 22 ++++++++++++ daemon/main.c | 34 ++++++++++++++++++ daemon/worker.c | 77 ++++++++++++++++++++++++++++++++++++++++ daemon/worker.h | 31 ++++++++++++++++ knot-resolver.files | 7 +++- 9 files changed, 273 insertions(+), 2 deletions(-) create mode 100644 daemon/Makefile.am create mode 100644 daemon/layer/query.c create mode 100644 daemon/layer/query.h create mode 100644 daemon/main.c create mode 100644 daemon/worker.c create mode 100644 daemon/worker.h diff --git a/Makefile.am b/Makefile.am index 790e539c2..cff123807 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,2 +1,2 @@ ACLOCAL_AMFLAGS = -I m4 -SUBDIRS = lib tests +SUBDIRS = lib tests daemon diff --git a/configure.ac b/configure.ac index 691cfbef0..915d183b1 100644 --- a/configure.ac +++ b/configure.ac @@ -42,6 +42,7 @@ AC_SEARCH_LIBS([knot_rrset_clear], [knot]) # Config files AC_CONFIG_FILES([Makefile lib/Makefile + daemon/Makefile tests/Makefile ]) diff --git a/daemon/Makefile.am b/daemon/Makefile.am new file mode 100644 index 000000000..5544b0f3e --- /dev/null +++ b/daemon/Makefile.am @@ -0,0 +1,17 @@ +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) diff --git a/daemon/layer/query.c b/daemon/layer/query.c new file mode 100644 index 000000000..c39fd41e3 --- /dev/null +++ b/daemon/layer/query.c @@ -0,0 +1,84 @@ +/* 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; +} diff --git a/daemon/layer/query.h b/daemon/layer/query.h new file mode 100644 index 000000000..4f6c6e17b --- /dev/null +++ b/daemon/layer/query.h @@ -0,0 +1,22 @@ +/* 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() diff --git a/daemon/main.c b/daemon/main.c new file mode 100644 index 000000000..cc133b331 --- /dev/null +++ b/daemon/main.c @@ -0,0 +1,34 @@ +#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; +} diff --git a/daemon/worker.c b/daemon/worker.c new file mode 100644 index 000000000..3cda2f2af --- /dev/null +++ b/daemon/worker.c @@ -0,0 +1,77 @@ +#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, ¶m, 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); +} diff --git a/daemon/worker.h b/daemon/worker.h new file mode 100644 index 000000000..7312a6eda --- /dev/null +++ b/daemon/worker.h @@ -0,0 +1,31 @@ +/* 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); diff --git a/knot-resolver.files b/knot-resolver.files index df843b883..cfde92e6f 100644 --- a/knot-resolver.files +++ b/knot-resolver.files @@ -1,3 +1,8 @@ +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 -- GitLab