diff options
Diffstat (limited to 'usr.sbin/unbound/iterator/iter_fwd.c')
-rw-r--r-- | usr.sbin/unbound/iterator/iter_fwd.c | 266 |
1 files changed, 101 insertions, 165 deletions
diff --git a/usr.sbin/unbound/iterator/iter_fwd.c b/usr.sbin/unbound/iterator/iter_fwd.c index 0feee032c96..2df1f9c46f6 100644 --- a/usr.sbin/unbound/iterator/iter_fwd.c +++ b/usr.sbin/unbound/iterator/iter_fwd.c @@ -21,16 +21,16 @@ * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. */ /** @@ -40,14 +40,16 @@ * Keep track of forward zones and config settings. */ #include "config.h" +#include <ldns/rdata.h> +#include <ldns/dname.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" #include "util/data/dname.h" -#include "sldns/rrdef.h" -#include "sldns/str2wire.h" int fwd_cmp(const void* k1, const void* k2) @@ -71,36 +73,21 @@ 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; - fwd_del_tree(fwd); + regional_destroy(fwd->region); + free(fwd->tree); free(fwd); } @@ -109,30 +96,20 @@ 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 = (struct iter_forward_zone*)malloc( + struct iter_forward_zone* node = regional_alloc(fwd->region, sizeof(struct iter_forward_zone)); - if(!node) { - delegpt_free_mlc(dp); + if(!node) return 0; - } node->node.key = node; node->dclass = c; - node->name = memdup(nm, nmlen); - if(!node->name) { - delegpt_free_mlc(dp); - free(node); + node->name = regional_alloc_init(fwd->region, nm, nmlen); + if(!node->name) return 0; - } node->namelen = nmlen; node->namelabs = nmlabs; node->dp = dp; if(!rbtree_insert(fwd->tree, &node->node)) { - char buf[257]; - dname_str(nm, buf); - log_err("duplicate forward zone %s ignored.", buf); - delegpt_free_mlc(dp); - free(node->name); - free(node); + log_err("duplicate forward zone ignored."); } return 1; } @@ -175,58 +152,58 @@ fwd_init_parents(struct iter_forwards* fwd) } /** set zone name */ -static struct delegpt* -read_fwds_name(struct config_stub* s) +static int +read_fwds_name(struct iter_forwards* fwd, struct config_stub* s, + struct delegpt* dp) { - struct delegpt* dp; - uint8_t* dname; - size_t dname_len; + ldns_rdf* rdf; if(!s->name) { log_err("forward zone without a name (use name \".\" to forward everything)"); - return NULL; + return 0; } - dname = sldns_str2wire_dname(s->name, &dname_len); - if(!dname) { + rdf = ldns_dname_new_frm_str(s->name); + if(!rdf) { log_err("cannot parse forward zone name %s", s->name); - return NULL; + return 0; } - if(!(dp=delegpt_create_mlc(dname))) { - free(dname); + if(!delegpt_set_name(dp, fwd->region, ldns_rdf_data(rdf))) { + ldns_rdf_deep_free(rdf); log_err("out of memory"); - return NULL; + return 0; } - free(dname); - return dp; + ldns_rdf_deep_free(rdf); + return 1; } /** set fwd host names */ static int -read_fwds_host(struct config_stub* s, struct delegpt* dp) +read_fwds_host(struct iter_forwards* fwd, struct config_stub* s, + struct delegpt* dp) { struct config_strlist* p; - uint8_t* dname; - size_t dname_len; + ldns_rdf* rdf; for(p = s->hosts; p; p = p->next) { log_assert(p->str); - dname = sldns_str2wire_dname(p->str, &dname_len); - if(!dname) { + rdf = ldns_dname_new_frm_str(p->str); + if(!rdf) { log_err("cannot parse forward %s server name: '%s'", s->name, p->str); return 0; } - if(!delegpt_add_ns_mlc(dp, dname, 0)) { - free(dname); + if(!delegpt_add_ns(dp, fwd->region, ldns_rdf_data(rdf), 0)) { + ldns_rdf_deep_free(rdf); log_err("out of memory"); return 0; } - free(dname); + ldns_rdf_deep_free(rdf); } return 1; } /** set fwd server addresses */ static int -read_fwds_addr(struct config_stub* s, struct delegpt* dp) +read_fwds_addr(struct iter_forwards* fwd, struct config_stub* s, + struct delegpt* dp) { struct config_strlist* p; struct sockaddr_storage addr; @@ -238,7 +215,7 @@ read_fwds_addr(struct config_stub* s, struct delegpt* dp) s->name, p->str); return 0; } - if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0)) { + if(!delegpt_add_addr(dp, fwd->region, &addr, addrlen, 0, 0)) { log_err("out of memory"); return 0; } @@ -252,38 +229,43 @@ 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; - if(!(dp=read_fwds_name(s))) - return 0; - if(!read_fwds_host(s, dp) || !read_fwds_addr(s, dp)) { - delegpt_free_mlc(dp); + struct delegpt* dp = delegpt_create(fwd->region); + if(!dp) { + log_err("out of memory"); return 0; } /* set flag that parent side NS information is included. * Asking a (higher up) server on the internet is not useful */ - /* the flag is turned off for 'forward-first' so that the - * last resort will ask for parent-side NS record and thus - * fallback to the internet name servers on a failure */ - dp->has_parent_side_NS = (uint8_t)!s->isfirst; - verbose(VERB_QUERY, "Forward zone server list:"); - delegpt_log(VERB_QUERY, dp); + 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:"); + delegpt_log(VERB_QUERY, dp); } return 1; } -/** insert a stub hole (if necessary) for stub name */ +/** see if zone needs to have a hole inserted */ static int -fwd_add_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm) +need_hole_insert(rbtree_t* tree, struct iter_forward_zone* zone) { - 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); - return forwards_insert_data(fwd, key.dclass, key.name, - key.namelen, key.namelabs, NULL); + struct iter_forward_zone k; + if(rbtree_search(tree, zone)) + return 0; /* exact match exists */ + k = *zone; + k.node.key = &k; + /* search up the tree */ + do { + dname_remove_label(&k.name, &k.namelen); + k.namelabs --; + if(rbtree_search(tree, &k)) + return 1; /* found an upper forward zone, need hole */ + } while(k.namelabs > 1); + return 0; /* no forwards above, no holes needed */ } /** make NULL entries for stubs */ @@ -291,20 +273,28 @@ static int make_stub_holes(struct iter_forwards* fwd, struct config_file* cfg) { struct config_stub* s; - uint8_t* dname; - size_t dname_len; + struct iter_forward_zone key; + key.node.key = &key; + key.dclass = LDNS_RR_CLASS_IN; for(s = cfg->stubs; s; s = s->next) { - dname = sldns_str2wire_dname(s->name, &dname_len); - if(!dname) { + ldns_rdf* rdf = ldns_dname_new_frm_str(s->name); + if(!rdf) { log_err("cannot parse stub name '%s'", s->name); return 0; } - if(!fwd_add_stub_hole(fwd, LDNS_RR_CLASS_IN, dname)) { - free(dname); + 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)) { + ldns_rdf_deep_free(rdf); log_err("out of memory"); return 0; } - free(dname); + ldns_rdf_deep_free(rdf); } return 1; } @@ -312,7 +302,8 @@ make_stub_holes(struct iter_forwards* fwd, struct config_file* cfg) int forwards_apply_cfg(struct iter_forwards* fwd, struct config_file* cfg) { - fwd_del_tree(fwd); + free(fwd->tree); + regional_free_all(fwd->region); fwd->tree = rbtree_create(fwd_cmp); if(!fwd->tree) return 0; @@ -327,20 +318,6 @@ forwards_apply_cfg(struct iter_forwards* fwd, struct config_file* cfg) } struct delegpt* -forwards_find(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass) -{ - rbnode_t* res = NULL; - struct iter_forward_zone key; - key.node.key = &key; - key.dclass = qclass; - key.name = qname; - key.namelabs = dname_count_size_labels(qname, &key.namelen); - res = rbtree_search(fwd->tree, &key); - if(res) return ((struct iter_forward_zone*)res)->dp; - return NULL; -} - -struct delegpt* forwards_lookup(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass) { /* lookup the forward zone in the tree */ @@ -434,36 +411,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; - 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); + return sizeof(*fwd) + sizeof(*fwd->tree) + + regional_get_mem(fwd->region); } 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); @@ -473,34 +429,14 @@ 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) { - 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))) + 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)) return; /* nothing to do */ - if(z->dp != NULL) - return; /* not a stub hole */ - (void)rbtree_delete(fwd->tree, &z->node); - fwd_zone_free(z); + (void)rbtree_delete(fwd->tree, &key); fwd_init_parents(fwd); } |