diff options
-rw-r--r-- | .gitignore | 3 | ||||
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | configure.ac | 7 | ||||
-rw-r--r-- | knot-resolver.files | 8 | ||||
-rw-r--r-- | lib/Makefile.am | 8 | ||||
-rw-r--r-- | lib/context.c | 16 | ||||
-rw-r--r-- | lib/context.h | 49 | ||||
-rw-r--r-- | lib/layer/iterate.c | 128 | ||||
-rw-r--r-- | lib/layer/iterate.h | 31 | ||||
-rw-r--r-- | lib/layer/static.c | 0 | ||||
-rw-r--r-- | lib/layer/static.h | 0 | ||||
-rw-r--r-- | lib/resolve.c | 67 | ||||
-rw-r--r-- | lib/resolve.h | 21 | ||||
-rw-r--r-- | tests/Makefile.am | 18 | ||||
-rw-r--r-- | tests/context.c | 26 | ||||
-rw-r--r-- | tests/resolve.c | 30 | ||||
-rwxr-xr-x | tests/runtests | 18 |
17 files changed, 429 insertions, 3 deletions
@@ -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, ¶m); + 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 |