char buf[257];
struct delegpt_addr* a;
int lame, dlame, rlame, rto, edns_vs, to, delay, entry_ttl,
- tA, tAAAA, tother;
+ 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) {
/** 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* root)
{
/* parse args and add in */
char* p = args;
char* todo;
- struct delegpt* dp = delegpt_create(region);
+ struct delegpt* dp = delegpt_create_mlc(root);
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;
}
return NULL;
}
/* add address */
- if(!delegpt_add_addr(dp, region, &addr, addrlen, 0, 0)) {
+ if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0)) {
(void)ssl_printf(ssl, "error out of memory\n");
return NULL;
}
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)))
return;
if(!forwards_add_zone(fwd, LDNS_RR_CLASS_IN, dp)) {
(void)ssl_printf(ssl, "error out of memory\n");
14 February 2012: Wouter
- Fix sticky NS (ghost domain problem) if prefetch is yes.
+ - iter forwards uses malloc inside for more dynamicity.
13 February 2012: Wouter
- RT#2955. Fix for cygwin compilation.
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;
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))
ns->lame = (uint8_t)lame;
ns->done_pside4 = 0;
ns->done_pside6 = 0;
- return 1;
+ return ns->name != 0;
}
struct delegpt_ns*
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;
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)
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++) {
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);
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);
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;
+ 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_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;
+}
* 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;
};
/**
*/
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);
+
+/**
+ * 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 */
#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"
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);
}
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,
- sizeof(struct iter_forward_zone));
+ struct iter_forward_zone* node = malloc(sizeof(*node));
if(!node)
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) {
+ 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.");
+ free(node->name);
+ free(node);
}
return 1;
}
}
/** 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;
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;
/** 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;
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;
}
{
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:");
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;
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;
}
int
void
forwards_delete_zone(struct iter_forwards* fwd, uint16_t c, uint8_t* nm)
{
+ rbnode_t* n;
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))
+ if(!(n=rbtree_search(fwd->tree, &key)))
return; /* nothing to do */
+ fwd_zone_free((struct iter_forward_zone*)n);
(void)rbtree_delete(fwd->tree, &key);
fwd_init_parents(fwd);
}
* 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
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;
else runtime->pending_list = p->next;
ldns_buffer_free(p->buffer);
ldns_pkt_free(p->pkt);
+ free(p->zone);
free(p);
return;
}