forward zones.

git-svn-id: file:///svn/unbound/trunk@429 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2007-07-17 13:45:45 +00:00
parent 6907d9a989
commit 62dd62efd0
12 changed files with 571 additions and 44 deletions

View 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

View 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

View 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

285
iterator/iter_fwd.c Normal file
View file

@ -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;
}

121
iterator/iter_fwd.h Normal file
View file

@ -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 */

View 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 */

View 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 */

View 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 */

View 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);
}

View 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;

View 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 */

View 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 */