summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--Makefile.am2
-rw-r--r--configure.ac7
-rw-r--r--knot-resolver.files8
-rw-r--r--lib/Makefile.am8
-rw-r--r--lib/context.c16
-rw-r--r--lib/context.h49
-rw-r--r--lib/layer/iterate.c128
-rw-r--r--lib/layer/iterate.h31
-rw-r--r--lib/layer/static.c0
-rw-r--r--lib/layer/static.h0
-rw-r--r--lib/resolve.c67
-rw-r--r--lib/resolve.h21
-rw-r--r--tests/Makefile.am18
-rw-r--r--tests/context.c26
-rw-r--r--tests/resolve.c30
-rwxr-xr-xtests/runtests18
17 files changed, 429 insertions, 3 deletions
diff --git a/.gitignore b/.gitignore
index 0c553423..eb1c16e6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,10 +2,13 @@
*.a
*.so
*.so.*
+*.lo
+*.la
*.in
*.Plo
*.swp
.libs
+.deps
autom4te.cache/*
config.*
configure
diff --git a/Makefile.am b/Makefile.am
index a3b80f68..790e539c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,2 +1,2 @@
ACLOCAL_AMFLAGS = -I m4
-SUBDIRS = lib
+SUBDIRS = lib tests
diff --git a/configure.ac b/configure.ac
index 0060927e..691cfbef 100644
--- a/configure.ac
+++ b/configure.ac
@@ -29,15 +29,20 @@ LT_INIT
# Use pkg-config
PKG_PROG_PKG_CONFIG
+# Check for dependencies
+AM_CHECK_CMOCKA
+AM_CHECK_LIBUV
+
# Check headers
AC_CHECK_HEADERS([stdlib.h],,, [AC_INCLUDES_DEFAULT])
# Search libraries
-AC_SEARCH_LIBS([socket], [socket])
+AC_SEARCH_LIBS([knot_rrset_clear], [knot])
# Config files
AC_CONFIG_FILES([Makefile
lib/Makefile
+ tests/Makefile
])
# Output
diff --git a/knot-resolver.files b/knot-resolver.files
index 2fb2f9d0..1b8b7faa 100644
--- a/knot-resolver.files
+++ b/knot-resolver.files
@@ -1,3 +1,11 @@
include/kgetdns.h
+lib/layer/iterate.c
+lib/layer/iterate.h
+lib/layer/static.c
+lib/layer/static.h
lib/context.c
lib/context.h
+lib/resolve.c
+lib/resolve.h
+tests/context.c
+tests/resolve.c
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 81bb495e..c64e8bbb 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -3,5 +3,11 @@ SUBDIRS = .
lib_LTLIBRARIES = libknotresolve.la
libknotresolve_la_SOURCES = \
+ layer/iterate.h \
+ layer/iterate.c \
+ layer/static.h \
+ layer/static.c \
context.h \
- context.c
+ context.c \
+ resolve.h \
+ resolve.c
diff --git a/lib/context.c b/lib/context.c
new file mode 100644
index 00000000..b25eae14
--- /dev/null
+++ b/lib/context.c
@@ -0,0 +1,16 @@
+#include <string.h>
+
+#include "context.h"
+
+int kresolve_ctx_init(struct kresolve_ctx *ctx, mm_ctx_t *mm)
+{
+ memset(ctx, 0, sizeof(struct kresolve_ctx));
+ ctx->mm = mm;
+ return 0;
+}
+
+int kresolve_ctx_close(struct kresolve_ctx *ctx)
+{
+ /* free requestor, pending queries. */
+ return -1;
+}
diff --git a/lib/context.h b/lib/context.h
new file mode 100644
index 00000000..551deaa4
--- /dev/null
+++ b/lib/context.h
@@ -0,0 +1,49 @@
+/* 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 <stdint.h>
+#include <libknot/mempattern.h>
+#include <libknot/packet/pkt.h>
+
+/*! \brief Name resolution result. */
+struct kresolve_result {
+ /* Nameserver. */
+ struct {
+ const knot_dname_t *name;
+ struct sockaddr_storage addr;
+ } ns;
+ /* Query */
+ const knot_dname_t *qname;
+ uint16_t qtype;
+ uint16_t qclass;
+ /* Result */
+ const knot_dname_t *cname;
+ uint16_t rcode;
+ knot_rrset_t *data[32];
+ unsigned count;
+ unsigned flags;
+};
+
+/*! \brief Name resolution context. */
+struct kresolve_ctx {
+ mm_ctx_t *mm;
+ unsigned state;
+ unsigned options;
+};
+
+int kresolve_ctx_init(struct kresolve_ctx *ctx, mm_ctx_t *mm);
+int kresolve_ctx_close(struct kresolve_ctx *ctx);
diff --git a/lib/layer/iterate.c b/lib/layer/iterate.c
new file mode 100644
index 00000000..5662099b
--- /dev/null
+++ b/lib/layer/iterate.c
@@ -0,0 +1,128 @@
+/* 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 <libknot/descriptor.h>
+#include <libknot/rrtype/rdname.h>
+#include <libknot/rrtype/aaaa.h>
+
+#include "lib/layer/iterate.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; }
+
+/* Set resolution context and parameters. */
+static int begin(knot_process_t *ctx, void *module_param)
+{
+ ctx->data = module_param;
+ return NS_PROC_MORE;
+}
+
+/* Resolve input query or continue resolution with followups. */
+static int resolve(knot_pkt_t *pkt, knot_process_t *ctx)
+{
+ assert(pkt && ctx);
+ struct layer_iterate_param *param = ctx->data;
+
+ struct kresolve_ctx *resolution = param->ctx;
+ struct kresolve_result *result = param->result;
+
+ /* Is the answer authoritative? */
+ bool is_aa = knot_wire_get_aa(pkt->wire);
+ printf("got packet: AA? %d RRs %d RCODE %d\n", is_aa, pkt->rrset_count, knot_wire_get_rcode(pkt->wire));
+ if (is_aa) {
+ /* Add results to the answer section. */
+ const knot_pktsection_t *an = knot_pkt_section(pkt, KNOT_ANSWER);
+ for (unsigned i = 0; i < an->count; ++i) {
+ knot_rrset_t *copy = knot_rrset_copy(an->rr + i, resolution->mm);
+ result->data[result->count] = copy;
+ result->count += 1;
+ }
+ /* Store canonical name. */
+ result->cname = knot_dname_copy(knot_pkt_qname(pkt), resolution->mm);
+ /* TODO: store flags */
+ /* Finished. */
+ resolution->state = NS_PROC_DONE;
+ } else {
+ /* Is there a NS to add into SLIST? */
+ knot_pktsection_t *ns = knot_pkt_section(pkt, KNOT_AUTHORITY);
+ result->ns.name = NULL;
+ memset(&result->ns.addr, 0, sizeof(result->ns.addr));
+ for (unsigned i = 0; i < ns->count; ++i) {
+ if (ns->rr[i].type == KNOT_RRTYPE_NS) {
+ result->ns.name = knot_ns_name(&ns->rr[i].rrs, 0);
+ /* TODO: fill SLIST */
+ printf("next nameserver: %s\n", knot_dname_to_str(result->ns.name));
+ break;
+ }
+ }
+
+ /* No next nameserver? */
+ if (result->ns.name == NULL) {
+ printf("no next nameserver\n");
+ resolution->state = NS_PROC_FAIL;
+ return NS_PROC_FAIL;
+ }
+
+ /* Is the address in additional records? */
+ knot_pktsection_t *ar = knot_pkt_section(pkt, KNOT_ADDITIONAL);
+ for (unsigned i = 0; i < ar->count; ++i) {
+ printf("checking additional: %s type %d\n", knot_dname_to_str(ar->rr[i].owner), ar->rr[i].type);
+ if (knot_dname_is_equal(result->ns.name, ar->rr[i].owner)) {
+
+ /* Fill next server address. */
+ switch(ar->rr[i].type) {
+ case KNOT_RRTYPE_A:
+ knot_a_addr(&ar->rr[i].rrs, 0, &result->ns.addr);
+ break;
+ case KNOT_RRTYPE_AAAA:
+ knot_aaaa_addr(&ar->rr[i].rrs, 0, &result->ns.addr);
+ break;
+ default:
+ resolution->state = NS_PROC_FAIL;
+ return NS_PROC_FAIL;
+ }
+
+ /* Fill port. */
+ sockaddr_port_set(&result->ns.addr, 53);
+
+ break;
+ }
+ }
+
+ char tmpbuf[512];
+ sockaddr_tostr(&result->ns.addr, tmpbuf, 512);
+ printf("next addr: %s\n", tmpbuf);
+ }
+
+ printf("done\n");
+
+ return NS_PROC_DONE;
+}
+
+/*! \brief Module implementation. */
+static const knot_process_module_t LAYER_ITERATE_MODULE = {
+ &begin,
+ &reset,
+ &finish,
+ &resolve,
+ &knot_process_noop, /* No output. */
+ &knot_process_noop /* No error processing. */
+};
+
+const knot_process_module_t *layer_iterate_module(void)
+{
+ return &LAYER_ITERATE_MODULE;
+}
diff --git a/lib/layer/iterate.h b/lib/layer/iterate.h
new file mode 100644
index 00000000..e8f9f7e0
--- /dev/null
+++ b/lib/layer/iterate.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 <libknot/processing/process.h>
+#include "lib/context.h"
+
+/* Processing module implementation. */
+const knot_process_module_t *layer_iterate_module(void);
+#define LAYER_ITERATE layer_iterate_module()
+
+/*!
+ * \brief Processing module parameters.
+ */
+struct layer_iterate_param {
+ struct kresolve_ctx *ctx;
+ struct kresolve_result *result;
+};
diff --git a/lib/layer/static.c b/lib/layer/static.c
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/lib/layer/static.c
diff --git a/lib/layer/static.h b/lib/layer/static.h
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/lib/layer/static.h
diff --git a/lib/resolve.c b/lib/resolve.c
new file mode 100644
index 00000000..da9c94d1
--- /dev/null
+++ b/lib/resolve.c
@@ -0,0 +1,67 @@
+#include <stdio.h>
+#include <uv.h>
+
+#include <libknot/processing/requestor.h>
+#include "lib/resolve.h"
+#include "lib/layer/iterate.h"
+#include "lib/layer/static.h"
+
+/* TODO: temporary */
+#include <libknot/rrset-dump.h>
+
+int kresolve_resolve(struct kresolve_ctx* ctx, struct kresolve_result* result,
+ const knot_dname_t *qname, uint16_t qclass, uint16_t qtype)
+{
+ /* TODO: how to load all the layers? no API support yet */
+ struct knot_requestor req;
+ memset(result, 0, sizeof(struct kresolve_result));
+ result->qname = qname;
+ result->qclass = qclass;
+ result->qtype = qtype;
+ result->rcode = KNOT_RCODE_SERVFAIL;
+
+ /* TODO: layer logic, where to? do one iteration step now */
+ struct layer_iterate_param param;
+ param.ctx = ctx;
+ param.result = result;
+ knot_requestor_init(&req, LAYER_ITERATE, ctx->mm);
+
+ /* TODO: read root hints. */
+ struct sockaddr_in root = uv_ip4_addr("198.41.0.4", 53);
+ result->ns.name = NULL;
+ memcpy(&result->ns.addr, &root, sizeof(root));
+
+ /* Resolve. */
+ ctx->state = NS_PROC_MORE;
+ struct timeval tv = { 5, 0 };
+ while (ctx->state == NS_PROC_MORE) {
+ printf("execing\n");
+ /* Create name resolution result structure and prepare first query. */
+ knot_pkt_t *query = knot_pkt_new(NULL, KNOT_WIRE_MIN_PKTSIZE, ctx->mm);
+ if (query == NULL) {
+ return -1;
+ }
+ knot_pkt_put_question(query, qname, qclass, qtype);
+ /* Check if the next address is valid. */
+ struct knot_request *tx = knot_requestor_make(&req, &result->ns.addr, NULL, query);
+ knot_requestor_enqueue(&req, tx, &param);
+ knot_requestor_exec(&req, &tv);
+ printf("exec'd\n");
+ }
+ knot_requestor_clear(&req);
+
+ char *qnamestr = knot_dname_to_str(qname);
+ char *cnamestr = knot_dname_to_str(result->cname);
+ printf("resolution of %s -> %s\n", qnamestr, cnamestr);
+ free(qnamestr); free(cnamestr);
+ printf("rcode = %d (%u RR)\n", result->rcode, result->count);
+ char strbuf[4096] = {0}; int buflen = sizeof(strbuf);
+ knot_dump_style_t style = {0};
+ for (unsigned i = 0; i < result->count; ++i) {
+ int r = knot_rrset_txt_dump(result->data[i], strbuf, buflen, &style);
+ if (r > 0) buflen -= r;
+ }
+ printf("%s\n", strbuf);
+
+ return 0;
+}
diff --git a/lib/resolve.h b/lib/resolve.h
new file mode 100644
index 00000000..ac6d799c
--- /dev/null
+++ b/lib/resolve.h
@@ -0,0 +1,21 @@
+/* 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 "context.h"
+
+int kresolve_resolve(struct kresolve_ctx* ctx, struct kresolve_result* result,
+ const knot_dname_t *qname, uint16_t qclass, uint16_t qtype); \ No newline at end of file
diff --git a/tests/Makefile.am b/tests/Makefile.am
new file mode 100644
index 00000000..dab72e6d
--- /dev/null
+++ b/tests/Makefile.am
@@ -0,0 +1,18 @@
+AM_CPPFLAGS = \
+ -include $(top_builddir)/config.h \
+ -I$(top_srcdir)/lib
+
+LDADD = \
+ $(top_builddir)/lib/libknotresolve.la \
+ $(KNOT_LIBS) \
+ $(libuv_LIBS) \
+ $(cmocka_LIBS)
+
+check_PROGRAMS = \
+ context \
+ resolve
+
+check-compile-only: $(check_PROGRAMS)
+
+check-local: $(check_PROGRAMS)
+ $(top_builddir)/tests/runtests -b $(top_builddir)/tests $(check_PROGRAMS)
diff --git a/tests/context.c b/tests/context.c
new file mode 100644
index 00000000..72ce3aad
--- /dev/null
+++ b/tests/context.c
@@ -0,0 +1,26 @@
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+#include <libknot/mempattern.h>
+#include "lib/context.h"
+
+/* \note Create context and close it. */
+static void tests_ctx_create(void **state)
+{
+ mm_ctx_t mm;
+ mm_ctx_init(&mm);
+ struct kresolve_ctx ctx;
+ assert_int_equal(kresolve_ctx_init(&ctx, &mm), 0);
+ assert_int_equal(kresolve_ctx_close(&ctx), 0);
+}
+
+int main(void)
+{
+ const UnitTest tests[] = {
+ unit_test(tests_ctx_create),
+ };
+
+ return run_tests(tests);
+}
diff --git a/tests/resolve.c b/tests/resolve.c
new file mode 100644
index 00000000..50f53629
--- /dev/null
+++ b/tests/resolve.c
@@ -0,0 +1,30 @@
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+#include <libknot/mempattern.h>
+#include <libknot/descriptor.h>
+#include "lib/resolve.h"
+
+/* \note Synchronous resolution. */
+void test_resolve_sync(void **state)
+{
+ struct kresolve_ctx ctx;
+ kresolve_ctx_init(&ctx, NULL);
+ struct kresolve_result res;
+ const knot_dname_t *qname = (const uint8_t *)"\x06""dnssec""\x02""cz";
+ int ret = kresolve_resolve(&ctx, &res, qname, KNOT_CLASS_IN, KNOT_RRTYPE_A);
+ assert_int_equal(ret, 0);
+ kresolve_ctx_close(&ctx);
+}
+
+int main(void)
+{
+ const UnitTest tests[] = {
+ unit_test(test_resolve_sync),
+ };
+
+ return run_tests(tests);
+}
diff --git a/tests/runtests b/tests/runtests
new file mode 100755
index 00000000..483d1111
--- /dev/null
+++ b/tests/runtests
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+# Parse options
+BASEDIR="."
+eval set -- `getopt b: "$@"`
+while [ $# -gt 0 ]; do
+ case "$1" in
+ -b) BASEDIR="$2"; shift;;
+ --) shift; break;;
+ esac
+ shift
+done
+
+# Process tests
+while [ $# -gt 0 ]; do
+ ${BASEDIR}/$1
+ shift
+done