diff --git a/lib/context.c b/lib/context.c index b25eae14fc8e3ea26f32e6e09350b58975a29278..b6b4293253369aa49ae8d8661a07dffac9523c71 100644 --- a/lib/context.c +++ b/lib/context.c @@ -1,16 +1,129 @@ #include <string.h> +#include <sys/time.h> +#include <common/sockaddr.h> #include "context.h" -int kresolve_ctx_init(struct kresolve_ctx *ctx, mm_ctx_t *mm) +/*! \brief Initialize NS descriptor. */ +static struct kr_ns *init_ns(mm_ctx_t *mm, const knot_dname_t *name, + const struct sockaddr *addr, unsigned closeness) { - memset(ctx, 0, sizeof(struct kresolve_ctx)); + 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)); + ns->closeness = closeness; + + return ns; +} + +/*! \brief Insert NS before an item. */ +static void insert_ns(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 Remove NS descriptor. */ +static void remove_ns(mm_ctx_t *mm, struct kr_ns *ns) +{ + mm_free(mm, ns->name); + mm_free(mm, ns); +} + +int kr_context_init(struct kr_context *ctx, mm_ctx_t *mm) +{ + memset(ctx, 0, sizeof(struct kr_context)); + ctx->mm = mm; + init_list(&ctx->slist); + return 0; } -int kresolve_ctx_close(struct kresolve_ctx *ctx) +int kr_context_close(struct kr_context *ctx) { - /* free requestor, pending queries. */ + /* TODO: free slist, pending queries. */ return -1; } + +int kr_result_init(struct kr_context *ctx, struct kr_result *result) +{ + memset(result, 0, sizeof(struct kr_result)); + + knot_pkt_t *ans = knot_pkt_new(NULL, KNOT_WIRE_MAX_PKTSIZE, ctx->mm); + if (ans == NULL) { + return -1; + } + + knot_pkt_put_question(ans, ctx->sname, ctx->sclass, ctx->stype); + knot_wire_set_rcode(ans->wire, KNOT_RCODE_SERVFAIL); + knot_wire_set_qr(ans->wire); + + result->ans = ans; + result->cname = ctx->sname; + gettimeofday(&result->t_start, NULL); + + return 0; +} + +int kr_result_clear(struct kr_result *result) +{ + knot_pkt_free(&result->ans); + + return 0; +} + +int kr_slist_add(struct kr_context *ctx, const knot_dname_t *name, const struct sockaddr *addr) +{ + /* Closeness is represented by a number of common labels. */ + int closeness = knot_dname_matched_labels(name, ctx->sname); + + struct kr_ns *ns = init_ns(ctx->mm, name, addr, closeness); + if (ns == NULL) { + return -1; + } + + struct kr_ns *iter = NULL; + WALK_LIST(iter, ctx->slist) { + if (iter->closeness < closeness) { + insert_ns(iter, ns); + return 0; + } + } + + /* No closer match found. */ + add_tail(&ctx->slist, (node_t *)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_pop(struct kr_context *ctx) +{ + struct kr_ns *top = kr_slist_top(ctx); + if (top) { + return -1; + } + + rem_node((node_t *)top); + remove_ns(ctx->mm, top); + return 0; +} diff --git a/lib/context.h b/lib/context.h index 551deaa441e2cf43b63ee36dd05d9ffdfec986b4..40571805a6ec01e5f3ddee5bb5bc197df9997580 100644 --- a/lib/context.h +++ b/lib/context.h @@ -19,31 +19,47 @@ limitations under the License. #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; +}; + /*! \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 */ +struct kr_result { const knot_dname_t *cname; - uint16_t rcode; - knot_rrset_t *data[32]; - unsigned count; + knot_pkt_t *ans; unsigned flags; + struct timeval t_start, t_end; + unsigned nr_queries; }; /*! \brief Name resolution context. */ -struct kresolve_ctx { +struct kr_context +{ + const knot_dname_t *sname; + uint16_t stype; + uint16_t sclass; + uint16_t next_id; + list_t slist; 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); +int kr_context_init(struct kr_context *ctx, mm_ctx_t *mm); +int kr_context_close(struct kr_context *ctx); + +int kr_result_init(struct kr_context *ctx, struct kr_result *result); +int kr_result_clear(struct kr_result *result); + +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_pop(struct kr_context *ctx); \ No newline at end of file