59d02b141d
Thsi can dynamically add/remove forwarding zones for when a VPN connection is up.
3317 lines
104 KiB
Diff
3317 lines
104 KiB
Diff
diff -Naur unbound-1.4.16/compat/memcmp.h unbound-trunk/compat/memcmp.h
|
|
--- unbound-1.4.16/compat/memcmp.h 1969-12-31 19:00:00.000000000 -0500
|
|
+++ unbound-trunk/compat/memcmp.h 2012-02-22 20:37:14.182368184 -0500
|
|
@@ -0,0 +1,16 @@
|
|
+/*
|
|
+ * memcmp.h: undef memcmp for compat.
|
|
+ *
|
|
+ * Copyright (c) 2012, NLnet Labs. All rights reserved.
|
|
+ *
|
|
+ * See LICENSE for the license.
|
|
+*/
|
|
+#ifndef COMPAT_MEMCMP_H
|
|
+#define COMPAT_MEMCMP_H
|
|
+
|
|
+#ifdef memcmp
|
|
+/* undef here otherwise autoheader messes it up in config.h */
|
|
+# undef memcmp
|
|
+#endif
|
|
+
|
|
+#endif /* COMPAT_MEMCMP_H */
|
|
diff -Naur unbound-1.4.16/daemon/cachedump.c unbound-trunk/daemon/cachedump.c
|
|
--- unbound-1.4.16/daemon/cachedump.c 2012-01-10 04:42:32.000000000 -0500
|
|
+++ unbound-trunk/daemon/cachedump.c 2012-02-22 20:37:15.803368186 -0500
|
|
@@ -765,7 +765,7 @@
|
|
if(!go_on)
|
|
return 1; /* skip this one, not all references satisfied */
|
|
|
|
- if(!dns_cache_store(&worker->env, &qinf, &rep, 0, 0, NULL)) {
|
|
+ if(!dns_cache_store(&worker->env, &qinf, &rep, 0, 0, 0, NULL)) {
|
|
log_warn("error out of memory");
|
|
return 0;
|
|
}
|
|
@@ -802,7 +802,8 @@
|
|
{
|
|
char buf[257];
|
|
struct delegpt_addr* a;
|
|
- int lame, dlame, rlame, rto, edns_vs, to, delay, entry_ttl;
|
|
+ int lame, dlame, rlame, rto, edns_vs, to, delay, entry_ttl,
|
|
+ tA = 0, tAAAA = 0, tother = 0;
|
|
struct rtt_info ri;
|
|
uint8_t edns_lame_known;
|
|
for(a = dp->target_list; a; a = a->next_target) {
|
|
@@ -817,9 +818,11 @@
|
|
delay=0;
|
|
entry_ttl = infra_get_host_rto(worker->env.infra_cache,
|
|
&a->addr, a->addrlen, dp->name, dp->namelen,
|
|
- &ri, &delay, *worker->env.now);
|
|
+ &ri, &delay, *worker->env.now, &tA, &tAAAA, &tother);
|
|
if(entry_ttl == -2 && ri.rto >= USEFUL_SERVER_TOP_TIMEOUT) {
|
|
- if(!ssl_printf(ssl, "expired, rto %d msec.\n", ri.rto))
|
|
+ if(!ssl_printf(ssl, "expired, rto %d msec, tA %d "
|
|
+ "tAAAA %d tother %d.\n", ri.rto, tA, tAAAA,
|
|
+ tother))
|
|
return;
|
|
continue;
|
|
}
|
|
@@ -840,11 +843,12 @@
|
|
continue; /* skip stuff not in infra cache */
|
|
}
|
|
if(!ssl_printf(ssl, "%s%s%s%srto %d msec, ttl %d, ping %d "
|
|
- "var %d rtt %d",
|
|
+ "var %d rtt %d, tA %d, tAAAA %d, tother %d",
|
|
lame?"LAME ":"", dlame?"NoDNSSEC ":"",
|
|
a->lame?"AddrWasParentSide ":"",
|
|
rlame?"NoAuthButRecursive ":"", rto, entry_ttl,
|
|
- ri.srtt, ri.rttvar, rtt_notimeout(&ri)))
|
|
+ ri.srtt, ri.rttvar, rtt_notimeout(&ri),
|
|
+ tA, tAAAA, tother))
|
|
return;
|
|
if(delay)
|
|
if(!ssl_printf(ssl, ", probedelay %d", delay))
|
|
@@ -907,19 +911,12 @@
|
|
char b[260];
|
|
struct query_info qinfo;
|
|
struct iter_hints_stub* stub;
|
|
- struct iter_env* ie;
|
|
regional_free_all(region);
|
|
qinfo.qname = nm;
|
|
qinfo.qname_len = nmlen;
|
|
qinfo.qtype = LDNS_RR_TYPE_A;
|
|
qinfo.qclass = LDNS_RR_CLASS_IN;
|
|
|
|
- if(modstack_find(&worker->daemon->mods, "iterator") == -1) {
|
|
- return ssl_printf(ssl, "error: no iterator module\n");
|
|
- }
|
|
- ie = (struct iter_env*)worker->env.modinfo[modstack_find(&worker->
|
|
- daemon->mods, "iterator")];
|
|
-
|
|
dname_str(nm, b);
|
|
if(!ssl_printf(ssl, "The following name servers are used for lookup "
|
|
"of %s\n", b))
|
|
@@ -964,7 +961,8 @@
|
|
continue;
|
|
}
|
|
}
|
|
- stub = hints_lookup_stub(ie->hints, nm, qinfo.qclass, dp);
|
|
+ stub = hints_lookup_stub(worker->env.hints, nm, qinfo.qclass,
|
|
+ dp);
|
|
if(stub) {
|
|
if(stub->noprime) {
|
|
if(!ssl_printf(ssl, "The noprime stub servers "
|
|
diff -Naur unbound-1.4.16/daemon/remote.c unbound-trunk/daemon/remote.c
|
|
--- unbound-1.4.16/daemon/remote.c 2011-11-10 13:44:06.000000000 -0500
|
|
+++ unbound-trunk/daemon/remote.c 2012-02-22 20:37:15.804368186 -0500
|
|
@@ -68,6 +68,7 @@
|
|
#include "validator/validator.h"
|
|
#include "validator/val_kcache.h"
|
|
#include "validator/val_kentry.h"
|
|
+#include "validator/val_anchor.h"
|
|
#include "iterator/iterator.h"
|
|
#include "iterator/iter_fwd.h"
|
|
#include "iterator/iter_hints.h"
|
|
@@ -1337,15 +1338,15 @@
|
|
|
|
/** parse args into delegpt */
|
|
static struct delegpt*
|
|
-parse_delegpt(SSL* ssl, struct regional* region, char* args, uint8_t* root)
|
|
+parse_delegpt(SSL* ssl, char* args, uint8_t* nm, int allow_names)
|
|
{
|
|
/* parse args and add in */
|
|
char* p = args;
|
|
char* todo;
|
|
- struct delegpt* dp = delegpt_create(region);
|
|
+ struct delegpt* dp = delegpt_create_mlc(nm);
|
|
struct sockaddr_storage addr;
|
|
socklen_t addrlen;
|
|
- if(!dp || !delegpt_set_name(dp, region, root)) {
|
|
+ if(!dp) {
|
|
(void)ssl_printf(ssl, "error out of memory\n");
|
|
return NULL;
|
|
}
|
|
@@ -1358,14 +1359,37 @@
|
|
}
|
|
/* parse address */
|
|
if(!extstrtoaddr(todo, &addr, &addrlen)) {
|
|
- (void)ssl_printf(ssl, "error cannot parse"
|
|
- " IP address '%s'\n", todo);
|
|
- return NULL;
|
|
- }
|
|
- /* add address */
|
|
- if(!delegpt_add_addr(dp, region, &addr, addrlen, 0, 0)) {
|
|
- (void)ssl_printf(ssl, "error out of memory\n");
|
|
- return NULL;
|
|
+ if(allow_names) {
|
|
+ uint8_t* n = NULL;
|
|
+ size_t ln;
|
|
+ int lb;
|
|
+ if(!parse_arg_name(ssl, todo, &n, &ln, &lb)) {
|
|
+ (void)ssl_printf(ssl, "error cannot "
|
|
+ "parse IP address or name "
|
|
+ "'%s'\n", todo);
|
|
+ delegpt_free_mlc(dp);
|
|
+ return NULL;
|
|
+ }
|
|
+ if(!delegpt_add_ns_mlc(dp, n, 0)) {
|
|
+ (void)ssl_printf(ssl, "error out of memory\n");
|
|
+ delegpt_free_mlc(dp);
|
|
+ return NULL;
|
|
+ }
|
|
+ free(n);
|
|
+
|
|
+ } else {
|
|
+ (void)ssl_printf(ssl, "error cannot parse"
|
|
+ " IP address '%s'\n", todo);
|
|
+ delegpt_free_mlc(dp);
|
|
+ return NULL;
|
|
+ }
|
|
+ } else {
|
|
+ /* add address */
|
|
+ if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0)) {
|
|
+ (void)ssl_printf(ssl, "error out of memory\n");
|
|
+ delegpt_free_mlc(dp);
|
|
+ return NULL;
|
|
+ }
|
|
}
|
|
}
|
|
return dp;
|
|
@@ -1389,20 +1413,166 @@
|
|
* the actual mesh is not running, so we can freely edit it. */
|
|
/* delete all the existing queries first */
|
|
mesh_delete_all(worker->env.mesh);
|
|
- /* reset the fwd structure ; the cfg is unchanged (shared by threads)*/
|
|
- /* this reset frees up memory */
|
|
- forwards_apply_cfg(fwd, worker->env.cfg);
|
|
if(strcmp(args, "off") == 0) {
|
|
forwards_delete_zone(fwd, LDNS_RR_CLASS_IN, root);
|
|
} else {
|
|
struct delegpt* dp;
|
|
- if(!(dp = parse_delegpt(ssl, fwd->region, args, root)))
|
|
+ if(!(dp = parse_delegpt(ssl, args, root, 0)))
|
|
return;
|
|
if(!forwards_add_zone(fwd, LDNS_RR_CLASS_IN, dp)) {
|
|
(void)ssl_printf(ssl, "error out of memory\n");
|
|
+ delegpt_free_mlc(dp);
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+ send_ok(ssl);
|
|
+}
|
|
+
|
|
+static int
|
|
+parse_fs_args(SSL* ssl, char* args, uint8_t** nm, struct delegpt** dp,
|
|
+ int* insecure, int* prime)
|
|
+{
|
|
+ char* zonename;
|
|
+ char* rest;
|
|
+ size_t nmlen;
|
|
+ int nmlabs;
|
|
+ /* parse all -x args */
|
|
+ while(args[0] == '+') {
|
|
+ if(!find_arg2(ssl, args, &rest))
|
|
+ return 0;
|
|
+ while(*(++args) != 0) {
|
|
+ if(*args == 'i' && insecure)
|
|
+ *insecure = 1;
|
|
+ else if(*args == 'p' && prime)
|
|
+ *prime = 1;
|
|
+ else {
|
|
+ (void)ssl_printf(ssl, "error: unknown option %s\n", args);
|
|
+ return 0;
|
|
+ }
|
|
+ }
|
|
+ args = rest;
|
|
+ }
|
|
+ /* parse name */
|
|
+ if(dp) {
|
|
+ if(!find_arg2(ssl, args, &rest))
|
|
+ return 0;
|
|
+ zonename = args;
|
|
+ args = rest;
|
|
+ } else zonename = args;
|
|
+ if(!parse_arg_name(ssl, zonename, nm, &nmlen, &nmlabs))
|
|
+ return 0;
|
|
+
|
|
+ /* parse dp */
|
|
+ if(dp) {
|
|
+ if(!(*dp = parse_delegpt(ssl, args, *nm, 1))) {
|
|
+ free(*nm);
|
|
+ return 0;
|
|
+ }
|
|
+ }
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+/** do the forward_add command */
|
|
+static void
|
|
+do_forward_add(SSL* ssl, struct worker* worker, char* args)
|
|
+{
|
|
+ struct iter_forwards* fwd = worker->env.fwds;
|
|
+ int insecure = 0;
|
|
+ uint8_t* nm = NULL;
|
|
+ struct delegpt* dp = NULL;
|
|
+ if(!parse_fs_args(ssl, args, &nm, &dp, &insecure, NULL))
|
|
+ return;
|
|
+ if(insecure) {
|
|
+ if(!anchors_add_insecure(worker->env.anchors, LDNS_RR_CLASS_IN,
|
|
+ nm)) {
|
|
+ (void)ssl_printf(ssl, "error out of memory\n");
|
|
+ delegpt_free_mlc(dp);
|
|
+ free(nm);
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+ if(!forwards_add_zone(fwd, LDNS_RR_CLASS_IN, dp)) {
|
|
+ (void)ssl_printf(ssl, "error out of memory\n");
|
|
+ delegpt_free_mlc(dp);
|
|
+ free(nm);
|
|
+ return;
|
|
+ }
|
|
+ free(nm);
|
|
+ send_ok(ssl);
|
|
+}
|
|
+
|
|
+/** do the forward_remove command */
|
|
+static void
|
|
+do_forward_remove(SSL* ssl, struct worker* worker, char* args)
|
|
+{
|
|
+ struct iter_forwards* fwd = worker->env.fwds;
|
|
+ int insecure = 0;
|
|
+ uint8_t* nm = NULL;
|
|
+ if(!parse_fs_args(ssl, args, &nm, NULL, &insecure, NULL))
|
|
+ return;
|
|
+ if(insecure)
|
|
+ anchors_delete_insecure(worker->env.anchors, LDNS_RR_CLASS_IN,
|
|
+ nm);
|
|
+ forwards_delete_zone(fwd, LDNS_RR_CLASS_IN, nm);
|
|
+ free(nm);
|
|
+ send_ok(ssl);
|
|
+}
|
|
+
|
|
+/** do the stub_add command */
|
|
+static void
|
|
+do_stub_add(SSL* ssl, struct worker* worker, char* args)
|
|
+{
|
|
+ struct iter_forwards* fwd = worker->env.fwds;
|
|
+ int insecure = 0, prime = 0;
|
|
+ uint8_t* nm = NULL;
|
|
+ struct delegpt* dp = NULL;
|
|
+ if(!parse_fs_args(ssl, args, &nm, &dp, &insecure, &prime))
|
|
+ return;
|
|
+ if(insecure) {
|
|
+ if(!anchors_add_insecure(worker->env.anchors, LDNS_RR_CLASS_IN,
|
|
+ nm)) {
|
|
+ (void)ssl_printf(ssl, "error out of memory\n");
|
|
+ delegpt_free_mlc(dp);
|
|
+ free(nm);
|
|
return;
|
|
}
|
|
}
|
|
+ if(!forwards_add_stub_hole(fwd, LDNS_RR_CLASS_IN, nm)) {
|
|
+ if(insecure) anchors_delete_insecure(worker->env.anchors,
|
|
+ LDNS_RR_CLASS_IN, nm);
|
|
+ (void)ssl_printf(ssl, "error out of memory\n");
|
|
+ delegpt_free_mlc(dp);
|
|
+ free(nm);
|
|
+ return;
|
|
+ }
|
|
+ if(!hints_add_stub(worker->env.hints, LDNS_RR_CLASS_IN, dp, !prime)) {
|
|
+ (void)ssl_printf(ssl, "error out of memory\n");
|
|
+ forwards_delete_stub_hole(fwd, LDNS_RR_CLASS_IN, nm);
|
|
+ if(insecure) anchors_delete_insecure(worker->env.anchors,
|
|
+ LDNS_RR_CLASS_IN, nm);
|
|
+ delegpt_free_mlc(dp);
|
|
+ free(nm);
|
|
+ return;
|
|
+ }
|
|
+ free(nm);
|
|
+ send_ok(ssl);
|
|
+}
|
|
+
|
|
+/** do the stub_remove command */
|
|
+static void
|
|
+do_stub_remove(SSL* ssl, struct worker* worker, char* args)
|
|
+{
|
|
+ struct iter_forwards* fwd = worker->env.fwds;
|
|
+ int insecure = 0;
|
|
+ uint8_t* nm = NULL;
|
|
+ if(!parse_fs_args(ssl, args, &nm, NULL, &insecure, NULL))
|
|
+ return;
|
|
+ if(insecure)
|
|
+ anchors_delete_insecure(worker->env.anchors, LDNS_RR_CLASS_IN,
|
|
+ nm);
|
|
+ forwards_delete_stub_hole(fwd, LDNS_RR_CLASS_IN, nm);
|
|
+ hints_delete_stub(worker->env.hints, LDNS_RR_CLASS_IN, nm);
|
|
+ free(nm);
|
|
send_ok(ssl);
|
|
}
|
|
|
|
@@ -1570,9 +1740,11 @@
|
|
return;
|
|
}
|
|
if(!ssl_printf(a->ssl, "%s %s ttl %d ping %d var %d rtt %d rto %d "
|
|
+ "tA %d tAAAA %d tother %d "
|
|
"ednsknown %d edns %d delay %d lame dnssec %d rec %d A %d "
|
|
"other %d\n", ip_str, name, (int)(d->ttl - a->now),
|
|
d->rtt.srtt, d->rtt.rttvar, rtt_notimeout(&d->rtt), d->rtt.rto,
|
|
+ d->timeout_A, d->timeout_AAAA, d->timeout_other,
|
|
(int)d->edns_lame_known, (int)d->edns_version,
|
|
(int)(a->now<d->probedelay?d->probedelay-a->now:0),
|
|
(int)d->isdnsseclame, (int)d->rec_lame, (int)d->lame_type_A,
|
|
@@ -1652,17 +1824,8 @@
|
|
static void
|
|
do_list_stubs(SSL* ssl, struct worker* worker)
|
|
{
|
|
- /* readonly structure */
|
|
- int m;
|
|
struct iter_hints_stub* z;
|
|
- struct iter_env* ie;
|
|
- m = modstack_find(&worker->env.mesh->mods, "iterator");
|
|
- if(m == -1) {
|
|
- (void)ssl_printf(ssl, "error no iterator module\n");
|
|
- return;
|
|
- }
|
|
- ie = (struct iter_env*)worker->env.modinfo[m];
|
|
- RBTREE_FOR(z, struct iter_hints_stub*, &ie->hints->tree) {
|
|
+ RBTREE_FOR(z, struct iter_hints_stub*, &worker->env.hints->tree) {
|
|
if(!ssl_print_name_dp(ssl,
|
|
z->noprime?"stub noprime":"stub prime", z->node.name,
|
|
z->node.dclass, z->dp))
|
|
@@ -1780,6 +1943,26 @@
|
|
} else if(cmdcmp(p, "list_local_data", 15)) {
|
|
do_list_local_data(ssl, worker);
|
|
return;
|
|
+ } else if(cmdcmp(p, "stub_add", 8)) {
|
|
+ /* must always distribute this cmd */
|
|
+ if(rc) distribute_cmd(rc, ssl, cmd);
|
|
+ do_stub_add(ssl, worker, skipwhite(p+8));
|
|
+ return;
|
|
+ } else if(cmdcmp(p, "stub_remove", 11)) {
|
|
+ /* must always distribute this cmd */
|
|
+ if(rc) distribute_cmd(rc, ssl, cmd);
|
|
+ do_stub_remove(ssl, worker, skipwhite(p+11));
|
|
+ return;
|
|
+ } else if(cmdcmp(p, "forward_add", 11)) {
|
|
+ /* must always distribute this cmd */
|
|
+ if(rc) distribute_cmd(rc, ssl, cmd);
|
|
+ do_forward_add(ssl, worker, skipwhite(p+11));
|
|
+ return;
|
|
+ } else if(cmdcmp(p, "forward_remove", 14)) {
|
|
+ /* must always distribute this cmd */
|
|
+ if(rc) distribute_cmd(rc, ssl, cmd);
|
|
+ do_forward_remove(ssl, worker, skipwhite(p+14));
|
|
+ return;
|
|
} else if(cmdcmp(p, "forward", 7)) {
|
|
/* must always distribute this cmd */
|
|
if(rc) distribute_cmd(rc, ssl, cmd);
|
|
diff -Naur unbound-1.4.16/daemon/worker.c unbound-trunk/daemon/worker.c
|
|
--- unbound-1.4.16/daemon/worker.c 2011-11-10 13:44:06.000000000 -0500
|
|
+++ unbound-trunk/daemon/worker.c 2012-02-22 20:37:15.803368186 -0500
|
|
@@ -67,7 +67,9 @@
|
|
#include "util/fptr_wlist.h"
|
|
#include "util/tube.h"
|
|
#include "iterator/iter_fwd.h"
|
|
+#include "iterator/iter_hints.h"
|
|
#include "validator/autotrust.h"
|
|
+#include "validator/val_anchor.h"
|
|
|
|
#ifdef HAVE_SYS_TYPES_H
|
|
# include <sys/types.h>
|
|
@@ -148,7 +150,7 @@
|
|
#ifdef UNBOUND_ALLOC_STATS
|
|
/* debug func in validator module */
|
|
size_t total, front, back, mesh, msg, rrset, infra, ac, superac;
|
|
- size_t me, iter, val;
|
|
+ size_t me, iter, val, anch;
|
|
int i;
|
|
if(verbosity < VERB_ALGO)
|
|
return;
|
|
@@ -160,6 +162,7 @@
|
|
mesh = mesh_get_mem(worker->env.mesh);
|
|
ac = alloc_get_mem(&worker->alloc);
|
|
superac = alloc_get_mem(&worker->daemon->superalloc);
|
|
+ anch = anchors_get_mem(worker->env.anchors);
|
|
iter = 0;
|
|
val = 0;
|
|
for(i=0; i<worker->env.mesh->mods.num; i++) {
|
|
@@ -177,7 +180,8 @@
|
|
+ regional_get_mem(worker->scratchpad)
|
|
+ sizeof(*worker->env.scratch_buffer)
|
|
+ ldns_buffer_capacity(worker->env.scratch_buffer)
|
|
- + forwards_get_mem(worker->env.fwds);
|
|
+ + forwards_get_mem(worker->env.fwds)
|
|
+ + hints_get_mem(worker->env.hints;
|
|
if(worker->thread_num == 0)
|
|
me += acl_list_get_mem(worker->daemon->acl);
|
|
if(cur_serv) {
|
|
@@ -185,12 +189,12 @@
|
|
}
|
|
total = front+back+mesh+msg+rrset+infra+iter+val+ac+superac+me;
|
|
log_info("Memory conditions: %u front=%u back=%u mesh=%u msg=%u "
|
|
- "rrset=%u infra=%u iter=%u val=%u "
|
|
+ "rrset=%u infra=%u iter=%u val=%u anchors=%u "
|
|
"alloccache=%u globalalloccache=%u me=%u",
|
|
(unsigned)total, (unsigned)front, (unsigned)back,
|
|
(unsigned)mesh, (unsigned)msg, (unsigned)rrset,
|
|
- (unsigned)infra, (unsigned)iter, (unsigned)val, (unsigned)ac,
|
|
- (unsigned)superac, (unsigned)me);
|
|
+ (unsigned)infra, (unsigned)iter, (unsigned)val, (unsigned)anch,
|
|
+ (unsigned)ac, (unsigned)superac, (unsigned)me);
|
|
debug_total_mem(total);
|
|
#else /* no UNBOUND_ALLOC_STATS */
|
|
size_t val = 0;
|
|
@@ -1158,6 +1162,12 @@
|
|
worker_delete(worker);
|
|
return 0;
|
|
}
|
|
+ if(!(worker->env.hints = hints_create()) ||
|
|
+ !hints_apply_cfg(worker->env.hints, cfg)) {
|
|
+ log_err("Could not set root or stub hints");
|
|
+ worker_delete(worker);
|
|
+ return 0;
|
|
+ }
|
|
/* one probe timer per process -- if we have 5011 anchors */
|
|
if(autr_get_num_anchors(worker->env.anchors) > 0
|
|
#ifndef THREADS_DISABLED
|
|
@@ -1210,6 +1220,7 @@
|
|
mesh_delete(worker->env.mesh);
|
|
ldns_buffer_free(worker->env.scratch_buffer);
|
|
forwards_delete(worker->env.fwds);
|
|
+ hints_delete(worker->env.hints);
|
|
listen_delete(worker->front);
|
|
outside_network_delete(worker->back);
|
|
comm_signal_delete(worker->comsig);
|
|
diff -Naur unbound-1.4.16/iterator/iterator.c unbound-trunk/iterator/iterator.c
|
|
--- unbound-1.4.16/iterator/iterator.c 2012-01-10 04:42:32.000000000 -0500
|
|
+++ unbound-trunk/iterator/iterator.c 2012-02-22 20:37:15.042368186 -0500
|
|
@@ -89,7 +89,6 @@
|
|
iter_env = (struct iter_env*)env->modinfo[id];
|
|
free(iter_env->target_fetch_policy);
|
|
priv_delete(iter_env->priv);
|
|
- hints_delete(iter_env->hints);
|
|
donotq_delete(iter_env->donotq);
|
|
free(iter_env);
|
|
env->modinfo[id] = NULL;
|
|
@@ -260,7 +259,7 @@
|
|
/* do not waste time trying to validate this servfail */
|
|
err.security = sec_status_indeterminate;
|
|
verbose(VERB_ALGO, "store error response in message cache");
|
|
- if(!iter_dns_store(qstate->env, &qstate->qinfo, &err, 0, 0, NULL)) {
|
|
+ if(!iter_dns_store(qstate->env, &qstate->qinfo, &err, 0, 0, 0, NULL)) {
|
|
log_err("error_response_cache: could not store error (nomem)");
|
|
}
|
|
return error_response(qstate, id, rcode);
|
|
@@ -532,21 +531,20 @@
|
|
* Generate and send a root priming request.
|
|
* @param qstate: the qtstate that triggered the need to prime.
|
|
* @param iq: iterator query state.
|
|
- * @param ie: iterator global state.
|
|
* @param id: module id.
|
|
* @param qclass: the class to prime.
|
|
* @return 0 on failure
|
|
*/
|
|
static int
|
|
-prime_root(struct module_qstate* qstate, struct iter_qstate* iq,
|
|
- struct iter_env* ie, int id, uint16_t qclass)
|
|
+prime_root(struct module_qstate* qstate, struct iter_qstate* iq, int id,
|
|
+ uint16_t qclass)
|
|
{
|
|
struct delegpt* dp;
|
|
struct module_qstate* subq;
|
|
verbose(VERB_DETAIL, "priming . %s NS",
|
|
ldns_lookup_by_id(ldns_rr_classes, (int)qclass)?
|
|
ldns_lookup_by_id(ldns_rr_classes, (int)qclass)->name:"??");
|
|
- dp = hints_lookup_root(ie->hints, qclass);
|
|
+ dp = hints_lookup_root(qstate->env->hints, qclass);
|
|
if(!dp) {
|
|
verbose(VERB_ALGO, "Cannot prime due to lack of hints");
|
|
return 0;
|
|
@@ -590,7 +588,6 @@
|
|
*
|
|
* @param qstate: the qtstate that triggered the need to prime.
|
|
* @param iq: iterator query state.
|
|
- * @param ie: iterator global state.
|
|
* @param id: module id.
|
|
* @param q: request name.
|
|
* @return true if a priming subrequest was made, false if not. The will only
|
|
@@ -599,8 +596,8 @@
|
|
* that a noprime-stub is available and resolution can continue.
|
|
*/
|
|
static int
|
|
-prime_stub(struct module_qstate* qstate, struct iter_qstate* iq,
|
|
- struct iter_env* ie, int id, struct query_info* q)
|
|
+prime_stub(struct module_qstate* qstate, struct iter_qstate* iq, int id,
|
|
+ struct query_info* q)
|
|
{
|
|
/* Lookup the stub hint. This will return null if the stub doesn't
|
|
* need to be re-primed. */
|
|
@@ -614,7 +611,8 @@
|
|
/* remove first label, but not for root */
|
|
dname_remove_label(&delname, &delnamelen);
|
|
|
|
- stub = hints_lookup_stub(ie->hints, delname, q->qclass, iq->dp);
|
|
+ stub = hints_lookup_stub(qstate->env->hints, delname, q->qclass,
|
|
+ iq->dp);
|
|
/* The stub (if there is one) does not need priming. */
|
|
if(!stub)
|
|
return 0;
|
|
@@ -1042,14 +1040,15 @@
|
|
if(delname)
|
|
iq->dp = dns_cache_find_delegation(qstate->env, delname,
|
|
delnamelen, iq->qchase.qtype, iq->qchase.qclass,
|
|
- qstate->region, &iq->deleg_msg, *qstate->env->now);
|
|
+ qstate->region, &iq->deleg_msg,
|
|
+ *qstate->env->now+qstate->prefetch_leeway);
|
|
else iq->dp = NULL;
|
|
|
|
/* If the cache has returned nothing, then we have a
|
|
* root priming situation. */
|
|
if(iq->dp == NULL) {
|
|
/* if there is a stub, then no root prime needed */
|
|
- int r = prime_stub(qstate, iq, ie, id, &iq->qchase);
|
|
+ int r = prime_stub(qstate, iq, id, &iq->qchase);
|
|
if(r == 2)
|
|
break; /* got noprime-stub-zone, continue */
|
|
else if(r)
|
|
@@ -1058,7 +1057,7 @@
|
|
iq->qchase.qclass)) {
|
|
/* forward zone root, no root prime needed */
|
|
/* fill in some dp - safety belt */
|
|
- iq->dp = hints_lookup_root(ie->hints,
|
|
+ iq->dp = hints_lookup_root(qstate->env->hints,
|
|
iq->qchase.qclass);
|
|
if(!iq->dp) {
|
|
log_err("internal error: no hints dp");
|
|
@@ -1075,7 +1074,7 @@
|
|
}
|
|
/* Note that the result of this will set a new
|
|
* DelegationPoint based on the result of priming. */
|
|
- if(!prime_root(qstate, iq, ie, id, iq->qchase.qclass))
|
|
+ if(!prime_root(qstate, iq, id, iq->qchase.qclass))
|
|
return error_response(qstate, id,
|
|
LDNS_RCODE_REFUSED);
|
|
|
|
@@ -1104,7 +1103,7 @@
|
|
/* use safety belt */
|
|
verbose(VERB_QUERY, "Cache has root NS but "
|
|
"no addresses. Fallback to the safety belt.");
|
|
- iq->dp = hints_lookup_root(ie->hints,
|
|
+ iq->dp = hints_lookup_root(qstate->env->hints,
|
|
iq->qchase.qclass);
|
|
/* note deleg_msg is from previous lookup,
|
|
* but RD is on, so it is not used */
|
|
@@ -1151,20 +1150,19 @@
|
|
*
|
|
* @param qstate: query state.
|
|
* @param iq: iterator query state.
|
|
- * @param ie: iterator shared global environment.
|
|
* @param id: module id.
|
|
* @return true if the event needs more request processing immediately,
|
|
* false if not.
|
|
*/
|
|
static int
|
|
processInitRequest2(struct module_qstate* qstate, struct iter_qstate* iq,
|
|
- struct iter_env* ie, int id)
|
|
+ int id)
|
|
{
|
|
log_query_info(VERB_QUERY, "resolving (init part 2): ",
|
|
&qstate->qinfo);
|
|
|
|
/* Check to see if we need to prime a stub zone. */
|
|
- if(prime_stub(qstate, iq, ie, id, &iq->qchase)) {
|
|
+ if(prime_stub(qstate, iq, id, &iq->qchase)) {
|
|
/* A priming sub request was made */
|
|
return 0;
|
|
}
|
|
@@ -1261,7 +1259,8 @@
|
|
} else {
|
|
subiq->dp = dns_cache_find_delegation(qstate->env,
|
|
name, namelen, qtype, qclass, subq->region,
|
|
- &subiq->deleg_msg, *qstate->env->now);
|
|
+ &subiq->deleg_msg,
|
|
+ *qstate->env->now+subq->prefetch_leeway);
|
|
/* if no dp, then it's from root, refetch unneeded */
|
|
if(subiq->dp) {
|
|
subiq->dnssec_expected = iter_indicates_dnssec(
|
|
@@ -1833,6 +1832,7 @@
|
|
}
|
|
if(!iter_dns_store(qstate->env, &iq->response->qinfo,
|
|
iq->response->rep, 0, qstate->prefetch_leeway,
|
|
+ iq->dp&&iq->dp->has_parent_side_NS,
|
|
qstate->region))
|
|
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
|
/* close down outstanding requests to be discarded */
|
|
@@ -1872,7 +1872,7 @@
|
|
/* Store the referral under the current query */
|
|
/* no prefetch-leeway, since its not the answer */
|
|
if(!iter_dns_store(qstate->env, &iq->response->qinfo,
|
|
- iq->response->rep, 1, 0, NULL))
|
|
+ iq->response->rep, 1, 0, 0, NULL))
|
|
return error_response(qstate, id,
|
|
LDNS_RCODE_SERVFAIL);
|
|
if(iq->store_parent_NS)
|
|
@@ -1958,7 +1958,9 @@
|
|
* the partial query answer (CNAME only). */
|
|
/* prefetchleeway applied because this updates answer parts */
|
|
if(!iter_dns_store(qstate->env, &iq->response->qinfo,
|
|
- iq->response->rep, 1, qstate->prefetch_leeway, NULL))
|
|
+ iq->response->rep, 1, qstate->prefetch_leeway,
|
|
+ iq->dp&&iq->dp->has_parent_side_NS,
|
|
+ NULL))
|
|
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
|
/* set the current request's qname to the new value. */
|
|
iq->qchase.qname = sname;
|
|
@@ -2336,7 +2338,6 @@
|
|
processCollectClass(struct module_qstate* qstate, int id)
|
|
{
|
|
struct iter_qstate* iq = (struct iter_qstate*)qstate->minfo[id];
|
|
- struct iter_env* ie = (struct iter_env*)qstate->env->modinfo[id];
|
|
struct module_qstate* subq;
|
|
/* If qchase.qclass == 0 then send out queries for all classes.
|
|
* Otherwise, do nothing (wait for all answers to arrive and the
|
|
@@ -2345,7 +2346,8 @@
|
|
if(iq->qchase.qclass == 0) {
|
|
uint16_t c = 0;
|
|
iq->qchase.qclass = LDNS_RR_CLASS_ANY;
|
|
- while(iter_get_next_root(ie->hints, qstate->env->fwds, &c)) {
|
|
+ while(iter_get_next_root(qstate->env->hints,
|
|
+ qstate->env->fwds, &c)) {
|
|
/* generate query for this class */
|
|
log_nametypeclass(VERB_ALGO, "spawn collect query",
|
|
qstate->qinfo.qname, qstate->qinfo.qtype, c);
|
|
@@ -2435,6 +2437,7 @@
|
|
if(qstate->query_flags&BIT_RD) {
|
|
if(!iter_dns_store(qstate->env, &qstate->qinfo,
|
|
iq->response->rep, 0, qstate->prefetch_leeway,
|
|
+ iq->dp&&iq->dp->has_parent_side_NS,
|
|
qstate->region))
|
|
return error_response(qstate, id,
|
|
LDNS_RCODE_SERVFAIL);
|
|
@@ -2493,7 +2496,7 @@
|
|
cont = processInitRequest(qstate, iq, ie, id);
|
|
break;
|
|
case INIT_REQUEST_2_STATE:
|
|
- cont = processInitRequest2(qstate, iq, ie, id);
|
|
+ cont = processInitRequest2(qstate, iq, id);
|
|
break;
|
|
case INIT_REQUEST_3_STATE:
|
|
cont = processInitRequest3(qstate, iq, id);
|
|
@@ -2705,8 +2708,7 @@
|
|
if(!ie)
|
|
return 0;
|
|
return sizeof(*ie) + sizeof(int)*((size_t)ie->max_dependency_depth+1)
|
|
- + hints_get_mem(ie->hints) + donotq_get_mem(ie->donotq)
|
|
- + priv_get_mem(ie->priv);
|
|
+ + donotq_get_mem(ie->donotq) + priv_get_mem(ie->priv);
|
|
}
|
|
|
|
/**
|
|
diff -Naur unbound-1.4.16/iterator/iterator.h unbound-trunk/iterator/iterator.h
|
|
--- unbound-1.4.16/iterator/iterator.h 2011-09-16 10:11:12.000000000 -0400
|
|
+++ unbound-trunk/iterator/iterator.h 2012-02-22 20:37:15.038368186 -0500
|
|
@@ -86,14 +86,6 @@
|
|
* Global state for the iterator.
|
|
*/
|
|
struct iter_env {
|
|
- /**
|
|
- * The hints -- these aren't stored in the cache because they don't
|
|
- * expire. The hints are always used to "prime" the cache. Note
|
|
- * that both root hints and stub zone "hints" are stored in this
|
|
- * data structure.
|
|
- */
|
|
- struct iter_hints* hints;
|
|
-
|
|
/** A flag to indicate whether or not we have an IPv6 route */
|
|
int supports_ipv6;
|
|
|
|
diff -Naur unbound-1.4.16/iterator/iter_delegpt.c unbound-trunk/iterator/iter_delegpt.c
|
|
--- unbound-1.4.16/iterator/iter_delegpt.c 2011-09-07 10:34:10.000000000 -0400
|
|
+++ unbound-trunk/iterator/iter_delegpt.c 2012-02-22 20:37:15.040368186 -0500
|
|
@@ -90,6 +90,7 @@
|
|
int
|
|
delegpt_set_name(struct delegpt* dp, struct regional* region, uint8_t* name)
|
|
{
|
|
+ log_assert(!dp->dp_type_mlc);
|
|
dp->namelabs = dname_count_size_labels(name, &dp->namelen);
|
|
dp->name = regional_alloc_init(region, name, dp->namelen);
|
|
return dp->name != 0;
|
|
@@ -102,6 +103,7 @@
|
|
struct delegpt_ns* ns;
|
|
size_t len;
|
|
(void)dname_count_size_labels(name, &len);
|
|
+ log_assert(!dp->dp_type_mlc);
|
|
/* slow check for duplicates to avoid counting failures when
|
|
* adding the same server as a dependency twice */
|
|
if(delegpt_find_ns(dp, name, len))
|
|
@@ -120,7 +122,7 @@
|
|
ns->lame = (uint8_t)lame;
|
|
ns->done_pside4 = 0;
|
|
ns->done_pside6 = 0;
|
|
- return 1;
|
|
+ return ns->name != 0;
|
|
}
|
|
|
|
struct delegpt_ns*
|
|
@@ -157,6 +159,7 @@
|
|
socklen_t addrlen, int bogus, int lame)
|
|
{
|
|
struct delegpt_ns* ns = delegpt_find_ns(dp, name, namelen);
|
|
+ log_assert(!dp->dp_type_mlc);
|
|
if(!ns) {
|
|
/* ignore it */
|
|
return 1;
|
|
@@ -177,6 +180,7 @@
|
|
int lame)
|
|
{
|
|
struct delegpt_addr* a;
|
|
+ log_assert(!dp->dp_type_mlc);
|
|
/* check for duplicates */
|
|
if((a = delegpt_find_addr(dp, addr, addrlen))) {
|
|
if(bogus)
|
|
@@ -377,6 +381,7 @@
|
|
struct packed_rrset_data* nsdata = (struct packed_rrset_data*)
|
|
ns_rrset->entry.data;
|
|
size_t i;
|
|
+ log_assert(!dp->dp_type_mlc);
|
|
if(nsdata->security == sec_status_bogus)
|
|
dp->bogus = 1;
|
|
for(i=0; i<nsdata->count; i++) {
|
|
@@ -399,6 +404,7 @@
|
|
size_t i;
|
|
struct sockaddr_in sa;
|
|
socklen_t len = (socklen_t)sizeof(sa);
|
|
+ log_assert(!dp->dp_type_mlc);
|
|
memset(&sa, 0, len);
|
|
sa.sin_family = AF_INET;
|
|
sa.sin_port = (in_port_t)htons(UNBOUND_DNS_PORT);
|
|
@@ -422,6 +428,7 @@
|
|
size_t i;
|
|
struct sockaddr_in6 sa;
|
|
socklen_t len = (socklen_t)sizeof(sa);
|
|
+ log_assert(!dp->dp_type_mlc);
|
|
memset(&sa, 0, len);
|
|
sa.sin6_family = AF_INET6;
|
|
sa.sin6_port = (in_port_t)htons(UNBOUND_DNS_PORT);
|
|
@@ -492,3 +499,141 @@
|
|
ns->resolved = 1;
|
|
}
|
|
}
|
|
+
|
|
+struct delegpt* delegpt_create_mlc(uint8_t* name)
|
|
+{
|
|
+ struct delegpt* dp=(struct delegpt*)calloc(1, sizeof(*dp));
|
|
+ if(!dp)
|
|
+ return NULL;
|
|
+ memset(dp, 0, sizeof(*dp));
|
|
+ dp->dp_type_mlc = 1;
|
|
+ if(name) {
|
|
+ dp->namelabs = dname_count_size_labels(name, &dp->namelen);
|
|
+ dp->name = memdup(name, dp->namelen);
|
|
+ if(!dp->name) {
|
|
+ free(dp);
|
|
+ return NULL;
|
|
+ }
|
|
+ }
|
|
+ return dp;
|
|
+}
|
|
+
|
|
+void delegpt_free_mlc(struct delegpt* dp)
|
|
+{
|
|
+ struct delegpt_ns* n, *nn;
|
|
+ struct delegpt_addr* a, *na;
|
|
+ if(!dp) return;
|
|
+ log_assert(dp->dp_type_mlc);
|
|
+ n = dp->nslist;
|
|
+ while(n) {
|
|
+ nn = n->next;
|
|
+ free(n->name);
|
|
+ free(n);
|
|
+ n = nn;
|
|
+ }
|
|
+ a = dp->target_list;
|
|
+ while(a) {
|
|
+ na = a->next_target;
|
|
+ free(a);
|
|
+ a = na;
|
|
+ }
|
|
+ free(dp->name);
|
|
+ free(dp);
|
|
+}
|
|
+
|
|
+int delegpt_set_name_mlc(struct delegpt* dp, uint8_t* name)
|
|
+{
|
|
+ log_assert(dp->dp_type_mlc);
|
|
+ dp->namelabs = dname_count_size_labels(name, &dp->namelen);
|
|
+ dp->name = memdup(name, dp->namelen);
|
|
+ return (dp->name != NULL);
|
|
+}
|
|
+
|
|
+int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, int lame)
|
|
+{
|
|
+ struct delegpt_ns* ns;
|
|
+ size_t len;
|
|
+ (void)dname_count_size_labels(name, &len);
|
|
+ log_assert(dp->dp_type_mlc);
|
|
+ /* slow check for duplicates to avoid counting failures when
|
|
+ * adding the same server as a dependency twice */
|
|
+ if(delegpt_find_ns(dp, name, len))
|
|
+ return 1;
|
|
+ ns = (struct delegpt_ns*)malloc(sizeof(struct delegpt_ns));
|
|
+ if(!ns)
|
|
+ return 0;
|
|
+ ns->namelen = len;
|
|
+ ns->name = memdup(name, ns->namelen);
|
|
+ if(!ns->name) {
|
|
+ free(ns);
|
|
+ return 0;
|
|
+ }
|
|
+ ns->next = dp->nslist;
|
|
+ dp->nslist = ns;
|
|
+ ns->resolved = 0;
|
|
+ ns->got4 = 0;
|
|
+ ns->got6 = 0;
|
|
+ ns->lame = (uint8_t)lame;
|
|
+ ns->done_pside4 = 0;
|
|
+ ns->done_pside6 = 0;
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+int delegpt_add_addr_mlc(struct delegpt* dp, struct sockaddr_storage* addr,
|
|
+ socklen_t addrlen, int bogus, int lame)
|
|
+{
|
|
+ struct delegpt_addr* a;
|
|
+ log_assert(dp->dp_type_mlc);
|
|
+ /* check for duplicates */
|
|
+ if((a = delegpt_find_addr(dp, addr, addrlen))) {
|
|
+ if(bogus)
|
|
+ a->bogus = bogus;
|
|
+ if(!lame)
|
|
+ a->lame = 0;
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
+ a = (struct delegpt_addr*)malloc(sizeof(struct delegpt_addr));
|
|
+ if(!a)
|
|
+ return 0;
|
|
+ a->next_target = dp->target_list;
|
|
+ dp->target_list = a;
|
|
+ a->next_result = 0;
|
|
+ a->next_usable = dp->usable_list;
|
|
+ dp->usable_list = a;
|
|
+ memcpy(&a->addr, addr, addrlen);
|
|
+ a->addrlen = addrlen;
|
|
+ a->attempts = 0;
|
|
+ a->bogus = bogus;
|
|
+ a->lame = lame;
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+int delegpt_add_target_mlc(struct delegpt* dp, uint8_t* name, size_t namelen,
|
|
+ struct sockaddr_storage* addr, socklen_t addrlen, int bogus, int lame)
|
|
+{
|
|
+ struct delegpt_ns* ns = delegpt_find_ns(dp, name, namelen);
|
|
+ log_assert(dp->dp_type_mlc);
|
|
+ if(!ns) {
|
|
+ /* ignore it */
|
|
+ return 1;
|
|
+ }
|
|
+ if(!lame) {
|
|
+ if(addr_is_ip6(addr, addrlen))
|
|
+ ns->got6 = 1;
|
|
+ else ns->got4 = 1;
|
|
+ if(ns->got4 && ns->got6)
|
|
+ ns->resolved = 1;
|
|
+ }
|
|
+ return delegpt_add_addr_mlc(dp, addr, addrlen, bogus, lame);
|
|
+}
|
|
+
|
|
+size_t delegpt_get_mem(struct delegpt* dp)
|
|
+{
|
|
+ struct delegpt_ns* ns;
|
|
+ size_t s = sizeof(*dp) + dp->namelen +
|
|
+ delegpt_count_targets(dp)*sizeof(struct delegpt_addr);
|
|
+ for(ns=dp->nslist; ns; ns=ns->next)
|
|
+ s += sizeof(*ns)+ns->namelen;
|
|
+ return s;
|
|
+}
|
|
diff -Naur unbound-1.4.16/iterator/iter_delegpt.h unbound-trunk/iterator/iter_delegpt.h
|
|
--- unbound-1.4.16/iterator/iter_delegpt.h 2011-09-07 10:34:10.000000000 -0400
|
|
+++ unbound-trunk/iterator/iter_delegpt.h 2012-02-22 20:37:15.041368186 -0500
|
|
@@ -79,6 +79,8 @@
|
|
* Also true if the delegationpoint was created from a delegation
|
|
* message and thus contains the parent-side-info already. */
|
|
uint8_t has_parent_side_NS;
|
|
+ /** for assertions on type of delegpt */
|
|
+ uint8_t dp_type_mlc;
|
|
};
|
|
|
|
/**
|
|
@@ -346,4 +348,64 @@
|
|
*/
|
|
void delegpt_no_ipv4(struct delegpt* dp);
|
|
|
|
+/**
|
|
+ * create malloced delegation point, with the given name
|
|
+ * @param name: uncompressed wireformat of degegpt name.
|
|
+ * @return NULL on alloc failure
|
|
+ */
|
|
+struct delegpt* delegpt_create_mlc(uint8_t* name);
|
|
+
|
|
+/**
|
|
+ * free malloced delegation point.
|
|
+ * @param dp: must have been created with delegpt_create_mlc, free'd.
|
|
+ */
|
|
+void delegpt_free_mlc(struct delegpt* dp);
|
|
+
|
|
+/**
|
|
+ * Set name of delegation point.
|
|
+ * @param dp: delegation point. malloced.
|
|
+ * @param name: name to use.
|
|
+ * @return false on error.
|
|
+ */
|
|
+int delegpt_set_name_mlc(struct delegpt* dp, uint8_t* name);
|
|
+
|
|
+/**
|
|
+ * add a name to malloced delegation point.
|
|
+ * @param dp: must have been created with delegpt_create_mlc.
|
|
+ * @param name: the name to add.
|
|
+ * @param lame: the name is lame, disprefer.
|
|
+ * @return false on error.
|
|
+ */
|
|
+int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, int lame);
|
|
+
|
|
+/**
|
|
+ * add an address to a malloced delegation point.
|
|
+ * @param dp: must have been created with delegpt_create_mlc.
|
|
+ * @param addr: the address.
|
|
+ * @param addrlen: the length of addr.
|
|
+ * @param bogus: if address is bogus.
|
|
+ * @param lame: if address is lame.
|
|
+ * @return false on error.
|
|
+ */
|
|
+int delegpt_add_addr_mlc(struct delegpt* dp, struct sockaddr_storage* addr,
|
|
+ socklen_t addrlen, int bogus, int lame);
|
|
+
|
|
+/**
|
|
+ * Add target address to the delegation point.
|
|
+ * @param dp: must have been created with delegpt_create_mlc.
|
|
+ * @param name: name for which target was found (must be in nslist).
|
|
+ * This name is marked resolved.
|
|
+ * @param namelen: length of name.
|
|
+ * @param addr: the address.
|
|
+ * @param addrlen: the length of addr.
|
|
+ * @param bogus: security status for the address, pass true if bogus.
|
|
+ * @param lame: address is lame.
|
|
+ * @return false on error.
|
|
+ */
|
|
+int delegpt_add_target_mlc(struct delegpt* dp, uint8_t* name, size_t namelen,
|
|
+ struct sockaddr_storage* addr, socklen_t addrlen, int bogus, int lame);
|
|
+
|
|
+/** get memory in use by dp */
|
|
+size_t delegpt_get_mem(struct delegpt* dp);
|
|
+
|
|
#endif /* ITERATOR_ITER_DELEGPT_H */
|
|
diff -Naur unbound-1.4.16/iterator/iter_fwd.c unbound-trunk/iterator/iter_fwd.c
|
|
--- unbound-1.4.16/iterator/iter_fwd.c 2011-11-10 13:44:06.000000000 -0500
|
|
+++ unbound-trunk/iterator/iter_fwd.c 2012-02-22 20:37:15.039368186 -0500
|
|
@@ -45,7 +45,6 @@
|
|
#include <ldns/rr.h>
|
|
#include "iterator/iter_fwd.h"
|
|
#include "iterator/iter_delegpt.h"
|
|
-#include "util/regional.h"
|
|
#include "util/log.h"
|
|
#include "util/config_file.h"
|
|
#include "util/net_help.h"
|
|
@@ -73,21 +72,36 @@
|
|
sizeof(struct iter_forwards));
|
|
if(!fwd)
|
|
return NULL;
|
|
- fwd->region = regional_create();
|
|
- if(!fwd->region) {
|
|
- forwards_delete(fwd);
|
|
- return NULL;
|
|
- }
|
|
return fwd;
|
|
}
|
|
|
|
+static void fwd_zone_free(struct iter_forward_zone* n)
|
|
+{
|
|
+ if(!n) return;
|
|
+ delegpt_free_mlc(n->dp);
|
|
+ free(n->name);
|
|
+ free(n);
|
|
+}
|
|
+
|
|
+static void delfwdnode(rbnode_t* n, void* ATTR_UNUSED(arg))
|
|
+{
|
|
+ struct iter_forward_zone* node = (struct iter_forward_zone*)n;
|
|
+ fwd_zone_free(node);
|
|
+}
|
|
+
|
|
+static void fwd_del_tree(struct iter_forwards* fwd)
|
|
+{
|
|
+ if(fwd->tree)
|
|
+ traverse_postorder(fwd->tree, &delfwdnode, NULL);
|
|
+ free(fwd->tree);
|
|
+}
|
|
+
|
|
void
|
|
forwards_delete(struct iter_forwards* fwd)
|
|
{
|
|
if(!fwd)
|
|
return;
|
|
- regional_destroy(fwd->region);
|
|
- free(fwd->tree);
|
|
+ fwd_del_tree(fwd);
|
|
free(fwd);
|
|
}
|
|
|
|
@@ -96,20 +110,28 @@
|
|
forwards_insert_data(struct iter_forwards* fwd, uint16_t c, uint8_t* nm,
|
|
size_t nmlen, int nmlabs, struct delegpt* dp)
|
|
{
|
|
- struct iter_forward_zone* node = regional_alloc(fwd->region,
|
|
+ struct iter_forward_zone* node = (struct iter_forward_zone*)malloc(
|
|
sizeof(struct iter_forward_zone));
|
|
- if(!node)
|
|
+ if(!node) {
|
|
+ delegpt_free_mlc(dp);
|
|
return 0;
|
|
+ }
|
|
node->node.key = node;
|
|
node->dclass = c;
|
|
- node->name = regional_alloc_init(fwd->region, nm, nmlen);
|
|
- if(!node->name)
|
|
+ node->name = memdup(nm, nmlen);
|
|
+ if(!node->name) {
|
|
+ delegpt_free_mlc(dp);
|
|
+ free(node);
|
|
return 0;
|
|
+ }
|
|
node->namelen = nmlen;
|
|
node->namelabs = nmlabs;
|
|
node->dp = dp;
|
|
if(!rbtree_insert(fwd->tree, &node->node)) {
|
|
log_err("duplicate forward zone ignored.");
|
|
+ delegpt_free_mlc(dp);
|
|
+ free(node->name);
|
|
+ free(node);
|
|
}
|
|
return 1;
|
|
}
|
|
@@ -152,33 +174,32 @@
|
|
}
|
|
|
|
/** set zone name */
|
|
-static int
|
|
-read_fwds_name(struct iter_forwards* fwd, struct config_stub* s,
|
|
- struct delegpt* dp)
|
|
+static struct delegpt*
|
|
+read_fwds_name(struct config_stub* s)
|
|
{
|
|
+ struct delegpt* dp;
|
|
ldns_rdf* rdf;
|
|
if(!s->name) {
|
|
log_err("forward zone without a name (use name \".\" to forward everything)");
|
|
- return 0;
|
|
+ return NULL;
|
|
}
|
|
rdf = ldns_dname_new_frm_str(s->name);
|
|
if(!rdf) {
|
|
log_err("cannot parse forward zone name %s", s->name);
|
|
- return 0;
|
|
+ return NULL;
|
|
}
|
|
- if(!delegpt_set_name(dp, fwd->region, ldns_rdf_data(rdf))) {
|
|
+ if(!(dp=delegpt_create_mlc(ldns_rdf_data(rdf)))) {
|
|
ldns_rdf_deep_free(rdf);
|
|
log_err("out of memory");
|
|
- return 0;
|
|
+ return NULL;
|
|
}
|
|
ldns_rdf_deep_free(rdf);
|
|
- return 1;
|
|
+ return dp;
|
|
}
|
|
|
|
/** set fwd host names */
|
|
static int
|
|
-read_fwds_host(struct iter_forwards* fwd, struct config_stub* s,
|
|
- struct delegpt* dp)
|
|
+read_fwds_host(struct config_stub* s, struct delegpt* dp)
|
|
{
|
|
struct config_strlist* p;
|
|
ldns_rdf* rdf;
|
|
@@ -190,7 +211,7 @@
|
|
s->name, p->str);
|
|
return 0;
|
|
}
|
|
- if(!delegpt_add_ns(dp, fwd->region, ldns_rdf_data(rdf), 0)) {
|
|
+ if(!delegpt_add_ns_mlc(dp, ldns_rdf_data(rdf), 0)) {
|
|
ldns_rdf_deep_free(rdf);
|
|
log_err("out of memory");
|
|
return 0;
|
|
@@ -202,8 +223,7 @@
|
|
|
|
/** set fwd server addresses */
|
|
static int
|
|
-read_fwds_addr(struct iter_forwards* fwd, struct config_stub* s,
|
|
- struct delegpt* dp)
|
|
+read_fwds_addr(struct config_stub* s, struct delegpt* dp)
|
|
{
|
|
struct config_strlist* p;
|
|
struct sockaddr_storage addr;
|
|
@@ -215,7 +235,7 @@
|
|
s->name, p->str);
|
|
return 0;
|
|
}
|
|
- if(!delegpt_add_addr(dp, fwd->region, &addr, addrlen, 0, 0)) {
|
|
+ if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0)) {
|
|
log_err("out of memory");
|
|
return 0;
|
|
}
|
|
@@ -229,18 +249,14 @@
|
|
{
|
|
struct config_stub* s;
|
|
for(s = cfg->forwards; s; s = s->next) {
|
|
- struct delegpt* dp = delegpt_create(fwd->region);
|
|
- if(!dp) {
|
|
- log_err("out of memory");
|
|
+ struct delegpt* dp;
|
|
+ if(!(dp=read_fwds_name(s)) ||
|
|
+ !read_fwds_host(s, dp) ||
|
|
+ !read_fwds_addr(s, dp))
|
|
return 0;
|
|
- }
|
|
/* set flag that parent side NS information is included.
|
|
* Asking a (higher up) server on the internet is not useful */
|
|
dp->has_parent_side_NS = 1;
|
|
- if(!read_fwds_name(fwd, s, dp) ||
|
|
- !read_fwds_host(fwd, s, dp) ||
|
|
- !read_fwds_addr(fwd, s, dp))
|
|
- return 0;
|
|
if(!forwards_insert(fwd, LDNS_RR_CLASS_IN, dp))
|
|
return 0;
|
|
verbose(VERB_QUERY, "Forward zone server list:");
|
|
@@ -268,28 +284,35 @@
|
|
return 0; /* no forwards above, no holes needed */
|
|
}
|
|
|
|
+/** insert a stub hole (if necessary) for stub name */
|
|
+static int
|
|
+fwd_add_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm)
|
|
+{
|
|
+ struct iter_forward_zone key;
|
|
+ key.node.key = &key;
|
|
+ key.dclass = c;
|
|
+ key.name = nm;
|
|
+ key.namelabs = dname_count_size_labels(key.name, &key.namelen);
|
|
+ if(need_hole_insert(fwd->tree, &key)) {
|
|
+ return forwards_insert_data(fwd, key.dclass, key.name,
|
|
+ key.namelen, key.namelabs, NULL);
|
|
+ }
|
|
+ return 1;
|
|
+}
|
|
+
|
|
/** make NULL entries for stubs */
|
|
static int
|
|
make_stub_holes(struct iter_forwards* fwd, struct config_file* cfg)
|
|
{
|
|
struct config_stub* s;
|
|
- struct iter_forward_zone key;
|
|
- key.node.key = &key;
|
|
- key.dclass = LDNS_RR_CLASS_IN;
|
|
for(s = cfg->stubs; s; s = s->next) {
|
|
ldns_rdf* rdf = ldns_dname_new_frm_str(s->name);
|
|
if(!rdf) {
|
|
log_err("cannot parse stub name '%s'", s->name);
|
|
return 0;
|
|
}
|
|
- key.name = ldns_rdf_data(rdf);
|
|
- key.namelabs = dname_count_size_labels(key.name, &key.namelen);
|
|
- if(!need_hole_insert(fwd->tree, &key)) {
|
|
- ldns_rdf_deep_free(rdf);
|
|
- continue;
|
|
- }
|
|
- if(!forwards_insert_data(fwd, key.dclass, key.name,
|
|
- key.namelen, key.namelabs, NULL)) {
|
|
+ if(!fwd_add_stub_hole(fwd, LDNS_RR_CLASS_IN,
|
|
+ ldns_rdf_data(rdf))) {
|
|
ldns_rdf_deep_free(rdf);
|
|
log_err("out of memory");
|
|
return 0;
|
|
@@ -302,8 +325,7 @@
|
|
int
|
|
forwards_apply_cfg(struct iter_forwards* fwd, struct config_file* cfg)
|
|
{
|
|
- free(fwd->tree);
|
|
- regional_free_all(fwd->region);
|
|
+ fwd_del_tree(fwd);
|
|
fwd->tree = rbtree_create(fwd_cmp);
|
|
if(!fwd->tree)
|
|
return 0;
|
|
@@ -411,15 +433,36 @@
|
|
size_t
|
|
forwards_get_mem(struct iter_forwards* fwd)
|
|
{
|
|
+ struct iter_forward_zone* p;
|
|
+ size_t s;
|
|
if(!fwd)
|
|
return 0;
|
|
- return sizeof(*fwd) + sizeof(*fwd->tree) +
|
|
- regional_get_mem(fwd->region);
|
|
+ s = sizeof(*fwd) + sizeof(*fwd->tree);
|
|
+ RBTREE_FOR(p, struct iter_forward_zone*, fwd->tree) {
|
|
+ s += sizeof(*p) + p->namelen + delegpt_get_mem(p->dp);
|
|
+ }
|
|
+ return s;
|
|
+}
|
|
+
|
|
+static struct iter_forward_zone*
|
|
+fwd_zone_find(struct iter_forwards* fwd, uint16_t c, uint8_t* nm)
|
|
+{
|
|
+ struct iter_forward_zone key;
|
|
+ key.node.key = &key;
|
|
+ key.dclass = c;
|
|
+ key.name = nm;
|
|
+ key.namelabs = dname_count_size_labels(nm, &key.namelen);
|
|
+ return (struct iter_forward_zone*)rbtree_search(fwd->tree, &key);
|
|
}
|
|
|
|
int
|
|
forwards_add_zone(struct iter_forwards* fwd, uint16_t c, struct delegpt* dp)
|
|
{
|
|
+ struct iter_forward_zone *z;
|
|
+ if((z=fwd_zone_find(fwd, c, dp->name)) != NULL) {
|
|
+ (void)rbtree_delete(fwd->tree, &z->node);
|
|
+ fwd_zone_free(z);
|
|
+ }
|
|
if(!forwards_insert(fwd, c, dp))
|
|
return 0;
|
|
fwd_init_parents(fwd);
|
|
@@ -429,14 +472,34 @@
|
|
void
|
|
forwards_delete_zone(struct iter_forwards* fwd, uint16_t c, uint8_t* nm)
|
|
{
|
|
- struct iter_forward_zone key;
|
|
- key.node.key = &key;
|
|
- key.dclass = c;
|
|
- key.name = nm;
|
|
- key.namelabs = dname_count_size_labels(nm, &key.namelen);
|
|
- if(!rbtree_search(fwd->tree, &key))
|
|
+ struct iter_forward_zone *z;
|
|
+ if(!(z=fwd_zone_find(fwd, c, nm)))
|
|
+ return; /* nothing to do */
|
|
+ (void)rbtree_delete(fwd->tree, &z->node);
|
|
+ fwd_zone_free(z);
|
|
+ fwd_init_parents(fwd);
|
|
+}
|
|
+
|
|
+int
|
|
+forwards_add_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm)
|
|
+{
|
|
+ if(!fwd_add_stub_hole(fwd, c, nm)) {
|
|
+ return 0;
|
|
+ }
|
|
+ fwd_init_parents(fwd);
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+void
|
|
+forwards_delete_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm)
|
|
+{
|
|
+ struct iter_forward_zone *z;
|
|
+ if(!(z=fwd_zone_find(fwd, c, nm)))
|
|
return; /* nothing to do */
|
|
- (void)rbtree_delete(fwd->tree, &key);
|
|
+ if(z->dp != NULL)
|
|
+ return; /* not a stub hole */
|
|
+ (void)rbtree_delete(fwd->tree, &z->node);
|
|
+ fwd_zone_free(z);
|
|
fwd_init_parents(fwd);
|
|
}
|
|
|
|
diff -Naur unbound-1.4.16/iterator/iter_fwd.h unbound-trunk/iterator/iter_fwd.h
|
|
--- unbound-1.4.16/iterator/iter_fwd.h 2010-07-07 09:13:36.000000000 -0400
|
|
+++ unbound-trunk/iterator/iter_fwd.h 2012-02-22 20:37:15.041368186 -0500
|
|
@@ -45,14 +45,11 @@
|
|
#include "util/rbtree.h"
|
|
struct config_file;
|
|
struct delegpt;
|
|
-struct regional;
|
|
|
|
/**
|
|
* Iterator forward zones structure
|
|
*/
|
|
struct iter_forwards {
|
|
- /** regional where forward zone server addresses are allocated */
|
|
- struct regional* region;
|
|
/**
|
|
* Zones are stored in this tree. Sort order is specially chosen.
|
|
* first sorted on qclass. Then on dname in nsec-like order, so that
|
|
@@ -77,7 +74,9 @@
|
|
int namelabs;
|
|
/** delegation point with forward server information for this zone.
|
|
* If NULL then this forward entry is used to indicate that a
|
|
- * stub-zone with the same name exists, and should be used. */
|
|
+ * stub-zone with the same name exists, and should be used.
|
|
+ * This delegation point is malloced.
|
|
+ */
|
|
struct delegpt* dp;
|
|
/** pointer to parent in tree (or NULL if none) */
|
|
struct iter_forward_zone* parent;
|
|
@@ -152,9 +151,7 @@
|
|
* @param fwd: the forward data structure
|
|
* @param c: class of zone
|
|
* @param dp: delegation point with name and target nameservers for new
|
|
- * forward zone. This delegation point and all its data must be
|
|
- * malloced in the fwd->region. (then it is freed when the fwd is
|
|
- * deleted).
|
|
+ * forward zone. malloced.
|
|
* @return false on failure (out of memory);
|
|
*/
|
|
int forwards_add_zone(struct iter_forwards* fwd, uint16_t c,
|
|
@@ -162,12 +159,31 @@
|
|
|
|
/**
|
|
* Remove zone from forward structure. For external use since it
|
|
- * recalcs the tree parents. Does not actually release any memory, the region
|
|
- * is unchanged.
|
|
+ * recalcs the tree parents.
|
|
* @param fwd: the forward data structure
|
|
* @param c: class of zone
|
|
* @param nm: name of zone (in uncompressed wireformat).
|
|
*/
|
|
void forwards_delete_zone(struct iter_forwards* fwd, uint16_t c, uint8_t* nm);
|
|
|
|
+/**
|
|
+ * Add stub hole (empty entry in forward table, that makes resolution skip
|
|
+ * a forward-zone because the stub zone should override the forward zone).
|
|
+ * Does not add one if not necessary.
|
|
+ * @param fwd: the forward data structure
|
|
+ * @param c: class of zone
|
|
+ * @param nm: name of zone (in uncompressed wireformat).
|
|
+ * @return false on failure (out of memory);
|
|
+ */
|
|
+int forwards_add_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm);
|
|
+
|
|
+/**
|
|
+ * Remove stub hole, if one exists.
|
|
+ * @param fwd: the forward data structure
|
|
+ * @param c: class of zone
|
|
+ * @param nm: name of zone (in uncompressed wireformat).
|
|
+ */
|
|
+void forwards_delete_stub_hole(struct iter_forwards* fwd, uint16_t c,
|
|
+ uint8_t* nm);
|
|
+
|
|
#endif /* ITERATOR_ITER_FWD_H */
|
|
diff -Naur unbound-1.4.16/iterator/iter_hints.c unbound-trunk/iterator/iter_hints.c
|
|
--- unbound-1.4.16/iterator/iter_hints.c 2011-11-10 13:44:06.000000000 -0500
|
|
+++ unbound-trunk/iterator/iter_hints.c 2012-02-22 20:37:15.041368186 -0500
|
|
@@ -44,7 +44,6 @@
|
|
#include <ldns/rr.h>
|
|
#include "iterator/iter_hints.h"
|
|
#include "iterator/iter_delegpt.h"
|
|
-#include "util/regional.h"
|
|
#include "util/log.h"
|
|
#include "util/config_file.h"
|
|
#include "util/net_help.h"
|
|
@@ -57,26 +56,39 @@
|
|
sizeof(struct iter_hints));
|
|
if(!hints)
|
|
return NULL;
|
|
- hints->region = regional_create();
|
|
- if(!hints->region) {
|
|
- hints_delete(hints);
|
|
- return NULL;
|
|
- }
|
|
return hints;
|
|
}
|
|
|
|
+static void hints_stub_free(struct iter_hints_stub* s)
|
|
+{
|
|
+ if(!s) return;
|
|
+ delegpt_free_mlc(s->dp);
|
|
+ free(s);
|
|
+}
|
|
+
|
|
+static void delhintnode(rbnode_t* n, void* ATTR_UNUSED(arg))
|
|
+{
|
|
+ struct iter_hints_stub* node = (struct iter_hints_stub*)n;
|
|
+ hints_stub_free(node);
|
|
+}
|
|
+
|
|
+static void hints_del_tree(struct iter_hints* hints)
|
|
+{
|
|
+ traverse_postorder(&hints->tree, &delhintnode, NULL);
|
|
+}
|
|
+
|
|
void
|
|
hints_delete(struct iter_hints* hints)
|
|
{
|
|
if(!hints)
|
|
return;
|
|
- regional_destroy(hints->region);
|
|
+ hints_del_tree(hints);
|
|
free(hints);
|
|
}
|
|
|
|
/** add hint to delegation hints */
|
|
static int
|
|
-ah(struct delegpt* dp, struct regional* r, const char* sv, const char* ip)
|
|
+ah(struct delegpt* dp, const char* sv, const char* ip)
|
|
{
|
|
struct sockaddr_storage addr;
|
|
socklen_t addrlen;
|
|
@@ -85,9 +97,9 @@
|
|
log_err("could not parse %s", sv);
|
|
return 0;
|
|
}
|
|
- if(!delegpt_add_ns(dp, r, ldns_rdf_data(rdf), 0) ||
|
|
+ if(!delegpt_add_ns_mlc(dp, ldns_rdf_data(rdf), 0) ||
|
|
!extstrtoaddr(ip, &addr, &addrlen) ||
|
|
- !delegpt_add_target(dp, r, ldns_rdf_data(rdf), ldns_rdf_size(rdf),
|
|
+ !delegpt_add_target_mlc(dp, ldns_rdf_data(rdf), ldns_rdf_size(rdf),
|
|
&addr, addrlen, 0, 0)) {
|
|
ldns_rdf_deep_free(rdf);
|
|
return 0;
|
|
@@ -98,7 +110,7 @@
|
|
|
|
/** obtain compiletime provided root hints */
|
|
static struct delegpt*
|
|
-compile_time_root_prime(struct regional* r, int do_ip4, int do_ip6)
|
|
+compile_time_root_prime(int do_ip4, int do_ip6)
|
|
{
|
|
/* from:
|
|
; This file is made available by InterNIC
|
|
@@ -109,37 +121,35 @@
|
|
;
|
|
; related version of root zone: 2010061700
|
|
*/
|
|
- struct delegpt* dp = delegpt_create(r);
|
|
+ struct delegpt* dp = delegpt_create_mlc((uint8_t*)"\000");
|
|
if(!dp)
|
|
return NULL;
|
|
dp->has_parent_side_NS = 1;
|
|
- if(!delegpt_set_name(dp, r, (uint8_t*)"\000"))
|
|
- return NULL;
|
|
if(do_ip4) {
|
|
- if(!ah(dp, r, "A.ROOT-SERVERS.NET.", "198.41.0.4")) return 0;
|
|
- if(!ah(dp, r, "B.ROOT-SERVERS.NET.", "192.228.79.201")) return 0;
|
|
- if(!ah(dp, r, "C.ROOT-SERVERS.NET.", "192.33.4.12")) return 0;
|
|
- if(!ah(dp, r, "D.ROOT-SERVERS.NET.", "128.8.10.90")) return 0;
|
|
- if(!ah(dp, r, "E.ROOT-SERVERS.NET.", "192.203.230.10")) return 0;
|
|
- if(!ah(dp, r, "F.ROOT-SERVERS.NET.", "192.5.5.241")) return 0;
|
|
- if(!ah(dp, r, "G.ROOT-SERVERS.NET.", "192.112.36.4")) return 0;
|
|
- if(!ah(dp, r, "H.ROOT-SERVERS.NET.", "128.63.2.53")) return 0;
|
|
- if(!ah(dp, r, "I.ROOT-SERVERS.NET.", "192.36.148.17")) return 0;
|
|
- if(!ah(dp, r, "J.ROOT-SERVERS.NET.", "192.58.128.30")) return 0;
|
|
- if(!ah(dp, r, "K.ROOT-SERVERS.NET.", "193.0.14.129")) return 0;
|
|
- if(!ah(dp, r, "L.ROOT-SERVERS.NET.", "199.7.83.42")) return 0;
|
|
- if(!ah(dp, r, "M.ROOT-SERVERS.NET.", "202.12.27.33")) return 0;
|
|
+ if(!ah(dp, "A.ROOT-SERVERS.NET.", "198.41.0.4")) return 0;
|
|
+ if(!ah(dp, "B.ROOT-SERVERS.NET.", "192.228.79.201")) return 0;
|
|
+ if(!ah(dp, "C.ROOT-SERVERS.NET.", "192.33.4.12")) return 0;
|
|
+ if(!ah(dp, "D.ROOT-SERVERS.NET.", "128.8.10.90")) return 0;
|
|
+ if(!ah(dp, "E.ROOT-SERVERS.NET.", "192.203.230.10")) return 0;
|
|
+ if(!ah(dp, "F.ROOT-SERVERS.NET.", "192.5.5.241")) return 0;
|
|
+ if(!ah(dp, "G.ROOT-SERVERS.NET.", "192.112.36.4")) return 0;
|
|
+ if(!ah(dp, "H.ROOT-SERVERS.NET.", "128.63.2.53")) return 0;
|
|
+ if(!ah(dp, "I.ROOT-SERVERS.NET.", "192.36.148.17")) return 0;
|
|
+ if(!ah(dp, "J.ROOT-SERVERS.NET.", "192.58.128.30")) return 0;
|
|
+ if(!ah(dp, "K.ROOT-SERVERS.NET.", "193.0.14.129")) return 0;
|
|
+ if(!ah(dp, "L.ROOT-SERVERS.NET.", "199.7.83.42")) return 0;
|
|
+ if(!ah(dp, "M.ROOT-SERVERS.NET.", "202.12.27.33")) return 0;
|
|
}
|
|
if(do_ip6) {
|
|
- if(!ah(dp, r, "A.ROOT-SERVERS.NET.", "2001:503:ba3e::2:30")) return 0;
|
|
- if(!ah(dp, r, "D.ROOT-SERVERS.NET.", "2001:500:2d::d")) return 0;
|
|
- if(!ah(dp, r, "F.ROOT-SERVERS.NET.", "2001:500:2f::f")) return 0;
|
|
- if(!ah(dp, r, "H.ROOT-SERVERS.NET.", "2001:500:1::803f:235")) return 0;
|
|
- if(!ah(dp, r, "I.ROOT-SERVERS.NET.", "2001:7fe::53")) return 0;
|
|
- if(!ah(dp, r, "J.ROOT-SERVERS.NET.", "2001:503:c27::2:30")) return 0;
|
|
- if(!ah(dp, r, "K.ROOT-SERVERS.NET.", "2001:7fd::1")) return 0;
|
|
- if(!ah(dp, r, "L.ROOT-SERVERS.NET.", "2001:500:3::42")) return 0;
|
|
- if(!ah(dp, r, "M.ROOT-SERVERS.NET.", "2001:dc3::35")) return 0;
|
|
+ if(!ah(dp, "A.ROOT-SERVERS.NET.", "2001:503:ba3e::2:30")) return 0;
|
|
+ if(!ah(dp, "D.ROOT-SERVERS.NET.", "2001:500:2d::d")) return 0;
|
|
+ if(!ah(dp, "F.ROOT-SERVERS.NET.", "2001:500:2f::f")) return 0;
|
|
+ if(!ah(dp, "H.ROOT-SERVERS.NET.", "2001:500:1::803f:235")) return 0;
|
|
+ if(!ah(dp, "I.ROOT-SERVERS.NET.", "2001:7fe::53")) return 0;
|
|
+ if(!ah(dp, "J.ROOT-SERVERS.NET.", "2001:503:c27::2:30")) return 0;
|
|
+ if(!ah(dp, "K.ROOT-SERVERS.NET.", "2001:7fd::1")) return 0;
|
|
+ if(!ah(dp, "L.ROOT-SERVERS.NET.", "2001:500:3::42")) return 0;
|
|
+ if(!ah(dp, "M.ROOT-SERVERS.NET.", "2001:dc3::35")) return 0;
|
|
}
|
|
return dp;
|
|
}
|
|
@@ -149,51 +159,50 @@
|
|
hints_insert(struct iter_hints* hints, uint16_t c, struct delegpt* dp,
|
|
int noprime)
|
|
{
|
|
- struct iter_hints_stub* node = regional_alloc(hints->region,
|
|
+ struct iter_hints_stub* node = (struct iter_hints_stub*)malloc(
|
|
sizeof(struct iter_hints_stub));
|
|
- uint8_t* nm;
|
|
- if(!node)
|
|
- return 0;
|
|
- nm = regional_alloc_init(hints->region, dp->name, dp->namelen);
|
|
- if(!nm)
|
|
+ if(!node) {
|
|
+ delegpt_free_mlc(dp);
|
|
return 0;
|
|
+ }
|
|
node->dp = dp;
|
|
node->noprime = (uint8_t)noprime;
|
|
- if(!name_tree_insert(&hints->tree, &node->node, nm, dp->namelen,
|
|
+ if(!name_tree_insert(&hints->tree, &node->node, dp->name, dp->namelen,
|
|
dp->namelabs, c)) {
|
|
log_err("second hints ignored.");
|
|
+ delegpt_free_mlc(dp);
|
|
+ free(node);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/** set stub name */
|
|
-static int
|
|
-read_stubs_name(struct iter_hints* hints, struct config_stub* s,
|
|
- struct delegpt* dp)
|
|
+static struct delegpt*
|
|
+read_stubs_name(struct config_stub* s)
|
|
{
|
|
+ struct delegpt* dp;
|
|
ldns_rdf* rdf;
|
|
if(!s->name) {
|
|
log_err("stub zone without a name");
|
|
- return 0;
|
|
+ return NULL;
|
|
}
|
|
rdf = ldns_dname_new_frm_str(s->name);
|
|
if(!rdf) {
|
|
log_err("cannot parse stub zone name %s", s->name);
|
|
- return 0;
|
|
+ return NULL;
|
|
}
|
|
- if(!delegpt_set_name(dp, hints->region, ldns_rdf_data(rdf))) {
|
|
+ if(!(dp=delegpt_create_mlc(ldns_rdf_data(rdf)))) {
|
|
ldns_rdf_deep_free(rdf);
|
|
log_err("out of memory");
|
|
- return 0;
|
|
+ return NULL;
|
|
}
|
|
ldns_rdf_deep_free(rdf);
|
|
- return 1;
|
|
+ return dp;
|
|
}
|
|
|
|
/** set stub host names */
|
|
static int
|
|
-read_stubs_host(struct iter_hints* hints, struct config_stub* s,
|
|
- struct delegpt* dp)
|
|
+read_stubs_host(struct config_stub* s, struct delegpt* dp)
|
|
{
|
|
struct config_strlist* p;
|
|
ldns_rdf* rdf;
|
|
@@ -205,7 +214,7 @@
|
|
s->name, p->str);
|
|
return 0;
|
|
}
|
|
- if(!delegpt_add_ns(dp, hints->region, ldns_rdf_data(rdf), 0)) {
|
|
+ if(!delegpt_add_ns_mlc(dp, ldns_rdf_data(rdf), 0)) {
|
|
ldns_rdf_deep_free(rdf);
|
|
log_err("out of memory");
|
|
return 0;
|
|
@@ -217,8 +226,7 @@
|
|
|
|
/** set stub server addresses */
|
|
static int
|
|
-read_stubs_addr(struct iter_hints* hints, struct config_stub* s,
|
|
- struct delegpt* dp)
|
|
+read_stubs_addr(struct config_stub* s, struct delegpt* dp)
|
|
{
|
|
struct config_strlist* p;
|
|
struct sockaddr_storage addr;
|
|
@@ -230,7 +238,7 @@
|
|
s->name, p->str);
|
|
return 0;
|
|
}
|
|
- if(!delegpt_add_addr(dp, hints->region, &addr, addrlen, 0, 0)) {
|
|
+ if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0)) {
|
|
log_err("out of memory");
|
|
return 0;
|
|
}
|
|
@@ -243,17 +251,13 @@
|
|
read_stubs(struct iter_hints* hints, struct config_file* cfg)
|
|
{
|
|
struct config_stub* s;
|
|
+ struct delegpt* dp;
|
|
for(s = cfg->stubs; s; s = s->next) {
|
|
- struct delegpt* dp = delegpt_create(hints->region);
|
|
- if(!dp) {
|
|
- log_err("out of memory");
|
|
+ if(!(dp=read_stubs_name(s)) ||
|
|
+ !read_stubs_host(s, dp) ||
|
|
+ !read_stubs_addr(s, dp))
|
|
return 0;
|
|
- }
|
|
dp->has_parent_side_NS = 1;
|
|
- if(!read_stubs_name(hints, s, dp) ||
|
|
- !read_stubs_host(hints, s, dp) ||
|
|
- !read_stubs_addr(hints, s, dp))
|
|
- return 0;
|
|
if(!hints_insert(hints, LDNS_RR_CLASS_IN, dp, !s->isprime))
|
|
return 0;
|
|
delegpt_log(VERB_QUERY, dp);
|
|
@@ -279,7 +283,7 @@
|
|
fname, strerror(errno));
|
|
return 0;
|
|
}
|
|
- dp = delegpt_create(hints->region);
|
|
+ dp = delegpt_create_mlc(NULL);
|
|
if(!dp) {
|
|
log_err("out of memory reading root hints");
|
|
fclose(f);
|
|
@@ -300,14 +304,14 @@
|
|
goto stop_read;
|
|
}
|
|
if(ldns_rr_get_type(rr) == LDNS_RR_TYPE_NS) {
|
|
- if(!delegpt_add_ns(dp, hints->region,
|
|
+ if(!delegpt_add_ns_mlc(dp,
|
|
ldns_rdf_data(ldns_rr_rdf(rr, 0)), 0)) {
|
|
log_err("out of memory reading root hints");
|
|
goto stop_read;
|
|
}
|
|
c = ldns_rr_get_class(rr);
|
|
if(!dp->name) {
|
|
- if(!delegpt_set_name(dp, hints->region,
|
|
+ if(!delegpt_set_name_mlc(dp,
|
|
ldns_rdf_data(ldns_rr_owner(rr)))){
|
|
log_err("out of memory.");
|
|
goto stop_read;
|
|
@@ -321,7 +325,7 @@
|
|
sa.sin_port = (in_port_t)htons(UNBOUND_DNS_PORT);
|
|
memmove(&sa.sin_addr,
|
|
ldns_rdf_data(ldns_rr_rdf(rr, 0)), INET_SIZE);
|
|
- if(!delegpt_add_target(dp, hints->region,
|
|
+ if(!delegpt_add_target_mlc(dp,
|
|
ldns_rdf_data(ldns_rr_owner(rr)),
|
|
ldns_rdf_size(ldns_rr_owner(rr)),
|
|
(struct sockaddr_storage*)&sa, len,
|
|
@@ -337,7 +341,7 @@
|
|
sa.sin6_port = (in_port_t)htons(UNBOUND_DNS_PORT);
|
|
memmove(&sa.sin6_addr,
|
|
ldns_rdf_data(ldns_rr_rdf(rr, 0)), INET6_SIZE);
|
|
- if(!delegpt_add_target(dp, hints->region,
|
|
+ if(!delegpt_add_target_mlc(dp,
|
|
ldns_rdf_data(ldns_rr_owner(rr)),
|
|
ldns_rdf_size(ldns_rr_owner(rr)),
|
|
(struct sockaddr_storage*)&sa, len,
|
|
@@ -360,6 +364,7 @@
|
|
fclose(f);
|
|
if(!dp->name) {
|
|
log_warn("root hints %s: no NS content", fname);
|
|
+ delegpt_free_mlc(dp);
|
|
return 1;
|
|
}
|
|
if(!hints_insert(hints, c, dp, 0)) {
|
|
@@ -373,6 +378,7 @@
|
|
ldns_rdf_deep_free(origin);
|
|
if (prev_rr)
|
|
ldns_rdf_deep_free(prev_rr);
|
|
+ delegpt_free_mlc(dp);
|
|
fclose(f);
|
|
return 0;
|
|
}
|
|
@@ -400,7 +406,7 @@
|
|
int
|
|
hints_apply_cfg(struct iter_hints* hints, struct config_file* cfg)
|
|
{
|
|
- regional_free_all(hints->region);
|
|
+ hints_del_tree(hints);
|
|
name_tree_init(&hints->tree);
|
|
|
|
/* read root hints */
|
|
@@ -413,8 +419,8 @@
|
|
|
|
/* use fallback compiletime root hints */
|
|
if(!hints_lookup_root(hints, LDNS_RR_CLASS_IN)) {
|
|
- struct delegpt* dp = compile_time_root_prime(hints->region,
|
|
- cfg->do_ip4, cfg->do_ip6);
|
|
+ struct delegpt* dp = compile_time_root_prime(cfg->do_ip4,
|
|
+ cfg->do_ip6);
|
|
verbose(VERB_ALGO, "no config, using builtin root hints.");
|
|
if(!dp)
|
|
return 0;
|
|
@@ -483,6 +489,43 @@
|
|
size_t
|
|
hints_get_mem(struct iter_hints* hints)
|
|
{
|
|
+ size_t s;
|
|
+ struct iter_hints_stub* p;
|
|
if(!hints) return 0;
|
|
- return sizeof(*hints) + regional_get_mem(hints->region);
|
|
+ s = sizeof(*hints);
|
|
+ RBTREE_FOR(p, struct iter_hints_stub*, &hints->tree) {
|
|
+ s += sizeof(*p) + delegpt_get_mem(p->dp);
|
|
+ }
|
|
+ return s;
|
|
}
|
|
+
|
|
+int
|
|
+hints_add_stub(struct iter_hints* hints, uint16_t c, struct delegpt* dp,
|
|
+ int noprime)
|
|
+{
|
|
+ struct iter_hints_stub *z;
|
|
+ if((z=(struct iter_hints_stub*)name_tree_find(&hints->tree,
|
|
+ dp->name, dp->namelen, dp->namelabs, c)) != NULL) {
|
|
+ (void)rbtree_delete(&hints->tree, &z->node);
|
|
+ hints_stub_free(z);
|
|
+ }
|
|
+ if(!hints_insert(hints, c, dp, noprime))
|
|
+ return 0;
|
|
+ name_tree_init_parents(&hints->tree);
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+void
|
|
+hints_delete_stub(struct iter_hints* hints, uint16_t c, uint8_t* nm)
|
|
+{
|
|
+ struct iter_hints_stub *z;
|
|
+ size_t len;
|
|
+ int labs = dname_count_size_labels(nm, &len);
|
|
+ if(!(z=(struct iter_hints_stub*)name_tree_find(&hints->tree,
|
|
+ nm, len, labs, c)))
|
|
+ return; /* nothing to do */
|
|
+ (void)rbtree_delete(&hints->tree, &z->node);
|
|
+ hints_stub_free(z);
|
|
+ name_tree_init_parents(&hints->tree);
|
|
+}
|
|
+
|
|
diff -Naur unbound-1.4.16/iterator/iter_hints.h unbound-trunk/iterator/iter_hints.h
|
|
--- unbound-1.4.16/iterator/iter_hints.h 2010-07-07 09:13:36.000000000 -0400
|
|
+++ unbound-trunk/iterator/iter_hints.h 2012-02-22 20:37:15.042368186 -0500
|
|
@@ -46,14 +46,11 @@
|
|
struct iter_env;
|
|
struct config_file;
|
|
struct delegpt;
|
|
-struct regional;
|
|
|
|
/**
|
|
* Iterator hints structure
|
|
*/
|
|
struct iter_hints {
|
|
- /** regional where hints are allocated */
|
|
- struct regional* region;
|
|
/**
|
|
* Hints are stored in this tree. Sort order is specially chosen.
|
|
* first sorted on qclass. Then on dname in nsec-like order, so that
|
|
@@ -71,7 +68,7 @@
|
|
struct iter_hints_stub {
|
|
/** tree sorted by name, class */
|
|
struct name_tree_node node;
|
|
- /** delegation point with hint information for this stub. */
|
|
+ /** delegation point with hint information for this stub. malloced. */
|
|
struct delegpt* dp;
|
|
/** does the stub need to forego priming (like on other ports) */
|
|
uint8_t noprime;
|
|
@@ -139,4 +136,26 @@
|
|
*/
|
|
size_t hints_get_mem(struct iter_hints* hints);
|
|
|
|
+/**
|
|
+ * Add stub to hints structure. For external use since it recalcs
|
|
+ * the tree parents.
|
|
+ * @param hints: the hints data structure
|
|
+ * @param c: class of zone
|
|
+ * @param dp: delegation point with name and target nameservers for new
|
|
+ * hints stub. malloced.
|
|
+ * @param noprime: set noprime option to true or false on new hint stub.
|
|
+ * @return false on failure (out of memory);
|
|
+ */
|
|
+int hints_add_stub(struct iter_hints* hints, uint16_t c, struct delegpt* dp,
|
|
+ int noprime);
|
|
+
|
|
+/**
|
|
+ * Remove stub from hints structure. For external use since it
|
|
+ * recalcs the tree parents.
|
|
+ * @param hints: the hints data structure
|
|
+ * @param c: class of stub zone
|
|
+ * @param nm: name of stub zone (in uncompressed wireformat).
|
|
+ */
|
|
+void hints_delete_stub(struct iter_hints* hints, uint16_t c, uint8_t* nm);
|
|
+
|
|
#endif /* ITERATOR_ITER_HINTS_H */
|
|
diff -Naur unbound-1.4.16/iterator/iter_utils.c unbound-trunk/iterator/iter_utils.c
|
|
--- unbound-1.4.16/iterator/iter_utils.c 2012-01-10 04:42:32.000000000 -0500
|
|
+++ unbound-trunk/iterator/iter_utils.c 2012-02-22 20:37:15.042368186 -0500
|
|
@@ -113,12 +113,6 @@
|
|
verbose(VERB_QUERY, "target fetch policy for level %d is %d",
|
|
i, iter_env->target_fetch_policy[i]);
|
|
|
|
- if(!iter_env->hints)
|
|
- iter_env->hints = hints_create();
|
|
- if(!iter_env->hints || !hints_apply_cfg(iter_env->hints, cfg)) {
|
|
- log_err("Could not set root or stub hints");
|
|
- return 0;
|
|
- }
|
|
if(!iter_env->donotq)
|
|
iter_env->donotq = donotq_create();
|
|
if(!iter_env->donotq || !donotq_apply_cfg(iter_env->donotq, cfg)) {
|
|
@@ -425,11 +419,11 @@
|
|
|
|
int
|
|
iter_dns_store(struct module_env* env, struct query_info* msgqinf,
|
|
- struct reply_info* msgrep, int is_referral, uint32_t leeway,
|
|
+ struct reply_info* msgrep, int is_referral, uint32_t leeway, int pside,
|
|
struct regional* region)
|
|
{
|
|
return dns_cache_store(env, msgqinf, msgrep, is_referral, leeway,
|
|
- region);
|
|
+ pside, region);
|
|
}
|
|
|
|
int
|
|
diff -Naur unbound-1.4.16/iterator/iter_utils.h unbound-trunk/iterator/iter_utils.h
|
|
--- unbound-1.4.16/iterator/iter_utils.h 2012-01-10 04:42:32.000000000 -0500
|
|
+++ unbound-trunk/iterator/iter_utils.h 2012-02-22 20:37:15.042368186 -0500
|
|
@@ -121,11 +121,13 @@
|
|
* @param is_referral: If true, then the given message to be stored is a
|
|
* referral. The cache implementation may use this as a hint.
|
|
* @param leeway: prefetch TTL leeway to expire old rrsets quicker.
|
|
+ * @param pside: true if dp is parentside, thus message is 'fresh' and NS
|
|
+ * can be prefetch-updates.
|
|
* @param region: to copy modified (cache is better) rrs back to.
|
|
* @return 0 on alloc error (out of memory).
|
|
*/
|
|
int iter_dns_store(struct module_env* env, struct query_info* qinf,
|
|
- struct reply_info* rep, int is_referral, uint32_t leeway,
|
|
+ struct reply_info* rep, int is_referral, uint32_t leeway, int pside,
|
|
struct regional* region);
|
|
|
|
/**
|
|
diff -Naur unbound-1.4.16/libunbound/libworker.c unbound-trunk/libunbound/libworker.c
|
|
--- unbound-1.4.16/libunbound/libworker.c 2012-01-10 10:07:16.000000000 -0500
|
|
+++ unbound-trunk/libunbound/libworker.c 2012-02-22 20:37:15.600368186 -0500
|
|
@@ -66,6 +66,7 @@
|
|
#include "util/data/msgencode.h"
|
|
#include "util/tube.h"
|
|
#include "iterator/iter_fwd.h"
|
|
+#include "iterator/iter_hints.h"
|
|
|
|
/** handle new query command for bg worker */
|
|
static void handle_newq(struct libworker* w, uint8_t* buf, uint32_t len);
|
|
@@ -83,6 +84,7 @@
|
|
ldns_buffer_free(w->env->scratch_buffer);
|
|
regional_destroy(w->env->scratch);
|
|
forwards_delete(w->env->fwds);
|
|
+ hints_delete(w->env->hints);
|
|
ub_randfree(w->env->rnd);
|
|
free(w->env);
|
|
}
|
|
@@ -127,17 +129,24 @@
|
|
forwards_delete(w->env->fwds);
|
|
w->env->fwds = NULL;
|
|
}
|
|
+ w->env->hints = hints_create();
|
|
+ if(w->env->hints && !hints_apply_cfg(w->env->hints, cfg)) {
|
|
+ hints_delete(w->env->hints);
|
|
+ w->env->hints = NULL;
|
|
+ }
|
|
if(cfg->ssl_upstream) {
|
|
w->sslctx = connect_sslctx_create(NULL, NULL, NULL);
|
|
if(!w->sslctx) {
|
|
- libworker_delete(w);
|
|
- return NULL;
|
|
+ /* to make the setup fail after unlock */
|
|
+ hints_delete(w->env->hints);
|
|
+ w->env->hints = NULL;
|
|
}
|
|
}
|
|
if(!w->is_bg || w->is_bg_thread) {
|
|
lock_basic_unlock(&ctx->cfglock);
|
|
}
|
|
- if(!w->env->scratch || !w->env->scratch_buffer || !w->env->fwds) {
|
|
+ if(!w->env->scratch || !w->env->scratch_buffer || !w->env->fwds ||
|
|
+ !w->env->hints) {
|
|
libworker_delete(w);
|
|
return NULL;
|
|
}
|
|
diff -Naur unbound-1.4.16/pythonmod/pythonmod_utils.c unbound-trunk/pythonmod/pythonmod_utils.c
|
|
--- unbound-1.4.16/pythonmod/pythonmod_utils.c 2012-01-10 04:42:32.000000000 -0500
|
|
+++ unbound-trunk/pythonmod/pythonmod_utils.c 2012-02-22 20:37:12.805368182 -0500
|
|
@@ -66,7 +66,7 @@
|
|
}
|
|
|
|
return dns_cache_store(qstate->env, qinfo, msgrep, is_referral,
|
|
- qstate->prefetch_leeway, NULL);
|
|
+ qstate->prefetch_leeway, 0, NULL);
|
|
}
|
|
|
|
/* Invalidate the message associated with query_info stored in message cache */
|
|
diff -Naur unbound-1.4.16/services/cache/dns.c unbound-trunk/services/cache/dns.c
|
|
--- unbound-1.4.16/services/cache/dns.c 2012-01-10 04:42:32.000000000 -0500
|
|
+++ unbound-trunk/services/cache/dns.c 2012-02-22 20:37:14.065368184 -0500
|
|
@@ -55,12 +55,20 @@
|
|
* @param env: module environment with caches.
|
|
* @param rep: contains list of rrsets to store.
|
|
* @param now: current time.
|
|
+ * @param leeway: during prefetch how much leeway to update TTLs.
|
|
+ * This makes rrsets (other than type NS) timeout sooner so they get
|
|
+ * updated with a new full TTL.
|
|
+ * Type NS does not get this, because it must not be refreshed from the
|
|
+ * child domain, but keep counting down properly.
|
|
+ * @param pside: if from parentside discovered NS, so that its NS is okay
|
|
+ * in a prefetch situation to be updated (without becoming sticky).
|
|
* @param qrep: update rrsets here if cache is better
|
|
* @param region: for qrep allocs.
|
|
*/
|
|
static void
|
|
store_rrsets(struct module_env* env, struct reply_info* rep, uint32_t now,
|
|
- struct reply_info* qrep, struct regional* region)
|
|
+ uint32_t leeway, int pside, struct reply_info* qrep,
|
|
+ struct regional* region)
|
|
{
|
|
size_t i;
|
|
/* see if rrset already exists in cache, if not insert it. */
|
|
@@ -69,7 +77,8 @@
|
|
rep->ref[i].id = rep->rrsets[i]->id;
|
|
/* update ref if it was in the cache */
|
|
switch(rrset_cache_update(env->rrset_cache, &rep->ref[i],
|
|
- env->alloc, now)) {
|
|
+ env->alloc, now + ((ntohs(rep->ref[i].key->rk.type)==
|
|
+ LDNS_RR_TYPE_NS && !pside)?0:leeway))) {
|
|
case 0: /* ref unchanged, item inserted */
|
|
break;
|
|
case 2: /* ref updated, cache is superior */
|
|
@@ -96,7 +105,7 @@
|
|
|
|
void
|
|
dns_cache_store_msg(struct module_env* env, struct query_info* qinfo,
|
|
- hashvalue_t hash, struct reply_info* rep, uint32_t leeway,
|
|
+ hashvalue_t hash, struct reply_info* rep, uint32_t leeway, int pside,
|
|
struct reply_info* qrep, struct regional* region)
|
|
{
|
|
struct msgreply_entry* e;
|
|
@@ -112,7 +121,7 @@
|
|
/* there was a reply_info_sortref(rep) here but it seems to be
|
|
* unnecessary, because the cache gets locked per rrset. */
|
|
reply_info_set_ttls(rep, *env->now);
|
|
- store_rrsets(env, rep, *env->now+leeway, qrep, region);
|
|
+ store_rrsets(env, rep, *env->now, leeway, pside, qrep, region);
|
|
if(ttl == 0) {
|
|
/* we do not store the message, but we did store the RRs,
|
|
* which could be useful for delegation information */
|
|
@@ -730,7 +739,7 @@
|
|
|
|
int
|
|
dns_cache_store(struct module_env* env, struct query_info* msgqinf,
|
|
- struct reply_info* msgrep, int is_referral, uint32_t leeway,
|
|
+ struct reply_info* msgrep, int is_referral, uint32_t leeway, int pside,
|
|
struct regional* region)
|
|
{
|
|
struct reply_info* rep = NULL;
|
|
@@ -752,8 +761,11 @@
|
|
ref.key = rep->rrsets[i];
|
|
ref.id = rep->rrsets[i]->id;
|
|
/*ignore ret: it was in the cache, ref updated */
|
|
+ /* no leeway for typeNS */
|
|
(void)rrset_cache_update(env->rrset_cache, &ref,
|
|
- env->alloc, *env->now + leeway);
|
|
+ env->alloc, *env->now +
|
|
+ ((ntohs(ref.key->rk.type)==LDNS_RR_TYPE_NS
|
|
+ && !pside) ? 0:leeway));
|
|
}
|
|
free(rep);
|
|
return 1;
|
|
@@ -774,7 +786,8 @@
|
|
rep->flags |= (BIT_RA | BIT_QR);
|
|
rep->flags &= ~(BIT_AA | BIT_CD);
|
|
h = query_info_hash(&qinf);
|
|
- dns_cache_store_msg(env, &qinf, h, rep, leeway, msgrep, region);
|
|
+ dns_cache_store_msg(env, &qinf, h, rep, leeway, pside, msgrep,
|
|
+ region);
|
|
/* qname is used inside query_info_entrysetup, and set to
|
|
* NULL. If it has not been used, free it. free(0) is safe. */
|
|
free(qinf.qname);
|
|
diff -Naur unbound-1.4.16/services/cache/dns.h unbound-trunk/services/cache/dns.h
|
|
--- unbound-1.4.16/services/cache/dns.h 2012-01-10 04:42:32.000000000 -0500
|
|
+++ unbound-trunk/services/cache/dns.h 2012-02-22 20:37:14.066368184 -0500
|
|
@@ -74,12 +74,15 @@
|
|
* It will store only the RRsets, not the message.
|
|
* @param leeway: TTL value, if not 0, other rrsets are considered expired
|
|
* that many seconds before actual TTL expiry.
|
|
+ * @param pside: if true, information came from a server which was fetched
|
|
+ * from the parentside of the zonecut. This means that the type NS
|
|
+ * can be updated to full TTL even in prefetch situations.
|
|
* @param region: region to allocate better entries from cache into.
|
|
* (used when is_referral is false).
|
|
* @return 0 on alloc error (out of memory).
|
|
*/
|
|
int dns_cache_store(struct module_env* env, struct query_info* qinf,
|
|
- struct reply_info* rep, int is_referral, uint32_t leeway,
|
|
+ struct reply_info* rep, int is_referral, uint32_t leeway, int pside,
|
|
struct regional* region);
|
|
|
|
/**
|
|
@@ -95,11 +98,14 @@
|
|
* Adjusts the reply info TTLs to absolute time.
|
|
* @param leeway: TTL value, if not 0, other rrsets are considered expired
|
|
* that many seconds before actual TTL expiry.
|
|
+ * @param pside: if true, information came from a server which was fetched
|
|
+ * from the parentside of the zonecut. This means that the type NS
|
|
+ * can be updated to full TTL even in prefetch situations.
|
|
* @param qrep: message that can be altered with better rrs from cache.
|
|
* @param region: to allocate into for qmsg.
|
|
*/
|
|
void dns_cache_store_msg(struct module_env* env, struct query_info* qinfo,
|
|
- hashvalue_t hash, struct reply_info* rep, uint32_t leeway,
|
|
+ hashvalue_t hash, struct reply_info* rep, uint32_t leeway, int pside,
|
|
struct reply_info* qrep, struct regional* region);
|
|
|
|
/**
|
|
diff -Naur unbound-1.4.16/services/cache/infra.c unbound-trunk/services/cache/infra.c
|
|
--- unbound-1.4.16/services/cache/infra.c 2012-01-10 10:07:16.000000000 -0500
|
|
+++ unbound-trunk/services/cache/infra.c 2012-02-22 20:37:14.063368184 -0500
|
|
@@ -52,6 +52,11 @@
|
|
/** Timeout when only a single probe query per IP is allowed. */
|
|
#define PROBE_MAXRTO 12000 /* in msec */
|
|
|
|
+/** number of timeouts for a type when the domain can be blocked ;
|
|
+ * even if another type has completely rtt maxed it, the different type
|
|
+ * can do this number of packets (until those all timeout too) */
|
|
+#define TIMEOUT_COUNT_MAX 3
|
|
+
|
|
size_t
|
|
infra_sizefunc(void* k, void* ATTR_UNUSED(d))
|
|
{
|
|
@@ -196,6 +201,9 @@
|
|
data->rec_lame = 0;
|
|
data->lame_type_A = 0;
|
|
data->lame_other = 0;
|
|
+ data->timeout_A = 0;
|
|
+ data->timeout_AAAA = 0;
|
|
+ data->timeout_other = 0;
|
|
}
|
|
|
|
/**
|
|
@@ -250,6 +258,9 @@
|
|
if(e && ((struct infra_data*)e->data)->ttl < timenow) {
|
|
/* it expired, try to reuse existing entry */
|
|
int old = ((struct infra_data*)e->data)->rtt.rto;
|
|
+ uint8_t tA = ((struct infra_data*)e->data)->timeout_A;
|
|
+ uint8_t tAAAA = ((struct infra_data*)e->data)->timeout_AAAA;
|
|
+ uint8_t tother = ((struct infra_data*)e->data)->timeout_other;
|
|
lock_rw_unlock(&e->lock);
|
|
e = infra_lookup_nottl(infra, addr, addrlen, nm, nmlen, 1);
|
|
if(e) {
|
|
@@ -259,9 +270,13 @@
|
|
data_entry_init(infra, e, timenow);
|
|
wr = 1;
|
|
/* TOP_TIMEOUT remains on reuse */
|
|
- if(old >= USEFUL_SERVER_TOP_TIMEOUT)
|
|
+ if(old >= USEFUL_SERVER_TOP_TIMEOUT) {
|
|
((struct infra_data*)e->data)->rtt.rto
|
|
= USEFUL_SERVER_TOP_TIMEOUT;
|
|
+ ((struct infra_data*)e->data)->timeout_A = tA;
|
|
+ ((struct infra_data*)e->data)->timeout_AAAA = tAAAA;
|
|
+ ((struct infra_data*)e->data)->timeout_other = tother;
|
|
+ }
|
|
}
|
|
}
|
|
if(!e) {
|
|
@@ -358,8 +373,8 @@
|
|
|
|
int
|
|
infra_rtt_update(struct infra_cache* infra, struct sockaddr_storage* addr,
|
|
- socklen_t addrlen, uint8_t* nm, size_t nmlen, int roundtrip,
|
|
- int orig_rtt, uint32_t timenow)
|
|
+ socklen_t addrlen, uint8_t* nm, size_t nmlen, int qtype,
|
|
+ int roundtrip, int orig_rtt, uint32_t timenow)
|
|
{
|
|
struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
|
|
nm, nmlen, 1);
|
|
@@ -377,9 +392,24 @@
|
|
data = (struct infra_data*)e->data;
|
|
if(roundtrip == -1) {
|
|
rtt_lost(&data->rtt, orig_rtt);
|
|
+ if(qtype == LDNS_RR_TYPE_A) {
|
|
+ if(data->timeout_A < TIMEOUT_COUNT_MAX)
|
|
+ data->timeout_A++;
|
|
+ } else if(qtype == LDNS_RR_TYPE_AAAA) {
|
|
+ if(data->timeout_AAAA < TIMEOUT_COUNT_MAX)
|
|
+ data->timeout_AAAA++;
|
|
+ } else {
|
|
+ if(data->timeout_other < TIMEOUT_COUNT_MAX)
|
|
+ data->timeout_other++;
|
|
+ }
|
|
} else {
|
|
rtt_update(&data->rtt, roundtrip);
|
|
data->probedelay = 0;
|
|
+ if(qtype == LDNS_RR_TYPE_A)
|
|
+ data->timeout_A = 0;
|
|
+ else if(qtype == LDNS_RR_TYPE_AAAA)
|
|
+ data->timeout_AAAA = 0;
|
|
+ else data->timeout_other = 0;
|
|
}
|
|
if(data->rtt.rto > 0)
|
|
rto = data->rtt.rto;
|
|
@@ -392,7 +422,8 @@
|
|
|
|
int infra_get_host_rto(struct infra_cache* infra,
|
|
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* nm,
|
|
- size_t nmlen, struct rtt_info* rtt, int* delay, uint32_t timenow)
|
|
+ size_t nmlen, struct rtt_info* rtt, int* delay, uint32_t timenow,
|
|
+ int* tA, int* tAAAA, int* tother)
|
|
{
|
|
struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
|
|
nm, nmlen, 0);
|
|
@@ -407,6 +438,9 @@
|
|
*delay = (int)(data->probedelay - timenow);
|
|
else *delay = 0;
|
|
}
|
|
+ *tA = (int)data->timeout_A;
|
|
+ *tAAAA = (int)data->timeout_AAAA;
|
|
+ *tother = (int)data->timeout_other;
|
|
lock_rw_unlock(&e->lock);
|
|
return ttl;
|
|
}
|
|
@@ -456,20 +490,34 @@
|
|
host = (struct infra_data*)e->data;
|
|
*rtt = rtt_unclamped(&host->rtt);
|
|
if(host->rtt.rto >= PROBE_MAXRTO && timenow < host->probedelay
|
|
- && rtt_notimeout(&host->rtt)*4 <= host->rtt.rto)
|
|
+ && rtt_notimeout(&host->rtt)*4 <= host->rtt.rto) {
|
|
/* single probe for this domain, and we are not probing */
|
|
- *rtt = USEFUL_SERVER_TOP_TIMEOUT;
|
|
+ /* unless the query type allows a probe to happen */
|
|
+ if(qtype == LDNS_RR_TYPE_A) {
|
|
+ if(host->timeout_A >= TIMEOUT_COUNT_MAX)
|
|
+ *rtt = USEFUL_SERVER_TOP_TIMEOUT;
|
|
+ else *rtt = USEFUL_SERVER_TOP_TIMEOUT-1000;
|
|
+ } else if(qtype == LDNS_RR_TYPE_AAAA) {
|
|
+ if(host->timeout_AAAA >= TIMEOUT_COUNT_MAX)
|
|
+ *rtt = USEFUL_SERVER_TOP_TIMEOUT;
|
|
+ else *rtt = USEFUL_SERVER_TOP_TIMEOUT-1000;
|
|
+ } else {
|
|
+ if(host->timeout_other >= TIMEOUT_COUNT_MAX)
|
|
+ *rtt = USEFUL_SERVER_TOP_TIMEOUT;
|
|
+ else *rtt = USEFUL_SERVER_TOP_TIMEOUT-1000;
|
|
+ }
|
|
+ }
|
|
if(timenow > host->ttl) {
|
|
/* expired entry */
|
|
/* see if this can be a re-probe of an unresponsive server */
|
|
/* minus 1000 because that is outside of the RTTBAND, so
|
|
* blacklisted servers stay blacklisted if this is chosen */
|
|
if(host->rtt.rto >= USEFUL_SERVER_TOP_TIMEOUT) {
|
|
+ lock_rw_unlock(&e->lock);
|
|
*rtt = USEFUL_SERVER_TOP_TIMEOUT-1000;
|
|
*lame = 0;
|
|
*dnsseclame = 0;
|
|
*reclame = 0;
|
|
- lock_rw_unlock(&e->lock);
|
|
return 1;
|
|
}
|
|
lock_rw_unlock(&e->lock);
|
|
diff -Naur unbound-1.4.16/services/cache/infra.h unbound-trunk/services/cache/infra.h
|
|
--- unbound-1.4.16/services/cache/infra.h 2011-10-26 11:46:23.000000000 -0400
|
|
+++ unbound-trunk/services/cache/infra.h 2012-02-22 20:37:14.065368184 -0500
|
|
@@ -91,6 +91,13 @@
|
|
uint8_t lame_type_A;
|
|
/** the host is lame (not authoritative) for other query types */
|
|
uint8_t lame_other;
|
|
+
|
|
+ /** timeouts counter for type A */
|
|
+ uint8_t timeout_A;
|
|
+ /** timeouts counter for type AAAA */
|
|
+ uint8_t timeout_AAAA;
|
|
+ /** timeouts counter for others */
|
|
+ uint8_t timeout_other;
|
|
};
|
|
|
|
/**
|
|
@@ -195,6 +202,7 @@
|
|
* @param addrlen: length of addr.
|
|
* @param name: zone name
|
|
* @param namelen: zone name length
|
|
+ * @param qtype: query type.
|
|
* @param roundtrip: estimate of roundtrip time in milliseconds or -1 for
|
|
* timeout.
|
|
* @param orig_rtt: original rtt for the query that timed out (roundtrip==-1).
|
|
@@ -203,7 +211,7 @@
|
|
* @return: 0 on error. new rto otherwise.
|
|
*/
|
|
int infra_rtt_update(struct infra_cache* infra, struct sockaddr_storage* addr,
|
|
- socklen_t addrlen, uint8_t* name, size_t namelen,
|
|
+ socklen_t addrlen, uint8_t* name, size_t namelen, int qtype,
|
|
int roundtrip, int orig_rtt, uint32_t timenow);
|
|
|
|
/**
|
|
@@ -267,12 +275,16 @@
|
|
* @param rtt: the rtt_info is copied into here (caller alloced return struct).
|
|
* @param delay: probe delay (if any).
|
|
* @param timenow: what time it is now.
|
|
+ * @param tA: timeout counter on type A.
|
|
+ * @param tAAAA: timeout counter on type AAAA.
|
|
+ * @param tother: timeout counter on type other.
|
|
* @return TTL the infra host element is valid for. If -1: not found in cache.
|
|
* TTL -2: found but expired.
|
|
*/
|
|
int infra_get_host_rto(struct infra_cache* infra,
|
|
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* name,
|
|
- size_t namelen, struct rtt_info* rtt, int* delay, uint32_t timenow);
|
|
+ size_t namelen, struct rtt_info* rtt, int* delay, uint32_t timenow,
|
|
+ int* tA, int* tAAAA, int* tother);
|
|
|
|
/**
|
|
* Get memory used by the infra cache.
|
|
diff -Naur unbound-1.4.16/services/outside_network.c unbound-trunk/services/outside_network.c
|
|
--- unbound-1.4.16/services/outside_network.c 2011-12-24 06:27:53.000000000 -0500
|
|
+++ unbound-trunk/services/outside_network.c 2012-02-22 20:37:14.106368184 -0500
|
|
@@ -1166,7 +1166,7 @@
|
|
serviced_create(struct outside_network* outnet, ldns_buffer* buff, int dnssec,
|
|
int want_dnssec, int tcp_upstream, int ssl_upstream,
|
|
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
|
|
- size_t zonelen)
|
|
+ size_t zonelen, int qtype)
|
|
{
|
|
struct serviced_query* sq = (struct serviced_query*)malloc(sizeof(*sq));
|
|
#ifdef UNBOUND_DEBUG
|
|
@@ -1188,6 +1188,7 @@
|
|
return NULL;
|
|
}
|
|
sq->zonelen = zonelen;
|
|
+ sq->qtype = qtype;
|
|
sq->dnssec = dnssec;
|
|
sq->want_dnssec = want_dnssec;
|
|
sq->tcp_upstream = tcp_upstream;
|
|
@@ -1566,8 +1567,8 @@
|
|
* huge due to system-hibernated and we woke up */
|
|
if(roundtime < TCP_AUTH_QUERY_TIMEOUT*1000) {
|
|
if(!infra_rtt_update(sq->outnet->infra, &sq->addr,
|
|
- sq->addrlen, sq->zone, sq->zonelen, roundtime,
|
|
- sq->last_rtt, (uint32_t)now.tv_sec))
|
|
+ sq->addrlen, sq->zone, sq->zonelen, sq->qtype,
|
|
+ roundtime, sq->last_rtt, (uint32_t)now.tv_sec))
|
|
log_err("out of memory noting rtt.");
|
|
}
|
|
}
|
|
@@ -1658,7 +1659,7 @@
|
|
}
|
|
sq->retry++;
|
|
if(!(rto=infra_rtt_update(outnet->infra, &sq->addr, sq->addrlen,
|
|
- sq->zone, sq->zonelen, -1, sq->last_rtt,
|
|
+ sq->zone, sq->zonelen, sq->qtype, -1, sq->last_rtt,
|
|
(uint32_t)now.tv_sec)))
|
|
log_err("out of memory in UDP exponential backoff");
|
|
if(sq->retry < OUTBOUND_UDP_RETRY) {
|
|
@@ -1752,8 +1753,8 @@
|
|
* above this value gives trouble with server selection */
|
|
if(roundtime < 60000) {
|
|
if(!infra_rtt_update(outnet->infra, &sq->addr, sq->addrlen,
|
|
- sq->zone, sq->zonelen, roundtime, sq->last_rtt,
|
|
- (uint32_t)now.tv_sec))
|
|
+ sq->zone, sq->zonelen, sq->qtype, roundtime,
|
|
+ sq->last_rtt, (uint32_t)now.tv_sec))
|
|
log_err("out of memory noting rtt.");
|
|
}
|
|
}
|
|
@@ -1814,7 +1815,7 @@
|
|
/* make new serviced query entry */
|
|
sq = serviced_create(outnet, buff, dnssec, want_dnssec,
|
|
tcp_upstream, ssl_upstream, addr, addrlen, zone,
|
|
- zonelen);
|
|
+ zonelen, (int)qtype);
|
|
if(!sq) {
|
|
free(cb);
|
|
return NULL;
|
|
diff -Naur unbound-1.4.16/services/outside_network.h unbound-trunk/services/outside_network.h
|
|
--- unbound-1.4.16/services/outside_network.h 2011-11-01 06:18:56.000000000 -0400
|
|
+++ unbound-trunk/services/outside_network.h 2012-02-22 20:37:14.107368184 -0500
|
|
@@ -312,6 +312,8 @@
|
|
uint8_t* zone;
|
|
/** length of zone name */
|
|
size_t zonelen;
|
|
+ /** qtype */
|
|
+ int qtype;
|
|
/** current status */
|
|
enum serviced_query_status {
|
|
/** initial status */
|
|
diff -Naur unbound-1.4.16/smallapp/unbound-checkconf.c unbound-trunk/smallapp/unbound-checkconf.c
|
|
--- unbound-1.4.16/smallapp/unbound-checkconf.c 2011-08-26 02:50:23.000000000 -0400
|
|
+++ unbound-trunk/smallapp/unbound-checkconf.c 2012-02-22 20:37:16.189368186 -0500
|
|
@@ -50,6 +50,7 @@
|
|
#include "util/regional.h"
|
|
#include "iterator/iterator.h"
|
|
#include "iterator/iter_fwd.h"
|
|
+#include "iterator/iter_hints.h"
|
|
#include "validator/validator.h"
|
|
#include "services/localzone.h"
|
|
#ifdef HAVE_GETOPT_H
|
|
@@ -434,6 +435,17 @@
|
|
forwards_delete(fwd);
|
|
}
|
|
|
|
+/** check hints */
|
|
+static void
|
|
+check_hints(struct config_file* cfg)
|
|
+{
|
|
+ struct iter_hints* hints = hints_create();
|
|
+ if(!hints || !hints_apply_cfg(hints, cfg)) {
|
|
+ fatal_exit("Could not set root or stub hints");
|
|
+ }
|
|
+ hints_delete(hints);
|
|
+}
|
|
+
|
|
/** check config file */
|
|
static void
|
|
checkconf(const char* cfgfile, const char* opt)
|
|
@@ -454,6 +466,7 @@
|
|
check_mod(cfg, pythonmod_get_funcblock());
|
|
#endif
|
|
check_fwd(cfg);
|
|
+ check_hints(cfg);
|
|
if(opt) print_option(cfg, opt);
|
|
else printf("unbound-checkconf: no errors in %s\n", cfgfile);
|
|
config_delete(cfg);
|
|
diff -Naur unbound-1.4.16/smallapp/unbound-control.c unbound-trunk/smallapp/unbound-control.c
|
|
--- unbound-1.4.16/smallapp/unbound-control.c 2011-06-10 06:11:38.000000000 -0400
|
|
+++ unbound-trunk/smallapp/unbound-control.c 2012-02-22 20:37:16.188368186 -0500
|
|
@@ -104,6 +104,12 @@
|
|
printf(" list_forwards list forward-zones in use\n");
|
|
printf(" list_local_zones list local-zones in use\n");
|
|
printf(" list_local_data list local-data RRs in use\n");
|
|
+ printf(" forward_add [+i] zone addr.. add forward-zone with servers\n");
|
|
+ printf(" forward_remove [+i] zone remove forward zone\n");
|
|
+ printf(" stub_add [+ip] zone addr.. add stub-zone with servers\n");
|
|
+ printf(" stub_remove [+i] zone remove stub zone\n");
|
|
+ printf(" +i also do dnssec insecure point\n");
|
|
+ printf(" +p set stub to use priming\n");
|
|
printf(" forward [off | addr ...] without arg show forward setup\n");
|
|
printf(" or off to turn off root forwarding\n");
|
|
printf(" or give list of ip addresses\n");
|
|
diff -Naur unbound-1.4.16/testcode/fake_event.c unbound-trunk/testcode/fake_event.c
|
|
--- unbound-1.4.16/testcode/fake_event.c 2011-11-01 06:18:56.000000000 -0400
|
|
+++ unbound-trunk/testcode/fake_event.c 2012-02-22 20:37:22.995368196 -0500
|
|
@@ -147,6 +147,7 @@
|
|
{
|
|
if(!pend)
|
|
return;
|
|
+ free(pend->zone);
|
|
ldns_buffer_free(pend->buffer);
|
|
ldns_pkt_free(pend->pkt);
|
|
free(pend);
|
|
@@ -554,7 +555,7 @@
|
|
if(!dp) fatal_exit("cannot parse %s", now->variable);
|
|
rto = infra_rtt_update(runtime->infra, &now->addr,
|
|
now->addrlen, ldns_rdf_data(dp), ldns_rdf_size(dp),
|
|
- atoi(now->string), -1, runtime->now_secs);
|
|
+ LDNS_RR_TYPE_A, atoi(now->string), -1, runtime->now_secs);
|
|
log_addr(0, "INFRA_RTT for", &now->addr, now->addrlen);
|
|
log_info("INFRA_RTT(%s roundtrip %d): rto of %d", now->variable,
|
|
atoi(now->string), rto);
|
|
@@ -562,6 +563,24 @@
|
|
ldns_rdf_deep_free(dp);
|
|
}
|
|
|
|
+/** perform exponential backoff on the timout */
|
|
+static void
|
|
+expon_timeout_backoff(struct replay_runtime* runtime)
|
|
+{
|
|
+ struct fake_pending* p = runtime->pending_list;
|
|
+ int rtt, vs;
|
|
+ uint8_t edns_lame_known;
|
|
+ int last_rtt, rto;
|
|
+ if(!p) return; /* no pending packet to backoff */
|
|
+ if(!infra_host(runtime->infra, &p->addr, p->addrlen, p->zone,
|
|
+ p->zonelen, runtime->now_secs, &vs, &edns_lame_known, &rtt))
|
|
+ return;
|
|
+ last_rtt = rtt;
|
|
+ rto = infra_rtt_update(runtime->infra, &p->addr, p->addrlen, p->zone,
|
|
+ p->zonelen, p->qtype, -1, last_rtt, runtime->now_secs);
|
|
+ log_info("infra_rtt_update returned rto %d", rto);
|
|
+}
|
|
+
|
|
/**
|
|
* Advance to the next moment.
|
|
*/
|
|
@@ -608,6 +627,7 @@
|
|
case repevt_timeout:
|
|
mom = runtime->now;
|
|
advance_moment(runtime);
|
|
+ expon_timeout_backoff(runtime);
|
|
fake_pending_callback(runtime, mom, NETEVENT_TIMEOUT);
|
|
break;
|
|
case repevt_back_reply:
|
|
@@ -929,6 +949,7 @@
|
|
pend->timeout = timeout/1000;
|
|
pend->transport = transport_udp;
|
|
pend->pkt = NULL;
|
|
+ pend->zone = NULL;
|
|
pend->serviced = 0;
|
|
pend->runtime = runtime;
|
|
status = ldns_buffer2pkt_wire(&pend->pkt, packet);
|
|
@@ -982,6 +1003,7 @@
|
|
pend->timeout = timeout;
|
|
pend->transport = transport_tcp;
|
|
pend->pkt = NULL;
|
|
+ pend->zone = NULL;
|
|
pend->runtime = runtime;
|
|
pend->serviced = 0;
|
|
status = ldns_buffer2pkt_wire(&pend->pkt, packet);
|
|
@@ -1017,9 +1039,8 @@
|
|
uint16_t flags, int dnssec, int ATTR_UNUSED(want_dnssec),
|
|
int ATTR_UNUSED(tcp_upstream), int ATTR_UNUSED(ssl_upstream),
|
|
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
|
|
- size_t ATTR_UNUSED(zonelen), comm_point_callback_t* callback,
|
|
- void* callback_arg, ldns_buffer* ATTR_UNUSED(buff),
|
|
- int (*arg_compare)(void*,void*))
|
|
+ size_t zonelen, comm_point_callback_t* callback, void* callback_arg,
|
|
+ ldns_buffer* ATTR_UNUSED(buff), int (*arg_compare)(void*,void*))
|
|
{
|
|
struct replay_runtime* runtime = (struct replay_runtime*)outnet->base;
|
|
struct fake_pending* pend = (struct fake_pending*)calloc(1,
|
|
@@ -1062,6 +1083,10 @@
|
|
}
|
|
memcpy(&pend->addr, addr, addrlen);
|
|
pend->addrlen = addrlen;
|
|
+ pend->zone = memdup(zone, zonelen);
|
|
+ pend->zonelen = zonelen;
|
|
+ pend->qtype = (int)qtype;
|
|
+ log_assert(pend->zone);
|
|
pend->callback = callback;
|
|
pend->cb_arg = callback_arg;
|
|
pend->timeout = UDP_AUTH_QUERY_TIMEOUT;
|
|
@@ -1112,6 +1137,7 @@
|
|
else runtime->pending_list = p->next;
|
|
ldns_buffer_free(p->buffer);
|
|
ldns_pkt_free(p->pkt);
|
|
+ free(p->zone);
|
|
free(p);
|
|
return;
|
|
}
|
|
diff -Naur unbound-1.4.16/testcode/replay.h unbound-trunk/testcode/replay.h
|
|
--- unbound-1.4.16/testcode/replay.h 2011-10-26 11:46:23.000000000 -0400
|
|
+++ unbound-trunk/testcode/replay.h 2012-02-22 20:37:22.950368196 -0500
|
|
@@ -323,6 +323,12 @@
|
|
struct sockaddr_storage addr;
|
|
/** len of addr */
|
|
socklen_t addrlen;
|
|
+ /** zone name, uncompressed wire format (as used when sent) */
|
|
+ uint8_t* zone;
|
|
+ /** length of zone name */
|
|
+ size_t zonelen;
|
|
+ /** qtype */
|
|
+ int qtype;
|
|
/** The callback function to call when answer arrives (or timeout) */
|
|
comm_point_callback_t* callback;
|
|
/** callback user argument */
|
|
diff -Naur unbound-1.4.16/testcode/testbound.c unbound-trunk/testcode/testbound.c
|
|
--- unbound-1.4.16/testcode/testbound.c 2010-09-15 03:15:30.000000000 -0400
|
|
+++ unbound-trunk/testcode/testbound.c 2012-02-22 20:37:22.995368196 -0500
|
|
@@ -70,6 +70,7 @@
|
|
printf("-p file playback text file\n");
|
|
printf("-2 detect SHA256 support (exit code 0 or 1)\n");
|
|
printf("-g detect GOST support (exit code 0 or 1)\n");
|
|
+ printf("-e detect ECDSA support (exit code 0 or 1)\n");
|
|
printf("-s testbound self-test - unit test of testbound parts.\n");
|
|
printf("-o str unbound commandline options separated by spaces.\n");
|
|
printf("Version %s\n", PACKAGE_VERSION);
|
|
@@ -272,7 +273,7 @@
|
|
pass_argc = 1;
|
|
pass_argv[0] = "unbound";
|
|
add_opts("-d", &pass_argc, pass_argv);
|
|
- while( (c=getopt(argc, argv, "2gho:p:s")) != -1) {
|
|
+ while( (c=getopt(argc, argv, "2egho:p:s")) != -1) {
|
|
switch(c) {
|
|
case 's':
|
|
free(pass_argv[1]);
|
|
@@ -288,6 +289,15 @@
|
|
exit(1);
|
|
#endif
|
|
break;
|
|
+ case 'e':
|
|
+#if defined(USE_ECDSA)
|
|
+ printf("ECDSA supported\n");
|
|
+ exit(0);
|
|
+#else
|
|
+ printf("ECDSA not supported\n");
|
|
+ exit(1);
|
|
+#endif
|
|
+ break;
|
|
case 'g':
|
|
#ifdef USE_GOST
|
|
if(ldns_key_EVP_load_gost_id()) {
|
|
diff -Naur unbound-1.4.16/testcode/unitmain.c unbound-trunk/testcode/unitmain.c
|
|
--- unbound-1.4.16/testcode/unitmain.c 2011-11-10 13:44:06.000000000 -0500
|
|
+++ unbound-trunk/testcode/unitmain.c 2012-02-22 20:37:22.996368196 -0500
|
|
@@ -445,7 +445,7 @@
|
|
&vs, &edns_lame, &to) );
|
|
unit_assert( vs == 0 && to == init && edns_lame == 0 );
|
|
|
|
- unit_assert( infra_rtt_update(slab, &one, onelen, zone, zonelen, -1, init, now) );
|
|
+ unit_assert( infra_rtt_update(slab, &one, onelen, zone, zonelen, LDNS_RR_TYPE_A, -1, init, now) );
|
|
unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
|
|
now, &vs, &edns_lame, &to) );
|
|
unit_assert( vs == 0 && to == init*2 && edns_lame == 0 );
|
|
diff -Naur unbound-1.4.16/testcode/unitverify.c unbound-trunk/testcode/unitverify.c
|
|
--- unbound-1.4.16/testcode/unitverify.c 2010-12-20 11:08:52.000000000 -0500
|
|
+++ unbound-trunk/testcode/unitverify.c 2012-02-22 20:37:22.994368196 -0500
|
|
@@ -520,6 +520,11 @@
|
|
verifytest_file("testdata/test_sigs.gost", "20090807060504");
|
|
else printf("Warning: skipped GOST, openssl does not provide gost.\n");
|
|
#endif
|
|
+#ifdef USE_ECDSA
|
|
+ verifytest_file("testdata/test_sigs.ecdsa_p256", "20100908100439");
|
|
+ verifytest_file("testdata/test_sigs.ecdsa_p384", "20100908100439");
|
|
+ dstest_file("testdata/test_ds.sha384");
|
|
+#endif
|
|
dstest_file("testdata/test_ds.sha1");
|
|
nsectest();
|
|
nsec3_hash_test("testdata/test_nsec3_hash.1");
|
|
diff -Naur unbound-1.4.16/util/iana_ports.inc unbound-trunk/util/iana_ports.inc
|
|
--- unbound-1.4.16/util/iana_ports.inc 2012-01-10 04:42:55.000000000 -0500
|
|
+++ unbound-trunk/util/iana_ports.inc 2012-02-22 20:37:23.866368198 -0500
|
|
@@ -5026,6 +5026,7 @@
|
|
12006,
|
|
12007,
|
|
12008,
|
|
+12009,
|
|
12012,
|
|
12013,
|
|
12109,
|
|
@@ -5272,6 +5273,7 @@
|
|
32896,
|
|
33123,
|
|
33331,
|
|
+33334,
|
|
33434,
|
|
33656,
|
|
34249,
|
|
@@ -5304,6 +5306,7 @@
|
|
43188,
|
|
43189,
|
|
43190,
|
|
+43439,
|
|
43440,
|
|
43441,
|
|
44321,
|
|
diff -Naur unbound-1.4.16/util/module.h unbound-trunk/util/module.h
|
|
--- unbound-1.4.16/util/module.h 2011-10-26 11:46:23.000000000 -0400
|
|
+++ unbound-trunk/util/module.h 2012-02-22 20:37:23.867368198 -0500
|
|
@@ -60,6 +60,7 @@
|
|
struct val_anchors;
|
|
struct val_neg_cache;
|
|
struct iter_forwards;
|
|
+struct iter_hints;
|
|
|
|
/** Maximum number of modules in operation */
|
|
#define MAX_MODULE 5
|
|
@@ -204,6 +205,14 @@
|
|
/** Mapping of forwarding zones to targets.
|
|
* iterator forwarder information. per-thread, created by worker */
|
|
struct iter_forwards* fwds;
|
|
+ /**
|
|
+ * iterator forwarder information. per-thread, created by worker.
|
|
+ * The hints -- these aren't stored in the cache because they don't
|
|
+ * expire. The hints are always used to "prime" the cache. Note
|
|
+ * that both root hints and stub zone "hints" are stored in this
|
|
+ * data structure.
|
|
+ */
|
|
+ struct iter_hints* hints;
|
|
/** module specific data. indexed by module id. */
|
|
void* modinfo[MAX_MODULE];
|
|
};
|
|
diff -Naur unbound-1.4.16/util/netevent.c unbound-trunk/util/netevent.c
|
|
--- unbound-1.4.16/util/netevent.c 2011-11-10 13:44:06.000000000 -0500
|
|
+++ unbound-trunk/util/netevent.c 2012-02-22 20:37:23.867368198 -0500
|
|
@@ -367,11 +367,15 @@
|
|
strncpy(buf1, "(inet_ntop error)", sizeof(buf1));
|
|
}
|
|
buf1[sizeof(buf1)-1]=0;
|
|
+#ifdef HAVE_STRUCT_IN_PKTINFO_IPI_SPEC_DST
|
|
if(inet_ntop(AF_INET, &r->pktinfo.v4info.ipi_spec_dst,
|
|
buf2, (socklen_t)sizeof(buf2)) == 0) {
|
|
strncpy(buf2, "(inet_ntop error)", sizeof(buf2));
|
|
}
|
|
buf2[sizeof(buf2)-1]=0;
|
|
+#else
|
|
+ buf2[0]=0;
|
|
+#endif
|
|
log_info("%s: %d %s %s", str, r->pktinfo.v4info.ipi_ifindex,
|
|
buf1, buf2);
|
|
#elif defined(IP_RECVDSTADDR)
|
|
diff -Naur unbound-1.4.16/validator/autotrust.c unbound-trunk/validator/autotrust.c
|
|
--- unbound-1.4.16/validator/autotrust.c 2012-01-19 09:17:22.000000000 -0500
|
|
+++ unbound-trunk/validator/autotrust.c 2012-02-22 20:37:14.741368184 -0500
|
|
@@ -996,6 +996,9 @@
|
|
/* success; overwrite actual file */
|
|
fclose(out);
|
|
verbose(VERB_ALGO, "autotrust: replaced %s", fname);
|
|
+#ifdef UB_ON_WINDOWS
|
|
+ (void)unlink(fname); /* windows does not replace file with rename() */
|
|
+#endif
|
|
if(rename(tempf, fname) < 0) {
|
|
log_err("rename(%s to %s): %s", tempf, fname, strerror(errno));
|
|
}
|
|
diff -Naur unbound-1.4.16/validator/val_anchor.c unbound-trunk/validator/val_anchor.c
|
|
--- unbound-1.4.16/validator/val_anchor.c 2011-11-10 13:44:06.000000000 -0500
|
|
+++ unbound-trunk/validator/val_anchor.c 2012-02-22 20:37:14.741368184 -0500
|
|
@@ -49,7 +49,6 @@
|
|
#include "util/data/dname.h"
|
|
#include "util/log.h"
|
|
#include "util/net_help.h"
|
|
-#include "util/regional.h"
|
|
#include "util/config_file.h"
|
|
#ifdef HAVE_GLOB_H
|
|
#include <glob.h>
|
|
@@ -77,11 +76,6 @@
|
|
struct val_anchors* a = (struct val_anchors*)calloc(1, sizeof(*a));
|
|
if(!a)
|
|
return NULL;
|
|
- a->region = regional_create();
|
|
- if(!a->region) {
|
|
- free(a);
|
|
- return NULL;
|
|
- }
|
|
a->tree = rbtree_create(anchor_cmp);
|
|
if(!a->tree) {
|
|
anchors_delete(a);
|
|
@@ -98,15 +92,45 @@
|
|
return a;
|
|
}
|
|
|
|
+/** delete assembled rrset */
|
|
+static void
|
|
+assembled_rrset_delete(struct ub_packed_rrset_key* pkey)
|
|
+{
|
|
+ if(!pkey) return;
|
|
+ if(pkey->entry.data) {
|
|
+ struct packed_rrset_data* pd = (struct packed_rrset_data*)
|
|
+ pkey->entry.data;
|
|
+ free(pd->rr_data);
|
|
+ free(pd->rr_ttl);
|
|
+ free(pd->rr_len);
|
|
+ free(pd);
|
|
+ }
|
|
+ free(pkey->rk.dname);
|
|
+ free(pkey);
|
|
+}
|
|
+
|
|
/** destroy locks in tree and delete autotrust anchors */
|
|
static void
|
|
anchors_delfunc(rbnode_t* elem, void* ATTR_UNUSED(arg))
|
|
{
|
|
struct trust_anchor* ta = (struct trust_anchor*)elem;
|
|
+ if(!ta) return;
|
|
if(ta->autr) {
|
|
autr_point_delete(ta);
|
|
} else {
|
|
+ struct ta_key* p, *np;
|
|
lock_basic_destroy(&ta->lock);
|
|
+ free(ta->name);
|
|
+ p = ta->keylist;
|
|
+ while(p) {
|
|
+ np = p->next;
|
|
+ free(p->data);
|
|
+ free(p);
|
|
+ p = np;
|
|
+ }
|
|
+ assembled_rrset_delete(ta->ds_rrset);
|
|
+ assembled_rrset_delete(ta->dnskey_rrset);
|
|
+ free(ta);
|
|
}
|
|
}
|
|
|
|
@@ -118,9 +142,9 @@
|
|
lock_unprotect(&anchors->lock, anchors->autr);
|
|
lock_unprotect(&anchors->lock, anchors);
|
|
lock_basic_destroy(&anchors->lock);
|
|
- traverse_postorder(anchors->tree, anchors_delfunc, NULL);
|
|
+ if(anchors->tree)
|
|
+ traverse_postorder(anchors->tree, anchors_delfunc, NULL);
|
|
free(anchors->tree);
|
|
- regional_destroy(anchors->region);
|
|
autr_global_delete(anchors->autr);
|
|
free(anchors);
|
|
}
|
|
@@ -193,30 +217,34 @@
|
|
/** create new trust anchor object */
|
|
static struct trust_anchor*
|
|
anchor_new_ta(struct val_anchors* anchors, uint8_t* name, int namelabs,
|
|
- size_t namelen, uint16_t dclass)
|
|
+ size_t namelen, uint16_t dclass, int lockit)
|
|
{
|
|
#ifdef UNBOUND_DEBUG
|
|
rbnode_t* r;
|
|
#endif
|
|
- struct trust_anchor* ta = (struct trust_anchor*)regional_alloc(
|
|
- anchors->region, sizeof(struct trust_anchor));
|
|
+ struct trust_anchor* ta = (struct trust_anchor*)malloc(
|
|
+ sizeof(struct trust_anchor));
|
|
if(!ta)
|
|
return NULL;
|
|
memset(ta, 0, sizeof(*ta));
|
|
ta->node.key = ta;
|
|
- ta->name = regional_alloc_init(anchors->region, name, namelen);
|
|
- if(!ta->name)
|
|
+ ta->name = memdup(name, namelen);
|
|
+ if(!ta->name) {
|
|
+ free(ta);
|
|
return NULL;
|
|
+ }
|
|
ta->namelabs = namelabs;
|
|
ta->namelen = namelen;
|
|
ta->dclass = dclass;
|
|
lock_basic_init(&ta->lock);
|
|
- lock_basic_lock(&anchors->lock);
|
|
+ if(lockit)
|
|
+ lock_basic_lock(&anchors->lock);
|
|
#ifdef UNBOUND_DEBUG
|
|
r =
|
|
#endif
|
|
rbtree_insert(anchors->tree, &ta->node);
|
|
- lock_basic_unlock(&anchors->lock);
|
|
+ if(lockit)
|
|
+ lock_basic_unlock(&anchors->lock);
|
|
log_assert(r != NULL);
|
|
return ta;
|
|
}
|
|
@@ -237,17 +265,17 @@
|
|
|
|
/** create new trustanchor key */
|
|
static struct ta_key*
|
|
-anchor_new_ta_key(struct val_anchors* anchors, uint8_t* rdata, size_t rdata_len,
|
|
- uint16_t type)
|
|
+anchor_new_ta_key(uint8_t* rdata, size_t rdata_len, uint16_t type)
|
|
{
|
|
- struct ta_key* k = (struct ta_key*)regional_alloc(anchors->region,
|
|
- sizeof(*k));
|
|
+ struct ta_key* k = (struct ta_key*)malloc(sizeof(*k));
|
|
if(!k)
|
|
return NULL;
|
|
memset(k, 0, sizeof(*k));
|
|
- k->data = regional_alloc_init(anchors->region, rdata, rdata_len);
|
|
- if(!k->data)
|
|
+ k->data = memdup(rdata, rdata_len);
|
|
+ if(!k->data) {
|
|
+ free(k);
|
|
return NULL;
|
|
+ }
|
|
k->len = rdata_len;
|
|
k->type = type;
|
|
return k;
|
|
@@ -282,7 +310,7 @@
|
|
/* lookup or create trustanchor */
|
|
ta = anchor_find(anchors, name, namelabs, namelen, dclass);
|
|
if(!ta) {
|
|
- ta = anchor_new_ta(anchors, name, namelabs, namelen, dclass);
|
|
+ ta = anchor_new_ta(anchors, name, namelabs, namelen, dclass, 1);
|
|
if(!ta)
|
|
return NULL;
|
|
lock_basic_lock(&ta->lock);
|
|
@@ -296,7 +324,7 @@
|
|
lock_basic_unlock(&ta->lock);
|
|
return ta;
|
|
}
|
|
- k = anchor_new_ta_key(anchors, rdata, rdata_len, type);
|
|
+ k = anchor_new_ta_key(rdata, rdata_len, type);
|
|
if(!k) {
|
|
lock_basic_unlock(&ta->lock);
|
|
return NULL;
|
|
@@ -826,55 +854,73 @@
|
|
|
|
/**
|
|
* Assemble an rrset structure for the type
|
|
- * @param region: allocated in this region.
|
|
* @param ta: trust anchor.
|
|
* @param num: number of items to fetch from list.
|
|
* @param type: fetch only items of this type.
|
|
* @return rrset or NULL on error.
|
|
*/
|
|
static struct ub_packed_rrset_key*
|
|
-assemble_it(struct regional* region, struct trust_anchor* ta, size_t num,
|
|
- uint16_t type)
|
|
+assemble_it(struct trust_anchor* ta, size_t num, uint16_t type)
|
|
{
|
|
struct ub_packed_rrset_key* pkey = (struct ub_packed_rrset_key*)
|
|
- regional_alloc(region, sizeof(*pkey));
|
|
+ malloc(sizeof(*pkey));
|
|
struct packed_rrset_data* pd;
|
|
struct ta_key* tk;
|
|
size_t i;
|
|
if(!pkey)
|
|
return NULL;
|
|
memset(pkey, 0, sizeof(*pkey));
|
|
- pkey->rk.dname = regional_alloc_init(region, ta->name, ta->namelen);
|
|
- if(!pkey->rk.dname)
|
|
+ pkey->rk.dname = memdup(ta->name, ta->namelen);
|
|
+ if(!pkey->rk.dname) {
|
|
+ free(pkey);
|
|
return NULL;
|
|
-
|
|
+ }
|
|
+
|
|
pkey->rk.dname_len = ta->namelen;
|
|
pkey->rk.type = htons(type);
|
|
pkey->rk.rrset_class = htons(ta->dclass);
|
|
/* The rrset is build in an uncompressed way. This means it
|
|
* cannot be copied in the normal way. */
|
|
- pd = (struct packed_rrset_data*)regional_alloc(region, sizeof(*pd));
|
|
- if(!pd)
|
|
+ pd = (struct packed_rrset_data*)malloc(sizeof(*pd));
|
|
+ if(!pd) {
|
|
+ free(pkey->rk.dname);
|
|
+ free(pkey);
|
|
return NULL;
|
|
+ }
|
|
memset(pd, 0, sizeof(*pd));
|
|
pd->count = num;
|
|
pd->trust = rrset_trust_ultimate;
|
|
- pd->rr_len = (size_t*)regional_alloc(region, num*sizeof(size_t));
|
|
- if(!pd->rr_len)
|
|
- return NULL;
|
|
- pd->rr_ttl = (uint32_t*)regional_alloc(region, num*sizeof(uint32_t));
|
|
- if(!pd->rr_ttl)
|
|
- return NULL;
|
|
- pd->rr_data = (uint8_t**)regional_alloc(region, num*sizeof(uint8_t*));
|
|
- if(!pd->rr_data)
|
|
+ pd->rr_len = (size_t*)malloc(num*sizeof(size_t));
|
|
+ if(!pd->rr_len) {
|
|
+ free(pd);
|
|
+ free(pkey->rk.dname);
|
|
+ free(pkey);
|
|
+ return NULL;
|
|
+ }
|
|
+ pd->rr_ttl = (uint32_t*)malloc(num*sizeof(uint32_t));
|
|
+ if(!pd->rr_ttl) {
|
|
+ free(pd->rr_len);
|
|
+ free(pd);
|
|
+ free(pkey->rk.dname);
|
|
+ free(pkey);
|
|
+ return NULL;
|
|
+ }
|
|
+ pd->rr_data = (uint8_t**)malloc(num*sizeof(uint8_t*));
|
|
+ if(!pd->rr_data) {
|
|
+ free(pd->rr_ttl);
|
|
+ free(pd->rr_len);
|
|
+ free(pd);
|
|
+ free(pkey->rk.dname);
|
|
+ free(pkey);
|
|
return NULL;
|
|
+ }
|
|
/* fill in rrs */
|
|
i=0;
|
|
for(tk = ta->keylist; tk; tk = tk->next) {
|
|
if(tk->type != type)
|
|
continue;
|
|
pd->rr_len[i] = tk->len;
|
|
- /* reuse data ptr to allocation in region */
|
|
+ /* reuse data ptr to allocation in talist */
|
|
pd->rr_data[i] = tk->data;
|
|
pd->rr_ttl[i] = 0;
|
|
i++;
|
|
@@ -885,22 +931,20 @@
|
|
|
|
/**
|
|
* Assemble structures for the trust DS and DNSKEY rrsets.
|
|
- * @param anchors: trust anchor storage.
|
|
* @param ta: trust anchor
|
|
* @return: false on error.
|
|
*/
|
|
static int
|
|
-anchors_assemble(struct val_anchors* anchors, struct trust_anchor* ta)
|
|
+anchors_assemble(struct trust_anchor* ta)
|
|
{
|
|
if(ta->numDS > 0) {
|
|
- ta->ds_rrset = assemble_it(anchors->region, ta,
|
|
- ta->numDS, LDNS_RR_TYPE_DS);
|
|
+ ta->ds_rrset = assemble_it(ta, ta->numDS, LDNS_RR_TYPE_DS);
|
|
if(!ta->ds_rrset)
|
|
return 0;
|
|
}
|
|
if(ta->numDNSKEY > 0) {
|
|
- ta->dnskey_rrset = assemble_it(anchors->region, ta,
|
|
- ta->numDNSKEY, LDNS_RR_TYPE_DNSKEY);
|
|
+ ta->dnskey_rrset = assemble_it(ta, ta->numDNSKEY,
|
|
+ LDNS_RR_TYPE_DNSKEY);
|
|
if(!ta->dnskey_rrset)
|
|
return 0;
|
|
}
|
|
@@ -961,7 +1005,7 @@
|
|
ta = next; /* skip */
|
|
continue;
|
|
}
|
|
- if(!anchors_assemble(anchors, ta)) {
|
|
+ if(!anchors_assemble(ta)) {
|
|
log_err("out of memory");
|
|
lock_basic_unlock(&ta->lock);
|
|
lock_basic_unlock(&anchors->lock);
|
|
@@ -987,7 +1031,7 @@
|
|
" upgrade unbound and openssl)", b);
|
|
(void)rbtree_delete(anchors->tree, &ta->node);
|
|
lock_basic_unlock(&ta->lock);
|
|
- lock_basic_destroy(&ta->lock);
|
|
+ anchors_delfunc(&ta->node, NULL);
|
|
ta = next;
|
|
continue;
|
|
}
|
|
@@ -1146,5 +1190,72 @@
|
|
size_t
|
|
anchors_get_mem(struct val_anchors* anchors)
|
|
{
|
|
- return sizeof(*anchors) + regional_get_mem(anchors->region);
|
|
+ struct trust_anchor *ta;
|
|
+ size_t s = sizeof(*anchors);
|
|
+ RBTREE_FOR(ta, struct trust_anchor*, anchors->tree) {
|
|
+ s += sizeof(*ta) + ta->namelen;
|
|
+ /* keys and so on */
|
|
+ }
|
|
+ return s;
|
|
+}
|
|
+
|
|
+int
|
|
+anchors_add_insecure(struct val_anchors* anchors, uint16_t c, uint8_t* nm)
|
|
+{
|
|
+ struct trust_anchor key;
|
|
+ key.node.key = &key;
|
|
+ key.name = nm;
|
|
+ key.namelabs = dname_count_size_labels(nm, &key.namelen);
|
|
+ key.dclass = c;
|
|
+ lock_basic_lock(&anchors->lock);
|
|
+ if(rbtree_search(anchors->tree, &key)) {
|
|
+ lock_basic_unlock(&anchors->lock);
|
|
+ /* nothing to do, already an anchor or insecure point */
|
|
+ return 1;
|
|
+ }
|
|
+ if(!anchor_new_ta(anchors, nm, key.namelabs, key.namelen, c, 0)) {
|
|
+ log_err("out of memory");
|
|
+ lock_basic_unlock(&anchors->lock);
|
|
+ return 0;
|
|
+ }
|
|
+ /* no other contents in new ta, because it is insecure point */
|
|
+ anchors_init_parents_locked(anchors);
|
|
+ lock_basic_unlock(&anchors->lock);
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+void
|
|
+anchors_delete_insecure(struct val_anchors* anchors, uint16_t c,
|
|
+ uint8_t* nm)
|
|
+{
|
|
+ struct trust_anchor key;
|
|
+ struct trust_anchor* ta;
|
|
+ key.node.key = &key;
|
|
+ key.name = nm;
|
|
+ key.namelabs = dname_count_size_labels(nm, &key.namelen);
|
|
+ key.dclass = c;
|
|
+ lock_basic_lock(&anchors->lock);
|
|
+ if(!(ta=(struct trust_anchor*)rbtree_search(anchors->tree, &key))) {
|
|
+ lock_basic_unlock(&anchors->lock);
|
|
+ /* nothing there */
|
|
+ return;
|
|
+ }
|
|
+ /* lock it to drive away other threads that use it */
|
|
+ lock_basic_lock(&ta->lock);
|
|
+ /* see if its really an insecure point */
|
|
+ if(ta->keylist || ta->autr || ta->numDS || ta->numDNSKEY) {
|
|
+ lock_basic_unlock(&ta->lock);
|
|
+ /* its not an insecure point, do not remove it */
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ /* remove from tree */
|
|
+ (void)rbtree_delete(anchors->tree, &ta->node);
|
|
+ anchors_init_parents_locked(anchors);
|
|
+ lock_basic_unlock(&anchors->lock);
|
|
+
|
|
+ /* actual free of data */
|
|
+ lock_basic_unlock(&ta->lock);
|
|
+ anchors_delfunc(&ta->node, NULL);
|
|
}
|
|
+
|
|
diff -Naur unbound-1.4.16/validator/val_anchor.h unbound-trunk/validator/val_anchor.h
|
|
--- unbound-1.4.16/validator/val_anchor.h 2010-07-07 09:13:36.000000000 -0400
|
|
+++ unbound-trunk/validator/val_anchor.h 2012-02-22 20:37:14.743368184 -0500
|
|
@@ -43,7 +43,6 @@
|
|
#define VALIDATOR_VAL_ANCHOR_H
|
|
#include "util/rbtree.h"
|
|
#include "util/locks.h"
|
|
-struct regional;
|
|
struct trust_anchor;
|
|
struct config_file;
|
|
struct ub_packed_rrset_key;
|
|
@@ -60,11 +59,6 @@
|
|
struct val_anchors {
|
|
/** lock on trees */
|
|
lock_basic_t lock;
|
|
- /**
|
|
- * region where trust anchors are allocated.
|
|
- * Autotrust anchors are malloced so they can be updated.
|
|
- */
|
|
- struct regional* region;
|
|
/**
|
|
* Anchors are store in this tree. Sort order is chosen, so that
|
|
* dnames are in nsec-like order. A lookup on class, name will return
|
|
@@ -111,7 +105,6 @@
|
|
struct trust_anchor* parent;
|
|
/**
|
|
* List of DS or DNSKEY rrs that form the trust anchor.
|
|
- * It is allocated in the region.
|
|
*/
|
|
struct ta_key* keylist;
|
|
/** Autotrust anchor point data, or NULL */
|
|
@@ -203,4 +196,23 @@
|
|
/** compare two trust anchors */
|
|
int anchor_cmp(const void* k1, const void* k2);
|
|
|
|
+/**
|
|
+ * Add insecure point trust anchor. For external use (locks and init_parents)
|
|
+ * @param anchors: anchor storage.
|
|
+ * @param c: class.
|
|
+ * @param nm: name of insecure trust point.
|
|
+ * @return false on alloc failure.
|
|
+ */
|
|
+int anchors_add_insecure(struct val_anchors* anchors, uint16_t c, uint8_t* nm);
|
|
+
|
|
+/**
|
|
+ * Delete insecure point trust anchor. Does not remove if no such point.
|
|
+ * For external use (locks and init_parents)
|
|
+ * @param anchors: anchor storage.
|
|
+ * @param c: class.
|
|
+ * @param nm: name of insecure trust point.
|
|
+ */
|
|
+void anchors_delete_insecure(struct val_anchors* anchors, uint16_t c,
|
|
+ uint8_t* nm);
|
|
+
|
|
#endif /* VALIDATOR_VAL_ANCHOR_H */
|
|
diff -Naur unbound-1.4.16/validator/validator.c unbound-trunk/validator/validator.c
|
|
--- unbound-1.4.16/validator/validator.c 2012-01-10 04:42:32.000000000 -0500
|
|
+++ unbound-trunk/validator/validator.c 2012-02-22 20:37:14.743368184 -0500
|
|
@@ -1977,15 +1977,17 @@
|
|
|
|
/* store results in cache */
|
|
if(qstate->query_flags&BIT_RD) {
|
|
+ /* if secure, this will override cache anyway, no need
|
|
+ * to check if from parentNS */
|
|
if(!dns_cache_store(qstate->env, &vq->orig_msg->qinfo,
|
|
- vq->orig_msg->rep, 0, qstate->prefetch_leeway, NULL)) {
|
|
+ vq->orig_msg->rep, 0, qstate->prefetch_leeway, 0, NULL)) {
|
|
log_err("out of memory caching validator results");
|
|
}
|
|
} else {
|
|
/* for a referral, store the verified RRsets */
|
|
/* and this does not get prefetched, so no leeway */
|
|
if(!dns_cache_store(qstate->env, &vq->orig_msg->qinfo,
|
|
- vq->orig_msg->rep, 1, 0, NULL)) {
|
|
+ vq->orig_msg->rep, 1, 0, 0, NULL)) {
|
|
log_err("out of memory caching validator results");
|
|
}
|
|
}
|
|
@@ -2923,7 +2925,6 @@
|
|
return 0;
|
|
return sizeof(*ve) + key_cache_get_mem(ve->kcache) +
|
|
val_neg_get_mem(ve->neg_cache) +
|
|
- anchors_get_mem(env->anchors) +
|
|
sizeof(size_t)*2*ve->nsec3_keyiter_count;
|
|
}
|
|
|
|
diff -Naur unbound-1.4.16/validator/val_sigcrypt.c unbound-trunk/validator/val_sigcrypt.c
|
|
--- unbound-1.4.16/validator/val_sigcrypt.c 2012-01-17 04:06:18.000000000 -0500
|
|
+++ unbound-trunk/validator/val_sigcrypt.c 2012-02-22 20:37:14.739368184 -0500
|
|
@@ -280,6 +280,10 @@
|
|
return 32;
|
|
else return 0;
|
|
#endif
|
|
+#ifdef USE_ECDSA
|
|
+ case LDNS_SHA384:
|
|
+ return SHA384_DIGEST_LENGTH;
|
|
+#endif
|
|
default: break;
|
|
}
|
|
return 0;
|
|
@@ -348,6 +352,12 @@
|
|
ldns_buffer_limit(b), (unsigned char*)digest))
|
|
return 1;
|
|
#endif
|
|
+#ifdef USE_ECDSA
|
|
+ case LDNS_SHA384:
|
|
+ (void)SHA384((unsigned char*)ldns_buffer_begin(b),
|
|
+ ldns_buffer_limit(b), (unsigned char*)digest);
|
|
+ return 1;
|
|
+#endif
|
|
default:
|
|
verbose(VERB_QUERY, "unknown DS digest algorithm %d",
|
|
(int) ds_get_digest_algo(ds_rrset, ds_idx));
|
|
@@ -418,6 +428,10 @@
|
|
#if defined(HAVE_EVP_SHA512) && defined(USE_SHA2)
|
|
case LDNS_RSASHA512:
|
|
#endif
|
|
+#ifdef USE_ECDSA
|
|
+ case LDNS_ECDSAP256SHA256:
|
|
+ case LDNS_ECDSAP384SHA384:
|
|
+#endif
|
|
return 1;
|
|
#ifdef USE_GOST
|
|
case LDNS_ECC_GOST:
|
|
@@ -1321,7 +1335,7 @@
|
|
* Setup DSA key digest in DER encoding ...
|
|
* @param sig: input is signature output alloced ptr (unless failure).
|
|
* caller must free alloced ptr if this routine returns true.
|
|
- * @param len: intput is initial siglen, output is output len.
|
|
+ * @param len: input is initial siglen, output is output len.
|
|
* @return false on failure.
|
|
*/
|
|
static int
|
|
@@ -1350,6 +1364,7 @@
|
|
*sig = NULL;
|
|
newlen = i2d_DSA_SIG(dsasig, sig);
|
|
if(newlen < 0) {
|
|
+ DSA_SIG_free(dsasig);
|
|
free(*sig);
|
|
return 0;
|
|
}
|
|
@@ -1358,6 +1373,48 @@
|
|
return 1;
|
|
}
|
|
|
|
+#ifdef USE_ECDSA
|
|
+/**
|
|
+ * Setup the ECDSA signature in its encoding that the library wants.
|
|
+ * Converts from plain numbers to ASN formatted.
|
|
+ * @param sig: input is signature, output alloced ptr (unless failure).
|
|
+ * caller must free alloced ptr if this routine returns true.
|
|
+ * @param len: input is initial siglen, output is output len.
|
|
+ * @return false on failure.
|
|
+ */
|
|
+static int
|
|
+setup_ecdsa_sig(unsigned char** sig, unsigned int* len)
|
|
+{
|
|
+ ECDSA_SIG* ecdsa_sig;
|
|
+ int newlen;
|
|
+ int bnsize = (int)((*len)/2);
|
|
+ /* if too short or not even length, fails */
|
|
+ if(*len < 16 || bnsize*2 != (int)*len)
|
|
+ return 0;
|
|
+ /* use the raw data to parse two evenly long BIGNUMs, "r | s". */
|
|
+ ecdsa_sig = ECDSA_SIG_new();
|
|
+ if(!ecdsa_sig) return 0;
|
|
+ ecdsa_sig->r = BN_bin2bn(*sig, bnsize, ecdsa_sig->r);
|
|
+ ecdsa_sig->s = BN_bin2bn(*sig+bnsize, bnsize, ecdsa_sig->s);
|
|
+ if(!ecdsa_sig->r || !ecdsa_sig->s) {
|
|
+ ECDSA_SIG_free(ecdsa_sig);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ /* spool it into ASN format */
|
|
+ *sig = NULL;
|
|
+ newlen = i2d_ECDSA_SIG(ecdsa_sig, sig);
|
|
+ if(newlen <= 0) {
|
|
+ ECDSA_SIG_free(ecdsa_sig);
|
|
+ free(*sig);
|
|
+ return 0;
|
|
+ }
|
|
+ *len = (unsigned int)newlen;
|
|
+ ECDSA_SIG_free(ecdsa_sig);
|
|
+ return 1;
|
|
+}
|
|
+#endif /* USE_ECDSA */
|
|
+
|
|
/**
|
|
* Setup key and digest for verification. Adjust sig if necessary.
|
|
*
|
|
@@ -1472,6 +1529,62 @@
|
|
}
|
|
break;
|
|
#endif
|
|
+#ifdef USE_ECDSA
|
|
+ case LDNS_ECDSAP256SHA256:
|
|
+ *evp_key = ldns_ecdsa2pkey_raw(key, keylen,
|
|
+ LDNS_ECDSAP256SHA256);
|
|
+ if(!*evp_key) {
|
|
+ verbose(VERB_QUERY, "verify: "
|
|
+ "ldns_ecdsa2pkey_raw failed");
|
|
+ return 0;
|
|
+ }
|
|
+#ifdef USE_ECDSA_EVP_WORKAROUND
|
|
+ /* openssl before 1.0.0 fixes RSA with the SHA256
|
|
+ * hash in EVP. We create one for ecdsa_sha256 */
|
|
+ {
|
|
+ static int md_ecdsa_256_done = 0;
|
|
+ static EVP_MD md;
|
|
+ if(!md_ecdsa_256_done) {
|
|
+ EVP_MD m = *EVP_sha256();
|
|
+ md_ecdsa_256_done = 1;
|
|
+ m.required_pkey_type[0] = (*evp_key)->type;
|
|
+ m.verify = (void*)ECDSA_verify;
|
|
+ md = m;
|
|
+ }
|
|
+ *digest_type = &md;
|
|
+ }
|
|
+#else
|
|
+ *digest_type = EVP_sha256();
|
|
+#endif
|
|
+ break;
|
|
+ case LDNS_ECDSAP384SHA384:
|
|
+ *evp_key = ldns_ecdsa2pkey_raw(key, keylen,
|
|
+ LDNS_ECDSAP384SHA384);
|
|
+ if(!*evp_key) {
|
|
+ verbose(VERB_QUERY, "verify: "
|
|
+ "ldns_ecdsa2pkey_raw failed");
|
|
+ return 0;
|
|
+ }
|
|
+#ifdef USE_ECDSA_EVP_WORKAROUND
|
|
+ /* openssl before 1.0.0 fixes RSA with the SHA384
|
|
+ * hash in EVP. We create one for ecdsa_sha384 */
|
|
+ {
|
|
+ static int md_ecdsa_384_done = 0;
|
|
+ static EVP_MD md;
|
|
+ if(!md_ecdsa_384_done) {
|
|
+ EVP_MD m = *EVP_sha384();
|
|
+ md_ecdsa_384_done = 1;
|
|
+ m.required_pkey_type[0] = (*evp_key)->type;
|
|
+ m.verify = (void*)ECDSA_verify;
|
|
+ md = m;
|
|
+ }
|
|
+ *digest_type = &md;
|
|
+ }
|
|
+#else
|
|
+ *digest_type = EVP_sha384();
|
|
+#endif
|
|
+ break;
|
|
+#endif /* USE_ECDSA */
|
|
default:
|
|
verbose(VERB_QUERY, "verify: unknown algorithm %d",
|
|
algo);
|
|
@@ -1519,7 +1632,19 @@
|
|
return sec_status_bogus;
|
|
}
|
|
dofree = 1;
|
|
- }
|
|
+ }
|
|
+#ifdef USE_ECDSA
|
|
+ else if(algo == LDNS_ECDSAP256SHA256 || algo == LDNS_ECDSAP384SHA384) {
|
|
+ /* EVP uses ASN prefix on sig, which is not in the wire data */
|
|
+ if(!setup_ecdsa_sig(&sigblock, &sigblock_len)) {
|
|
+ verbose(VERB_QUERY, "verify: failed to setup ECDSA sig");
|
|
+ *reason = "use of signature for ECDSA crypto failed";
|
|
+ EVP_PKEY_free(evp_key);
|
|
+ return sec_status_bogus;
|
|
+ }
|
|
+ dofree = 1;
|
|
+ }
|
|
+#endif /* USE_ECDSA */
|
|
|
|
/* do the signature cryptography work */
|
|
EVP_MD_CTX_init(&ctx);
|
|
@@ -1536,7 +1661,7 @@
|
|
if(dofree) free(sigblock);
|
|
return sec_status_unchecked;
|
|
}
|
|
-
|
|
+
|
|
res = EVP_VerifyFinal(&ctx, sigblock, sigblock_len, evp_key);
|
|
if(EVP_MD_CTX_cleanup(&ctx) == 0) {
|
|
verbose(VERB_QUERY, "verify: EVP_MD_CTX_cleanup failed");
|