#include <common/sockaddr.h>
#include "context.h"
+/* \brief Root hint descriptor. */
+struct hint_info {
+ const char *name;
+ const char *addr;
+ const char *zone;
+};
+
+/* Initialize with SBELT name servers. */
+#define HINT_COUNT 13
+static const struct hint_info SBELT[HINT_COUNT] = {
+ { "a.root-servers.net.", "198.41.0.4", "." },
+ { "b.root-servers.net.", "192.228.79.201", "." },
+ { "c.root-servers.net.", "192.33.4.12", "." },
+ { "d.root-servers.net.", "199.7.91.13", "." },
+ { "e.root-servers.net.", "192.203.230.10", "." },
+ { "f.root-servers.net.", "192.5.5.241", "." },
+ { "g.root-servers.net.", "192.112.36.4", "." },
+ { "h.root-servers.net.", "128.63.2.53", "." },
+ { "i.root-servers.net.", "192.36.148.17", "." },
+ { "j.root-servers.net.", "192.58.128.30", "." },
+ { "k.root-servers.net.", "193.0.14.129", "." },
+ { "l.root-servers.net.", "199.7.83.42", "." },
+ { "m.root-servers.net.", "202.12.27.33", "." }
+};
+
+/* 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, unsigned closeness)
+ const struct sockaddr *addr)
{
struct kr_ns *ns = mm_alloc(mm, sizeof(struct kr_ns));
if (ns == 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)
+/*! \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);
}
{
memset(ctx, 0, sizeof(struct kr_context));
- ctx->mm = mm;
+ ctx->pool = mm;
init_list(&ctx->slist);
+ kr_context_reset(ctx);
return 0;
}
-int kr_context_close(struct kr_context *ctx)
+int kr_context_reset(struct kr_context *ctx)
+{
+ while(kr_slist_pop(ctx) == 0);
+
+ kr_slist_init(ctx);
+
+ return 0;
+}
+
+int kr_context_deinit(struct kr_context *ctx)
{
/* TODO: free slist, pending queries. */
return -1;
{
memset(result, 0, sizeof(struct kr_result));
- knot_pkt_t *ans = knot_pkt_new(NULL, KNOT_WIRE_MAX_PKTSIZE, ctx->mm);
+ knot_pkt_t *ans = knot_pkt_new(NULL, KNOT_WIRE_MAX_PKTSIZE, ctx->pool);
if (ans == NULL) {
return -1;
}
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)
+int kr_result_deinit(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)
+int kr_slist_init(struct kr_context *ctx)
{
- /* Closeness is represented by a number of common labels. */
- int closeness = knot_dname_matched_labels(name, ctx->sname);
+ int ret = 0;
+ struct sockaddr_storage ss;
+ for (unsigned i = 0; i < HINT_COUNT; ++i) {
+ ret = sockaddr_set(&ss, AF_INET, SBELT[i].addr, 53);
+ assert(ret == 0);
+ kr_slist_add(ctx, knot_dname_from_str(SBELT[i].zone),
+ (struct sockaddr *)&ss);
+ }
+
+ return 0;
+}
- struct kr_ns *ns = init_ns(ctx->mm, name, addr, closeness);
+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;
}
- struct kr_ns *iter = NULL;
- WALK_LIST(iter, ctx->slist) {
- if (iter->closeness < closeness) {
- insert_ns(iter, ns);
- return 0;
- }
- }
+ insert_ns(ctx, ns);
- /* No closer match found. */
- add_tail(&ctx->slist, (node_t *)ns);
return 0;
}
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) {
+ if (top == NULL) {
return -1;
}
- rem_node((node_t *)top);
- remove_ns(ctx->mm, top);
+ remove_ns(ctx->pool, top);
+
return 0;
}