Commit 63a87dd6 authored by Marek Vavruša's avatar Marek Vavruša

resolve: hey, it's iteratively solving a name!

parent d442fe7b
......@@ -2,10 +2,13 @@
*.a
*.so
*.so.*
*.lo
*.la
*.in
*.Plo
*.swp
.libs
.deps
autom4te.cache/*
config.*
configure
......
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = lib
SUBDIRS = lib tests
......@@ -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
......
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
......@@ -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
#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;
}
/* 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);
/* 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;
}
/* 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;
};
#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;
}
/* 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
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)
#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);
}
#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);
}
#!/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
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