diff --git a/knot-resolver.files b/knot-resolver.files index cfde92e6f74a4990973d93f8fa0f2bd0c23b7297..0046274403daa6663e8a21b5f348ae9013e05691 100644 --- a/knot-resolver.files +++ b/knot-resolver.files @@ -15,3 +15,5 @@ lib/resolve.c lib/resolve.h tests/context.c tests/resolve.c +lib/nslist.h +lib/nslist.c diff --git a/lib/Makefile.am b/lib/Makefile.am index 817be935671a9865717940c65b14f0ceb26de2f2..1aa76b50413976e2c74dfbb83db53c0375ad3cd1 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -11,4 +11,6 @@ libknotresolve_la_SOURCES = \ context.h \ context.c \ resolve.h \ - resolve.c + resolve.c \ + nslist.c \ + nslist.h diff --git a/lib/context.c b/lib/context.c index 91d55eb321f9f84a74b75c95e978a2f7f39ae233..56d19fb2a6a5298632e3605c2e72563fb59f8f05 100644 --- a/lib/context.c +++ b/lib/context.c @@ -2,89 +2,7 @@ #include <sys/time.h> #include <common/sockaddr.h> -#include "context.h" - -/* TODO: debug, remove */ -#ifndef NDEBUG -static void print_slist(struct kr_context *ctx) -{ - char *sname = knot_dname_to_str(ctx->sname); - printf("SLIST(%s): \n", sname); - free(sname); - struct kr_ns *ns = NULL; - WALK_LIST(ns, ctx->slist) { - char *strname = knot_dname_to_str(ns->name); - char addr_str[SOCKADDR_STRLEN]; - sockaddr_tostr(&ns->addr, addr_str, sizeof(addr_str)); - printf("[%d] %s:%s ", ns->closeness, strname, addr_str); - free(strname); - } - printf("\n"); -} -#endif - -/*! \brief Initialize NS descriptor. */ -static struct kr_ns *init_ns(mm_ctx_t *mm, const knot_dname_t *name, - const struct sockaddr *addr) -{ - struct kr_ns *ns = mm_alloc(mm, sizeof(struct kr_ns)); - if (ns == NULL) { - return NULL; - } - - memset(ns, 0, sizeof(struct kr_ns)); - ns->name = knot_dname_copy(name, mm); - if (ns->name == NULL) { - mm_free(mm, ns); - return NULL; - } - - memcpy(&ns->addr, addr, sockaddr_len(addr)); - - return ns; -} - -/*! \brief Insert before an item. */ -static void insert_before(struct kr_ns *cur, struct kr_ns *inserted) -{ - insert_node((node_t *)inserted, (node_t *)cur); - rem_node((node_t *)cur); - insert_node((node_t *)cur, (node_t *)inserted); -} - -/*! \brief Calculate closeness (# of common labels with sname). */ -static unsigned closeness_score(const knot_dname_t *sname, const knot_dname_t *zone) -{ - /* Longer or non-equal names of the same length can't contain delegations. */ - if (sname && (knot_dname_is_sub(sname, zone) || knot_dname_is_equal(zone, sname))) { - return KNOT_DNAME_MAXLABELS - knot_dname_matched_labels(zone, sname); - } - - return KNOT_DNAME_MAXLABELS + 1; /* N/A */ -} - -/* \brief (Re)insert name server to SLIST. */ -static void insert_ns(struct kr_context *ctx, struct kr_ns *ns) -{ - struct kr_ns *it = NULL; - WALK_LIST(it, ctx->slist) { - if (it->closeness > ns->closeness) { - insert_before(it, ns); - return; - } - } - - /* No closer match found. */ - add_tail(&ctx->slist, (node_t *)ns); -} - -/*! \brief Remove NS descriptor. */ -static void remove_ns(mm_ctx_t *mm, struct kr_ns *ns) -{ - rem_node((node_t *)ns); - mm_free(mm, ns->name); - mm_free(mm, ns); -} +#include "lib/context.h" int kr_context_init(struct kr_context *ctx, mm_ctx_t *mm) { @@ -136,67 +54,3 @@ int kr_result_deinit(struct kr_result *result) return 0; } - -int kr_slist_init(struct kr_context *ctx) -{ - init_list(&ctx->slist); - - return 0; -} - -int kr_slist_clear(struct kr_context *ctx) -{ - while(kr_slist_pop(ctx) == 0) - ; - - return 0; -} - -int kr_slist_add(struct kr_context *ctx, const knot_dname_t *name, const struct sockaddr *addr) -{ - struct kr_ns *ns = init_ns(ctx->pool, name, addr); - if (ns == NULL) { - return -1; - } - - insert_ns(ctx, ns); - - return 0; -} - -struct kr_ns *kr_slist_top(struct kr_context *ctx) -{ - if (EMPTY_LIST(ctx->slist)) { - return NULL; - } - - return (struct kr_ns *)HEAD(ctx->slist); -} - -int kr_slist_sort(struct kr_context *ctx) -{ - list_t copy = ctx->slist; - init_list(&ctx->slist); - - /* Recalculate closeness and reinsert. */ - struct kr_ns *it = NULL, *next = NULL; - WALK_LIST_DELSAFE(it, next, copy) { - it->closeness = closeness_score(ctx->sname, it->name); - insert_ns(ctx, it); - } - - return 0; -} - -int kr_slist_pop(struct kr_context *ctx) -{ - struct kr_ns *top = kr_slist_top(ctx); - if (top == NULL) { - return -1; - } - - - remove_ns(ctx->pool, top); - - return 0; -} diff --git a/lib/context.h b/lib/context.h index 75133166e9e65f07881c96265d67ba7fa37dd679..3ac513cc115eed33d42d3ea5a39dcf8feed3ee64 100644 --- a/lib/context.h +++ b/lib/context.h @@ -17,20 +17,11 @@ limitations under the License. #include <stdint.h> #include <libknot/mempattern.h> -#include <libknot/packet/pkt.h> #warning TODO: this is private define -#include <common/lists.h> #include <common/sockaddr.h> -/*! \brief Name server information. */ -struct kr_ns { - node_t node; - knot_dname_t *name; - struct sockaddr_storage addr; - unsigned mean_rtt; - unsigned closeness; -}; +#include "lib/nslist.h" /*! \brief Name resolution result. */ struct kr_result { @@ -59,11 +50,4 @@ int kr_context_reset(struct kr_context *ctx); int kr_context_deinit(struct kr_context *ctx); int kr_result_init(struct kr_context *ctx, struct kr_result *result); -int kr_result_deinit(struct kr_result *result); - -int kr_slist_init(struct kr_context *ctx); -int kr_slist_clear(struct kr_context *ctx); -int kr_slist_add(struct kr_context *ctx, const knot_dname_t *name, const struct sockaddr *addr); -struct kr_ns *kr_slist_top(struct kr_context *ctx); -int kr_slist_sort(struct kr_context *ctx); -int kr_slist_pop(struct kr_context *ctx); \ No newline at end of file +int kr_result_deinit(struct kr_result *result); \ No newline at end of file diff --git a/lib/nslist.c b/lib/nslist.c new file mode 100644 index 0000000000000000000000000000000000000000..1edc371b75e7a96b23bebe9321a9b8b4cc59f966 --- /dev/null +++ b/lib/nslist.c @@ -0,0 +1,150 @@ +#include "lib/nslist.h" +#include "lib/context.h" + + +/* TODO: debug, remove */ +#ifndef NDEBUG +static void print_slist(struct kr_context *ctx) +{ + char *sname = knot_dname_to_str(ctx->sname); + printf("SLIST(%s): \n", sname); + free(sname); + struct kr_ns *ns = NULL; + WALK_LIST(ns, ctx->slist) { + char *strname = knot_dname_to_str(ns->name); + char addr_str[SOCKADDR_STRLEN]; + sockaddr_tostr(&ns->addr, addr_str, sizeof(addr_str)); + printf("[%d] %s:%s ", ns->closeness, strname, addr_str); + free(strname); + } + printf("\n"); +} +#endif + +/*! \brief Initialize NS descriptor. */ +static struct kr_ns *init_ns(mm_ctx_t *mm, const knot_dname_t *name, + const struct sockaddr *addr) +{ + struct kr_ns *ns = mm_alloc(mm, sizeof(struct kr_ns)); + if (ns == NULL) { + return NULL; + } + + memset(ns, 0, sizeof(struct kr_ns)); + ns->name = knot_dname_copy(name, mm); + if (ns->name == NULL) { + mm_free(mm, ns); + return NULL; + } + + memcpy(&ns->addr, addr, sockaddr_len(addr)); + + return ns; +} + + +/*! \brief Insert before an item. */ +static void insert_before(struct kr_ns *cur, struct kr_ns *inserted) +{ + insert_node((node_t *)inserted, (node_t *)cur); + rem_node((node_t *)cur); + insert_node((node_t *)cur, (node_t *)inserted); +} + +/*! \brief Calculate closeness (# of common labels with sname). */ +static unsigned closeness_score(const knot_dname_t *sname, const knot_dname_t *zone) +{ + /* Longer or non-equal names of the same length can't contain delegations. */ + if (sname && (knot_dname_is_sub(sname, zone) || knot_dname_is_equal(zone, sname))) { + return KNOT_DNAME_MAXLABELS - knot_dname_matched_labels(zone, sname); + } + + return KNOT_DNAME_MAXLABELS + 1; /* N/A */ +} + +/* \brief (Re)insert name server to SLIST. */ +static void insert_ns(struct kr_context *ctx, struct kr_ns *ns) +{ + struct kr_ns *it = NULL; + WALK_LIST(it, ctx->slist) { + if (it->closeness > ns->closeness) { + insert_before(it, ns); + return; + } + } + + /* No closer match found. */ + add_tail(&ctx->slist, (node_t *)ns); +} + +/*! \brief Remove NS descriptor. */ +static void remove_ns(mm_ctx_t *mm, struct kr_ns *ns) +{ + rem_node((node_t *)ns); + mm_free(mm, ns->name); + mm_free(mm, ns); +} + +int kr_slist_init(struct kr_context *ctx) +{ + init_list(&ctx->slist); + + return 0; +} + +int kr_slist_clear(struct kr_context *ctx) +{ + while(kr_slist_pop(ctx) == 0) + ; + + return 0; +} + +int kr_slist_add(struct kr_context *ctx, const knot_dname_t *name, const struct sockaddr *addr) +{ + struct kr_ns *ns = init_ns(ctx->pool, name, addr); + if (ns == NULL) { + return -1; + } + + insert_ns(ctx, ns); + + return 0; +} + +struct kr_ns *kr_slist_top(struct kr_context *ctx) +{ + if (EMPTY_LIST(ctx->slist)) { + return NULL; + } + + return (struct kr_ns *)HEAD(ctx->slist); +} + +int kr_slist_sort(struct kr_context *ctx) +{ + list_t copy = ctx->slist; + init_list(&ctx->slist); + + /* Recalculate closeness and reinsert. */ + struct kr_ns *it = NULL, *next = NULL; + WALK_LIST_DELSAFE(it, next, copy) { + it->closeness = closeness_score(ctx->sname, it->name); + insert_ns(ctx, it); + } + + return 0; +} + +int kr_slist_pop(struct kr_context *ctx) +{ + struct kr_ns *top = kr_slist_top(ctx); + if (top == NULL) { + return -1; + } + + + remove_ns(ctx->pool, top); + + return 0; +} \ No newline at end of file diff --git a/lib/nslist.h b/lib/nslist.h new file mode 100644 index 0000000000000000000000000000000000000000..9910e380cd0bc869e9e71740416435d0608c02ba --- /dev/null +++ b/lib/nslist.h @@ -0,0 +1,40 @@ +/* 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/packet/pkt.h> + +#warning TODO: this is private define +#include <common/lists.h> +#include <common/sockaddr.h> + +struct kr_context; + +/*! \brief Name server information. */ +struct kr_ns { + node_t node; + knot_dname_t *name; + struct sockaddr_storage addr; + unsigned mean_rtt; + unsigned closeness; +}; + +int kr_slist_init(struct kr_context *ctx); +int kr_slist_clear(struct kr_context *ctx); +int kr_slist_add(struct kr_context *ctx, const knot_dname_t *name, const struct sockaddr *addr); +struct kr_ns *kr_slist_top(struct kr_context *ctx); +int kr_slist_sort(struct kr_context *ctx); +int kr_slist_pop(struct kr_context *ctx); \ No newline at end of file