]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
Do not query addresses and configuration.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Wed, 18 Jul 2007 08:14:44 +0000 (08:14 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Wed, 18 Jul 2007 08:14:44 +0000 (08:14 +0000)
git-svn-id: file:///svn/unbound/trunk@434 be551aaa-1e26-0410-a405-d3ace91eadb9

18 files changed:
doc/Changelog
doc/TODO
doc/example.conf
doc/unbound.conf.5
iterator/iter_donotq.c [new file with mode: 0644]
iterator/iter_donotq.h [new file with mode: 0644]
iterator/iter_fwd.h
iterator/iter_utils.c
iterator/iterator.c
iterator/iterator.h
services/cache/infra.c
services/outside_network.c
util/config_file.c
util/config_file.h
util/configlexer.lex
util/configparser.y
util/net_help.c
util/net_help.h

index e97782f2341082419b6736cc7fe68f9a4ce3f3d3..555795af49450d692d69f9530dd1a6f770c15209 100644 (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
        - forward zone options in config file.
        - forward per zone in iterator. takes precendence over stubs.
index 3c1af63aaf7d3ef50d8ac29e1708c1248afe23e6..d8277ba0057073d6f37b962f551f5bade48c2e15 100644 (file)
--- a/doc/TODO
+++ b/doc/TODO
@@ -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 scrubber has slow pkt_subdomain and pkt_strict_subdomain functions.
 o get serverselection algorithm out of local optimum.
+o donotqueryaddresses allow specification of subnets, use trie to store.
index 9926bcd16c2b162ff3558c0c442b90b29769abbd..dbafea0d8dc090a08f647b263ed6c07b8d6118af 100644 (file)
@@ -122,10 +122,16 @@ server:
        # target-fetch-policy: "3 2 1 0 0"
        
        # Harden against very small EDNS buffer sizes. 
-       # harden_short_bufsize: no
+       # harden-short-bufsize: no
        
        # 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.
 # Create entries like below, to make all queries for 'example.com' and 
index 8ebc310479d3238c82e150a328312437b14d1f48..f5064e8b59386533a2157704ec72792af01b008f 100644 (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
 wise to send these, and could be necessary for operation if TSIG or EDNS
 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
 
 .Ss Stub Zone Options
diff --git a/iterator/iter_donotq.c b/iterator/iter_donotq.c
new file mode 100644 (file)
index 0000000..593ae0f
--- /dev/null
@@ -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;
+}
diff --git a/iterator/iter_donotq.h b/iterator/iter_donotq.h
new file mode 100644 (file)
index 0000000..70813f2
--- /dev/null
@@ -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 */
index c94f33e0dd0eb217f800ceef33b98109336d54f0..3d992b4e6379fd03b67949ab3ec8a54d71f5e58c 100644 (file)
@@ -105,7 +105,7 @@ void forwards_delete(struct iter_forwards* fwd);
 int forwards_apply_cfg(struct iter_forwards* fwd, struct config_file* cfg);
 
 /**
- * Find forward zone information
+ * Find 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.
  *
index 6986bb659f58cf2272bfd4437d6fd19c91319451..300c22e91acf2d3fbda075c92fd17bdef73d137e 100644 (file)
@@ -44,6 +44,7 @@
 #include "iterator/iterator.h"
 #include "iterator/iter_hints.h"
 #include "iterator/iter_fwd.h"
+#include "iterator/iter_donotq.h"
 #include "iterator/iter_delegpt.h"
 #include "services/cache/infra.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");
                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;
        return 1;
 }
@@ -149,9 +156,11 @@ iter_filter_unsuitable(struct iter_env* iter_env, struct module_env* env,
 {
        int rtt;
        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)) {
-               return -1;
+               return -1; /* there is no ip6 available */
        }
        /* check lameness - need zone , class info */
        if(infra_get_lame_rtt(env->infra_cache, &a->addr, a->addrlen, 
index 661add47d8eaa63604075df7f71dd955f7209962..f4bbee8abb57cd2fb875fbc20a9588c7bf68d873 100644 (file)
@@ -45,6 +45,7 @@
 #include "iterator/iter_utils.h"
 #include "iterator/iter_hints.h"
 #include "iterator/iter_fwd.h"
+#include "iterator/iter_donotq.h"
 #include "iterator/iter_delegpt.h"
 #include "iterator/iter_resptype.h"
 #include "iterator/iter_scrub.h"
@@ -86,6 +87,7 @@ iter_deinit(struct module_env* env, int id)
        free(iter_env->target_fetch_policy);
        hints_delete(iter_env->hints);
        forwards_delete(iter_env->fwds);
+       donotq_delete(iter_env->donotq);
        if(iter_env)
                free(iter_env);
 }
index e543e614dd3ebc04965979202dbf160c9221e72c..f6587900dedfce42a4818aeda33a93e3d7c30f21 100644 (file)
@@ -48,6 +48,7 @@ struct module_func_block;
 struct delegpt;
 struct iter_hints;
 struct iter_forwards;
+struct iter_donotq;
 struct iter_prep_list;
 
 /** max number of query restarts. Determines max number of CNAME chain. */
@@ -83,7 +84,7 @@ struct iter_env {
        struct iter_forwards* fwds;
 
        /** 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. */
        int max_dependency_depth;
index fcae6b53542e9825cb040966c6375ef7a7eaafe4..feac56e53108fd0f2ddc0a1be90df346dd773ef8 100644 (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* k2 = (struct infra_host_key*)key2;
-       if(k1->addrlen != k2->addrlen) {
-               if(k1->addrlen < k2->addrlen)
-                       return -1;
-               return 1;
-       }
-       return memcmp(&k1->addr, &k2->addr, k1->addrlen);
+       return sockaddr_cmp(&k1->addr, k1->addrlen, &k2->addr, k2->addrlen);
 }
 
 /** delete key, and destroy the lock */
index 1a1ba2c95c53f0294d5e7af9bd7f6bf51ff584f4..facc87cd72c58d2899007b15bdf1905915ec43b0 100644 (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, 
        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 */
 static int 
 pending_cmp(const void* key1, const void* key2)
index 3f5bbd49fa342f22cb4ee9579f1adedda1840d0c..c5300bd8b5743070f6c6e9c9add7323c0843b5b2 100644 (file)
@@ -94,6 +94,11 @@ config_create()
        if(!(cfg->logfile = strdup(""))) 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;
+       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->num_ifs = 0;
        cfg->ifs = NULL;
@@ -190,6 +195,7 @@ config_delete(struct config_file* cfg)
        }
        config_delstubs(cfg->stubs);
        config_delstubs(cfg->forwards);
+       config_delstrlist(cfg->donotqueryaddrs);
        free(cfg);
 }
 
@@ -224,3 +230,17 @@ int ub_c_wrap()
        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;
+}
index f141d76278df711291aac7404ec6656bebe831b9..c49fb7b1182dfdb300d3a3c6fc81b9332a8f41e8 100644 (file)
@@ -106,6 +106,8 @@ struct config_file {
        struct config_stub* stubs;
        /** the forward zone definitions, linked list */
        struct config_stub* forwards;
+       /** list of donotquery addresses, linked list */
+       struct config_strlist* donotqueryaddrs;
 
        /** harden against very small edns buffer sizes */
        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);
 
+/**
+ * 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
  */
index e93989de0c1c56f6cca00f9fdc4a94f54889f1f6..a5ba7432cb5b9d4d3bb56de037fae0fb58ad600a 100644 (file)
@@ -135,6 +135,7 @@ 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;}
+do-not-query-address{COLON}    { YDOUT; return VAR_DO_NOT_QUERY_ADDRESS;}
 {NEWLINE}              { LEXOUT(("NL\n")); cfg_parser->line++;}
 
        /* Quoted strings. Strip leading and ending quotes */
index 0e32bb71f560962ddb6a47b2120b478c582f574b..38335eefc93926eee9411b4c6c32e101a5a3bf50 100644 (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_HARDEN_SHORT_BUFSIZE VAR_HARDEN_LARGE_QUERIES
 %token VAR_FORWARD_ZONE VAR_FORWARD_HOST VAR_FORWARD_ADDR
+%token VAR_DO_NOT_QUERY_ADDRESS
 
 %%
 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_cache_slabs | server_infra_cache_numhosts |
        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
        {
@@ -408,6 +410,13 @@ server_harden_large_queries: VAR_HARDEN_LARGE_QUERIES STRING
                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
        {
                OUTYY(("P(name:%s)\n", $2));
@@ -417,27 +426,15 @@ stub_name: VAR_NAME 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));
-               if(s) {
-                       s->str = $2;
-                       s->next = cfg_parser->cfg->stubs->hosts;
-                       cfg_parser->cfg->stubs->hosts = s;
-               } else
+               if(!cfg_strlist_insert(&cfg_parser->cfg->stubs->hosts, $2))
                        yyerror("out of memory");
        }
        ;
 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));
-               if(s) {
-                       s->str = $2;
-                       s->next = cfg_parser->cfg->stubs->addrs;
-                       cfg_parser->cfg->stubs->addrs = s;
-               } else
+               if(!cfg_strlist_insert(&cfg_parser->cfg->stubs->addrs, $2))
                        yyerror("out of memory");
        }
        ;
@@ -450,27 +447,15 @@ forward_name: VAR_NAME 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));
-               if(s) {
-                       s->str = $2;
-                       s->next = cfg_parser->cfg->forwards->hosts;
-                       cfg_parser->cfg->forwards->hosts = s;
-               } else
+               if(!cfg_strlist_insert(&cfg_parser->cfg->forwards->hosts, $2))
                        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
+               if(!cfg_strlist_insert(&cfg_parser->cfg->forwards->addrs, $2))
                        yyerror("out of memory");
        }
        ;
index 6656398aaa6aaf0b3f9efe9edf4362348880e6fd..8d46fe0d8c367461bedda0a3f34dd65cf376baa1 100644 (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);
 }
 
+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
 addr_is_ip6(struct sockaddr_storage* addr)
 {
index 681f568b9303c398012c37905eaa3d7fa7762238..9e543e484573f9ab5667cccdd0f9bdb034844680 100644 (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, 
        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.
  * @param addr: the sockaddr to examine.