Do not query addresses and configuration.

git-svn-id: file:///svn/unbound/trunk@434 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2007-07-18 08:14:44 +00:00
parent 9db3f47b98
commit 0b9807d677
18 changed files with 386 additions and 84 deletions

View file

@ -1,3 +1,6 @@
18 July 2007: Wouter
- do not query addresses, 127.0.0.1, and ::1 by default.
17 July 2007: Wouter 17 July 2007: Wouter
- forward zone options in config file. - forward zone options in config file.
- forward per zone in iterator. takes precendence over stubs. - forward per zone in iterator. takes precendence over stubs.

View file

@ -24,3 +24,4 @@ o understand NSEC/NSEC3, aggressive negative caching, so that updates to
o fallback without EDNS if result is NOTIMPL, now only on FORMERR like in java. o fallback without EDNS if result is NOTIMPL, now only on FORMERR like in java.
o scrubber has slow pkt_subdomain and pkt_strict_subdomain functions. o scrubber has slow pkt_subdomain and pkt_strict_subdomain functions.
o get serverselection algorithm out of local optimum. o get serverselection algorithm out of local optimum.
o donotqueryaddresses allow specification of subnets, use trie to store.

View file

@ -122,10 +122,16 @@ server:
# target-fetch-policy: "3 2 1 0 0" # target-fetch-policy: "3 2 1 0 0"
# Harden against very small EDNS buffer sizes. # Harden against very small EDNS buffer sizes.
# harden_short_bufsize: no # harden-short-bufsize: no
# Harden against unseemly large queries. # Harden against unseemly large queries.
# harden_large_queries: no # harden-large-queries: no
# Do not query the following addresses. No DNS queries are sent there.
# List one address per entry. To block other ports than the default
# DNS port, use "1.2.3.4@123" to block port 123 for 1.2.3.4.
# do-not-query-address: 127.0.0.1
# do-not-query-address: ::1
# Stub zones. # Stub zones.
# Create entries like below, to make all queries for 'example.com' and # Create entries like below, to make all queries for 'example.com' and

View file

@ -136,6 +136,10 @@ small answers to these queries, where possible.
Very large queries are ignored. Default is off, since it is legal protocol Very large queries are ignored. Default is off, since it is legal protocol
wise to send these, and could be necessary for operation if TSIG or EDNS wise to send these, and could be necessary for operation if TSIG or EDNS
payload is very large. payload is very large.
.It \fBdo-not-query-address:\fR <IP address>
Do not query the given IP address. Can be IP4 or IP6. By default the
DNS port is blocked for that address. Appending "@portnumber" will block
other port numbers.
.El .El
.Ss Stub Zone Options .Ss Stub Zone Options

149
iterator/iter_donotq.c Normal file
View file

@ -0,0 +1,149 @@
/*
* iterator/iter_donotq.c - iterative resolver donotqueryaddresses storage.
*
* 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.
* The donotqueryaddresses are stored and looked up. These addresses
* (like 127.0.0.1) must not be used to send queries to, and can be
* discarded immediately from the server selection.
*/
#include "config.h"
#include "iterator/iter_donotq.h"
#include "util/region-allocator.h"
#include "util/log.h"
#include "util/config_file.h"
#include "util/net_help.h"
/** compare two donotq entries */
static int
donotq_cmp(const void* k1, const void* k2)
{
struct iter_donotq_addr* n1 = (struct iter_donotq_addr*)k1;
struct iter_donotq_addr* n2 = (struct iter_donotq_addr*)k2;
return sockaddr_cmp(&n1->addr, n1->addrlen, &n2->addr, n2->addrlen);
}
struct iter_donotq*
donotq_create()
{
struct iter_donotq* dq = (struct iter_donotq*)calloc(1,
sizeof(struct iter_donotq));
if(!dq)
return NULL;
dq->region = region_create(malloc, free);
if(!dq->region) {
donotq_delete(dq);
return NULL;
}
return dq;
}
void
donotq_delete(struct iter_donotq* dq)
{
if(!dq)
return;
region_destroy(dq->region);
free(dq->tree);
free(dq);
}
/** insert new address into donotq structure */
static int
donotq_insert(struct iter_donotq* dq, struct sockaddr_storage* addr,
socklen_t addrlen)
{
struct iter_donotq_addr* node = region_alloc(dq->region,
sizeof(struct iter_donotq_addr));
if(!node)
return 0;
node->node.key = node;
memcpy(&node->addr, addr, addrlen);
node->addrlen = addrlen;
if(!rbtree_insert(dq->tree, &node->node)) {
log_warn("duplicate donotquery address ignored.");
}
return 1;
}
/** read donotq config */
static int
read_donotq(struct iter_donotq* dq, struct config_file* cfg)
{
struct config_strlist* p;
struct sockaddr_storage addr;
socklen_t addrlen;
for(p = cfg->donotqueryaddrs; p; p = p->next) {
log_assert(p->str);
if(!extstrtoaddr(p->str, &addr, &addrlen)) {
log_err("cannot parse donotquery ip address: '%s'",
p->str);
return 0;
}
if(!donotq_insert(dq, &addr, addrlen)) {
log_err("out of memory");
return 0;
}
}
return 1;
}
int
donotq_apply_cfg(struct iter_donotq* dq, struct config_file* cfg)
{
free(dq->tree);
dq->tree = rbtree_create(donotq_cmp);
if(!dq->tree)
return 0;
if(!read_donotq(dq, cfg))
return 0;
return 1;
}
int
donotq_lookup(struct iter_donotq* donotq, struct sockaddr_storage* addr,
socklen_t addrlen)
{
/* lookup in the tree */
struct iter_donotq_addr key;
key.node.key = &key;
memcpy(&key.addr, addr, addrlen);
key.addrlen = addrlen;
if(rbtree_search(donotq->tree, &key))
return 1;
return 0;
}

106
iterator/iter_donotq.h Normal file
View file

@ -0,0 +1,106 @@
/*
* iterator/iter_donotq.h - iterative resolver donotqueryaddresses storage.
*
* 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 the donotquery addresses and lookup fast.
*/
#ifndef ITERATOR_ITER_DONOTQ_H
#define ITERATOR_ITER_DONOTQ_H
#include "util/rbtree.h"
struct iter_env;
struct config_file;
struct region;
/**
* Iterator donotqueryaddresses structure
*/
struct iter_donotq {
/** region for allocation */
struct region* region;
/**
* Tree of the single addresses that are blocked.
* contents of type iter_donotq_addr.
*/
rbtree_t* tree;
};
/**
* Iterator donotquery address.
* A single address that must not be used to send queries to.
*/
struct iter_donotq_addr {
/** redblacktree node, key is this structure: addr and addrlen */
rbnode_t node;
/** address */
struct sockaddr_storage addr;
/** length of addr */
socklen_t addrlen;
};
/**
* Create donotqueryaddresses structure
* @return new structure or NULL on error.
*/
struct iter_donotq* donotq_create();
/**
* Delete donotqueryaddresses structure.
* @param donotq: to delete.
*/
void donotq_delete(struct iter_donotq* donotq);
/**
* Process donotqueryaddresses config.
* @param donotq: where to store.
* @param cfg: config options.
* @return 0 on error.
*/
int donotq_apply_cfg(struct iter_donotq* donotq, struct config_file* cfg);
/**
* See if an address is blocked.
* @param donotq: structure for address storage.
* @param addr: address to check
* @param addrlen: length of addr.
* @return: true if the address must not be queried. false if unlisted.
*/
int donotq_lookup(struct iter_donotq* donotq, struct sockaddr_storage* addr,
socklen_t addrlen);
#endif /* ITERATOR_ITER_DONOTQ_H */

View file

@ -105,7 +105,7 @@ void forwards_delete(struct iter_forwards* fwd);
int forwards_apply_cfg(struct iter_forwards* fwd, struct config_file* cfg); int forwards_apply_cfg(struct iter_forwards* fwd, struct config_file* cfg);
/** /**
* Find a forward zone information * Find forward zone information
* For this qname/qclass find forward zone information, returns delegation * For this qname/qclass find forward zone information, returns delegation
* point with server names and addresses, or NULL if no forwarding is needed. * point with server names and addresses, or NULL if no forwarding is needed.
* *

View file

@ -44,6 +44,7 @@
#include "iterator/iterator.h" #include "iterator/iterator.h"
#include "iterator/iter_hints.h" #include "iterator/iter_hints.h"
#include "iterator/iter_fwd.h" #include "iterator/iter_fwd.h"
#include "iterator/iter_donotq.h"
#include "iterator/iter_delegpt.h" #include "iterator/iter_delegpt.h"
#include "services/cache/infra.h" #include "services/cache/infra.h"
#include "services/cache/dns.h" #include "services/cache/dns.h"
@ -138,6 +139,12 @@ iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
log_err("Could not set forward zones"); log_err("Could not set forward zones");
return 0; return 0;
} }
if(!iter_env->donotq)
iter_env->donotq = donotq_create();
if(!iter_env->donotq || !donotq_apply_cfg(iter_env->donotq, cfg)) {
log_err("Could not set donotqueryaddresses");
return 0;
}
iter_env->supports_ipv6 = cfg->do_ip6; iter_env->supports_ipv6 = cfg->do_ip6;
return 1; return 1;
} }
@ -149,9 +156,11 @@ iter_filter_unsuitable(struct iter_env* iter_env, struct module_env* env,
{ {
int rtt; int rtt;
int lame; int lame;
/* TODO: check ie->donotqueryaddrs for a */ if(donotq_lookup(iter_env->donotq, &a->addr, a->addrlen)) {
return -1; /* server is on the donotquery list */
}
if(!iter_env->supports_ipv6 && addr_is_ip6(&a->addr)) { if(!iter_env->supports_ipv6 && addr_is_ip6(&a->addr)) {
return -1; return -1; /* there is no ip6 available */
} }
/* check lameness - need zone , class info */ /* check lameness - need zone , class info */
if(infra_get_lame_rtt(env->infra_cache, &a->addr, a->addrlen, if(infra_get_lame_rtt(env->infra_cache, &a->addr, a->addrlen,

View file

@ -45,6 +45,7 @@
#include "iterator/iter_utils.h" #include "iterator/iter_utils.h"
#include "iterator/iter_hints.h" #include "iterator/iter_hints.h"
#include "iterator/iter_fwd.h" #include "iterator/iter_fwd.h"
#include "iterator/iter_donotq.h"
#include "iterator/iter_delegpt.h" #include "iterator/iter_delegpt.h"
#include "iterator/iter_resptype.h" #include "iterator/iter_resptype.h"
#include "iterator/iter_scrub.h" #include "iterator/iter_scrub.h"
@ -86,6 +87,7 @@ iter_deinit(struct module_env* env, int id)
free(iter_env->target_fetch_policy); free(iter_env->target_fetch_policy);
hints_delete(iter_env->hints); hints_delete(iter_env->hints);
forwards_delete(iter_env->fwds); forwards_delete(iter_env->fwds);
donotq_delete(iter_env->donotq);
if(iter_env) if(iter_env)
free(iter_env); free(iter_env);
} }

View file

@ -48,6 +48,7 @@ struct module_func_block;
struct delegpt; struct delegpt;
struct iter_hints; struct iter_hints;
struct iter_forwards; struct iter_forwards;
struct iter_donotq;
struct iter_prep_list; struct iter_prep_list;
/** max number of query restarts. Determines max number of CNAME chain. */ /** max number of query restarts. Determines max number of CNAME chain. */
@ -83,7 +84,7 @@ struct iter_env {
struct iter_forwards* fwds; struct iter_forwards* fwds;
/** A set of inetaddrs that should never be queried. */ /** A set of inetaddrs that should never be queried. */
/* struct bla donotquery_addrs TODO */ struct iter_donotq* donotq;
/** The maximum dependency depth that this resolver will pursue. */ /** The maximum dependency depth that this resolver will pursue. */
int max_dependency_depth; int max_dependency_depth;

View file

@ -61,12 +61,7 @@ infra_host_compfunc(void* key1, void* key2)
{ {
struct infra_host_key* k1 = (struct infra_host_key*)key1; struct infra_host_key* k1 = (struct infra_host_key*)key1;
struct infra_host_key* k2 = (struct infra_host_key*)key2; struct infra_host_key* k2 = (struct infra_host_key*)key2;
if(k1->addrlen != k2->addrlen) { return sockaddr_cmp(&k1->addr, k1->addrlen, &k2->addr, k2->addrlen);
if(k1->addrlen < k2->addrlen)
return -1;
return 1;
}
return memcmp(&k1->addr, &k2->addr, k1->addrlen);
} }
/** delete key, and destroy the lock */ /** delete key, and destroy the lock */

View file

@ -69,49 +69,6 @@ static int serviced_udp_callback(struct comm_point* c, void* arg, int error,
static void serviced_tcp_initiate(struct outside_network* outnet, static void serviced_tcp_initiate(struct outside_network* outnet,
struct serviced_query* sq, ldns_buffer* buff); struct serviced_query* sq, ldns_buffer* buff);
/** compare sockaddr */
static int
sockaddr_cmp(struct sockaddr_storage* addr1, socklen_t len1,
struct sockaddr_storage* addr2, socklen_t len2)
{
struct sockaddr_in* p1_in = (struct sockaddr_in*)addr1;
struct sockaddr_in* p2_in = (struct sockaddr_in*)addr2;
struct sockaddr_in6* p1_in6 = (struct sockaddr_in6*)addr1;
struct sockaddr_in6* p2_in6 = (struct sockaddr_in6*)addr2;
if(len1 < len2)
return -1;
if(len1 > len2)
return 1;
log_assert(len1 == len2);
if( p1_in->sin_family < p2_in->sin_family)
return -1;
if( p1_in->sin_family > p2_in->sin_family)
return 1;
log_assert( p1_in->sin_family == p2_in->sin_family );
/* compare ip4 */
if( p1_in->sin_family == AF_INET ) {
/* just order it, ntohs not required */
if(p1_in->sin_port < p2_in->sin_port)
return -1;
if(p1_in->sin_port > p2_in->sin_port)
return 1;
log_assert(p1_in->sin_port == p2_in->sin_port);
return memcmp(&p1_in->sin_addr, &p2_in->sin_addr, INET_SIZE);
} else if (p1_in6->sin6_family == AF_INET6) {
/* just order it, ntohs not required */
if(p1_in6->sin6_port < p2_in6->sin6_port)
return -1;
if(p1_in6->sin6_port > p2_in6->sin6_port)
return 1;
log_assert(p1_in6->sin6_port == p2_in6->sin6_port);
return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr,
INET6_SIZE);
} else {
/* eek unknown type, perform this comparison for sanity. */
return memcmp(addr1, addr2, len1);
}
}
/** compare function of pending rbtree */ /** compare function of pending rbtree */
static int static int
pending_cmp(const void* key1, const void* key2) pending_cmp(const void* key1, const void* key2)

View file

@ -94,6 +94,11 @@ config_create()
if(!(cfg->logfile = strdup(""))) goto error_exit; if(!(cfg->logfile = strdup(""))) goto error_exit;
if(!(cfg->pidfile = strdup("unbound.pid"))) goto error_exit; if(!(cfg->pidfile = strdup("unbound.pid"))) goto error_exit;
if(!(cfg->target_fetch_policy = strdup("3 2 1 0 0"))) goto error_exit; if(!(cfg->target_fetch_policy = strdup("3 2 1 0 0"))) goto error_exit;
cfg->donotqueryaddrs = NULL;
if(!cfg_strlist_insert(&cfg->donotqueryaddrs, strdup("127.0.0.1")))
goto error_exit;
if(!cfg_strlist_insert(&cfg->donotqueryaddrs, strdup("::1")))
goto error_exit;
cfg->do_daemonize = 1; cfg->do_daemonize = 1;
cfg->num_ifs = 0; cfg->num_ifs = 0;
cfg->ifs = NULL; cfg->ifs = NULL;
@ -190,6 +195,7 @@ config_delete(struct config_file* cfg)
} }
config_delstubs(cfg->stubs); config_delstubs(cfg->stubs);
config_delstubs(cfg->forwards); config_delstubs(cfg->forwards);
config_delstrlist(cfg->donotqueryaddrs);
free(cfg); free(cfg);
} }
@ -224,3 +230,17 @@ int ub_c_wrap()
return 1; return 1;
} }
int
cfg_strlist_insert(struct config_strlist** head, char* item)
{
struct config_strlist *s;
if(!item || !head)
return 0;
s = (struct config_strlist*)calloc(1, sizeof(struct config_strlist));
if(!s)
return 0;
s->str = item;
s->next = *head;
*head = s;
return 1;
}

View file

@ -106,6 +106,8 @@ struct config_file {
struct config_stub* stubs; struct config_stub* stubs;
/** the forward zone definitions, linked list */ /** the forward zone definitions, linked list */
struct config_stub* forwards; struct config_stub* forwards;
/** list of donotquery addresses, linked list */
struct config_strlist* donotqueryaddrs;
/** harden against very small edns buffer sizes */ /** harden against very small edns buffer sizes */
int harden_short_bufsize; int harden_short_bufsize;
@ -171,6 +173,14 @@ int config_read(struct config_file* config, const char* filename);
*/ */
void config_delete(struct config_file* config); void config_delete(struct config_file* config);
/**
* Insert string into strlist.
* @param head: pointer to strlist head variable.
* @param item: new item. malloced by caller. If NULL the insertion fails.
* @return: true on success.
*/
int cfg_strlist_insert(struct config_strlist** head, char* item);
/** /**
* Used during options parsing * Used during options parsing
*/ */

View file

@ -135,6 +135,7 @@ stub-host{COLON} { YDOUT; return VAR_STUB_HOST;}
forward-zone{COLON} { YDOUT; return VAR_FORWARD_ZONE;} forward-zone{COLON} { YDOUT; return VAR_FORWARD_ZONE;}
forward-addr{COLON} { YDOUT; return VAR_FORWARD_ADDR;} forward-addr{COLON} { YDOUT; return VAR_FORWARD_ADDR;}
forward-host{COLON} { YDOUT; return VAR_FORWARD_HOST;} forward-host{COLON} { YDOUT; return VAR_FORWARD_HOST;}
do-not-query-address{COLON} { YDOUT; return VAR_DO_NOT_QUERY_ADDRESS;}
{NEWLINE} { LEXOUT(("NL\n")); cfg_parser->line++;} {NEWLINE} { LEXOUT(("NL\n")); cfg_parser->line++;}
/* Quoted strings. Strip leading and ending quotes */ /* Quoted strings. Strip leading and ending quotes */

View file

@ -78,6 +78,7 @@ extern struct config_parser_state* cfg_parser;
%token VAR_STUB_ZONE VAR_STUB_HOST VAR_STUB_ADDR VAR_TARGET_FETCH_POLICY %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_HARDEN_SHORT_BUFSIZE VAR_HARDEN_LARGE_QUERIES
%token VAR_FORWARD_ZONE VAR_FORWARD_HOST VAR_FORWARD_ADDR %token VAR_FORWARD_ZONE VAR_FORWARD_HOST VAR_FORWARD_ADDR
%token VAR_DO_NOT_QUERY_ADDRESS
%% %%
toplevelvars: /* empty */ | toplevelvars toplevelvar ; toplevelvars: /* empty */ | toplevelvars toplevelvar ;
@ -107,7 +108,8 @@ content_server: server_num_threads | server_verbosity | server_port |
server_infra_host_ttl | server_infra_lame_ttl | server_infra_host_ttl | server_infra_lame_ttl |
server_infra_cache_slabs | server_infra_cache_numhosts | server_infra_cache_slabs | server_infra_cache_numhosts |
server_infra_cache_numlame | server_target_fetch_policy | server_infra_cache_numlame | server_target_fetch_policy |
server_harden_short_bufsize | server_harden_large_queries server_harden_short_bufsize | server_harden_large_queries |
server_do_not_query_address
; ;
stubstart: VAR_STUB_ZONE stubstart: VAR_STUB_ZONE
{ {
@ -408,6 +410,13 @@ server_harden_large_queries: VAR_HARDEN_LARGE_QUERIES STRING
free($2); free($2);
} }
; ;
server_do_not_query_address: VAR_DO_NOT_QUERY_ADDRESS STRING
{
OUTYY(("P(server_do_not_query_address:%s)\n", $2));
if(!cfg_strlist_insert(&cfg_parser->cfg->donotqueryaddrs, $2))
yyerror("out of memory");
}
;
stub_name: VAR_NAME STRING stub_name: VAR_NAME STRING
{ {
OUTYY(("P(name:%s)\n", $2)); OUTYY(("P(name:%s)\n", $2));
@ -417,27 +426,15 @@ stub_name: VAR_NAME STRING
; ;
stub_host: VAR_STUB_HOST STRING stub_host: VAR_STUB_HOST STRING
{ {
struct config_strlist *s = (struct config_strlist*)calloc(1,
sizeof(struct config_strlist));
OUTYY(("P(stub-host:%s)\n", $2)); OUTYY(("P(stub-host:%s)\n", $2));
if(s) { if(!cfg_strlist_insert(&cfg_parser->cfg->stubs->hosts, $2))
s->str = $2;
s->next = cfg_parser->cfg->stubs->hosts;
cfg_parser->cfg->stubs->hosts = s;
} else
yyerror("out of memory"); yyerror("out of memory");
} }
; ;
stub_addr: VAR_STUB_ADDR STRING stub_addr: VAR_STUB_ADDR STRING
{ {
struct config_strlist *s = (struct config_strlist*)calloc(1,
sizeof(struct config_strlist));
OUTYY(("P(stub-addr:%s)\n", $2)); OUTYY(("P(stub-addr:%s)\n", $2));
if(s) { if(!cfg_strlist_insert(&cfg_parser->cfg->stubs->addrs, $2))
s->str = $2;
s->next = cfg_parser->cfg->stubs->addrs;
cfg_parser->cfg->stubs->addrs = s;
} else
yyerror("out of memory"); yyerror("out of memory");
} }
; ;
@ -450,27 +447,15 @@ forward_name: VAR_NAME STRING
; ;
forward_host: VAR_FORWARD_HOST STRING 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)); OUTYY(("P(forward-host:%s)\n", $2));
if(s) { if(!cfg_strlist_insert(&cfg_parser->cfg->forwards->hosts, $2))
s->str = $2;
s->next = cfg_parser->cfg->forwards->hosts;
cfg_parser->cfg->forwards->hosts = s;
} else
yyerror("out of memory"); yyerror("out of memory");
} }
; ;
forward_addr: VAR_FORWARD_ADDR STRING 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)); OUTYY(("P(forward-addr:%s)\n", $2));
if(s) { if(!cfg_strlist_insert(&cfg_parser->cfg->forwards->addrs, $2))
s->str = $2;
s->next = cfg_parser->cfg->forwards->addrs;
cfg_parser->cfg->forwards->addrs = s;
} else
yyerror("out of memory"); yyerror("out of memory");
} }
; ;

View file

@ -263,6 +263,48 @@ void log_name_addr(enum verbosity_value v, const char* str, uint8_t* zone,
str, namebuf, family, dest, (int)port); str, namebuf, family, dest, (int)port);
} }
int
sockaddr_cmp(struct sockaddr_storage* addr1, socklen_t len1,
struct sockaddr_storage* addr2, socklen_t len2)
{
struct sockaddr_in* p1_in = (struct sockaddr_in*)addr1;
struct sockaddr_in* p2_in = (struct sockaddr_in*)addr2;
struct sockaddr_in6* p1_in6 = (struct sockaddr_in6*)addr1;
struct sockaddr_in6* p2_in6 = (struct sockaddr_in6*)addr2;
if(len1 < len2)
return -1;
if(len1 > len2)
return 1;
log_assert(len1 == len2);
if( p1_in->sin_family < p2_in->sin_family)
return -1;
if( p1_in->sin_family > p2_in->sin_family)
return 1;
log_assert( p1_in->sin_family == p2_in->sin_family );
/* compare ip4 */
if( p1_in->sin_family == AF_INET ) {
/* just order it, ntohs not required */
if(p1_in->sin_port < p2_in->sin_port)
return -1;
if(p1_in->sin_port > p2_in->sin_port)
return 1;
log_assert(p1_in->sin_port == p2_in->sin_port);
return memcmp(&p1_in->sin_addr, &p2_in->sin_addr, INET_SIZE);
} else if (p1_in6->sin6_family == AF_INET6) {
/* just order it, ntohs not required */
if(p1_in6->sin6_port < p2_in6->sin6_port)
return -1;
if(p1_in6->sin6_port > p2_in6->sin6_port)
return 1;
log_assert(p1_in6->sin6_port == p2_in6->sin6_port);
return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr,
INET6_SIZE);
} else {
/* eek unknown type, perform this comparison for sanity. */
return memcmp(addr1, addr2, len1);
}
}
int int
addr_is_ip6(struct sockaddr_storage* addr) addr_is_ip6(struct sockaddr_storage* addr)
{ {

View file

@ -172,6 +172,17 @@ int ipstrtoaddr(const char* ip, int port, struct sockaddr_storage* addr,
void log_nametypeclass(enum verbosity_value v, const char* str, void log_nametypeclass(enum verbosity_value v, const char* str,
uint8_t* name, uint16_t type, uint16_t dclass); uint8_t* name, uint16_t type, uint16_t dclass);
/**
* Compare two sockaddrs. Imposes an ordering on the addresses.
* @param addr1: address 1.
* @param len1: lengths of addr1.
* @param addr2: address 2.
* @param len2: lengths of addr2.
* @return: 0 if addr1 == addr2. -1 if addr1 is smaller, +1 if larger.
*/
int sockaddr_cmp(struct sockaddr_storage* addr1, socklen_t len1,
struct sockaddr_storage* addr2, socklen_t len2);
/** /**
* Checkout address family. * Checkout address family.
* @param addr: the sockaddr to examine. * @param addr: the sockaddr to examine.