diff options
Diffstat (limited to 'usr.sbin/unbound/iterator/iter_fwd.c')
-rw-r--r-- | usr.sbin/unbound/iterator/iter_fwd.c | 119 |
1 files changed, 93 insertions, 26 deletions
diff --git a/usr.sbin/unbound/iterator/iter_fwd.c b/usr.sbin/unbound/iterator/iter_fwd.c index c4b2411297e..b9d42553a8b 100644 --- a/usr.sbin/unbound/iterator/iter_fwd.c +++ b/usr.sbin/unbound/iterator/iter_fwd.c @@ -71,6 +71,7 @@ forwards_create(void) sizeof(struct iter_forwards)); if(!fwd) return NULL; + lock_rw_init(&fwd->lock); return fwd; } @@ -100,6 +101,7 @@ forwards_delete(struct iter_forwards* fwd) { if(!fwd) return; + lock_rw_destroy(&fwd->lock); fwd_del_tree(fwd); free(fwd); } @@ -332,45 +334,64 @@ make_stub_holes(struct iter_forwards* fwd, struct config_file* cfg) int forwards_apply_cfg(struct iter_forwards* fwd, struct config_file* cfg) { + if(fwd->tree) { + lock_unprotect(&fwd->lock, fwd->tree); + } fwd_del_tree(fwd); fwd->tree = rbtree_create(fwd_cmp); if(!fwd->tree) return 0; + lock_protect(&fwd->lock, fwd->tree, sizeof(*fwd->tree)); + lock_rw_wrlock(&fwd->lock); /* read forward zones */ - if(!read_forwards(fwd, cfg)) + if(!read_forwards(fwd, cfg)) { + lock_rw_unlock(&fwd->lock); return 0; - if(!make_stub_holes(fwd, cfg)) + } + if(!make_stub_holes(fwd, cfg)) { + lock_rw_unlock(&fwd->lock); return 0; + } fwd_init_parents(fwd); + lock_rw_unlock(&fwd->lock); return 1; } struct delegpt* -forwards_find(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass) +forwards_find(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass, + int nolock) { - rbnode_type* res = NULL; + struct iter_forward_zone* res; struct iter_forward_zone key; + int has_dp; 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; + /* lock_() calls are macros that could be nothing, surround in {} */ + if(!nolock) { lock_rw_rdlock(&fwd->lock); } + res = (struct iter_forward_zone*)rbtree_search(fwd->tree, &key); + has_dp = res && res->dp; + if(!has_dp && !nolock) { lock_rw_unlock(&fwd->lock); } + return has_dp?res->dp:NULL; } struct delegpt* -forwards_lookup(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass) +forwards_lookup(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass, + int nolock) { /* lookup the forward zone in the tree */ rbnode_type* res = NULL; struct iter_forward_zone *result; struct iter_forward_zone key; + int has_dp; key.node.key = &key; key.dclass = qclass; key.name = qname; key.namelabs = dname_count_size_labels(qname, &key.namelen); + /* lock_() calls are macros that could be nothing, surround in {} */ + if(!nolock) { lock_rw_rdlock(&fwd->lock); } if(rbtree_find_less_equal(fwd->tree, &key, &res)) { /* exact */ result = (struct iter_forward_zone*)res; @@ -378,8 +399,10 @@ forwards_lookup(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass) /* smaller element (or no element) */ int m; result = (struct iter_forward_zone*)res; - if(!result || result->dclass != qclass) + if(!result || result->dclass != qclass) { + if(!nolock) { lock_rw_unlock(&fwd->lock); } return NULL; + } /* count number of labels matched */ (void)dname_lab_cmp(result->name, result->namelabs, key.name, key.namelabs, &m); @@ -389,20 +412,22 @@ forwards_lookup(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass) result = result->parent; } } - if(result) - return result->dp; - return NULL; + has_dp = result && result->dp; + if(!has_dp && !nolock) { lock_rw_unlock(&fwd->lock); } + return has_dp?result->dp:NULL; } struct delegpt* -forwards_lookup_root(struct iter_forwards* fwd, uint16_t qclass) +forwards_lookup_root(struct iter_forwards* fwd, uint16_t qclass, int nolock) { uint8_t root = 0; - return forwards_lookup(fwd, &root, qclass); + return forwards_lookup(fwd, &root, qclass, nolock); } -int -forwards_next_root(struct iter_forwards* fwd, uint16_t* dclass) +/* Finds next root item in forwards lookup tree. + * Caller needs to handle locking of the forwards structure. */ +static int +next_root_locked(struct iter_forwards* fwd, uint16_t* dclass) { struct iter_forward_zone key; rbnode_type* n; @@ -419,7 +444,7 @@ forwards_next_root(struct iter_forwards* fwd, uint16_t* dclass) } /* root not first item? search for higher items */ *dclass = p->dclass + 1; - return forwards_next_root(fwd, dclass); + return next_root_locked(fwd, dclass); } /* find class n in tree, we may get a direct hit, or if we don't * this is the last item of the previous class so rbtree_next() takes @@ -447,10 +472,21 @@ forwards_next_root(struct iter_forwards* fwd, uint16_t* dclass) } /* not a root node, return next higher item */ *dclass = p->dclass+1; - return forwards_next_root(fwd, dclass); + return next_root_locked(fwd, dclass); } } +int +forwards_next_root(struct iter_forwards* fwd, uint16_t* dclass, int nolock) +{ + int ret; + /* lock_() calls are macros that could be nothing, surround in {} */ + if(!nolock) { lock_rw_rdlock(&fwd->lock); } + ret = next_root_locked(fwd, dclass); + if(!nolock) { lock_rw_unlock(&fwd->lock); } + return ret; +} + size_t forwards_get_mem(struct iter_forwards* fwd) { @@ -458,10 +494,12 @@ forwards_get_mem(struct iter_forwards* fwd) size_t s; if(!fwd) return 0; + lock_rw_rdlock(&fwd->lock); 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); } + lock_rw_unlock(&fwd->lock); return s; } @@ -477,49 +515,78 @@ fwd_zone_find(struct iter_forwards* fwd, uint16_t c, uint8_t* nm) } int -forwards_add_zone(struct iter_forwards* fwd, uint16_t c, struct delegpt* dp) +forwards_add_zone(struct iter_forwards* fwd, uint16_t c, struct delegpt* dp, + int nolock) { struct iter_forward_zone *z; + /* lock_() calls are macros that could be nothing, surround in {} */ + if(!nolock) { lock_rw_wrlock(&fwd->lock); } 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)) + if(!forwards_insert(fwd, c, dp)) { + if(!nolock) { lock_rw_unlock(&fwd->lock); } return 0; + } fwd_init_parents(fwd); + if(!nolock) { lock_rw_unlock(&fwd->lock); } return 1; } void -forwards_delete_zone(struct iter_forwards* fwd, uint16_t c, uint8_t* nm) +forwards_delete_zone(struct iter_forwards* fwd, uint16_t c, uint8_t* nm, + int nolock) { struct iter_forward_zone *z; - if(!(z=fwd_zone_find(fwd, c, nm))) + /* lock_() calls are macros that could be nothing, surround in {} */ + if(!nolock) { lock_rw_wrlock(&fwd->lock); } + if(!(z=fwd_zone_find(fwd, c, nm))) { + if(!nolock) { lock_rw_unlock(&fwd->lock); } return; /* nothing to do */ + } (void)rbtree_delete(fwd->tree, &z->node); fwd_zone_free(z); fwd_init_parents(fwd); + if(!nolock) { lock_rw_unlock(&fwd->lock); } } int -forwards_add_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm) +forwards_add_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm, + int nolock) { + /* lock_() calls are macros that could be nothing, surround in {} */ + if(!nolock) { lock_rw_wrlock(&fwd->lock); } + if(fwd_zone_find(fwd, c, nm) != NULL) { + if(!nolock) { lock_rw_unlock(&fwd->lock); } + return 1; /* already a stub zone there */ + } if(!fwd_add_stub_hole(fwd, c, nm)) { + if(!nolock) { lock_rw_unlock(&fwd->lock); } return 0; } fwd_init_parents(fwd); + if(!nolock) { lock_rw_unlock(&fwd->lock); } return 1; } void -forwards_delete_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm) +forwards_delete_stub_hole(struct iter_forwards* fwd, uint16_t c, + uint8_t* nm, int nolock) { struct iter_forward_zone *z; - if(!(z=fwd_zone_find(fwd, c, nm))) + /* lock_() calls are macros that could be nothing, surround in {} */ + if(!nolock) { lock_rw_wrlock(&fwd->lock); } + if(!(z=fwd_zone_find(fwd, c, nm))) { + if(!nolock) { lock_rw_unlock(&fwd->lock); } return; /* nothing to do */ - if(z->dp != NULL) + } + if(z->dp != NULL) { + if(!nolock) { lock_rw_unlock(&fwd->lock); } return; /* not a stub hole */ + } (void)rbtree_delete(fwd->tree, &z->node); fwd_zone_free(z); fwd_init_parents(fwd); + if(!nolock) { lock_rw_unlock(&fwd->lock); } } |