From db6cd0a635f2a7488579d5b4b59debcde5dacde9 Mon Sep 17 00:00:00 2001 From: Wouter Wijngaards Date: Tue, 14 Feb 2012 15:41:09 +0000 Subject: [PATCH] - iter forwards uses malloc inside for more dynamicity. git-svn-id: file:///svn/unbound/trunk@2620 be551aaa-1e26-0410-a405-d3ace91eadb9 --- daemon/cachedump.c | 2 +- daemon/remote.c | 10 +-- doc/Changelog | 1 + iterator/iter_delegpt.c | 137 +++++++++++++++++++++++++++++++++++++++- iterator/iter_delegpt.h | 54 ++++++++++++++++ iterator/iter_fwd.c | 95 ++++++++++++++++------------ iterator/iter_fwd.h | 6 +- testcode/fake_event.c | 1 + 8 files changed, 257 insertions(+), 49 deletions(-) diff --git a/daemon/cachedump.c b/daemon/cachedump.c index b6a4de8c5..02a4caed0 100644 --- a/daemon/cachedump.c +++ b/daemon/cachedump.c @@ -803,7 +803,7 @@ print_dp_details(SSL* ssl, struct worker* worker, struct delegpt* dp) 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) { diff --git a/daemon/remote.c b/daemon/remote.c index 15847daf4..89c1fae9d 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -1337,15 +1337,15 @@ print_root_fwds(SSL* ssl, struct iter_forwards* fwds, uint8_t* root) /** 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; } @@ -1363,7 +1363,7 @@ parse_delegpt(SSL* ssl, struct regional* region, char* args, uint8_t* root) 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; } @@ -1396,7 +1396,7 @@ do_forward(SSL* ssl, struct worker* worker, char* args) 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"); diff --git a/doc/Changelog b/doc/Changelog index fb3a32282..25fb0c5ef 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,5 +1,6 @@ 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. diff --git a/iterator/iter_delegpt.c b/iterator/iter_delegpt.c index f49048d5c..7e39d8f40 100644 --- a/iterator/iter_delegpt.c +++ b/iterator/iter_delegpt.c @@ -90,6 +90,7 @@ struct delegpt* delegpt_copy(struct delegpt* dp, struct regional* region) 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 @@ delegpt_add_ns(struct delegpt* dp, struct regional* region, uint8_t* name, 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 @@ delegpt_add_ns(struct delegpt* dp, struct regional* region, uint8_t* name, 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 @@ delegpt_add_target(struct delegpt* dp, struct regional* region, 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 @@ delegpt_add_addr(struct delegpt* dp, struct regional* region, 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 @@ delegpt_rrset_add_ns(struct delegpt* dp, struct regional* region, 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; icount; i++) { @@ -399,6 +404,7 @@ delegpt_add_rrset_A(struct delegpt* dp, struct regional* region, 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 @@ delegpt_add_rrset_AAAA(struct delegpt* dp, struct regional* region, 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,131 @@ void delegpt_no_ipv4(struct delegpt* dp) 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; +} diff --git a/iterator/iter_delegpt.h b/iterator/iter_delegpt.h index c4ca62dc4..cd508ec7c 100644 --- a/iterator/iter_delegpt.h +++ b/iterator/iter_delegpt.h @@ -79,6 +79,8 @@ struct delegpt { * 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,56 @@ void delegpt_no_ipv6(struct delegpt* dp); */ 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 */ diff --git a/iterator/iter_fwd.c b/iterator/iter_fwd.c index 2df1f9c46..c3c8fd045 100644 --- a/iterator/iter_fwd.c +++ b/iterator/iter_fwd.c @@ -45,7 +45,6 @@ #include #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 @@ forwards_create(void) 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,23 @@ static int 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; } @@ -152,33 +169,32 @@ fwd_init_parents(struct iter_forwards* fwd) } /** 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 +206,7 @@ read_fwds_host(struct iter_forwards* fwd, struct config_stub* s, 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 +218,7 @@ read_fwds_host(struct iter_forwards* fwd, struct config_stub* s, /** 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 +230,7 @@ read_fwds_addr(struct iter_forwards* fwd, struct config_stub* s, 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 +244,14 @@ read_forwards(struct iter_forwards* fwd, struct config_file* cfg) { 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:"); @@ -302,8 +313,7 @@ make_stub_holes(struct iter_forwards* fwd, struct config_file* cfg) 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,10 +421,15 @@ forwards_next_root(struct iter_forwards* fwd, uint16_t* dclass) 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 @@ -429,13 +444,15 @@ forwards_add_zone(struct iter_forwards* fwd, uint16_t c, struct delegpt* dp) 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); } diff --git a/iterator/iter_fwd.h b/iterator/iter_fwd.h index 8f3bc1fa2..b66687f0b 100644 --- a/iterator/iter_fwd.h +++ b/iterator/iter_fwd.h @@ -51,8 +51,6 @@ 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 +75,9 @@ struct iter_forward_zone { 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; diff --git a/testcode/fake_event.c b/testcode/fake_event.c index d31fa79b0..8271d0092 100644 --- a/testcode/fake_event.c +++ b/testcode/fake_event.c @@ -1137,6 +1137,7 @@ void outnet_serviced_query_stop(struct serviced_query* sq, void* cb_arg) else runtime->pending_list = p->next; ldns_buffer_free(p->buffer); ldns_pkt_free(p->pkt); + free(p->zone); free(p); return; } -- 2.47.2