From: Wouter Wijngaards Date: Tue, 17 Jul 2007 13:45:45 +0000 (+0000) Subject: forward zones. X-Git-Tag: release-0.4~37 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=62dd62efd0450ffa3ec87300c041ce97e9397def;p=thirdparty%2Funbound.git forward zones. git-svn-id: file:///svn/unbound/trunk@429 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/doc/Changelog b/doc/Changelog index 815356c70..2e66c8107 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -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 diff --git a/doc/example.conf b/doc/example.conf index df5a96fed..3bba6531a 100644 --- a/doc/example.conf +++ b/doc/example.conf @@ -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 diff --git a/doc/unbound.conf.5 b/doc/unbound.conf.5 index 97f77947b..69cd64cf6 100644 --- a/doc/unbound.conf.5 +++ b/doc/unbound.conf.5 @@ -153,11 +153,28 @@ For the stub zone this list of nameservers is used. Class IN is assumed. .It \fBname:\fR Name of the stub zone. .It \fBstub-host:\fR -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 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 +Name of the forward zone. +.It \fBforward-host:\fR +Name of server to forward to. Is itself resolved before it is used. +.It \fBforward-addr:\fR +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 index 000000000..d3addb8c8 --- /dev/null +++ b/iterator/iter_fwd.c @@ -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 index 000000000..c94f33e0d --- /dev/null +++ b/iterator/iter_fwd.h @@ -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 */ diff --git a/iterator/iter_utils.c b/iterator/iter_utils.c index 2c9da2188..2a887b40a 100644 --- a/iterator/iter_utils.c +++ b/iterator/iter_utils.c @@ -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 */ diff --git a/iterator/iterator.c b/iterator/iterator.c index 4da3c6843..08625d9db 100644 --- a/iterator/iterator.c +++ b/iterator/iterator.c @@ -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 */ diff --git a/iterator/iterator.h b/iterator/iterator.h index ba9996695..81b1ec920 100644 --- a/iterator/iterator.h +++ b/iterator/iterator.h @@ -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 */ diff --git a/util/config_file.c b/util/config_file.c index e0c0a2b58..5318ba3f7 100644 --- a/util/config_file.c +++ b/util/config_file.c @@ -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); } diff --git a/util/config_file.h b/util/config_file.h index dfad7bea9..a64428b4c 100644 --- a/util/config_file.h +++ b/util/config_file.h @@ -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; diff --git a/util/configlexer.lex b/util/configlexer.lex index f44f58dca..59fa47266 100644 --- a/util/configlexer.lex +++ b/util/configlexer.lex @@ -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 */ diff --git a/util/configparser.y b/util/configparser.y index 91e0e96de..72c6b3a79 100644 --- a/util/configparser.y +++ b/util/configparser.y @@ -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 */