summaryrefslogtreecommitdiff
path: root/usr.sbin/unbound/iterator/iter_fwd.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/unbound/iterator/iter_fwd.c')
-rw-r--r--usr.sbin/unbound/iterator/iter_fwd.c266
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);
}