]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
forward zones.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Tue, 17 Jul 2007 13:45:45 +0000 (13:45 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Tue, 17 Jul 2007 13:45:45 +0000 (13:45 +0000)
git-svn-id: file:///svn/unbound/trunk@429 be551aaa-1e26-0410-a405-d3ace91eadb9

12 files changed:
doc/Changelog
doc/example.conf
doc/unbound.conf.5
iterator/iter_fwd.c [new file with mode: 0644]
iterator/iter_fwd.h [new file with mode: 0644]
iterator/iter_utils.c
iterator/iterator.c
iterator/iterator.h
util/config_file.c
util/config_file.h
util/configlexer.lex
util/configparser.y

index 815356c704f1187690878dddd0b2a55f83c0d763..2e66c810778a7f9bc260a36f1b2d0fc4612fa1a1 100644 (file)
@@ -1,3 +1,7 @@
+17 July 2007: Wouter
+       - forward zone options in config file.
+       - forward per zone in iterator. takes precendence over stubs.
+
 27 June 2007: Wouter
        - delete of mesh does a postorder traverse of the tree.
        - found and fixed a memory leak. For TTL=0 messages, that would
index df5a96fed54e85d80cc62680488d8f25e266d08f..3bba6531a67ef64efdc609f18b5c7e50e60af9b0 100644 (file)
@@ -137,7 +137,7 @@ server:
 
 # Stub zones.
 # Create entries like below, to make all queries for 'example.com' and 
-# subdomains go to the given list of nameservers. list zero or more 
+# 'example.org' go to the given list of nameservers. list zero or more 
 # nameservers by hostname or by ipaddress.
 # stub-zone:
 #      name: "example.com"
@@ -146,3 +146,14 @@ server:
 #      name: "example.org"
 #      stub-host: ns.example.com.
 
+# Forward zones
+# Create entries like below, to make all queries for 'example.com' and
+# 'example.org' go to the given list of servers. These servers have to handle
+# recursion to other nameservers. List zero or more nameservers by hostname
+# or by ipaddress. Use an entry with name "." to forward all queries.
+# forward-zone:
+#      name: "example.com"
+#      forward-addr: 192.0.2.68
+# forward-zone:
+#      name: "example.org"
+#      forward-host: fwd.example.com
index 97f77947b2f72bf4fc5f1dd981d0660fddb740b9..69cd64cf6da033e3e2f47288c156ee8cc8cab6cf 100644 (file)
@@ -153,11 +153,28 @@ For the stub zone this list of nameservers is used. Class IN is assumed.
 .It \fBname:\fR <domain name>
 Name of the stub zone.
 .It \fBstub-host:\fR <domain name>
-Name of stub zone nameserver. Will need to be resolved before it can be used.
+Name of stub zone nameserver. Is itself resolved before it is used.
 .It \fBstub-addr:\fR <IP address>
 IP address of stub zone nameserver. Can be IP 4 or IP 6.
 .El
 
+.Ss Forward Zone Options
+There may be multiple
+.Ic forward-zone:
+clauses. Each with a name: and zero or more hostnames or IP addresses.
+For the forward zone this list of nameservers is used to forward the queries
+to. The servers have to handle further recursion for the query. Class IN is 
+assumed. A forward-zone entry with name "." and a forward-addr target will 
+forward all queries to that other server (unless it can answer from the cache).
+.Bl -tag -width indent
+.It \fBname:\fR <domain name>
+Name of the forward zone.
+.It \fBforward-host:\fR <domain name>
+Name of server to forward to. Is itself resolved before it is used.
+.It \fBforward-addr:\fR <IP address>
+IP address of server to forward to. Can be IP 4 or IP 6.
+.El
+
 .Sh FILES
 .Bl -tag -width indent
 .It Pa unbound.conf
diff --git a/iterator/iter_fwd.c b/iterator/iter_fwd.c
new file mode 100644 (file)
index 0000000..d3addb8
--- /dev/null
@@ -0,0 +1,285 @@
+/*
+ * iterator/iter_fwd.c - iterative resolver module forward zones.
+ *
+ * Copyright (c) 2007, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 
+ * Neither the name of the NLNET LABS nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * 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 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.
+ */
+
+/**
+ * \file
+ *
+ * This file contains functions to assist the iterator module.
+ * Keep track of forward zones and config settings.
+ */
+#include "config.h"
+#include "iterator/iter_fwd.h"
+#include "iterator/iter_delegpt.h"
+#include "util/region-allocator.h"
+#include "util/log.h"
+#include "util/config_file.h"
+#include "util/net_help.h"
+#include "util/data/dname.h"
+
+/** compare two fwd entries */
+static int
+fwd_cmp(const void* k1, const void* k2)
+{
+       int m;
+       struct iter_forward_zone* n1 = (struct iter_forward_zone*)k1;
+       struct iter_forward_zone* n2 = (struct iter_forward_zone*)k2;
+       if(n1->dclass != n2->dclass) {
+               if(n1->dclass < n2->dclass)
+                       return -1;
+               return 1;
+       }
+       return dname_lab_cmp(n1->name, n1->namelabs, n2->name, n2->namelabs, 
+               &m);
+}
+
+struct iter_forwards* 
+forwards_create()
+{
+       struct iter_forwards* fwd = (struct iter_forwards*)calloc(1,
+               sizeof(struct iter_forwards));
+       if(!fwd)
+               return NULL;
+       fwd->region = region_create(malloc, free);
+       if(!fwd->region) {
+               forwards_delete(fwd);
+               return NULL;
+       }
+       return fwd;
+}
+
+void 
+forwards_delete(struct iter_forwards* fwd)
+{
+       if(!fwd) 
+               return;
+       region_destroy(fwd->region);
+       free(fwd->tree);
+       free(fwd);
+}
+
+/** insert new info into forward structure */
+static int
+forwards_insert(struct iter_forwards* fwd, uint16_t c, struct delegpt* dp)
+{
+       struct iter_forward_zone* node = region_alloc(fwd->region,
+               sizeof(struct iter_forward_zone));
+       if(!node)
+               return 0;
+       node->node.key = node;
+       node->dclass = c;
+       node->name = region_alloc_init(fwd->region, dp->name, dp->namelen);
+       if(!node->name)
+               return 0;
+       node->namelen = dp->namelen;
+       node->namelabs = dp->namelabs;
+       node->dp = dp;
+       if(!rbtree_insert(fwd->tree, &node->node)) {
+               log_err("duplicate forward zone ignored.");
+       }
+       return 1;
+}
+
+/** initialise parent pointers in the tree */
+static void
+fwd_init_parents(struct iter_forwards* fwd)
+{
+       struct iter_forward_zone* node, *prev = NULL, *p;
+       int m;
+       RBTREE_FOR(node, struct iter_forward_zone*, fwd->tree) {
+               node->parent = NULL;
+               if(!prev || prev->dclass != node->dclass) {
+                       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 zone name */
+static int 
+read_fwds_name(struct iter_forwards* fwd, 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;
+       }
+       rdf = ldns_dname_new_frm_str(s->name);
+       if(!rdf) {
+               log_err("cannot parse forward zone name %s", s->name);
+               return 0;
+       }
+       if(!delegpt_set_name(dp, fwd->region, ldns_rdf_data(rdf))) {
+               ldns_rdf_deep_free(rdf);
+               log_err("out of memory");
+               return 0;
+       }
+       ldns_rdf_deep_free(rdf);
+       return 1;
+}
+
+/** set fwd host names */
+static int 
+read_fwds_host(struct iter_forwards* fwd, struct config_stub* s, 
+       struct delegpt* dp)
+{
+       struct config_strlist* p;
+       ldns_rdf* rdf;
+       for(p = s->hosts; p; p = p->next) {
+               log_assert(p->str);
+               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(dp, fwd->region, ldns_rdf_data(rdf))) {
+                       ldns_rdf_deep_free(rdf);
+                       log_err("out of memory");
+                       return 0;
+               }
+               ldns_rdf_deep_free(rdf);
+       }
+       return 1;
+}
+
+/** set fwd server addresses */
+static int 
+read_fwds_addr(struct iter_forwards* fwd, struct config_stub* s, 
+       struct delegpt* dp)
+{
+       struct config_strlist* p;
+       struct sockaddr_storage addr;
+       socklen_t addrlen;
+       for(p = s->addrs; p; p = p->next) {
+               log_assert(p->str);
+               if(!ipstrtoaddr(p->str, UNBOUND_DNS_PORT, &addr, &addrlen)) {
+                       log_err("cannot parse forward %s ip address: '%s'", 
+                               s->name, p->str);
+                       return 0;
+               }
+               if(!delegpt_add_addr(dp, fwd->region, &addr, addrlen)) {
+                       log_err("out of memory");
+                       return 0;
+               }
+       }
+       return 1;
+}
+
+/** read forwards config */
+static int 
+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");
+                       return 0;
+               }
+               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;
+               log_info("Forward zone server list:");
+               delegpt_log(dp);
+       }
+       return 1;
+}
+
+int 
+forwards_apply_cfg(struct iter_forwards* fwd, struct config_file* cfg)
+{
+       free(fwd->tree);
+       fwd->tree = rbtree_create(fwd_cmp);
+       if(!fwd->tree)
+               return 0;
+
+       /* read forward zones */
+       if(!read_forwards(fwd, cfg))
+               return 0;
+       fwd_init_parents(fwd);
+       return 1;
+}
+
+struct delegpt* 
+forwards_lookup(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass)
+{
+       /* lookup the forward zone in the tree */
+       rbnode_t* res = NULL;
+       struct iter_forward_zone *result;
+       struct iter_forward_zone key;
+       key.node.key = &key;
+       key.dclass = qclass;
+       key.name = qname;
+       key.namelabs = dname_count_size_labels(qname, &key.namelen);
+       if(rbtree_find_less_equal(fwd->tree, &key, &res)) {
+               /* exact */
+               result = (struct iter_forward_zone*)res;
+       } else {
+               /* smaller element (or no element) */
+               int m;
+               result = (struct iter_forward_zone*)res;
+               if(!result || result->dclass != 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 result->dp;
+       return NULL;
+}
diff --git a/iterator/iter_fwd.h b/iterator/iter_fwd.h
new file mode 100644 (file)
index 0000000..c94f33e
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * iterator/iter_fwd.h - iterative resolver module forward zones.
+ *
+ * Copyright (c) 2007, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 
+ * Neither the name of the NLNET LABS nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * 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 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.
+ */
+
+/**
+ * \file
+ *
+ * This file contains functions to assist the iterator module.
+ * Keep track of forward zones, and read those from config.
+ */
+
+#ifndef ITERATOR_ITER_FWD_H
+#define ITERATOR_ITER_FWD_H
+#include "util/rbtree.h"
+struct iter_env;
+struct config_file;
+struct delegpt;
+struct region;
+
+/**
+ * Iterator forward zones structure
+ */
+struct iter_forwards {
+       /** region where forward zone server addresses are allocated */
+       struct region* region;
+       /** 
+        * Zones are stored in this tree. Sort order is specially chosen.
+        * first sorted on qtype. Then on dname in nsec-like order, so that
+        * a lookup on class, name will return an exact match or the closest
+        * match which gives the ancestor needed.
+        * contents of type iter_forward_zone.
+        */
+       rbtree_t* tree;
+};
+
+/**
+ * Iterator forward servers for a particular zone.
+ */
+struct iter_forward_zone {
+       /** 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;
+       /** delegation point with forward server information for this zone. */
+       struct delegpt* dp;
+       /** pointer to parent in tree (or NULL if none) */
+       struct iter_forward_zone* parent;
+       /** class. host order. */
+       uint16_t dclass;
+};
+
+/**
+ * Create forwards 
+ * @return new forwards or NULL on error.
+ */
+struct iter_forwards* forwards_create();
+
+/**
+ * Delete forwards.
+ * @param fwd: to delete.
+ */
+void forwards_delete(struct iter_forwards* fwd);
+
+/**
+ * Process forwards config.
+ * @param fwd: where to store.
+ * @param cfg: config options.
+ * @return 0 on error.
+ */
+int forwards_apply_cfg(struct iter_forwards* fwd, struct config_file* cfg);
+
+/**
+ * Find a forward zone information
+ * For this qname/qclass find forward zone information, returns delegation
+ * point with server names and addresses, or NULL if no forwarding is needed.
+ *
+ * @param fwd: forward storage.
+ * @param qname: The qname of the query.
+ * @param qclass: The qclass of the query.
+ * @return: A delegation point if the query has to be forwarded to that list,
+ *         otherwise null.
+ */
+struct delegpt* forwards_lookup(struct iter_forwards* fwd, 
+       uint8_t* qname, uint16_t qclass);
+
+#endif /* ITERATOR_ITER_FWD_H */
index 2c9da2188fa7b0df9a41211986758f6fb1070dd9..2a887b40af5061680d6e9bf121a30b2666818d70 100644 (file)
@@ -43,6 +43,7 @@
 #include "iterator/iter_utils.h"
 #include "iterator/iterator.h"
 #include "iterator/iter_hints.h"
+#include "iterator/iter_fwd.h"
 #include "iterator/iter_delegpt.h"
 #include "services/cache/infra.h"
 #include "services/cache/dns.h"
@@ -131,6 +132,12 @@ iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
                log_err("Could not set root or stub hints");
                return 0;
        }
+       if(!iter_env->fwds)
+               iter_env->fwds = forwards_create();
+       if(!iter_env->fwds || !forwards_apply_cfg(iter_env->fwds, cfg)) {
+               log_err("Could not set forward zones");
+               return 0;
+       }
        iter_env->supports_ipv6 = cfg->do_ip6;
 
        /* forwarder address */
index 4da3c6843341532d2be4203cdf8cad8803cbd1ff..08625d9db3eecc915ad70f1fc3b1640acc76cb01 100644 (file)
@@ -44,6 +44,7 @@
 #include "iterator/iterator.h"
 #include "iterator/iter_utils.h"
 #include "iterator/iter_hints.h"
+#include "iterator/iter_fwd.h"
 #include "iterator/iter_delegpt.h"
 #include "iterator/iter_resptype.h"
 #include "iterator/iter_scrub.h"
@@ -84,6 +85,7 @@ iter_deinit(struct module_env* env, int id)
        iter_env = (struct iter_env*)env->modinfo[id];
        free(iter_env->target_fetch_policy);
        hints_delete(iter_env->hints);
+       forwards_delete(iter_env->fwds);
        if(iter_env)
                free(iter_env);
 }
@@ -603,6 +605,31 @@ prime_stub(struct module_qstate* qstate, struct iter_qstate* iq,
        return 1;
 }
 
+/**
+ * See if the query needs forwarding.
+ * 
+ * @param qstate: query state.
+ * @param iq: iterator query state.
+ * @param ie: iterator shared global environment.
+ * @return true if the request is forwarded, false if not.
+ *     If returns true but, iq->dp is NULL then a malloc failure occurred.
+ */
+static int
+forward_request(struct module_qstate* qstate, struct iter_qstate* iq,
+       struct iter_env* ie)
+{
+       struct delegpt* dp = forwards_lookup(ie->fwds, iq->qchase.qname,
+               iq->qchase.qclass);
+       if(!dp) 
+               return 0;
+       /* send recursion desired to forward addr */
+       iq->chase_flags |= BIT_RD; 
+       iq->dp = delegpt_copy(dp, qstate->region);
+       /* iq->dp checked by caller */
+       verbose(VERB_ALGO, "forwarding request");
+       return 1;
+}
+
 /** 
  * Process the initial part of the request handling. This state roughly
  * corresponds to resolver algorithms steps 1 (find answer in cache) and 2
@@ -688,35 +715,18 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
                return final_state(iq);
        }
        
-       /* TODO attempt to forward the request */
-       /* if (forwardRequest(event, state, req))
-          {
-               // the request has been forwarded.
-               // forwarded requests need to be immediately sent to the 
-               // next state, QUERYTARGETS.
-               return nextState(event, req, state, 
-                       IterEventState.QUERYTARGETS_STATE);
-               }
-       */
-
-       /* TODO attempt to find a covering DNAME in the cache */
-       /* resp = mDNSCache.findDNAME(req.getQName(), req.getQType(), req
-               .getQClass());
-           if (resp != null)
+       /* attempt to forward the request */
+       if(forward_request(qstate, iq, ie))
        {
-log.trace("returning synthesized CNAME response from cache: " + resp);
-Name cname = handleCNAMEResponse(state, req, resp);
-// At this point, we just initiate the query restart.
-// This might not be a query restart situation (e.g., qtype == CNAME),
-// but
-// the answer returned from findDNAME() is likely to be one that we
-// don't want to return.
-// Thus we allow the cache and other resolution mojo kick in regardless.
-req.setQName(cname);
-state.queryRestartCount++;
-return nextState(event, req, state, IterEventState.INIT_REQUEST_STATE);
-}
-       */
+               if(!iq->dp) {
+                       log_err("alloc failure for forward dp");
+                       return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
+               }
+               /* the request has been forwarded.
+                * forwarded requests need to be immediately sent to the 
+                * next state, QUERYTARGETS. */
+               return next_state(iq, QUERYTARGETS_STATE);
+       }
 
        /* Resolver Algorithm Step 2 -- find the "best" servers. */
 
@@ -1002,7 +1012,8 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
         * they will not be show up again. */
        if(tf_policy != 0) {
                int extra = 0;
-               verbose(VERB_ALGO, "query for extra %d targets", tf_policy);
+               verbose(VERB_ALGO, "attempt to get extra %d targets", 
+                       tf_policy);
                if(!query_for_targets(qstate, iq, ie, id, tf_policy, &extra)) {
                        return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
                }
@@ -1120,6 +1131,13 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
                return next_state(iq, QUERYTARGETS_STATE);
        }
        type = response_type_from_server(iq->response, &iq->qchase, iq->dp);
+       if(type == RESPONSE_TYPE_REFERRAL && (iq->chase_flags&BIT_RD)) {
+               /* When forwarding (RD bit is set), we handle referrals 
+                * differently. No queries should be sent elsewhere */
+               type = RESPONSE_TYPE_ANSWER;
+       }
+
+       /* handle each of the type cases */
        if(type == RESPONSE_TYPE_ANSWER) {
                /* ANSWER type responses terminate the query algorithm, 
                 * so they sent on their */
index ba999669559b38dfb4c704123ee020b5edd3030c..81b1ec92047663a2d69c1212f68f85be37bd55c9 100644 (file)
@@ -47,6 +47,7 @@
 struct module_func_block;
 struct delegpt;
 struct iter_hints;
+struct iter_forwards;
 struct iter_prep_list;
 
 /** max number of query restarts. Determines max number of CNAME chain. */
@@ -84,7 +85,7 @@ struct iter_env {
        int supports_ipv6;
 
        /** Mapping of forwarding zones to targets. */
-       /* struct fwds fwd_map TODO */
+       struct iter_forwards* fwds;
 
        /** A set of inetaddrs that should never be queried. */
        /* struct bla donotquery_addrs TODO */
index e0c0a2b58e443c768f6d6c325181021f9a7bf150..5318ba3f7dcdd1e24354a2e7b5c62934c818bf9a 100644 (file)
@@ -100,6 +100,7 @@ config_create()
        cfg->num_ifs = 0;
        cfg->ifs = NULL;
        cfg->stubs = NULL;
+       cfg->forwards = NULL;
        cfg->harden_short_bufsize = 0;
        cfg->harden_large_queries = 0;
        return cfg;
@@ -158,6 +159,21 @@ config_delstrlist(struct config_strlist* p)
        }
 }
 
+/** delete config stublist */
+static void
+config_delstubs(struct config_stub* p)
+{
+       struct config_stub* np;
+       while(p) {
+               np = p->next;
+               free(p->name);
+               config_delstrlist(p->hosts);
+               config_delstrlist(p->addrs);
+               free(p);
+               p = np;
+       }
+}
+
 void 
 config_delete(struct config_file* cfg)
 {
@@ -175,17 +191,8 @@ config_delete(struct config_file* cfg)
                        free(cfg->ifs[i]);
                free(cfg->ifs);
        }
-       if(cfg->stubs) {
-               struct config_stub* p = cfg->stubs, *np;
-               while(p) {
-                       np = p->next;
-                       free(p->name);
-                       config_delstrlist(p->hosts);
-                       config_delstrlist(p->addrs);
-                       free(p);
-                       p = np;
-               }
-       }
+       config_delstubs(cfg->stubs);
+       config_delstubs(cfg->forwards);
        free(cfg);
 }
 
index dfad7bea973f7f20dfd584e0644e759d0576fcfb..a64428b4c8d9cc9debb69e41a29950b334a1d116 100644 (file)
@@ -109,6 +109,8 @@ struct config_file {
 
        /** the stub definitions, linked list */
        struct config_stub* stubs;
+       /** the forward definitions, linked list */
+       struct config_stub* forwards;
 
        /** harden against very small edns buffer sizes */
        int harden_short_bufsize;
index f44f58dca09a6861d5c45b49b6e8649260380b0d..59fa47266deb422d977e515b74dcc7c6bd1e1d71 100644 (file)
@@ -134,6 +134,9 @@ stub-zone{COLON}    { YDOUT; return VAR_STUB_ZONE;}
 name{COLON}            { YDOUT; return VAR_NAME;}
 stub-addr{COLON}       { YDOUT; return VAR_STUB_ADDR;}
 stub-host{COLON}       { YDOUT; return VAR_STUB_HOST;}
+forward-zone{COLON}    { YDOUT; return VAR_FORWARD_ZONE;}
+forward-addr{COLON}    { YDOUT; return VAR_FORWARD_ADDR;}
+forward-host{COLON}    { YDOUT; return VAR_FORWARD_HOST;}
 {NEWLINE}              { LEXOUT(("NL\n")); cfg_parser->line++;}
 
        /* Quoted strings. Strip leading and ending quotes */
index 91e0e96de5f6b760dec52334f06fd92f39f5ebf5..72c6b3a792fa74970685920ba2f57a2eee27f941 100644 (file)
@@ -78,6 +78,7 @@ extern struct config_parser_state* cfg_parser;
 %token VAR_INFRA_CACHE_NUMHOSTS VAR_INFRA_CACHE_NUMLAME VAR_NAME
 %token VAR_STUB_ZONE VAR_STUB_HOST VAR_STUB_ADDR VAR_TARGET_FETCH_POLICY
 %token VAR_HARDEN_SHORT_BUFSIZE VAR_HARDEN_LARGE_QUERIES
+%token VAR_FORWARD_ZONE VAR_FORWARD_HOST VAR_FORWARD_ADDR
 
 %%
 toplevelvars: /* empty */ | toplevelvars toplevelvar ;
@@ -106,7 +107,7 @@ content_server: server_num_threads | server_verbosity | server_port |
        server_infra_cache_slabs | server_infra_cache_numhosts |
        server_infra_cache_numlame | stubstart contents_stub | 
        server_target_fetch_policy | server_harden_short_bufsize |
-       server_harden_large_queries
+       server_harden_large_queries | forwardstart contents_forward
        ;
 stubstart: VAR_STUB_ZONE
        {
@@ -124,6 +125,22 @@ contents_stub: contents_stub content_stub
        | ;
 content_stub: stub_name | stub_host | stub_addr 
        ;
+forwardstart: VAR_FORWARD_ZONE
+       {
+               struct config_stub* s;
+               OUTYY(("\nP(forward_zone:)\n")); 
+               s = (struct config_stub*)calloc(1, sizeof(struct config_stub));
+               if(s) {
+                       s->next = cfg_parser->cfg->forwards;
+                       cfg_parser->cfg->forwards = s;
+               } else 
+                       yyerror("out of memory");
+       }
+       ;
+contents_forward: contents_forward content_forward 
+       | ;
+content_forward: forward_name | forward_host | forward_addr 
+       ;
 server_num_threads: VAR_NUM_THREADS STRING 
        { 
                OUTYY(("P(server_num_threads:%s)\n", $2)); 
@@ -410,6 +427,7 @@ server_harden_large_queries: VAR_HARDEN_LARGE_QUERIES STRING
 stub_name: VAR_NAME STRING
        {
                OUTYY(("P(name:%s)\n", $2));
+               free(cfg_parser->cfg->stubs->name);
                cfg_parser->cfg->stubs->name = $2;
        }
        ;
@@ -439,6 +457,39 @@ stub_addr: VAR_STUB_ADDR STRING
                        yyerror("out of memory");
        }
        ;
+forward_name: VAR_NAME STRING
+       {
+               OUTYY(("P(name:%s)\n", $2));
+               free(cfg_parser->cfg->forwards->name);
+               cfg_parser->cfg->forwards->name = $2;
+       }
+       ;
+forward_host: VAR_FORWARD_HOST STRING
+       {
+               struct config_strlist *s = (struct config_strlist*)calloc(1, 
+                       sizeof(struct config_strlist));
+               OUTYY(("P(forward-host:%s)\n", $2));
+               if(s) {
+                       s->str = $2;
+                       s->next = cfg_parser->cfg->forwards->hosts;
+                       cfg_parser->cfg->forwards->hosts = s;
+               } else
+                       yyerror("out of memory");
+       }
+       ;
+forward_addr: VAR_FORWARD_ADDR STRING
+       {
+               struct config_strlist *s = (struct config_strlist*)calloc(1, 
+                       sizeof(struct config_strlist));
+               OUTYY(("P(forward-addr:%s)\n", $2));
+               if(s) {
+                       s->str = $2;
+                       s->next = cfg_parser->cfg->forwards->addrs;
+                       cfg_parser->cfg->forwards->addrs = s;
+               } else
+                       yyerror("out of memory");
+       }
+       ;
 %%
 
 /* parse helper routines could be here */