diff --git a/daemon/acl_list.c b/daemon/acl_list.c index 436dc59e3..acc893a6c 100644 --- a/daemon/acl_list.c +++ b/daemon/acl_list.c @@ -46,21 +46,6 @@ #include "util/config_file.h" #include "util/net_help.h" -int -acl_list_cmp(const void* k1, const void* k2) -{ - struct acl_addr* n1 = (struct acl_addr*)k1; - struct acl_addr* n2 = (struct acl_addr*)k2; - int r = sockaddr_cmp_addr(&n1->addr, n1->addrlen, &n2->addr, - n2->addrlen); - if(r != 0) return r; - if(n1->net < n2->net) - return -1; - if(n1->net > n2->net) - return 1; - return 0; -} - struct acl_list* acl_list_create() { @@ -82,7 +67,6 @@ acl_list_delete(struct acl_list* acl) if(!acl) return; regional_destroy(acl->region); - free(acl->tree); free(acl); } @@ -96,13 +80,8 @@ acl_list_insert(struct acl_list* acl, struct sockaddr_storage* addr, sizeof(struct acl_addr)); if(!node) return 0; - node->node.key = node; - memcpy(&node->addr, addr, addrlen); - node->addrlen = addrlen; - node->net = net; - node->parent = NULL; node->control = control; - if(!rbtree_insert(acl->tree, &node->node)) { + if(!addr_tree_insert(&acl->tree, &node->node, addr, addrlen, net)) { if(complain_duplicates) verbose(VERB_QUERY, "duplicate acl address ignored."); } @@ -155,42 +134,11 @@ read_acl_list(struct acl_list* acl, struct config_file* cfg) return 1; } -/** initialise parent pointers in the tree */ -static void -acl_list_init_parents(struct acl_list* acl) -{ - struct acl_addr* node, *prev = NULL, *p; - int m; - RBTREE_FOR(node, struct acl_addr*, acl->tree) { - node->parent = NULL; - if(!prev || prev->addrlen != node->addrlen) { - prev = node; - continue; - } - m = addr_in_common(&prev->addr, prev->net, &node->addr, - node->net, node->addrlen); - /* sort order like: ::/0, 1::/2, 1::/4, ... 2::/2 */ - /* find the previous, or parent-parent-parent */ - for(p = prev; p; p = p->parent) - if(p->net <= m) { - /* ==: since prev matched m, this is closest*/ - /* <: prev matches more, but is not a parent, - * this one is a (grand)parent */ - node->parent = p; - break; - } - prev = node; - } -} - int acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg) { regional_free_all(acl->region); - free(acl->tree); - acl->tree = rbtree_create(acl_list_cmp); - if(!acl->tree) - return 0; + addr_tree_init(&acl->tree); if(!read_acl_list(acl, cfg)) return 0; /* insert defaults, with '0' to ignore them if they are duplicates */ @@ -206,7 +154,7 @@ acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg) if(!acl_list_str_cfg(acl, "::ffff:127.0.0.1", "allow", 0)) return 0; } - acl_list_init_parents(acl); + addr_tree_init_parents(&acl->tree); return 1; } @@ -214,33 +162,9 @@ enum acl_access acl_list_lookup(struct acl_list* acl, struct sockaddr_storage* addr, socklen_t addrlen) { - /* lookup in the tree */ - rbnode_t* res = NULL; - struct acl_addr* result; - struct acl_addr key; - key.node.key = &key; - memcpy(&key.addr, addr, addrlen); - key.addrlen = addrlen; - key.net = (addr_is_ip6(addr, addrlen)?128:32); - if(rbtree_find_less_equal(acl->tree, &key, &res)) { - /* exact */ - result = (struct acl_addr*)res; - return result->control; - } else { - /* smaller element (or no element) */ - int m; - result = (struct acl_addr*)res; - if(!result || result->addrlen != addrlen) - return acl_deny; - /* count number of bits matched */ - m = addr_in_common(&result->addr, result->net, addr, - key.net, addrlen); - while(result) { /* go up until addr is inside netblock */ - if(result->net <= m) - return result->control; - result = result->parent; - } - } + struct acl_addr* r = (struct acl_addr*)addr_tree_lookup(&acl->tree, + addr, addrlen); + if(r) return r->control; return acl_deny; } diff --git a/daemon/acl_list.h b/daemon/acl_list.h index e6082ad7e..47c4c5293 100644 --- a/daemon/acl_list.h +++ b/daemon/acl_list.h @@ -42,7 +42,7 @@ #ifndef DAEMON_ACL_LIST_H #define DAEMON_ACL_LIST_H -#include "util/rbtree.h" +#include "util/storage/dnstree.h" struct config_file; struct regional; @@ -71,7 +71,7 @@ struct acl_list { * Tree of the addresses that are allowed/blocked. * contents of type acl_addr. */ - rbtree_t* tree; + rbtree_t tree; }; /** @@ -79,16 +79,8 @@ struct acl_list { * An address span with access control information */ struct acl_addr { - /** redblacktree node, key is this structure: addr and addrlen, net */ - rbnode_t node; - /** parent node in acl tree that encompasses this entry */ - struct acl_addr* parent; - /** address */ - struct sockaddr_storage addr; - /** length of addr */ - socklen_t addrlen; - /** netblock size */ - int net; + /** node in address tree */ + struct addr_tree_node node; /** access control on this netblock */ enum acl_access control; }; @@ -130,7 +122,4 @@ enum acl_access acl_list_lookup(struct acl_list* acl, */ size_t acl_list_get_mem(struct acl_list* acl); -/** compare two acl list entries */ -int acl_list_cmp(const void* k1, const void* k2); - #endif /* DAEMON_ACL_LIST_H */ diff --git a/doc/Changelog b/doc/Changelog index d2674ee77..0c9f1e39a 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,6 +1,7 @@ 4 September 2008: Wouter - scrubber scrubs away private addresses. - test for private addresses. man page entry. + - code refactored for name and address tree lookups. 3 September 2008: Wouter - options for 'DNS Rebinding' protection: private-address and diff --git a/doc/plan b/doc/plan index c4e07ea9d..bf9e34ded 100644 --- a/doc/plan +++ b/doc/plan @@ -37,7 +37,7 @@ total 6 of 8 weeks; 2 weeks for maintenance activities. + records in the additional section should not be marked bogus if they have no signer or a different signed. Validate if you can, otherwise leave unchecked. -* block DNS rebinding attacks, block all A records from 1918 IP blocks, ++ block DNS rebinding attacks, block all A records from 1918 IP blocks, like dnswall does. Allow certain subdomains to do it, config options. one option that controls on/off of all private space. note in config/man that we may consider turning on by default. diff --git a/iterator/iter_donotq.c b/iterator/iter_donotq.c index a6b7d0695..cc2930ec3 100644 --- a/iterator/iter_donotq.c +++ b/iterator/iter_donotq.c @@ -48,21 +48,6 @@ #include "util/config_file.h" #include "util/net_help.h" -int -donotq_cmp(const void* k1, const void* k2) -{ - struct iter_donotq_addr* n1 = (struct iter_donotq_addr*)k1; - struct iter_donotq_addr* n2 = (struct iter_donotq_addr*)k2; - int r = sockaddr_cmp_addr(&n1->addr, n1->addrlen, &n2->addr, - n2->addrlen); - if(r != 0) return r; - if(n1->net < n2->net) - return -1; - if(n1->net > n2->net) - return 1; - return 0; -} - struct iter_donotq* donotq_create() { @@ -84,7 +69,6 @@ donotq_delete(struct iter_donotq* dq) if(!dq) return; regional_destroy(dq->region); - free(dq->tree); free(dq); } @@ -93,16 +77,11 @@ static int donotq_insert(struct iter_donotq* dq, struct sockaddr_storage* addr, socklen_t addrlen, int net) { - struct iter_donotq_addr* node = regional_alloc(dq->region, - sizeof(struct iter_donotq_addr)); + struct addr_tree_node* node = (struct addr_tree_node*)regional_alloc( + dq->region, sizeof(*node)); if(!node) return 0; - node->node.key = node; - memcpy(&node->addr, addr, addrlen); - node->addrlen = addrlen; - node->net = net; - node->parent = NULL; - if(!rbtree_insert(dq->tree, &node->node)) { + if(!addr_tree_insert(&dq->tree, node, addr, addrlen, net)) { verbose(VERB_QUERY, "duplicate donotquery address ignored."); } return 1; @@ -140,42 +119,11 @@ read_donotq(struct iter_donotq* dq, struct config_file* cfg) return 1; } -/** initialise parent pointers in the tree */ -static void -donotq_init_parents(struct iter_donotq* donotq) -{ - struct iter_donotq_addr* node, *prev = NULL, *p; - int m; - RBTREE_FOR(node, struct iter_donotq_addr*, donotq->tree) { - node->parent = NULL; - if(!prev || prev->addrlen != node->addrlen) { - prev = node; - continue; - } - m = addr_in_common(&prev->addr, prev->net, &node->addr, - node->net, node->addrlen); - /* sort order like: ::/0, 1::/2, 1::/4, ... 2::/2 */ - /* find the previous, or parent-parent-parent */ - for(p = prev; p; p = p->parent) - if(p->net <= m) { - /* ==: since prev matched m, this is closest*/ - /* <: prev matches more, but is not a parent, - * this one is a (grand)parent */ - node->parent = p; - break; - } - prev = node; - } -} - int donotq_apply_cfg(struct iter_donotq* dq, struct config_file* cfg) { - free(dq->tree); regional_free_all(dq->region); - dq->tree = rbtree_create(donotq_cmp); - if(!dq->tree) - return 0; + addr_tree_init(&dq->tree); if(!read_donotq(dq, cfg)) return 0; if(cfg->donotquery_localhost) { @@ -186,7 +134,7 @@ donotq_apply_cfg(struct iter_donotq* dq, struct config_file* cfg) return 0; } } - donotq_init_parents(dq); + addr_tree_init_parents(&dq->tree); return 1; } @@ -194,33 +142,7 @@ int donotq_lookup(struct iter_donotq* donotq, struct sockaddr_storage* addr, socklen_t addrlen) { - /* lookup in the tree */ - rbnode_t* res = NULL; - struct iter_donotq_addr* result; - struct iter_donotq_addr key; - key.node.key = &key; - memcpy(&key.addr, addr, addrlen); - key.addrlen = addrlen; - key.net = (addr_is_ip6(addr, addrlen)?128:32); - if(rbtree_find_less_equal(donotq->tree, &key, &res)) { - /* exact */ - return 1; - } else { - /* smaller element (or no element) */ - int m; - result = (struct iter_donotq_addr*)res; - if(!result || result->addrlen != addrlen) - return 0; - /* count number of bits matched */ - m = addr_in_common(&result->addr, result->net, addr, - key.net, addrlen); - while(result) { /* go up until addr is inside netblock */ - if(result->net <= m) - return 1; - result = result->parent; - } - } - return 0; + return addr_tree_lookup(&donotq->tree, addr, addrlen) != NULL; } size_t diff --git a/iterator/iter_donotq.h b/iterator/iter_donotq.h index 0274ebf60..c90b0ab2a 100644 --- a/iterator/iter_donotq.h +++ b/iterator/iter_donotq.h @@ -42,7 +42,7 @@ #ifndef ITERATOR_ITER_DONOTQ_H #define ITERATOR_ITER_DONOTQ_H -#include "util/rbtree.h" +#include "util/storage/dnstree.h" struct iter_env; struct config_file; struct regional; @@ -55,26 +55,10 @@ struct iter_donotq { struct regional* region; /** * Tree of the address spans that are blocked. - * contents of type iter_donotq_addr. + * contents of type addr_tree_node. Each node is an address span + * that must not be used to send queries to. */ - rbtree_t* tree; -}; - -/** - * Iterator donotquery address. - * An address span that must not be used to send queries to. - */ -struct iter_donotq_addr { - /** redblacktree node, key is this structure: addr and addrlen, net */ - rbnode_t node; - /** address */ - struct sockaddr_storage addr; - /** length of addr */ - socklen_t addrlen; - /** netblock size */ - int net; - /** parent node in donotq tree that encompasses this entry */ - struct iter_donotq_addr* parent; + rbtree_t tree; }; /** @@ -114,7 +98,4 @@ int donotq_lookup(struct iter_donotq* donotq, struct sockaddr_storage* addr, */ size_t donotq_get_mem(struct iter_donotq* donotq); -/** compare two donotq entries */ -int donotq_cmp(const void* k1, const void* k2); - #endif /* ITERATOR_ITER_DONOTQ_H */ diff --git a/iterator/iter_hints.c b/iterator/iter_hints.c index aed716cef..9f614b902 100644 --- a/iterator/iter_hints.c +++ b/iterator/iter_hints.c @@ -48,21 +48,6 @@ #include "util/net_help.h" #include "util/data/dname.h" -int -stub_cmp(const void* k1, const void* k2) -{ - int m; - struct iter_hints_stub* n1 = (struct iter_hints_stub*)k1; - struct iter_hints_stub* n2 = (struct iter_hints_stub*)k2; - if(n1->hint_class != n2->hint_class) { - if(n1->hint_class < n2->hint_class) - return -1; - return 1; - } - return dname_lab_cmp(n1->name, n1->namelabs, n2->name, n2->namelabs, - &m); -} - struct iter_hints* hints_create() { @@ -84,7 +69,6 @@ hints_delete(struct iter_hints* hints) if(!hints) return; regional_destroy(hints->region); - free(hints->tree); free(hints); } @@ -160,51 +144,20 @@ hints_insert(struct iter_hints* hints, uint16_t c, struct delegpt* dp) { struct iter_hints_stub* node = regional_alloc(hints->region, sizeof(struct iter_hints_stub)); + uint8_t* nm; if(!node) return 0; - node->node.key = node; - node->hint_class = c; - node->name = regional_alloc_init(hints->region, dp->name, dp->namelen); - if(!node->name) + nm = regional_alloc_init(hints->region, dp->name, dp->namelen); + if(!nm) return 0; - node->namelen = dp->namelen; - node->namelabs = dp->namelabs; node->dp = dp; - if(!rbtree_insert(hints->tree, &node->node)) { + if(!name_tree_insert(&hints->tree, &node->node, nm, dp->namelen, + dp->namelabs, c)) { log_err("second hints ignored."); } return 1; } -/** initialise parent pointers in the tree */ -static void -init_parents(struct iter_hints* hints) -{ - struct iter_hints_stub* node, *prev = NULL, *p; - int m; - RBTREE_FOR(node, struct iter_hints_stub*, hints->tree) { - node->parent = NULL; - if(!prev || prev->hint_class != node->hint_class) { - prev = node; - continue; - } - (void)dname_lab_cmp(prev->name, prev->namelabs, node->name, - node->namelabs, &m); /* we know prev is smaller */ - /* sort order like: . com. bla.com. zwb.com. net. */ - /* find the previous, or parent-parent-parent */ - for(p = prev; p; p = p->parent) - /* looking for name with few labels, a parent */ - if(p->namelabs <= m) { - /* ==: since prev matched m, this is closest*/ - /* <: prev matches more, but is not a parent, - * this one is a (grand)parent */ - node->parent = p; - break; - } - prev = node; - } -} - /** set stub name */ static int read_stubs_name(struct iter_hints* hints, struct config_stub* s, @@ -435,10 +388,8 @@ read_root_hints_list(struct iter_hints* hints, struct config_file* cfg) int hints_apply_cfg(struct iter_hints* hints, struct config_file* cfg) { - free(hints->tree); - hints->tree = rbtree_create(stub_cmp); - if(!hints->tree) - return 0; + regional_free_all(hints->region); + name_tree_init(&hints->tree); /* read root hints */ if(!read_root_hints_list(hints, cfg)) @@ -459,7 +410,7 @@ hints_apply_cfg(struct iter_hints* hints, struct config_file* cfg) return 0; } - init_parents(hints); + name_tree_init_parents(&hints->tree); return 1; } @@ -467,13 +418,9 @@ struct delegpt* hints_lookup_root(struct iter_hints* hints, uint16_t qclass) { uint8_t rootlab = 0; - struct iter_hints_stub key, *stub; - key.node.key = &key; - key.hint_class = qclass; - key.name = &rootlab; - key.namelen = 1; - key.namelabs = 1; - stub = (struct iter_hints_stub*)rbtree_search(hints->tree, &key); + struct iter_hints_stub *stub; + stub = (struct iter_hints_stub*)name_tree_find(&hints->tree, + &rootlab, 1, 1, qclass); if(!stub) return NULL; return stub->dp; @@ -483,40 +430,22 @@ struct delegpt* hints_lookup_stub(struct iter_hints* hints, uint8_t* qname, uint16_t qclass, struct delegpt* cache_dp) { + size_t len; + int labs; + struct iter_hints_stub *r; + /* first lookup the stub */ - rbnode_t* res = NULL; - struct iter_hints_stub *result; - struct iter_hints_stub key; - key.node.key = &key; - key.hint_class = qclass; - key.name = qname; - key.namelabs = dname_count_size_labels(qname, &key.namelen); - if(rbtree_find_less_equal(hints->tree, &key, &res)) { - /* exact */ - result = (struct iter_hints_stub*)res; - } else { - /* smaller element (or no element) */ - int m; - result = (struct iter_hints_stub*)res; - if(!result || result->hint_class != qclass) - return NULL; - /* count number of labels matched */ - (void)dname_lab_cmp(result->name, result->namelabs, key.name, - key.namelabs, &m); - while(result) { /* go up until qname is subdomain of stub */ - if(result->namelabs <= m) - break; - result = result->parent; - } - if(!result) - return NULL; - } + labs = dname_count_size_labels(qname, &len); + r = (struct iter_hints_stub*)name_tree_lookup(&hints->tree, qname, + len, labs, qclass); + if(!r) return NULL; + /* * If our cached delegation point is above the hint, we need to prime. */ - if(dname_strict_subdomain(result->dp->name, result->dp->namelabs, + if(dname_strict_subdomain(r->dp->name, r->dp->namelabs, cache_dp->name, cache_dp->namelabs)) - return result->dp; /* need to prime this stub */ + return r->dp; /* need to prime this stub */ return NULL; } diff --git a/iterator/iter_hints.h b/iterator/iter_hints.h index 363bdf209..d93d6e648 100644 --- a/iterator/iter_hints.h +++ b/iterator/iter_hints.h @@ -42,7 +42,7 @@ #ifndef ITERATOR_ITER_HINTS_H #define ITERATOR_ITER_HINTS_H -#include "util/rbtree.h" +#include "util/storage/dnstree.h" struct iter_env; struct config_file; struct delegpt; @@ -60,28 +60,19 @@ struct iter_hints { * a lookup on class, name will return an exact match or the closest * match which gives the ancestor needed. * contents of type iter_hints_stub. The class IN root is in here. + * uses name_tree_node from dnstree.h. */ - rbtree_t* tree; + rbtree_t tree; }; /** * Iterator hints for a particular stub. */ struct iter_hints_stub { - /** redblacktree node, key is this structure: class and name */ - rbnode_t node; - /** name */ - uint8_t* name; - /** length of name */ - size_t namelen; - /** number of labels in name */ - int namelabs; + /** tree sorted by name, class */ + struct name_tree_node node; /** delegation point with hint information for this stub. */ struct delegpt* dp; - /** pointer to parent in stub hint tree (or NULL if none) */ - struct iter_hints_stub* parent; - /** class of hints. host order. */ - uint16_t hint_class; }; /** @@ -134,7 +125,4 @@ struct delegpt* hints_lookup_stub(struct iter_hints* hints, */ size_t hints_get_mem(struct iter_hints* hints); -/** compare two hint entries */ -int stub_cmp(const void* k1, const void* k2); - #endif /* ITERATOR_ITER_HINTS_H */ diff --git a/libunbound/libworker.c b/libunbound/libworker.c index a4fe7a74b..457d66d87 100644 --- a/libunbound/libworker.c +++ b/libunbound/libworker.c @@ -799,13 +799,6 @@ worker_alloc_cleanup(void* ATTR_UNUSED(arg)) log_assert(0); } -int -acl_list_cmp(const void* ATTR_UNUSED(k1), const void* ATTR_UNUSED(k2)) -{ - log_assert(0); - return 0; -} - void worker_stat_timer_cb(void* ATTR_UNUSED(arg)) { log_assert(0); diff --git a/smallapp/worker_cb.c b/smallapp/worker_cb.c index fa3714666..0eb34a2e8 100644 --- a/smallapp/worker_cb.c +++ b/smallapp/worker_cb.c @@ -108,13 +108,6 @@ worker_alloc_cleanup(void* ATTR_UNUSED(arg)) log_assert(0); } -int -acl_list_cmp(const void* ATTR_UNUSED(k1), const void* ATTR_UNUSED(k2)) -{ - log_assert(0); - return 0; -} - int libworker_send_packet(ldns_buffer* ATTR_UNUSED(pkt), struct sockaddr_storage* ATTR_UNUSED(addr), socklen_t ATTR_UNUSED(addrlen), int ATTR_UNUSED(timeout), diff --git a/util/fptr_wlist.c b/util/fptr_wlist.c index 5f257d7d8..949b24b57 100644 --- a/util/fptr_wlist.c +++ b/util/fptr_wlist.c @@ -53,9 +53,7 @@ #include "services/cache/infra.h" #include "services/cache/rrset.h" #include "iterator/iterator.h" -#include "iterator/iter_donotq.h" #include "iterator/iter_fwd.h" -#include "iterator/iter_hints.h" #include "validator/validator.h" #include "validator/val_anchor.h" #include "validator/val_nsec3.h" @@ -67,7 +65,6 @@ #include "util/storage/slabhash.h" #include "util/storage/dnstree.h" #include "util/locks.h" -#include "daemon/acl_list.h" #include "libunbound/libworker.h" #include "libunbound/context.h" #include "util/tube.h" @@ -152,16 +149,13 @@ fptr_whitelist_rbtree_cmp(int (*fptr) (const void *, const void *)) { if(fptr == &mesh_state_compare) return 1; else if(fptr == &mesh_state_ref_compare) return 1; - else if(fptr == &acl_list_cmp) return 1; + else if(fptr == &addr_tree_compare) return 1; else if(fptr == &local_zone_cmp) return 1; else if(fptr == &local_data_cmp) return 1; - else if(fptr == &donotq_cmp) return 1; else if(fptr == &fwd_cmp) return 1; - else if(fptr == &stub_cmp) return 1; else if(fptr == &pending_cmp) return 1; else if(fptr == &serviced_cmp) return 1; else if(fptr == &name_tree_compare) return 1; - else if(fptr == &addr_tree_compare) return 1; else if(fptr == &order_lock_cmp) return 1; else if(fptr == &codeline_cmp) return 1; else if(fptr == &nsec3_hash_cmp) return 1; diff --git a/util/storage/dnstree.c b/util/storage/dnstree.c index 2677be97f..1dd45dc36 100644 --- a/util/storage/dnstree.c +++ b/util/storage/dnstree.c @@ -54,7 +54,7 @@ int name_tree_compare(const void* k1, const void* k2) return -1; return 1; } - return dname_canon_lab_cmp(x->name, x->labs, y->name, y->labs, &m); + return dname_lab_cmp(x->name, x->labs, y->name, y->labs, &m); } int addr_tree_compare(const void* k1, const void* k2) @@ -89,6 +89,7 @@ int name_tree_insert(rbtree_t* tree, struct name_tree_node* node, node->len = len; node->labs = labs; node->dclass = dclass; + node->parent = NULL; return rbtree_insert(tree, &node->node) != NULL; } @@ -99,6 +100,7 @@ int addr_tree_insert(rbtree_t* tree, struct addr_tree_node* node, memcpy(&node->addr, addr, addrlen); node->addrlen = addrlen; node->net = net; + node->parent = NULL; return rbtree_insert(tree, &node->node) != NULL; }