]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
resolve: hey, it's iteratively solving a name!
authorMarek Vavruša <marek.vavrusa@nic.cz>
Mon, 4 Aug 2014 17:44:33 +0000 (19:44 +0200)
committerMarek Vavruša <marek.vavrusa@nic.cz>
Mon, 4 Aug 2014 17:44:33 +0000 (19:44 +0200)
17 files changed:
.gitignore
Makefile.am
configure.ac
knot-resolver.files
lib/Makefile.am
lib/context.c [new file with mode: 0644]
lib/context.h [new file with mode: 0644]
lib/layer/iterate.c [new file with mode: 0644]
lib/layer/iterate.h [new file with mode: 0644]
lib/layer/static.c [new file with mode: 0644]
lib/layer/static.h [new file with mode: 0644]
lib/resolve.c [new file with mode: 0644]
lib/resolve.h [new file with mode: 0644]
tests/Makefile.am [new file with mode: 0644]
tests/context.c [new file with mode: 0644]
tests/resolve.c [new file with mode: 0644]
tests/runtests [new file with mode: 0755]

index 0c553423b3259ef0a81ade631ebecc65230aa595..eb1c16e6cc7d040fab1b3c2450986e9b719de021 100644 (file)
@@ -2,10 +2,13 @@
 *.a
 *.so
 *.so.*
+*.lo
+*.la
 *.in
 *.Plo
 *.swp
 .libs
+.deps
 autom4te.cache/*
 config.*
 configure
index a3b80f681ec80dd633a1008fd9ad7c451c1d4fa9..790e539c279ebc2b92f36620ca8699ac37216ff7 100644 (file)
@@ -1,2 +1,2 @@
 ACLOCAL_AMFLAGS = -I m4
-SUBDIRS = lib 
+SUBDIRS = lib tests
index 0060927ecc26b9009a02106dd6d340ac626cba49..691cfbef00179b6e610979fe60c802df1bff2330 100644 (file)
@@ -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
index 2fb2f9d0b0dc8940890c1d7fbaa4bdeb48a06a03..1b8b7faad61084624419498fbff6b54da59cbd88 100644 (file)
@@ -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
index 81bb495e7c458fe106cc3075d255e883435568a8..c64e8bbb6abd80ae37644f6a2c8335f165bc4080 100644 (file)
@@ -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 (file)
index 0000000..b25eae1
--- /dev/null
@@ -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 (file)
index 0000000..551deaa
--- /dev/null
@@ -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 (file)
index 0000000..5662099
--- /dev/null
@@ -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 (file)
index 0000000..e8f9f7e
--- /dev/null
@@ -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 (file)
index 0000000..e69de29
diff --git a/lib/layer/static.h b/lib/layer/static.h
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/lib/resolve.c b/lib/resolve.c
new file mode 100644 (file)
index 0000000..da9c94d
--- /dev/null
@@ -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 (file)
index 0000000..ac6d799
--- /dev/null
@@ -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 (file)
index 0000000..dab72e6
--- /dev/null
@@ -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 (file)
index 0000000..72ce3aa
--- /dev/null
@@ -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 (file)
index 0000000..50f5362
--- /dev/null
@@ -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 (executable)
index 0000000..483d111
--- /dev/null
@@ -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