mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-08-17 21:25:50 +02:00
Compare commits
28
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e12d274954 | ||
|
|
9ade3e4811 | ||
|
|
2c2eaecc6c | ||
|
|
16906c53e6 | ||
|
|
b6d9b4bfcc | ||
|
|
6bb12a5776 | ||
|
|
bce6c3405b | ||
|
|
aa0c26ddec | ||
|
|
a1cbd214a5 | ||
|
|
f64778a893 | ||
|
|
9d3b5fa30d | ||
|
|
99590f93bd | ||
|
|
b72563dcb7 | ||
|
|
6b0cf42b32 | ||
|
|
8df2959959 | ||
|
|
1cda904545 | ||
|
|
416129dedb | ||
|
|
b9c417481b | ||
|
|
eda6528c14 | ||
|
|
fc8657c421 | ||
|
|
5f50f5d2b4 | ||
|
|
31f803201d | ||
|
|
ff975871ab | ||
|
|
99a9914605 | ||
|
|
435fbd1794 | ||
|
|
fe09abe4e6 | ||
|
|
e900e44f9f | ||
|
|
bfbac6bb36 |
+3
-3
@@ -33,7 +33,7 @@ configfile=@ub_conf_file@
|
||||
YACC=@YACC@
|
||||
LEX=@LEX@
|
||||
CC=@CC@
|
||||
CPPFLAGS=-I$(srcdir) -I. @CPPFLAGS@ @DEFS@
|
||||
CPPFLAGS=-I$(srcdir) @CPPFLAGS@ @DEFS@
|
||||
CFLAGS=@CFLAGS@
|
||||
LDFLAGS=@LDFLAGS@
|
||||
LIBS=@LIBS@
|
||||
@@ -71,8 +71,8 @@ DAEMON_OBJ=$(addprefix $(BUILD),$(DAEMON_SRC:.c=.o)) $(COMPAT_OBJ)
|
||||
CHECKCONF_SRC=checkconf/unbound-checkconf.c checkconf/worker_cb.c $(COMMON_SRC)
|
||||
CHECKCONF_OBJ=$(addprefix $(BUILD),$(CHECKCONF_SRC:.c=.o)) $(COMPAT_OBJ)
|
||||
TESTBOUND_SRC=testcode/testbound.c testcode/ldns-testpkts.c \
|
||||
daemon/worker.c daemon/daemon.c daemon/stats.c testcode/replay.c \
|
||||
testcode/fake_event.c $(filter-out util/netevent.c \
|
||||
daemon/worker.c daemon/acl_list.c daemon/daemon.c daemon/stats.c \
|
||||
testcode/replay.c testcode/fake_event.c $(filter-out util/netevent.c \
|
||||
services/listen_dnsport.c services/outside_network.c, $(COMMON_SRC))
|
||||
TESTBOUND_OBJ=$(addprefix $(BUILD),$(TESTBOUND_SRC:.c=.o)) $(COMPAT_OBJ)
|
||||
LOCKVERIFY_SRC=testcode/lock_verify.c checkconf/worker_cb.c $(COMMON_SRC)
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
#include "util/regional.h"
|
||||
#include "iterator/iterator.h"
|
||||
#include "validator/validator.h"
|
||||
#include "services/localzone.h"
|
||||
#include <pwd.h>
|
||||
|
||||
/** Give checkconf usage, and exit (1). */
|
||||
@@ -92,6 +93,8 @@ morechecks(struct config_file* cfg)
|
||||
int i;
|
||||
struct sockaddr_storage a;
|
||||
socklen_t alen;
|
||||
struct config_str2list* acl;
|
||||
struct local_zones* zs;
|
||||
for(i=0; i<cfg->num_ifs; i++) {
|
||||
if(!ipstrtoaddr(cfg->ifs[i], UNBOUND_DNS_PORT, &a, &alen)) {
|
||||
fatal_exit("cannot parse interface specified as '%s'",
|
||||
@@ -105,6 +108,13 @@ morechecks(struct config_file* cfg)
|
||||
"specified as '%s'", cfg->out_ifs[i]);
|
||||
}
|
||||
}
|
||||
for(acl=cfg->acls; acl; acl = acl->next) {
|
||||
if(!netblockstrtoaddr(acl->str, UNBOUND_DNS_PORT, &a, &alen,
|
||||
&i)) {
|
||||
fatal_exit("cannot parse access control address %s %s",
|
||||
acl->str, acl->str2);
|
||||
}
|
||||
}
|
||||
|
||||
if(cfg->verbosity < 0)
|
||||
fatal_exit("verbosity value < 0");
|
||||
@@ -132,7 +142,7 @@ morechecks(struct config_file* cfg)
|
||||
|
||||
if(strcmp(cfg->module_conf, "iterator") != 0 &&
|
||||
strcmp(cfg->module_conf, "validator iterator") != 0) {
|
||||
fatal_exit("module conf %s is not known to work",
|
||||
fatal_exit("module conf '%s' is not known to work",
|
||||
cfg->module_conf);
|
||||
}
|
||||
|
||||
@@ -142,6 +152,13 @@ morechecks(struct config_file* cfg)
|
||||
fatal_exit("user '%s' does not exist.", cfg->username);
|
||||
endpwent();
|
||||
}
|
||||
|
||||
if(!(zs = local_zones_create()))
|
||||
fatal_exit("out of memory");
|
||||
if(!local_zones_apply_cfg(zs, cfg))
|
||||
fatal_exit("failed local-zone, local-data configuration");
|
||||
local_zones_print(zs); /* @@@ DEBUG */
|
||||
local_zones_delete(zs);
|
||||
}
|
||||
|
||||
/** check config file */
|
||||
|
||||
@@ -107,3 +107,10 @@ worker_alloc_cleanup(void* ATTR_UNUSED(arg))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
int
|
||||
acl_list_cmp(const void* ATTR_UNUSED(k1), const void* ATTR_UNUSED(k2))
|
||||
{
|
||||
log_assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.61 for unbound 0.7.2.
|
||||
# Generated by GNU Autoconf 2.61 for unbound 0.8.
|
||||
#
|
||||
# Report bugs to <unbound-bugs@nlnetlabs.nl>.
|
||||
#
|
||||
@@ -724,8 +724,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
|
||||
# Identity of this package.
|
||||
PACKAGE_NAME='unbound'
|
||||
PACKAGE_TARNAME='unbound'
|
||||
PACKAGE_VERSION='0.7.2'
|
||||
PACKAGE_STRING='unbound 0.7.2'
|
||||
PACKAGE_VERSION='0.8'
|
||||
PACKAGE_STRING='unbound 0.8'
|
||||
PACKAGE_BUGREPORT='unbound-bugs@nlnetlabs.nl'
|
||||
|
||||
# Factoring default headers for most tests.
|
||||
@@ -1358,7 +1358,7 @@ if test "$ac_init_help" = "long"; then
|
||||
# Omit some internal or obsolete options to make the list less imposing.
|
||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||
cat <<_ACEOF
|
||||
\`configure' configures unbound 0.7.2 to adapt to many kinds of systems.
|
||||
\`configure' configures unbound 0.8 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
@@ -1423,7 +1423,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of unbound 0.7.2:";;
|
||||
short | recursive ) echo "Configuration of unbound 0.8:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@@ -1544,7 +1544,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
unbound configure 0.7.2
|
||||
unbound configure 0.8
|
||||
generated by GNU Autoconf 2.61
|
||||
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
|
||||
@@ -1558,7 +1558,7 @@ cat >config.log <<_ACEOF
|
||||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
|
||||
It was created by unbound $as_me 0.7.2, which was
|
||||
It was created by unbound $as_me 0.8, which was
|
||||
generated by GNU Autoconf 2.61. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
@@ -24974,7 +24974,7 @@ exec 6>&1
|
||||
# report actual input values of CONFIG_FILES etc. instead of their
|
||||
# values after options handling.
|
||||
ac_log="
|
||||
This file was extended by unbound $as_me 0.7.2, which was
|
||||
This file was extended by unbound $as_me 0.8, which was
|
||||
generated by GNU Autoconf 2.61. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@@ -25023,7 +25023,7 @@ Report bugs to <bug-autoconf@gnu.org>."
|
||||
_ACEOF
|
||||
cat >>$CONFIG_STATUS <<_ACEOF
|
||||
ac_cs_version="\\
|
||||
unbound config.status 0.7.2
|
||||
unbound config.status 0.8
|
||||
configured by $0, generated by GNU Autoconf 2.61,
|
||||
with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
|
||||
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
AC_PREREQ(2.57)
|
||||
|
||||
AC_INIT(unbound, 0.7.2, unbound-bugs@nlnetlabs.nl, unbound)
|
||||
AC_INIT(unbound, 0.8, unbound-bugs@nlnetlabs.nl, unbound)
|
||||
|
||||
CFLAGS=
|
||||
AC_AIX
|
||||
|
||||
@@ -0,0 +1,246 @@
|
||||
/*
|
||||
* daemon/acl_list.h - client access control storage for the server.
|
||||
*
|
||||
* 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 helps the server keep out queries from outside sources, that
|
||||
* should not be answered.
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "daemon/acl_list.h"
|
||||
#include "util/regional.h"
|
||||
#include "util/log.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/net_help.h"
|
||||
|
||||
int
|
||||
acl_list_cmp(const void* k1, const void* k2)
|
||||
{
|
||||
struct acl_addr* n1 = (struct acl_addr*)k1;
|
||||
struct acl_addr* n2 = (struct acl_addr*)k2;
|
||||
int r = sockaddr_cmp_addr(&n1->addr, n1->addrlen, &n2->addr,
|
||||
n2->addrlen);
|
||||
if(r != 0) return r;
|
||||
if(n1->net < n2->net)
|
||||
return -1;
|
||||
if(n1->net > n2->net)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct acl_list*
|
||||
acl_list_create()
|
||||
{
|
||||
struct acl_list* acl = (struct acl_list*)calloc(1,
|
||||
sizeof(struct acl_list));
|
||||
if(!acl)
|
||||
return NULL;
|
||||
acl->region = regional_create();
|
||||
if(!acl->region) {
|
||||
acl_list_delete(acl);
|
||||
return NULL;
|
||||
}
|
||||
return acl;
|
||||
}
|
||||
|
||||
void
|
||||
acl_list_delete(struct acl_list* acl)
|
||||
{
|
||||
if(!acl)
|
||||
return;
|
||||
regional_destroy(acl->region);
|
||||
free(acl->tree);
|
||||
free(acl);
|
||||
}
|
||||
|
||||
/** insert new address into acl_list structure */
|
||||
static int
|
||||
acl_list_insert(struct acl_list* acl, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, int net, enum acl_access control,
|
||||
int complain_duplicates)
|
||||
{
|
||||
struct acl_addr* node = regional_alloc(acl->region,
|
||||
sizeof(struct acl_addr));
|
||||
if(!node)
|
||||
return 0;
|
||||
node->node.key = node;
|
||||
memcpy(&node->addr, addr, addrlen);
|
||||
node->addrlen = addrlen;
|
||||
node->net = net;
|
||||
node->parent = NULL;
|
||||
node->control = control;
|
||||
if(!rbtree_insert(acl->tree, &node->node)) {
|
||||
if(complain_duplicates)
|
||||
verbose(VERB_DETAIL, "duplicate acl address ignored.");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** apply acl_list string */
|
||||
static int
|
||||
acl_list_str_cfg(struct acl_list* acl, const char* str, const char* s2,
|
||||
int complain_duplicates)
|
||||
{
|
||||
struct sockaddr_storage addr;
|
||||
int net;
|
||||
socklen_t addrlen;
|
||||
enum acl_access control;
|
||||
if(strcmp(s2, "allow") == 0)
|
||||
control = acl_allow;
|
||||
else if(strcmp(s2, "deny") == 0)
|
||||
control = acl_deny;
|
||||
else if(strcmp(s2, "refuse") == 0)
|
||||
control = acl_refuse;
|
||||
else {
|
||||
log_err("access control type %s unknown", str);
|
||||
return 0;
|
||||
}
|
||||
if(!netblockstrtoaddr(str, UNBOUND_DNS_PORT, &addr, &addrlen, &net)) {
|
||||
log_err("cannot parse access control: %s %s", str, s2);
|
||||
return 0;
|
||||
}
|
||||
if(!acl_list_insert(acl, &addr, addrlen, net, control,
|
||||
complain_duplicates)) {
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** read acl_list config */
|
||||
static int
|
||||
read_acl_list(struct acl_list* acl, struct config_file* cfg)
|
||||
{
|
||||
struct config_str2list* p;
|
||||
for(p = cfg->acls; p; p = p->next) {
|
||||
log_assert(p->str && p->str2);
|
||||
if(!acl_list_str_cfg(acl, p->str, p->str2, 1))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** initialise parent pointers in the tree */
|
||||
static void
|
||||
acl_list_init_parents(struct acl_list* acl)
|
||||
{
|
||||
struct acl_addr* node, *prev = NULL, *p;
|
||||
int m;
|
||||
RBTREE_FOR(node, struct acl_addr*, acl->tree) {
|
||||
node->parent = NULL;
|
||||
if(!prev || prev->addrlen != node->addrlen) {
|
||||
prev = node;
|
||||
continue;
|
||||
}
|
||||
m = addr_in_common(&prev->addr, prev->net, &node->addr,
|
||||
node->net, node->addrlen);
|
||||
/* sort order like: ::/0, 1::/2, 1::/4, ... 2::/2 */
|
||||
/* find the previous, or parent-parent-parent */
|
||||
for(p = prev; p; p = p->parent)
|
||||
if(p->net <= 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;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg)
|
||||
{
|
||||
regional_free_all(acl->region);
|
||||
free(acl->tree);
|
||||
acl->tree = rbtree_create(acl_list_cmp);
|
||||
if(!acl->tree)
|
||||
return 0;
|
||||
if(!read_acl_list(acl, cfg))
|
||||
return 0;
|
||||
/* insert defaults, with '0' to ignore them if they are duplicates */
|
||||
if(!acl_list_str_cfg(acl, "0.0.0.0/0", "refuse", 0))
|
||||
return 0;
|
||||
if(!acl_list_str_cfg(acl, "::0/0", "refuse", 0))
|
||||
return 0;
|
||||
if(!acl_list_str_cfg(acl, "127.0.0.0/8", "allow", 0))
|
||||
return 0;
|
||||
if(!acl_list_str_cfg(acl, "::1", "allow", 0))
|
||||
return 0;
|
||||
acl_list_init_parents(acl);
|
||||
return 1;
|
||||
}
|
||||
|
||||
enum acl_access
|
||||
acl_list_lookup(struct acl_list* acl, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen)
|
||||
{
|
||||
/* lookup in the tree */
|
||||
rbnode_t* res = NULL;
|
||||
struct acl_addr* result;
|
||||
struct acl_addr key;
|
||||
key.node.key = &key;
|
||||
memcpy(&key.addr, addr, addrlen);
|
||||
key.addrlen = addrlen;
|
||||
key.net = (addr_is_ip6(addr, addrlen)?128:32);
|
||||
if(rbtree_find_less_equal(acl->tree, &key, &res)) {
|
||||
/* exact */
|
||||
result = (struct acl_addr*)res;
|
||||
return result->control;
|
||||
} else {
|
||||
/* smaller element (or no element) */
|
||||
int m;
|
||||
result = (struct acl_addr*)res;
|
||||
if(!result || result->addrlen != addrlen)
|
||||
return acl_deny;
|
||||
/* count number of bits matched */
|
||||
m = addr_in_common(&result->addr, result->net, addr,
|
||||
key.net, addrlen);
|
||||
while(result) { /* go up until addr is inside netblock */
|
||||
if(result->net <= m)
|
||||
return result->control;
|
||||
result = result->parent;
|
||||
}
|
||||
}
|
||||
return acl_deny;
|
||||
}
|
||||
|
||||
size_t
|
||||
acl_list_get_mem(struct acl_list* acl)
|
||||
{
|
||||
if(!acl) return 0;
|
||||
return sizeof(*acl) + regional_get_mem(acl->region);
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* daemon/acl_list.h - client access control storage for the server.
|
||||
*
|
||||
* 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 keeps track of the list of clients that are allowed to
|
||||
* access the server.
|
||||
*/
|
||||
|
||||
#ifndef DAEMON_ACL_LIST_H
|
||||
#define DAEMON_ACL_LIST_H
|
||||
#include "util/rbtree.h"
|
||||
struct config_file;
|
||||
struct regional;
|
||||
|
||||
/**
|
||||
* Enumeration of access control options for an address range.
|
||||
* Allow or deny access.
|
||||
*/
|
||||
enum acl_access {
|
||||
/** disallow any access whatsoever, drop it */
|
||||
acl_deny = 0,
|
||||
/** disallow access, send a polite 'REFUSED' reply */
|
||||
acl_refuse,
|
||||
/** allow full access */
|
||||
acl_allow
|
||||
};
|
||||
|
||||
/**
|
||||
* Access control storage structure
|
||||
*/
|
||||
struct acl_list {
|
||||
/** regional for allocation */
|
||||
struct regional* region;
|
||||
/**
|
||||
* Tree of the addresses that are allowed/blocked.
|
||||
* contents of type acl_addr.
|
||||
*/
|
||||
rbtree_t* tree;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* An address span with access control information
|
||||
*/
|
||||
struct acl_addr {
|
||||
/** redblacktree node, key is this structure: addr and addrlen, net */
|
||||
rbnode_t node;
|
||||
/** address */
|
||||
struct sockaddr_storage addr;
|
||||
/** length of addr */
|
||||
socklen_t addrlen;
|
||||
/** netblock size */
|
||||
int net;
|
||||
/** parent node in acl tree that encompasses this entry */
|
||||
struct acl_addr* parent;
|
||||
/** access control on this netblock */
|
||||
enum acl_access control;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create acl structure
|
||||
* @return new structure or NULL on error.
|
||||
*/
|
||||
struct acl_list* acl_list_create();
|
||||
|
||||
/**
|
||||
* Delete acl structure.
|
||||
* @param acl: to delete.
|
||||
*/
|
||||
void acl_list_delete(struct acl_list* acl);
|
||||
|
||||
/**
|
||||
* Process access control config.
|
||||
* @param acl: where to store.
|
||||
* @param cfg: config options.
|
||||
* @return 0 on error.
|
||||
*/
|
||||
int acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg);
|
||||
|
||||
/**
|
||||
* Lookup address to see its access control status.
|
||||
* @param acl: structure for address storage.
|
||||
* @param addr: address to check
|
||||
* @param addrlen: length of addr.
|
||||
* @return: what to do with message from this address.
|
||||
*/
|
||||
enum acl_access acl_list_lookup(struct acl_list* acl,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen);
|
||||
|
||||
/**
|
||||
* Get memory used by acl structure.
|
||||
* @param acl: structure for address storage.
|
||||
* @return bytes in use.
|
||||
*/
|
||||
size_t acl_list_get_mem(struct acl_list* acl);
|
||||
|
||||
/** compare two acl list entries */
|
||||
int acl_list_cmp(const void* k1, const void* k2);
|
||||
|
||||
#endif /* DAEMON_ACL_LIST_H */
|
||||
+20
-1
@@ -42,6 +42,7 @@
|
||||
#include "config.h"
|
||||
#include "daemon/daemon.h"
|
||||
#include "daemon/worker.h"
|
||||
#include "daemon/acl_list.h"
|
||||
#include "util/log.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/data/msgreply.h"
|
||||
@@ -49,6 +50,7 @@
|
||||
#include "services/listen_dnsport.h"
|
||||
#include "services/cache/rrset.h"
|
||||
#include "services/cache/infra.h"
|
||||
#include "services/localzone.h"
|
||||
#include "util/module.h"
|
||||
#include "iterator/iterator.h"
|
||||
#include "validator/validator.h"
|
||||
@@ -134,6 +136,12 @@ daemon_init()
|
||||
return NULL;
|
||||
}
|
||||
alloc_init(&daemon->superalloc, NULL, 0);
|
||||
daemon->acl = acl_list_create();
|
||||
if(!daemon->acl) {
|
||||
free(daemon->env);
|
||||
free(daemon);
|
||||
return NULL;
|
||||
}
|
||||
return daemon;
|
||||
}
|
||||
|
||||
@@ -273,7 +281,8 @@ static void daemon_setup_modules(struct daemon* daemon)
|
||||
daemon->env->worker = NULL;
|
||||
daemon->env->need_to_validate = 0; /* set by module init below */
|
||||
for(i=0; i<daemon->num_modules; i++) {
|
||||
log_info("init module %d: %s", i, daemon->modfunc[i]->name);
|
||||
verbose(VERB_OPS, "init module %d: %s",
|
||||
i, daemon->modfunc[i]->name);
|
||||
log_assert(fptr_whitelist_mod_init(daemon->modfunc[i]->init));
|
||||
if(!(*daemon->modfunc[i]->init)(daemon->env, i)) {
|
||||
fatal_exit("module init for module %s failed",
|
||||
@@ -397,6 +406,12 @@ void
|
||||
daemon_fork(struct daemon* daemon)
|
||||
{
|
||||
log_assert(daemon);
|
||||
if(!acl_list_apply_cfg(daemon->acl, daemon->cfg))
|
||||
fatal_exit("Could not setup access control list");
|
||||
if(!(daemon->local_zones = local_zones_create()))
|
||||
fatal_exit("Could not create local zones: out of memory");
|
||||
if(!local_zones_apply_cfg(daemon->local_zones, daemon->cfg))
|
||||
fatal_exit("Could not set up local zones");
|
||||
|
||||
/* setup modules */
|
||||
daemon_setup_modules(daemon);
|
||||
@@ -421,6 +436,7 @@ daemon_fork(struct daemon* daemon)
|
||||
/* Start resolver service on main thread. */
|
||||
log_info("start of service (%s).", PACKAGE_STRING);
|
||||
worker_work(daemon->workers[0]);
|
||||
log_info("service stopped (%s).", PACKAGE_STRING);
|
||||
|
||||
/* we exited! a signal happened! Stop other threads */
|
||||
daemon_stop_others(daemon);
|
||||
@@ -443,6 +459,8 @@ daemon_cleanup(struct daemon* daemon)
|
||||
* The infra cache is kept, the timing and edns info is still valid */
|
||||
slabhash_clear(&daemon->env->rrset_cache->table);
|
||||
slabhash_clear(daemon->env->msg_cache);
|
||||
local_zones_delete(daemon->local_zones);
|
||||
daemon->local_zones = NULL;
|
||||
/* key cache is cleared by module desetup during next daemon_init() */
|
||||
for(i=0; i<daemon->num; i++)
|
||||
worker_delete(daemon->workers[i]);
|
||||
@@ -465,6 +483,7 @@ daemon_delete(struct daemon* daemon)
|
||||
infra_delete(daemon->env->infra_cache);
|
||||
}
|
||||
alloc_clear(&daemon->superalloc);
|
||||
acl_list_delete(daemon->acl);
|
||||
free(daemon->pidfile);
|
||||
free(daemon->env);
|
||||
free(daemon);
|
||||
|
||||
@@ -50,6 +50,8 @@ struct listen_port;
|
||||
struct slabhash;
|
||||
struct module_env;
|
||||
struct rrset_cache;
|
||||
struct acl_list;
|
||||
struct local_zones;
|
||||
|
||||
/**
|
||||
* Structure holding worker list.
|
||||
@@ -78,6 +80,10 @@ struct daemon {
|
||||
int num_modules;
|
||||
/** the module callbacks, array of num_modules length */
|
||||
struct module_func_block** modfunc;
|
||||
/** access control, which client IPs are allowed to connect */
|
||||
struct acl_list* acl;
|
||||
/** local authority zones */
|
||||
struct local_zones* local_zones;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
+2
-2
@@ -339,8 +339,8 @@ run_daemon(char* cfgfile, int cmdline_verbose, int debug_mode)
|
||||
fatal_exit("alloc failure");
|
||||
while(!daemon->need_to_exit) {
|
||||
if(done_chroot)
|
||||
log_info("Restart of %s.", PACKAGE_STRING);
|
||||
else log_info("Start of %s.", PACKAGE_STRING);
|
||||
verbose(VERB_OPS, "Restart of %s.", PACKAGE_STRING);
|
||||
else verbose(VERB_OPS, "Start of %s.", PACKAGE_STRING);
|
||||
|
||||
/* config stuff */
|
||||
if(!(cfg = config_create()))
|
||||
|
||||
+26
-3
@@ -45,6 +45,7 @@
|
||||
#include "util/random.h"
|
||||
#include "daemon/worker.h"
|
||||
#include "daemon/daemon.h"
|
||||
#include "daemon/acl_list.h"
|
||||
#include "util/netevent.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/module.h"
|
||||
@@ -57,6 +58,7 @@
|
||||
#include "services/cache/infra.h"
|
||||
#include "services/cache/dns.h"
|
||||
#include "services/mesh.h"
|
||||
#include "services/localzone.h"
|
||||
#include "util/data/msgparse.h"
|
||||
#include "util/data/msgencode.h"
|
||||
#include "util/data/dname.h"
|
||||
@@ -663,12 +665,28 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
struct lruhash_entry* e;
|
||||
struct query_info qinfo;
|
||||
struct edns_data edns;
|
||||
enum acl_access acl;
|
||||
|
||||
if(error != NETEVENT_NOERROR) {
|
||||
/* some bad tcp query DNS formats give these error calls */
|
||||
verbose(VERB_ALGO, "handle request called with err=%d", error);
|
||||
return 0;
|
||||
}
|
||||
acl = acl_list_lookup(worker->daemon->acl, &repinfo->addr,
|
||||
repinfo->addrlen);
|
||||
if(acl == acl_deny) {
|
||||
comm_point_drop_reply(repinfo);
|
||||
return 0;
|
||||
} else if(acl == acl_refuse) {
|
||||
ldns_buffer_set_limit(c->buffer, LDNS_HEADER_SIZE);
|
||||
ldns_buffer_write_at(c->buffer, 4,
|
||||
(uint8_t*)"\0\0\0\0\0\0\0\0", 8);
|
||||
LDNS_QR_SET(ldns_buffer_begin(c->buffer));
|
||||
LDNS_RCODE_SET(ldns_buffer_begin(c->buffer),
|
||||
LDNS_RCODE_REFUSED);
|
||||
log_buf(VERB_ALGO, "refuse", c->buffer);
|
||||
return 1;
|
||||
}
|
||||
if((ret=worker_check_request(c->buffer, worker)) != 0) {
|
||||
verbose(VERB_ALGO, "worker check request: bad query.");
|
||||
if(ret != -1) {
|
||||
@@ -738,6 +756,10 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
&edns, c->buffer)) {
|
||||
return 1;
|
||||
}
|
||||
if(local_zones_answer(worker->daemon->local_zones, &qinfo, &edns,
|
||||
c->buffer, worker->scratchpad)) {
|
||||
return (ldns_buffer_limit(c->buffer) != 0);
|
||||
}
|
||||
h = query_info_hash(&qinfo);
|
||||
if((e=slabhash_lookup(worker->env.msg_cache, h, &qinfo, 0))) {
|
||||
/* answer from cache - we have acquired a readlock on it */
|
||||
@@ -971,10 +993,11 @@ worker_delete(struct worker* worker)
|
||||
{
|
||||
if(!worker)
|
||||
return;
|
||||
if(worker->env.mesh)
|
||||
if(worker->env.mesh && verbosity >= VERB_OPS) {
|
||||
mesh_stats(worker->env.mesh, "mesh has");
|
||||
server_stats_log(&worker->stats, worker->thread_num);
|
||||
worker_mem_report(worker, NULL);
|
||||
server_stats_log(&worker->stats, worker->thread_num);
|
||||
worker_mem_report(worker, NULL);
|
||||
}
|
||||
mesh_delete(worker->env.mesh);
|
||||
ldns_buffer_free(worker->env.scratch_buffer);
|
||||
listen_delete(worker->front);
|
||||
|
||||
+71
-11
@@ -1,16 +1,76 @@
|
||||
3 December 2007: Wouter
|
||||
- Fixup building in a subdirectory. (for 0.7.2)
|
||||
28 November 2007: Wouter
|
||||
- Changeup plan for 0.8 - no complication needed, a simple solution
|
||||
has been chosen for authoritative features.
|
||||
- you can use single quotes in the config file, so it is possible
|
||||
to specify TXT records in local data.
|
||||
- fixup small memory problem in implicit transparent zone creation.
|
||||
- test for implicit zone creation and multiple RR RRsets local data.
|
||||
- local-zone nodefault test.
|
||||
- show testbound testlist on commit.
|
||||
- iterator normalizer changes CNAME chains ending in NXDOMAIN where
|
||||
the packet got rcode NXDOMAIN into rcode NOERROR. (since the initial
|
||||
domain exists).
|
||||
- nicer verbosity: 0 and 1 levels.
|
||||
- lower nonRDquery chance of eliciting wrongly typed validation
|
||||
requiring message from the cache.
|
||||
- fix for nonRDquery validation typing; nodata is detected when
|
||||
SOA record in auth section (all validation-requiring nodata messages
|
||||
have a SOA record in authority, so this is OK for the validator),
|
||||
and NS record is needed to be a referral.
|
||||
- duplicate checking when adding NSECs for a CNAME, and test.
|
||||
|
||||
27 November 2007: Wouter
|
||||
- per suggestion in rfc2308, replaced default max-ttl value with 1 day.
|
||||
- set size of msgparse lookup table to 32, from 1024, so that its size
|
||||
is below the 2048 regional large size threshold, and does not cause
|
||||
a call to malloc when a message is parsed.
|
||||
- update of memstats tool to print number of allocation calls.
|
||||
This is what is taking time (not space) and indicates the avg size
|
||||
of the allocations as well. region_alloc stat is removed.
|
||||
|
||||
22 November 2007: Wouter
|
||||
- noted EDNS in-the-middle dropping trouble as a TODO.
|
||||
At this point theoretical, no user trouble has been reported.
|
||||
- added all default AS112 zones.
|
||||
- answers from local zone content.
|
||||
* positive answer, the rrset in question
|
||||
* nodata answer (exist, but not that type).
|
||||
* nxdomain answer (domain does not exist).
|
||||
* empty-nonterminal answer.
|
||||
* But not: wildcard, nsec, referral, rrsig, cname/dname,
|
||||
or additional section processing, NS put in auth.
|
||||
- test for correct working of static and transparent and couple
|
||||
of important defaults (localhost, as112, reverses).
|
||||
Also checks deny and refuse settings.
|
||||
- fixup implicit zone generation and AA bit for NXDOMAIN on localdata.
|
||||
|
||||
21 November 2007: Wouter
|
||||
- local zone internal data setup.
|
||||
|
||||
20 November 2007: Wouter
|
||||
- 0.8 - str2list config support for double string config options.
|
||||
- local-zone and local-data options, config storage and documentation.
|
||||
|
||||
19 November 2007: Wouter
|
||||
- version 0.7.1:
|
||||
* includes tpkg fixes to kill daemons at end of test
|
||||
* includes NSEC/RRSIG not downcasing fixup from
|
||||
dnssec-bis-updates draft-06.
|
||||
* README file updated.
|
||||
* nice libevent not found error.
|
||||
* README talks about gnu make.
|
||||
- for 0.7.2:
|
||||
* fixup for donotq matching.
|
||||
- do not downcase NSEC and RRSIG for verification. Follows
|
||||
draft-ietf-dnsext-dnssec-bis-updates-06.txt.
|
||||
- fixup leaking unbound daemons at end of tests.
|
||||
- README file updated.
|
||||
- nice libevent not found error.
|
||||
- README talks about gnu make.
|
||||
- 0.8: unit test for addr_mask and fixups for it.
|
||||
and unit test for addr_in_common().
|
||||
- 0.8: access-control config file element.
|
||||
and unit test rpl replay file.
|
||||
- 0.8: fixup address reporting from netevent.
|
||||
|
||||
16 November 2007: Wouter
|
||||
- privilege separation is not needed in unbound at this time.
|
||||
TODO item marked as such.
|
||||
- created beta-0.7 branch for support.
|
||||
- tagged 0.7 for beta release.
|
||||
- moved trunk to 0.8 for 0.8(auth features) development.
|
||||
- 0.8: access control list setup.
|
||||
|
||||
15 November 2007: Wouter
|
||||
- review fixups from Jelte.
|
||||
|
||||
@@ -56,3 +56,5 @@ o use privilege separation, to change privilege options during reload securely
|
||||
not needed.
|
||||
o check if for PowerDNS(2.9.21) CNAME in Answer section & rcode=NXDOMAIN needs
|
||||
to be fixed up to be rcode=NOERROR?
|
||||
o On Windows use CryptGenRandom() to get random seed for arc4random.
|
||||
o Think about intermediate firewalls dropping EDNS UDP & handling that.
|
||||
|
||||
+40
-1
@@ -81,7 +81,7 @@ server:
|
||||
|
||||
# the time to live (TTL) value cap for RRsets and messages in the
|
||||
# cache. Items are not cached for longer. In seconds.
|
||||
# cache-max-ttl: 864000
|
||||
# cache-max-ttl: 86400
|
||||
|
||||
# the time to live (TTL) value for cached roundtrip times and
|
||||
# EDNS version information for hosts. In seconds.
|
||||
@@ -113,6 +113,15 @@ server:
|
||||
# Enable TCP, "yes" or "no".
|
||||
# do-tcp: yes
|
||||
|
||||
# control which clients are allowed to make (recursive) queries
|
||||
# to this server. Specify classless netblocks with /size and action.
|
||||
# By default everything is refused, except for localhost.
|
||||
# Choose deny (drop message), refuse (polite error reply), allow.
|
||||
# access-control: 0.0.0.0/0 refuse
|
||||
# access-control: 127.0.0.0/8 allow
|
||||
# access-control: ::0/0 refuse
|
||||
# access-control: ::1 allow
|
||||
|
||||
# if given, a chroot(2) is done to the given directory.
|
||||
# i.e. you can chroot to the working directory, for example,
|
||||
# for extra security, but make sure all files are in that directory.
|
||||
@@ -246,6 +255,36 @@ server:
|
||||
# more slabs reduce lock contention, but fragment memory usage.
|
||||
# key-cache-slabs: 4
|
||||
|
||||
# a number of locally served zones can be configured.
|
||||
# local-zone: <zone> <type>
|
||||
# local-data: "<resource record string>"
|
||||
# o deny serves local data (if any), else, drops queries.
|
||||
# o refuse serves local data (if any), else, replies with error.
|
||||
# o static serves local data, else, nxdomain or nodata answer.
|
||||
# o transparent serves local data, else, resolves normally .
|
||||
# o redirect serves the zone data for any subdomain in the zone.
|
||||
# o nodefault can be used to normally resolve AS112 zones.
|
||||
#
|
||||
# defaults are localhost address, reverse for 127.0.0.1 and ::1
|
||||
# and nxdomain for AS112 zones. If you configure one of these zones
|
||||
# the default content is omitted, or you can omit it with 'nodefault'.
|
||||
#
|
||||
# If you configure local-data without specifying local-zone, by
|
||||
# default a transparent local-zone is created for the data.
|
||||
#
|
||||
# You can add locally served data with
|
||||
# local-zone: "local." static
|
||||
# local-data: "mycomputer.local. IN A 192.0.2.51"
|
||||
# local-data: 'mytext.local TXT "content of text record"'
|
||||
#
|
||||
# You can override certain queries with
|
||||
# local-data: "adserver.example.com A 127.0.0.1"
|
||||
#
|
||||
# You can redirect a domain to a fixed address with
|
||||
# (this makes example.com, www.example.com, etc, all go to 192.0.2.3)
|
||||
# local-zone: "example.com" redirect
|
||||
# local-data: "example.com A 192.0.2.3"
|
||||
|
||||
|
||||
# Stub zones.
|
||||
# Create entries like below, to make all queries for 'example.com' and
|
||||
|
||||
@@ -203,14 +203,18 @@ X make overload mode work; phase 0 all ok, phase 1 some threads close ports,
|
||||
can be used to block AS112 traffic, option to unblock a zone.
|
||||
* after checking acl, do iter: static, blacklist, forwards, recurse.
|
||||
* Forward-local-zone to NSD.
|
||||
- include in package, autoforkexec on localhost to do so.
|
||||
- in package, autoforkexec on localhost to do so.
|
||||
- not included. Not necessary for localhost and AS112 service.
|
||||
* forward local zone to remote server.
|
||||
- not included. Not necessary for localhost and AS112 service.
|
||||
* stub zones - send queries for a zone to configged nameserver.
|
||||
- Can be used for complicated setups. So, run auth server on a
|
||||
different port or pc, and stub it on the resolver. Resolver is
|
||||
not auth for zones, but resolution works. This enforces the split
|
||||
of recursive and auth servers.
|
||||
* test local zones
|
||||
* for speed
|
||||
* for correctness on corner cases
|
||||
* for validation
|
||||
* in case you get data on localzone in an answer (from rootserver).
|
||||
|
||||
*** Library use
|
||||
* Create library that can do:
|
||||
@@ -240,8 +244,6 @@ X make overload mode work; phase 0 all ok, phase 1 some threads close ports,
|
||||
*** Features features
|
||||
* aggressive negative caching for NSEC, NSEC3.
|
||||
* multiple queries per question, server exploration, server selection.
|
||||
* option to use real entropy for randomness (mix it in once in a while).
|
||||
* check query, enforce qdsection, checking for forgery-resilience.
|
||||
* NSID support.
|
||||
* support TSIG on queries, for validating resolver deployment.
|
||||
* Nicer statistics
|
||||
|
||||
@@ -175,3 +175,28 @@ o authority features.
|
||||
You can put authority data on a separate server, and set the server in
|
||||
unbound.conf as stub for those zones, this allows clients to access data
|
||||
from the server without making unbound authoritative for the zones.
|
||||
|
||||
o the access control denies queries before any other processing.
|
||||
This denies queries that are not authoritative, or version.bind, or any.
|
||||
And thus prevents cache-snooping (denied hosts cannot make non-recursive
|
||||
queries and get answers from the cache).
|
||||
|
||||
o If a client makes a query without RD bit, in the case of a returned
|
||||
message from cache which is:
|
||||
answer section: empty
|
||||
auth section: NS record present, no SOA record, no DS record,
|
||||
maybe NSEC or NSEC3 records present.
|
||||
additional: A records or other relevant records.
|
||||
A SOA record would indicate that this was a NODATA answer.
|
||||
A DS records would indicate a referral.
|
||||
Absence of NS record would indicate a NODATA answer as well.
|
||||
|
||||
Then the receiver does not know whether this was a referral
|
||||
with attempt at no-DS proof) or a nodata answer with attempt
|
||||
at no-data proof. It could be determined by attempting to prove
|
||||
either condition; and looking if only one is valid, but both
|
||||
proofs could be valid, or neither could be valid, which creates
|
||||
doubt. This case is validated by unbound as a 'referral' which
|
||||
ascertains that RRSIGs are OK (and not omitted), but does not
|
||||
check NSEC/NSEC3.
|
||||
|
||||
|
||||
+110
-1
@@ -48,6 +48,12 @@ server:
|
||||
# logfile: "/etc/unbound/unbound.log" #uncomment to use logfile.
|
||||
pidfile: "/etc/unbound/unbound.pid"
|
||||
# verbosity: 1 # uncomment and increase to get more logging.
|
||||
|
||||
# listen on all interfaces, answer queries from the local subnet.
|
||||
interface: 0.0.0.0
|
||||
interface: ::0
|
||||
access-control: 10.0.0.0/8 allow
|
||||
access-control: 2001:DB8::/64 allow
|
||||
.fi
|
||||
.Sh FILE FORMAT
|
||||
There must be whitespace between keywords. Attribute keywords end with a colon ':'. An attribute
|
||||
@@ -128,7 +134,7 @@ Number of slabs in the RRset cache. Slabs reduce lock contention by threads.
|
||||
Must be set to a power of 2.
|
||||
.It \fBcache-max-ttl:\fR <seconds>
|
||||
Time to live maximum for RRsets and messages in the cache. Default is
|
||||
864000 seconds (10 days). If the maximum kicks in, responses to clients
|
||||
86400 seconds (1 day). If the maximum kicks in, responses to clients
|
||||
still get decrementing TTLs based on the original (larger) values.
|
||||
When the internal TTL expires, the cache item has expired.
|
||||
Can be set lower to force the resolver to query for data often, and not
|
||||
@@ -155,6 +161,13 @@ Enable or disable whether ip6 queries are answered. Default is yes.
|
||||
Enable or disable whether UDP queries are answered. Default is yes.
|
||||
.It \fBdo-tcp:\fR <yes or no>
|
||||
Enable or disable whether TCP queries are answered. Default is yes.
|
||||
.It \fBaccess-control:\fR <IP netblock> <action>
|
||||
The netblock is given as an IP4 or IP6 address with /size appended for a
|
||||
classless network block. The action can be deny, refuse or allow.
|
||||
Deny stops queries from hosts from that netblock.
|
||||
Refuse stops queries too, but sends a DNS rcode REFUSED error message back.
|
||||
Allow gives access to clients from that netblock.
|
||||
By default only localhost is allowed, the rest is refused.
|
||||
.It \fBchroot:\fR <directory>
|
||||
If given a chroot is done to the given directory. The default is
|
||||
"/etc/unbound". If you give "" no chroot is performed.
|
||||
@@ -308,6 +321,102 @@ Number of bytes size of the key cache. Default is 4 megabytes.
|
||||
Number of slabs in the key cache. Slabs reduce lock contention by threads.
|
||||
Must be set to a power of 2. Setting (close) to the number of cpus is a
|
||||
reasonable guess.
|
||||
.It \fBlocal-zone:\fR <zone> <type>
|
||||
Configure a local zone. The type determines the answer to give if there is
|
||||
no match from local-data. The types are deny, refuse, static, transparent,
|
||||
redirect, nodefault, and are explained below. After that the default settings
|
||||
are listed. Use local-data: to enter data into the local zone. Answers for
|
||||
local zones are authoritative DNS answers. By default the zones are class IN.
|
||||
.Bl -tag -width indent
|
||||
.It \fIdeny\fR
|
||||
Do not send an answer, drop the query.
|
||||
If there is a match from local data, the query is answered.
|
||||
.It \fIrefuse\fR
|
||||
Send an error message reply, with rcode REFUSED.
|
||||
If there is a match from local data, the query is answered.
|
||||
.It \fIstatic\fR
|
||||
If there is a match from local data, the query is answered.
|
||||
Otherwise, the query is answered with nodata or nxdomain.
|
||||
For a negative answer a SOA is included in the answer if present
|
||||
as local-data for the zone apex domain.
|
||||
.It \fItransparent\fR
|
||||
If there is a match from local data, the query is answered.
|
||||
Otherwise, the query is resolved normally.
|
||||
If no local-zone is given local-data causes a transparent zone
|
||||
to be created by default.
|
||||
.It \fIredirect\fR
|
||||
The query is answered from the local data for the zone name.
|
||||
There may be no local data beneath the zone name.
|
||||
This answers queries for the zone, and all subdomains of the zone
|
||||
with the local data for the zone.
|
||||
It can be used to redirect a domain to a different address, with
|
||||
local-zone: "example.com." redirect and
|
||||
local-data: "example.com. A 127.0.0.1"
|
||||
queries for www.example.com and www.foo.example.com are redirected.
|
||||
.It \fInodefault\fR
|
||||
Used to turn off default contents for AS112 zones. The other types
|
||||
also turn off default contents for the zone. The 'nodefault' option
|
||||
has no other effect than turning off default contents for the
|
||||
given zone.
|
||||
.El
|
||||
The default zones are localhost, reverse 127.0.0.1 and ::1, and the AS112
|
||||
zones. The AS112 zones are reverse DNS zones for private use and reserved
|
||||
IP addresses for which the servers on the internet cannot provide correct
|
||||
answers. They are configured by default to give nxdomain (no reverse
|
||||
information) answers. The defaults can be turned off by specifying your
|
||||
own local-zone of that name, or using the 'nodefault' type. Below is a
|
||||
list of the default zone contents.
|
||||
.Bl -tag -width indent
|
||||
.It \fIlocalhost\fR
|
||||
The IP4 and IP6 localhost information is given. NS and SOA records are provided
|
||||
for completeness and to satisfy some DNS update tools. Default content:
|
||||
.nf
|
||||
local-zone: "localhost." static
|
||||
local-data: "localhost. 10800 IN NS localhost."
|
||||
local-data: "localhost. 10800 IN SOA localhost. nobody.invalid. 1 3600 1200 604800 10800"
|
||||
local-data: "localhost. 10800 IN A 127.0.0.1"
|
||||
local-data: "localhost. 10800 IN AAAA ::1"
|
||||
.fi
|
||||
.It \fIreverse IPv4 loopback\fR
|
||||
Default content:
|
||||
.nf
|
||||
local-zone: "127.in-addr.arpa." static
|
||||
local-data: "127.in-addr.arpa. 10800 IN NS localhost."
|
||||
local-data: "127.in-addr.arpa. 10800 IN SOA localhost. nobody.invalid. 1 3600 1200 604800 10800"
|
||||
local-data: "1.0.0.127.in-addr.arpa. 10800 IN PTR localhost."
|
||||
.fi
|
||||
.It \fIreverse IPv6 loopback\fR
|
||||
Default content:
|
||||
.nf
|
||||
local-zone: "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa." static
|
||||
local-data: "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. 10800 IN NS localhost."
|
||||
local-data: "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. 10800 IN SOA localhost. nobody.invalid. 1 3600 1200 604800 10800"
|
||||
local-data: "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. 10800 IN PTR localhost."
|
||||
.fi
|
||||
.It \fIreverse RFC1918 local use zones\fR
|
||||
Reverse data for zones 10.in-addr.arpa, 16.172.in-addr.arpa to
|
||||
31.172.in-addr.arpa, 168.192.in-addr.arpa.
|
||||
The \fBlocal-zone:\fR is set static and as \fBlocal-data:\fR SOA and NS
|
||||
records are provided.
|
||||
.It \fIreverse RFC3330 IP4 this, link-local, testnet and broadcast\fR
|
||||
Reverse data for zones 0.in-addr.arpa, 254.169.in-addr.arpa,
|
||||
2.0.192.in-addr.arpa, 255.255.255.255.in-addr.arpa.
|
||||
.It \fIreverse RFC4291 IP6 unspecified\fR
|
||||
Reverse data for zone 0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.
|
||||
.It \fIreverse RFC4193 IPv6 Locally Assigned Local Addresses\fR
|
||||
Reverse data for zone D.F.ip6.arpa.
|
||||
.It \fIreverse RFC4291 IPv6 Link Local Addresses\fR
|
||||
Reverse data for zones 8.E.F.ip6.arpa to B.E.F.ip6.arpa.
|
||||
.El
|
||||
.\" End of local-zone listing.
|
||||
.It \fBlocal-data:\fR "<resource record string>"
|
||||
Configure local data, which is served in reply to queries for it.
|
||||
The query has to match exactly unless you configure the local-zone as
|
||||
redirect. If not matched exactly, the local-zone type determines
|
||||
further processing. If local-data is configured that is not a subdomain of
|
||||
a local-zone, a transparent local-zone is configured.
|
||||
For record types such as TXT, use single quotes, as in
|
||||
local-data: 'example. TXT "text"'.
|
||||
.El
|
||||
.Ss Stub Zone Options
|
||||
There may be multiple
|
||||
|
||||
+2
-84
@@ -108,63 +108,17 @@ donotq_insert(struct iter_donotq* dq, struct sockaddr_storage* addr,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** make sure the netblock ends in zeroes for compare in tree */
|
||||
static void
|
||||
mask_block(int ip6, struct sockaddr_storage* addr, int net)
|
||||
{
|
||||
uint8_t mask[8] = {0x0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe};
|
||||
int i, max;
|
||||
uint8_t* s;
|
||||
if(ip6) {
|
||||
s = (uint8_t*)&((struct sockaddr_in6*)addr)->sin6_addr;
|
||||
max = 128;
|
||||
} else {
|
||||
s = (uint8_t*)&((struct sockaddr_in*)addr)->sin_addr;
|
||||
max = 32;
|
||||
}
|
||||
if(net >= max)
|
||||
return;
|
||||
for(i=net/8+1; i<max/8; i++) {
|
||||
s[i] = 0;
|
||||
}
|
||||
s[net/8] &= mask[net&0x7];
|
||||
}
|
||||
|
||||
/** apply donotq string */
|
||||
static int
|
||||
donotq_str_cfg(struct iter_donotq* dq, const char* str)
|
||||
{
|
||||
struct sockaddr_storage addr;
|
||||
int net;
|
||||
char* s = NULL;
|
||||
socklen_t addrlen;
|
||||
net = (str_is_ip6(str)?128:32);
|
||||
if((s=strchr(str, '/'))) {
|
||||
if(atoi(s+1) > net) {
|
||||
log_err("netblock too large: %s", str);
|
||||
return 0;
|
||||
}
|
||||
net = atoi(s+1);
|
||||
if(net == 0 && strcmp(s+1, "0") != 0) {
|
||||
log_err("cannot parse donotquery netblock:"
|
||||
" '%s'", str);
|
||||
return 0;
|
||||
}
|
||||
if(!(s = strdup(str))) {
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
*strchr(s, '/') = '\0';
|
||||
}
|
||||
if(!ipstrtoaddr(s?s:str, UNBOUND_DNS_PORT, &addr, &addrlen)) {
|
||||
free(s);
|
||||
log_err("cannot parse donotquery ip address: '%s'", str);
|
||||
if(!netblockstrtoaddr(str, UNBOUND_DNS_PORT, &addr, &addrlen, &net)) {
|
||||
log_err("cannot parse donotquery netblock: %s", str);
|
||||
return 0;
|
||||
}
|
||||
if(s) {
|
||||
free(s);
|
||||
mask_block(str_is_ip6(str), &addr, net);
|
||||
}
|
||||
if(!donotq_insert(dq, &addr, addrlen, net)) {
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
@@ -185,42 +139,6 @@ read_donotq(struct iter_donotq* dq, struct config_file* cfg)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** number of bits that two addrs share (are equal) */
|
||||
static int
|
||||
addr_in_common(struct sockaddr_storage* addr1, int net1,
|
||||
struct sockaddr_storage* addr2, int net2, socklen_t addrlen)
|
||||
{
|
||||
int min = (net1<net2)?net1:net2;
|
||||
int i, to;
|
||||
int match = 0;
|
||||
uint8_t* s1, *s2;
|
||||
if(addr_is_ip6(addr1, addrlen)) {
|
||||
s1 = (uint8_t*)&((struct sockaddr_in6*)addr1)->sin6_addr;
|
||||
s2 = (uint8_t*)&((struct sockaddr_in6*)addr2)->sin6_addr;
|
||||
to = 16;
|
||||
} else {
|
||||
s1 = (uint8_t*)&((struct sockaddr_in*)addr1)->sin_addr;
|
||||
s2 = (uint8_t*)&((struct sockaddr_in*)addr2)->sin_addr;
|
||||
to = 4;
|
||||
}
|
||||
/* match = bits_in_common(s1, s2, to); */
|
||||
for(i=0; i<to; i++) {
|
||||
if(s1[i] == s2[i]) {
|
||||
match += 8;
|
||||
} else {
|
||||
uint8_t z = s1[i]^s2[i];
|
||||
log_assert(z);
|
||||
while(!(z&0x80)) {
|
||||
match++;
|
||||
z<<=1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(match > min) match = min;
|
||||
return match;
|
||||
}
|
||||
|
||||
/** initialise parent pointers in the tree */
|
||||
static void
|
||||
donotq_init_parents(struct iter_donotq* donotq)
|
||||
|
||||
@@ -54,7 +54,7 @@ struct iter_donotq {
|
||||
/** regional for allocation */
|
||||
struct regional* region;
|
||||
/**
|
||||
* Tree of the single addresses that are blocked.
|
||||
* Tree of the address spans that are blocked.
|
||||
* contents of type iter_donotq_addr.
|
||||
*/
|
||||
rbtree_t* tree;
|
||||
@@ -62,10 +62,10 @@ struct iter_donotq {
|
||||
|
||||
/**
|
||||
* Iterator donotquery address.
|
||||
* A single address that must not be used to send queries to.
|
||||
* An address span that must not be used to send queries to.
|
||||
*/
|
||||
struct iter_donotq_addr {
|
||||
/** redblacktree node, key is this structure: addr and addrlen */
|
||||
/** redblacktree node, key is this structure: addr and addrlen, net */
|
||||
rbnode_t node;
|
||||
/** address */
|
||||
struct sockaddr_storage addr;
|
||||
|
||||
@@ -350,6 +350,10 @@ scrub_normalize(ldns_buffer* pkt, struct msg_parse* msg,
|
||||
"too long");
|
||||
return 0;
|
||||
}
|
||||
/* internally we have CNAME'd/DNAME'd chains ending
|
||||
* in nxdomain with NOERROR rcode, change rcode
|
||||
* to reflect this (if needed) */
|
||||
FLAGS_SET_RCODE(msg->flags, LDNS_RCODE_NOERROR);
|
||||
if(nx && nx->type == LDNS_RR_TYPE_CNAME &&
|
||||
dname_pkt_compare(pkt, sname, nx->dname) == 0) {
|
||||
/* check next cname */
|
||||
@@ -392,6 +396,10 @@ scrub_normalize(ldns_buffer* pkt, struct msg_parse* msg,
|
||||
return 0;
|
||||
prev = rrset;
|
||||
rrset = rrset->rrset_all_next;
|
||||
/* internally we have CNAME'd/DNAME'd chains ending
|
||||
* in nxdomain with NOERROR rcode, change rcode
|
||||
* to reflect this (if needed) */
|
||||
FLAGS_SET_RCODE(msg->flags, LDNS_RCODE_NOERROR);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
+23
-1
@@ -224,6 +224,23 @@ error_response(struct module_qstate* qstate, int id, int rcode)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** check if prepend item is duplicate item */
|
||||
static int
|
||||
prepend_is_duplicate(struct ub_packed_rrset_key** sets, size_t to,
|
||||
struct ub_packed_rrset_key* dup)
|
||||
{
|
||||
size_t i;
|
||||
for(i=0; i<to; i++) {
|
||||
if(sets[i]->rk.type == dup->rk.type &&
|
||||
sets[i]->rk.rrset_class == dup->rk.rrset_class &&
|
||||
sets[i]->rk.dname_len == dup->rk.dname_len &&
|
||||
query_dname_compare(sets[i]->rk.dname, dup->rk.dname)
|
||||
== 0)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** prepend the prepend list in the answer and authority section of dns_msg */
|
||||
static int
|
||||
iter_prepend(struct iter_qstate* iq, struct dns_msg* msg,
|
||||
@@ -253,6 +270,11 @@ iter_prepend(struct iter_qstate* iq, struct dns_msg* msg,
|
||||
/* AUTH section */
|
||||
num_ns = 0;
|
||||
for(p = iq->ns_prepend_list; p; p = p->next) {
|
||||
if(prepend_is_duplicate(sets+msg->rep->an_numrrsets+num_an,
|
||||
num_ns, p->rrset) || prepend_is_duplicate(
|
||||
msg->rep->rrsets+msg->rep->an_numrrsets,
|
||||
msg->rep->ns_numrrsets, p->rrset))
|
||||
continue;
|
||||
sets[msg->rep->an_numrrsets + num_an + num_ns++] = p->rrset;
|
||||
}
|
||||
memcpy(sets + num_an + msg->rep->an_numrrsets + num_ns,
|
||||
@@ -769,7 +791,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
if(iter_dp_is_useless(qstate, iq->dp)) {
|
||||
if(dname_is_root(iq->dp->name)) {
|
||||
/* use safety belt */
|
||||
verbose(VERB_OPS, "Priming problem: NS but "
|
||||
verbose(VERB_DETAIL, "Cache has root NS but "
|
||||
"no addresses. Fallback to the safety belt.");
|
||||
iq->dp = hints_lookup_root(ie->hints,
|
||||
iq->qchase.qclass);
|
||||
|
||||
Vendored
-2
@@ -137,6 +137,4 @@ struct dns_msg* dns_cache_lookup(struct module_env* env,
|
||||
int cache_fill_missing(struct module_env* env, uint16_t qclass,
|
||||
struct regional* region, struct delegpt* dp);
|
||||
|
||||
/** Find covering DNAME */
|
||||
|
||||
#endif /* SERVICES_CACHE_DNS_H */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,215 @@
|
||||
/*
|
||||
* services/localzone.h - local zones authority service.
|
||||
*
|
||||
* 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 enable local zone authority service.
|
||||
*/
|
||||
|
||||
#ifndef SERVICES_LOCALZONE_H
|
||||
#define SERVICES_LOCALZONE_H
|
||||
#include "util/rbtree.h"
|
||||
struct ub_packed_rrset_key;
|
||||
struct regional;
|
||||
struct config_file;
|
||||
struct edns_data;
|
||||
struct query_info;
|
||||
|
||||
/**
|
||||
* Local zone type
|
||||
* This type determines processing for queries that did not match
|
||||
* local-data directly.
|
||||
*/
|
||||
enum localzone_type {
|
||||
/** drop query */
|
||||
local_zone_deny = 0,
|
||||
/** answer with error */
|
||||
local_zone_refuse,
|
||||
/** answer nxdomain or nodata */
|
||||
local_zone_static,
|
||||
/** resolve normally */
|
||||
local_zone_transparent,
|
||||
/** answer with data at zone apex */
|
||||
local_zone_redirect,
|
||||
/** remove default AS112 blocking contents for zone
|
||||
* nodefault is used in config not during service. */
|
||||
local_zone_nodefault
|
||||
};
|
||||
|
||||
/**
|
||||
* Authoritative local zones storage, shared.
|
||||
* This tree is fixed at startup, so, readonly, no locks or mutexes necessary.
|
||||
*/
|
||||
struct local_zones {
|
||||
/** rbtree of struct local_zone */
|
||||
rbtree_t ztree;
|
||||
};
|
||||
|
||||
/**
|
||||
* Local zone. A locally served authoritative zone.
|
||||
*/
|
||||
struct local_zone {
|
||||
/** rbtree node, key is name and class */
|
||||
rbnode_t node;
|
||||
/** parent zone, if any. */
|
||||
struct local_zone* parent;
|
||||
|
||||
/** zone name, in uncompressed wireformat */
|
||||
uint8_t* name;
|
||||
/** length of zone name */
|
||||
size_t namelen;
|
||||
/** number of labels in zone name */
|
||||
int namelabs;
|
||||
/** the class of this zone.
|
||||
* uses 'dclass' to not conflict with c++ keyword class. */
|
||||
uint16_t dclass;
|
||||
|
||||
/** how to process zone */
|
||||
enum localzone_type type;
|
||||
|
||||
/** in this region the zone's data is allocated.
|
||||
* the struct local_zone itself is malloced. */
|
||||
struct regional* region;
|
||||
/** local data for this zone
|
||||
* rbtree of struct local_data */
|
||||
rbtree_t data;
|
||||
/** if data contains zone apex SOA data, this is a ptr to it. */
|
||||
struct ub_packed_rrset_key* soa;
|
||||
};
|
||||
|
||||
/**
|
||||
* Local data. One domain name, and the RRs to go with it.
|
||||
*/
|
||||
struct local_data {
|
||||
/** rbtree node, key is name only */
|
||||
rbnode_t node;
|
||||
/** domain name */
|
||||
uint8_t* name;
|
||||
/** length of name */
|
||||
size_t namelen;
|
||||
/** number of labels in name */
|
||||
int namelabs;
|
||||
/** the data rrsets, with different types, linked list.
|
||||
* If this list is NULL, the node is an empty non-terminal. */
|
||||
struct local_rrset* rrsets;
|
||||
};
|
||||
|
||||
/**
|
||||
* A local data RRset
|
||||
*/
|
||||
struct local_rrset {
|
||||
/** next in list */
|
||||
struct local_rrset* next;
|
||||
/** RRset data item */
|
||||
struct ub_packed_rrset_key* rrset;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create local zones storage
|
||||
* @return new struct or NULL on error.
|
||||
*/
|
||||
struct local_zones* local_zones_create();
|
||||
|
||||
/**
|
||||
* Delete local zones storage
|
||||
* @param zones: to delete.
|
||||
*/
|
||||
void local_zones_delete(struct local_zones* zones);
|
||||
|
||||
/**
|
||||
* Apply config settings; setup the local authoritative data.
|
||||
* @param zones: is set up.
|
||||
* @param cfg: config data.
|
||||
* @return false on error.
|
||||
*/
|
||||
int local_zones_apply_cfg(struct local_zones* zones, struct config_file* cfg);
|
||||
|
||||
/**
|
||||
* Compare two local_zone entries in rbtree. Sort hierarchical but not
|
||||
* canonical
|
||||
* @param z1: zone 1
|
||||
* @param z2: zone 2
|
||||
* @return: -1, 0, +1 comparison value.
|
||||
*/
|
||||
int local_zone_cmp(const void* z1, const void* z2);
|
||||
|
||||
/**
|
||||
* Compare two local_data entries in rbtree. Sort canonical.
|
||||
* @param d1: data 1
|
||||
* @param d2: data 2
|
||||
* @return: -1, 0, +1 comparison value.
|
||||
*/
|
||||
int local_data_cmp(const void* d1, const void* d2);
|
||||
|
||||
/**
|
||||
* Delete one zone
|
||||
* @param z: to delete.
|
||||
*/
|
||||
void local_zone_delete(struct local_zone* z);
|
||||
|
||||
/**
|
||||
* Lookup zone that contains the given name, class.
|
||||
* @param zones: the zones tree
|
||||
* @param name: dname to lookup
|
||||
* @param len: length of name.
|
||||
* @param labs: labelcount of name.
|
||||
* @param dclass: class to lookup.
|
||||
* @return closest local_zone or NULL if no covering zone is found.
|
||||
*/
|
||||
struct local_zone* local_zones_lookup(struct local_zones* zones,
|
||||
uint8_t* name, size_t len, int labs, uint16_t dclass);
|
||||
|
||||
/**
|
||||
* Debug helper. Print all zones
|
||||
* @param zones: the zones tree
|
||||
*/
|
||||
void local_zones_print(struct local_zones* zones);
|
||||
|
||||
/**
|
||||
* Answer authoritatively for local zones.
|
||||
* @param zones: the stored zones (shared, read only).
|
||||
* @param qinfo: query info (parsed).
|
||||
* @param edns: edns info (parsed).
|
||||
* @param buf: buffer with query ID and flags, also for reply.
|
||||
* @param temp: temporary storage region.
|
||||
* @return true if answer is in buffer. false if query is not answered
|
||||
* by authority data. If the reply should be dropped altogether, the return
|
||||
* value is true, but the buffer is cleared (empty).
|
||||
*/
|
||||
int local_zones_answer(struct local_zones* zones, struct query_info* qinfo,
|
||||
struct edns_data* edns, ldns_buffer* buf, struct regional* temp);
|
||||
|
||||
#endif /* SERVICES_LOCALZONE_H */
|
||||
@@ -150,6 +150,8 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len)
|
||||
w->outnet->tcp_free = pend->next_free;
|
||||
pend->next_free = NULL;
|
||||
pend->query = w;
|
||||
pend->c->repinfo.addrlen = w->addrlen;
|
||||
memcpy(&pend->c->repinfo.addr, &w->addr, w->addrlen);
|
||||
ldns_buffer_clear(pend->c->buffer);
|
||||
ldns_buffer_write(pend->c->buffer, pkt, pkt_len);
|
||||
ldns_buffer_flip(pend->c->buffer);
|
||||
|
||||
+14
-35
@@ -60,14 +60,8 @@ struct codeline {
|
||||
uint64_t alloc;
|
||||
/** number of bytes freed */
|
||||
uint64_t free;
|
||||
};
|
||||
|
||||
/**
|
||||
* Other allocation stats
|
||||
*/
|
||||
struct alloc_misc {
|
||||
/** number of region allocs */
|
||||
uint64_t region_alloc;
|
||||
/** number allocations and frees */
|
||||
uint64_t calls;
|
||||
};
|
||||
|
||||
/** print usage and exit */
|
||||
@@ -101,18 +95,6 @@ match(char* line)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** read up the region stats */
|
||||
static void
|
||||
read_region_stat(char* line, struct alloc_misc* misc)
|
||||
{
|
||||
long num = 0;
|
||||
if(sscanf(line+50, "%ld", &num) != 1) {
|
||||
printf("%s\n%s\n", line, line+50);
|
||||
fatal_exit("unhandled region");
|
||||
}
|
||||
misc->region_alloc += num;
|
||||
}
|
||||
|
||||
/** find or alloc codeline in tree */
|
||||
static struct codeline*
|
||||
get_codeline(rbtree_t* tree, char* key, char* func)
|
||||
@@ -153,6 +135,7 @@ read_malloc_stat(char* line, rbtree_t* tree)
|
||||
if(!cl)
|
||||
fatal_exit("alloc failure");
|
||||
cl->alloc += num;
|
||||
cl->calls ++;
|
||||
}
|
||||
|
||||
/** read up the calloc stats */
|
||||
@@ -177,6 +160,7 @@ read_calloc_stat(char* line, rbtree_t* tree)
|
||||
if(!cl)
|
||||
fatal_exit("alloc failure");
|
||||
cl->alloc += num*sz;
|
||||
cl->calls ++;
|
||||
}
|
||||
|
||||
/** get size of file */
|
||||
@@ -192,7 +176,7 @@ get_file_size(const char* fname)
|
||||
|
||||
/** read the logfile */
|
||||
static void
|
||||
readfile(rbtree_t* tree, const char* fname, struct alloc_misc* misc)
|
||||
readfile(rbtree_t* tree, const char* fname)
|
||||
{
|
||||
off_t total = get_file_size(fname);
|
||||
off_t done = (off_t)0;
|
||||
@@ -213,8 +197,6 @@ readfile(rbtree_t* tree, const char* fname, struct alloc_misc* misc)
|
||||
|
||||
if(!match(buf))
|
||||
continue;
|
||||
if(strncmp(buf+36, "region ", 7) == 0)
|
||||
read_region_stat(buf, misc);
|
||||
else if(strstr(buf+36, "malloc("))
|
||||
read_malloc_stat(buf, tree);
|
||||
else if(strstr(buf+36, "calloc("))
|
||||
@@ -230,20 +212,19 @@ readfile(rbtree_t* tree, const char* fname, struct alloc_misc* misc)
|
||||
|
||||
/** print memory stats */
|
||||
static void
|
||||
printstats(rbtree_t* tree, struct alloc_misc* misc)
|
||||
printstats(rbtree_t* tree)
|
||||
{
|
||||
struct codeline* cl;
|
||||
uint64_t total = 0;
|
||||
printf("%12lld in region alloc\n", (long long)misc->region_alloc);
|
||||
total += misc->region_alloc;
|
||||
uint64_t total = 0, tcalls = 0;
|
||||
RBTREE_FOR(cl, struct codeline*, tree) {
|
||||
printf("%12lld in %s %s\n", (long long)cl->alloc,
|
||||
cl->codeline, cl->func);
|
||||
printf("%12lld / %8lld in %s %s\n", (long long)cl->alloc,
|
||||
(long long)cl->calls, cl->codeline, cl->func);
|
||||
total += cl->alloc;
|
||||
tcalls += cl->calls;
|
||||
}
|
||||
printf("------------\n");
|
||||
printf("%12lld total in %ld code lines\n", (long long)total,
|
||||
(long)tree->count);
|
||||
printf("%12lld / %8lld total in %ld code lines\n", (long long)total,
|
||||
(long long)tcalls, (long)tree->count);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
@@ -251,15 +232,13 @@ printstats(rbtree_t* tree, struct alloc_misc* misc)
|
||||
int main(int argc, const char* argv[])
|
||||
{
|
||||
rbtree_t* tree = 0;
|
||||
struct alloc_misc misc;
|
||||
if(argc != 2) {
|
||||
usage();
|
||||
}
|
||||
tree = rbtree_create(codeline_cmp);
|
||||
if(!tree)
|
||||
fatal_exit("alloc failure");
|
||||
memset(&misc, 0, sizeof(misc));
|
||||
readfile(tree, argv[1], &misc);
|
||||
printstats(tree, &misc);
|
||||
readfile(tree, argv[1]);
|
||||
printstats(tree);
|
||||
return 0;
|
||||
}
|
||||
|
||||
+8
-1
@@ -208,6 +208,8 @@ replay_moment_read(char* remain, FILE* in, const char* name, int* lineno,
|
||||
} else if(parse_keyword(&remain, "QUERY")) {
|
||||
mom->evt_type = repevt_front_query;
|
||||
readentry = 1;
|
||||
if(!extstrtoaddr("127.0.0.1", &mom->addr, &mom->addrlen))
|
||||
fatal_exit("internal error");
|
||||
} else if(parse_keyword(&remain, "CHECK_ANSWER")) {
|
||||
mom->evt_type = repevt_front_reply;
|
||||
readentry = 1;
|
||||
@@ -229,13 +231,18 @@ replay_moment_read(char* remain, FILE* in, const char* name, int* lineno,
|
||||
while(isspace((int)*remain))
|
||||
remain++;
|
||||
if(parse_keyword(&remain, "ADDRESS")) {
|
||||
while(isspace((int)*remain))
|
||||
remain++;
|
||||
if(strlen(remain) > 0) /* remove \n */
|
||||
remain[strlen(remain)-1] = 0;
|
||||
printf("remain '%s'\n", remain);
|
||||
if(!extstrtoaddr(remain, &mom->addr, &mom->addrlen)) {
|
||||
log_err("line %d: could not parse ADDRESS: %s",
|
||||
*lineno, remain);
|
||||
free(mom);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(readentry) {
|
||||
mom->match = read_entry(in, name, lineno, ttl, or, prev);
|
||||
|
||||
@@ -89,6 +89,42 @@ alloc_test() {
|
||||
static void
|
||||
net_test()
|
||||
{
|
||||
char* t4[] = {"\000\000\000\000",
|
||||
"\200\000\000\000",
|
||||
"\300\000\000\000",
|
||||
"\340\000\000\000",
|
||||
"\360\000\000\000",
|
||||
"\370\000\000\000",
|
||||
"\374\000\000\000",
|
||||
"\376\000\000\000",
|
||||
"\377\000\000\000",
|
||||
"\377\200\000\000",
|
||||
"\377\300\000\000",
|
||||
"\377\340\000\000",
|
||||
"\377\360\000\000",
|
||||
"\377\370\000\000",
|
||||
"\377\374\000\000",
|
||||
"\377\376\000\000",
|
||||
"\377\377\000\000",
|
||||
"\377\377\200\000",
|
||||
"\377\377\300\000",
|
||||
"\377\377\340\000",
|
||||
"\377\377\360\000",
|
||||
"\377\377\370\000",
|
||||
"\377\377\374\000",
|
||||
"\377\377\376\000",
|
||||
"\377\377\377\000",
|
||||
"\377\377\377\200",
|
||||
"\377\377\377\300",
|
||||
"\377\377\377\340",
|
||||
"\377\377\377\360",
|
||||
"\377\377\377\370",
|
||||
"\377\377\377\374",
|
||||
"\377\377\377\376",
|
||||
"\377\377\377\377",
|
||||
"\377\377\377\377",
|
||||
"\377\377\377\377",
|
||||
};
|
||||
unit_assert( str_is_ip6("::") );
|
||||
unit_assert( str_is_ip6("::1") );
|
||||
unit_assert( str_is_ip6("2001:7b8:206:1:240:f4ff:fe37:8810") );
|
||||
@@ -117,6 +153,91 @@ net_test()
|
||||
unit_assert( !is_pow2(23) );
|
||||
unit_assert( !is_pow2(257) );
|
||||
unit_assert( !is_pow2(259) );
|
||||
|
||||
/* test addr_mask */
|
||||
if(1) {
|
||||
struct sockaddr_in a4;
|
||||
struct sockaddr_in6 a6;
|
||||
socklen_t l4 = (socklen_t)sizeof(a4);
|
||||
socklen_t l6 = (socklen_t)sizeof(a6);
|
||||
int i;
|
||||
a4.sin_family = AF_INET;
|
||||
a6.sin6_family = AF_INET6;
|
||||
for(i=0; i<35; i++) {
|
||||
/* address 255.255.255.255 */
|
||||
memcpy(&a4.sin_addr, "\377\377\377\377", 4);
|
||||
addr_mask((struct sockaddr_storage*)&a4, l4, i);
|
||||
unit_assert(memcmp(&a4.sin_addr, t4[i], 4) == 0);
|
||||
}
|
||||
memcpy(&a6.sin6_addr, "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377", 16);
|
||||
addr_mask((struct sockaddr_storage*)&a6, l6, 128);
|
||||
unit_assert(memcmp(&a6.sin6_addr, "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377", 16) == 0);
|
||||
addr_mask((struct sockaddr_storage*)&a6, l6, 122);
|
||||
unit_assert(memcmp(&a6.sin6_addr, "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\300", 16) == 0);
|
||||
addr_mask((struct sockaddr_storage*)&a6, l6, 120);
|
||||
unit_assert(memcmp(&a6.sin6_addr, "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\000", 16) == 0);
|
||||
addr_mask((struct sockaddr_storage*)&a6, l6, 64);
|
||||
unit_assert(memcmp(&a6.sin6_addr, "\377\377\377\377\377\377\377\377\000\000\000\000\000\000\000\000", 16) == 0);
|
||||
addr_mask((struct sockaddr_storage*)&a6, l6, 0);
|
||||
unit_assert(memcmp(&a6.sin6_addr, "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000", 16) == 0);
|
||||
}
|
||||
|
||||
/* test addr_in_common */
|
||||
if(1) {
|
||||
struct sockaddr_in a4, b4;
|
||||
struct sockaddr_in6 a6, b6;
|
||||
socklen_t l4 = (socklen_t)sizeof(a4);
|
||||
socklen_t l6 = (socklen_t)sizeof(a6);
|
||||
int i;
|
||||
a4.sin_family = AF_INET;
|
||||
b4.sin_family = AF_INET;
|
||||
a6.sin6_family = AF_INET6;
|
||||
b6.sin6_family = AF_INET6;
|
||||
memcpy(&a4.sin_addr, "abcd", 4);
|
||||
memcpy(&b4.sin_addr, "abcd", 4);
|
||||
unit_assert(addr_in_common((struct sockaddr_storage*)&a4, 32,
|
||||
(struct sockaddr_storage*)&b4, 32, l4) == 32);
|
||||
unit_assert(addr_in_common((struct sockaddr_storage*)&a4, 34,
|
||||
(struct sockaddr_storage*)&b4, 32, l4) == 32);
|
||||
for(i=0; i<=32; i++) {
|
||||
unit_assert(addr_in_common(
|
||||
(struct sockaddr_storage*)&a4, 32,
|
||||
(struct sockaddr_storage*)&b4, i, l4) == i);
|
||||
unit_assert(addr_in_common(
|
||||
(struct sockaddr_storage*)&a4, i,
|
||||
(struct sockaddr_storage*)&b4, 32, l4) == i);
|
||||
unit_assert(addr_in_common(
|
||||
(struct sockaddr_storage*)&a4, i,
|
||||
(struct sockaddr_storage*)&b4, i, l4) == i);
|
||||
}
|
||||
for(i=0; i<=32; i++) {
|
||||
memcpy(&a4.sin_addr, "\377\377\377\377", 4);
|
||||
memcpy(&b4.sin_addr, t4[i], 4);
|
||||
unit_assert(addr_in_common(
|
||||
(struct sockaddr_storage*)&a4, 32,
|
||||
(struct sockaddr_storage*)&b4, 32, l4) == i);
|
||||
unit_assert(addr_in_common(
|
||||
(struct sockaddr_storage*)&b4, 32,
|
||||
(struct sockaddr_storage*)&a4, 32, l4) == i);
|
||||
}
|
||||
memcpy(&a6.sin6_addr, "abcdefghabcdefgh", 16);
|
||||
memcpy(&b6.sin6_addr, "abcdefghabcdefgh", 16);
|
||||
unit_assert(addr_in_common((struct sockaddr_storage*)&a6, 128,
|
||||
(struct sockaddr_storage*)&b6, 128, l6) == 128);
|
||||
unit_assert(addr_in_common((struct sockaddr_storage*)&a6, 129,
|
||||
(struct sockaddr_storage*)&b6, 128, l6) == 128);
|
||||
for(i=0; i<=128; i++) {
|
||||
unit_assert(addr_in_common(
|
||||
(struct sockaddr_storage*)&a6, 128,
|
||||
(struct sockaddr_storage*)&b6, i, l6) == i);
|
||||
unit_assert(addr_in_common(
|
||||
(struct sockaddr_storage*)&a6, i,
|
||||
(struct sockaddr_storage*)&b6, 128, l6) == i);
|
||||
unit_assert(addr_in_common(
|
||||
(struct sockaddr_storage*)&a6, i,
|
||||
(struct sockaddr_storage*)&b6, i, l6) == i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#include "util/rtt.h"
|
||||
|
||||
Vendored
+52
@@ -0,0 +1,52 @@
|
||||
; config options
|
||||
server:
|
||||
hide-identity: no
|
||||
hide-version: no
|
||||
identity: "test-identity"
|
||||
version: "test-version"
|
||||
access-control: 20.0.0.0/8 allow
|
||||
access-control: 20.40.0.0/16 refuse
|
||||
access-control: 20.40.80.0/24 deny
|
||||
|
||||
CONFIG_END
|
||||
SCENARIO_BEGIN Test access control list
|
||||
|
||||
; version.bind.
|
||||
; allow
|
||||
STEP 1 QUERY ADDRESS 20.1.2.3
|
||||
ENTRY_BEGIN
|
||||
SECTION QUESTION
|
||||
version.bind. CH TXT
|
||||
ENTRY_END
|
||||
STEP 2 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RA
|
||||
SECTION QUESTION
|
||||
version.bind. CH TXT
|
||||
SECTION ANSWER
|
||||
version.bind. 0 CH TXT "test-version"
|
||||
ENTRY_END
|
||||
|
||||
; refuse
|
||||
STEP 3 QUERY ADDRESS 20.40.2.3
|
||||
ENTRY_BEGIN
|
||||
SECTION QUESTION
|
||||
version.bind. CH TXT
|
||||
ENTRY_END
|
||||
STEP 4 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR REFUSED
|
||||
ENTRY_END
|
||||
|
||||
; deny (drop)
|
||||
STEP 5 QUERY ADDRESS 20.40.80.3
|
||||
ENTRY_BEGIN
|
||||
SECTION QUESTION
|
||||
version.bind. CH TXT
|
||||
ENTRY_END
|
||||
|
||||
; no answer must be pending
|
||||
|
||||
SCENARIO_END
|
||||
Vendored
+60
@@ -0,0 +1,60 @@
|
||||
; config options
|
||||
; The island of trust is at example.com
|
||||
server:
|
||||
local-zone: "10.in-addr.arpa" nodefault
|
||||
|
||||
stub-zone:
|
||||
name: "."
|
||||
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
|
||||
CONFIG_END
|
||||
|
||||
SCENARIO_BEGIN Test local data with nodefault for as112 zone.
|
||||
|
||||
; K.ROOT-SERVERS.NET.
|
||||
RANGE_BEGIN 0 100
|
||||
ADDRESS 193.0.14.129
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
. IN NS
|
||||
SECTION ANSWER
|
||||
. IN NS K.ROOT-SERVERS.NET.
|
||||
SECTION ADDITIONAL
|
||||
K.ROOT-SERVERS.NET. IN A 193.0.14.129
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NXDOMAIN
|
||||
SECTION QUESTION
|
||||
40.30.20.10.in-addr-arpa. IN PTR
|
||||
SECTION ANSWER
|
||||
SECTION AUTHORITY
|
||||
. IN SOA invalid. invalid. 1 2 3 4 5
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
STEP 1 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD DO
|
||||
SECTION QUESTION
|
||||
40.30.20.10.in-addr-arpa. IN PTR
|
||||
ENTRY_END
|
||||
; not blocked!
|
||||
|
||||
; recursion happens here.
|
||||
STEP 10 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RD RA NXDOMAIN
|
||||
SECTION QUESTION
|
||||
40.30.20.10.in-addr-arpa. IN PTR
|
||||
SECTION ANSWER
|
||||
SECTION AUTHORITY
|
||||
. IN SOA invalid. invalid. 1 2 3 4 5
|
||||
ENTRY_END
|
||||
|
||||
SCENARIO_END
|
||||
Vendored
+321
@@ -0,0 +1,321 @@
|
||||
; config options
|
||||
server:
|
||||
hide-identity: no
|
||||
hide-version: no
|
||||
identity: "test-identity"
|
||||
version: "test-version"
|
||||
|
||||
; implicit transparent zone should not block id.server
|
||||
local-data: "mydata.server. CH A 10.11.12.13"
|
||||
local-data: "myd2.server. CH A 10.11.12.14"
|
||||
local-data: 'myd3.server. CH TXT "a text record"'
|
||||
; together implicit CH top domain .server is created transparent.
|
||||
|
||||
; static zone
|
||||
local-zone: "local" static
|
||||
local-data: "local SOA nobody nobody 1 2 3 4 5"
|
||||
local-data: "serv.local. A 20.30.40.50"
|
||||
; multiple RRs in this RRset.
|
||||
local-data: "bla.bla.local. A 20.30.40.51"
|
||||
local-data: "bla.bla.local. A 20.30.40.52"
|
||||
local-data: "bla.bla.local. A 20.30.40.53"
|
||||
|
||||
; static zone (no soa)
|
||||
local-zone: "noso.local" static
|
||||
local-data: "bla.bla.noso.local AAAA 2001::2"
|
||||
|
||||
; deny zone (no answer)
|
||||
local-zone: "deny.top." deny
|
||||
|
||||
; refuse zone (error)
|
||||
local-zone: "refuse.top." refuse
|
||||
|
||||
; create implicit data in the IN domain as well
|
||||
local-data: "a.a.implicit. A 20.30.41.50"
|
||||
local-data: "b.a.implicit. A 20.30.42.50"
|
||||
local-data: "b.b.implicit. A 20.30.43.50"
|
||||
local-data: "b.c.implicit. A 20.30.45.50"
|
||||
local-data: "c.c.implicit. A 20.30.44.50"
|
||||
|
||||
CONFIG_END
|
||||
SCENARIO_BEGIN Test local data queries
|
||||
|
||||
; id.server.
|
||||
STEP 1 QUERY
|
||||
ENTRY_BEGIN
|
||||
SECTION QUESTION
|
||||
id.server. CH TXT
|
||||
ENTRY_END
|
||||
STEP 2 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RA
|
||||
SECTION QUESTION
|
||||
id.server. CH TXT
|
||||
SECTION ANSWER
|
||||
id.server. 0 CH TXT "test-identity"
|
||||
ENTRY_END
|
||||
|
||||
; mydata.server.
|
||||
STEP 3 QUERY
|
||||
ENTRY_BEGIN
|
||||
SECTION QUESTION
|
||||
mydata.server. CH A
|
||||
ENTRY_END
|
||||
STEP 4 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RA AA
|
||||
SECTION QUESTION
|
||||
mydata.server. CH A
|
||||
SECTION ANSWER
|
||||
mydata.server. 3600 CH A 10.11.12.13
|
||||
ENTRY_END
|
||||
|
||||
; nodata with SOA
|
||||
STEP 5 QUERY
|
||||
ENTRY_BEGIN
|
||||
SECTION QUESTION
|
||||
local. IN A
|
||||
ENTRY_END
|
||||
STEP 6 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RA AA
|
||||
SECTION QUESTION
|
||||
local. IN A
|
||||
SECTION AUTHORITY
|
||||
local. 3600 IN SOA nobody nobody 1 2 3 4 5
|
||||
ENTRY_END
|
||||
|
||||
; positive SOA
|
||||
STEP 7 QUERY
|
||||
ENTRY_BEGIN
|
||||
SECTION QUESTION
|
||||
local. IN SOA
|
||||
ENTRY_END
|
||||
STEP 8 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RA AA
|
||||
SECTION QUESTION
|
||||
local. IN SOA
|
||||
SECTION ANSWER
|
||||
local. 3600 IN SOA nobody nobody 1 2 3 4 5
|
||||
ENTRY_END
|
||||
|
||||
; positive subdomain
|
||||
STEP 9 QUERY
|
||||
ENTRY_BEGIN
|
||||
SECTION QUESTION
|
||||
serv.local. IN A
|
||||
ENTRY_END
|
||||
STEP 10 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RA AA
|
||||
SECTION QUESTION
|
||||
serv.local. IN A
|
||||
SECTION ANSWER
|
||||
serv.local. IN A 20.30.40.50
|
||||
ENTRY_END
|
||||
|
||||
; no such type
|
||||
STEP 11 QUERY
|
||||
ENTRY_BEGIN
|
||||
SECTION QUESTION
|
||||
serv.local. IN MX
|
||||
ENTRY_END
|
||||
STEP 12 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RA AA
|
||||
SECTION QUESTION
|
||||
serv.local. IN MX
|
||||
SECTION AUTHORITY
|
||||
local. 3600 IN SOA nobody nobody 1 2 3 4 5
|
||||
ENTRY_END
|
||||
|
||||
; no such type, empty nonterminal
|
||||
STEP 13 QUERY
|
||||
ENTRY_BEGIN
|
||||
SECTION QUESTION
|
||||
bla.local. IN MX
|
||||
ENTRY_END
|
||||
STEP 14 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RA AA
|
||||
SECTION QUESTION
|
||||
bla.local. IN MX
|
||||
SECTION AUTHORITY
|
||||
local. 3600 IN SOA nobody nobody 1 2 3 4 5
|
||||
ENTRY_END
|
||||
|
||||
; nxdomain with SOA
|
||||
STEP 15 QUERY
|
||||
ENTRY_BEGIN
|
||||
SECTION QUESTION
|
||||
doing.local. IN MX
|
||||
ENTRY_END
|
||||
STEP 16 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RA AA NXDOMAIN
|
||||
SECTION QUESTION
|
||||
doing.local. IN MX
|
||||
SECTION AUTHORITY
|
||||
local. 3600 IN SOA nobody nobody 1 2 3 4 5
|
||||
ENTRY_END
|
||||
|
||||
; nxdomain without SOA
|
||||
STEP 17 QUERY
|
||||
ENTRY_BEGIN
|
||||
SECTION QUESTION
|
||||
doing.noso.local. IN MX
|
||||
ENTRY_END
|
||||
STEP 18 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RA AA NXDOMAIN
|
||||
SECTION QUESTION
|
||||
doing.noso.local. IN MX
|
||||
ENTRY_END
|
||||
|
||||
; positive multiple RR
|
||||
STEP 19 QUERY
|
||||
ENTRY_BEGIN
|
||||
SECTION QUESTION
|
||||
bla.bla.local. IN A
|
||||
ENTRY_END
|
||||
STEP 20 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RA AA
|
||||
SECTION QUESTION
|
||||
bla.bla.local. IN A
|
||||
SECTION ANSWER
|
||||
bla.bla.local. IN A 20.30.40.51
|
||||
bla.bla.local. IN A 20.30.40.52
|
||||
bla.bla.local. IN A 20.30.40.53
|
||||
ENTRY_END
|
||||
|
||||
; second implicit transparent zone.
|
||||
STEP 21 QUERY
|
||||
ENTRY_BEGIN
|
||||
SECTION QUESTION
|
||||
b.b.implicit. IN A
|
||||
ENTRY_END
|
||||
STEP 22 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RA AA
|
||||
SECTION QUESTION
|
||||
b.b.implicit. IN A
|
||||
SECTION ANSWER
|
||||
b.b.implicit. 3600 IN A 20.30.43.50
|
||||
ENTRY_END
|
||||
|
||||
; localhost A default
|
||||
STEP 30 QUERY
|
||||
ENTRY_BEGIN
|
||||
SECTION QUESTION
|
||||
localhost. IN A
|
||||
ENTRY_END
|
||||
STEP 31 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RA AA
|
||||
SECTION QUESTION
|
||||
localhost. IN A
|
||||
SECTION ANSWER
|
||||
localhost. 10800 IN A 127.0.0.1
|
||||
ENTRY_END
|
||||
|
||||
; localhost AAAA default
|
||||
STEP 32 QUERY
|
||||
ENTRY_BEGIN
|
||||
SECTION QUESTION
|
||||
localhost. IN AAAA
|
||||
ENTRY_END
|
||||
STEP 33 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RA AA
|
||||
SECTION QUESTION
|
||||
localhost. IN AAAA
|
||||
SECTION ANSWER
|
||||
localhost. 10800 IN AAAA ::1
|
||||
ENTRY_END
|
||||
|
||||
; localhost A reverse default
|
||||
STEP 34 QUERY
|
||||
ENTRY_BEGIN
|
||||
SECTION QUESTION
|
||||
1.0.0.127.in-addr.arpa. IN PTR
|
||||
ENTRY_END
|
||||
STEP 35 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RA AA
|
||||
SECTION QUESTION
|
||||
1.0.0.127.in-addr.arpa. IN PTR
|
||||
SECTION ANSWER
|
||||
1.0.0.127.in-addr.arpa. 10800 IN PTR localhost.
|
||||
ENTRY_END
|
||||
|
||||
; localhost AAAA reverse default
|
||||
STEP 36 QUERY
|
||||
ENTRY_BEGIN
|
||||
SECTION QUESTION
|
||||
1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. IN PTR
|
||||
ENTRY_END
|
||||
STEP 37 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RA AA
|
||||
SECTION QUESTION
|
||||
1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. IN PTR
|
||||
SECTION ANSWER
|
||||
1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. 10800 IN PTR localhost.
|
||||
ENTRY_END
|
||||
|
||||
; blocked AS112 reverse default
|
||||
STEP 38 QUERY
|
||||
ENTRY_BEGIN
|
||||
SECTION QUESTION
|
||||
1.0.0.10.in-addr.arpa. IN PTR
|
||||
ENTRY_END
|
||||
STEP 39 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RA AA NXDOMAIN
|
||||
SECTION QUESTION
|
||||
1.0.0.10.in-addr.arpa. IN PTR
|
||||
SECTION AUTHORITY
|
||||
10.in-addr.arpa. 10800 IN SOA localhost. nobody.invalid. 1 3600 1200 604800 10800
|
||||
ENTRY_END
|
||||
|
||||
; refuse zone
|
||||
STEP 40 QUERY
|
||||
ENTRY_BEGIN
|
||||
SECTION QUESTION
|
||||
www.refuse.top. IN A
|
||||
ENTRY_END
|
||||
STEP 41 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RA AA REFUSED
|
||||
SECTION QUESTION
|
||||
www.refuse.top. IN A
|
||||
ENTRY_END
|
||||
|
||||
; deny zone
|
||||
STEP 42 QUERY
|
||||
ENTRY_BEGIN
|
||||
SECTION QUESTION
|
||||
www.deny.top. IN A
|
||||
ENTRY_END
|
||||
; no answer is checked at exit of testbound.
|
||||
|
||||
SCENARIO_END
|
||||
Vendored
+150
@@ -0,0 +1,150 @@
|
||||
; config options
|
||||
; The island of trust is at example.com
|
||||
server:
|
||||
trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
|
||||
val-override-date: "20070916134226"
|
||||
|
||||
stub-zone:
|
||||
name: "."
|
||||
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
|
||||
CONFIG_END
|
||||
|
||||
SCENARIO_BEGIN Test validator with cname-nxdomain for duplicate NSEC detection
|
||||
|
||||
; K.ROOT-SERVERS.NET.
|
||||
RANGE_BEGIN 0 100
|
||||
ADDRESS 193.0.14.129
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
. IN NS
|
||||
SECTION ANSWER
|
||||
. IN NS K.ROOT-SERVERS.NET.
|
||||
SECTION ADDITIONAL
|
||||
K.ROOT-SERVERS.NET. IN A 193.0.14.129
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
cname.example.com. IN A
|
||||
SECTION AUTHORITY
|
||||
com. IN NS a.gtld-servers.net.
|
||||
SECTION ADDITIONAL
|
||||
a.gtld-servers.net. IN A 192.5.6.30
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
; a.gtld-servers.net.
|
||||
RANGE_BEGIN 0 100
|
||||
ADDRESS 192.5.6.30
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
cname.example.com. IN A
|
||||
SECTION AUTHORITY
|
||||
example.com. IN NS ns.example.com.
|
||||
SECTION ADDITIONAL
|
||||
ns.example.com. IN A 1.2.3.4
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
; ns.example.com.
|
||||
RANGE_BEGIN 0 100
|
||||
ADDRESS 1.2.3.4
|
||||
|
||||
; response to DNSKEY priming query
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
example.com. IN DNSKEY
|
||||
SECTION ANSWER
|
||||
example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}
|
||||
example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854}
|
||||
SECTION AUTHORITY
|
||||
example.com. IN NS ns.example.com.
|
||||
example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
|
||||
SECTION ADDITIONAL
|
||||
ns.example.com. IN A 1.2.3.4
|
||||
ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
|
||||
ENTRY_END
|
||||
|
||||
; response to query of interest
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NXDOMAIN
|
||||
SECTION QUESTION
|
||||
cname.example.com. IN A
|
||||
SECTION ANSWER
|
||||
cname.example.com. 3600 IN CNAME www.example.com.
|
||||
cname.example.com. 3600 IN RRSIG CNAME 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFBhJC8qi+g+EOYqzT2q6RxE8Im09AhUAotz8NFnpY+cpEDNBKjM940a74/E= ;{id = 2854}
|
||||
SECTION AUTHORITY
|
||||
; already includes the necessary NSECs
|
||||
example.com. IN SOA ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000
|
||||
example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFCNGZ+/OfElYQMCZ77O9Lw9rhk7PAhUAmDcvTAst6Bq83qPq3r6c/Dm1nFc= ;{id = 2854}
|
||||
; wildcard denial
|
||||
example.com. IN NSEC abc.example.com. SOA NS DNSKEY NSEC RRSIG
|
||||
example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFHV2IBWyTmDJvZ+sT+WsGrJX0op/AhQkAijjnjPAtx/tNub2FAGqcexJSg== ;{id = 2854}
|
||||
; qname denial
|
||||
wab.example.com. IN NSEC wzz.example.com. A NSEC RRSIG
|
||||
wab.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFG5DZSEIZC088rjcB1e6sQx8nQz4AhUAtQ09tP1YYLJkhL/Wg1KV2pW4Ivk= ;{id = 2854}
|
||||
SECTIO ADDITIONAL
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NXDOMAIN
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
SECTION ANSWER
|
||||
SECTION AUTHORITY
|
||||
example.com. IN SOA ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000
|
||||
example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFCNGZ+/OfElYQMCZ77O9Lw9rhk7PAhUAmDcvTAst6Bq83qPq3r6c/Dm1nFc= ;{id = 2854}
|
||||
; wildcard denial
|
||||
example.com. IN NSEC abc.example.com. SOA NS DNSKEY NSEC RRSIG
|
||||
example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFHV2IBWyTmDJvZ+sT+WsGrJX0op/AhQkAijjnjPAtx/tNub2FAGqcexJSg== ;{id = 2854}
|
||||
; qname denial
|
||||
wab.example.com. IN NSEC wzz.example.com. A NSEC RRSIG
|
||||
wab.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFG5DZSEIZC088rjcB1e6sQx8nQz4AhUAtQ09tP1YYLJkhL/Wg1KV2pW4Ivk= ;{id = 2854}
|
||||
SECTIO ADDITIONAL
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
STEP 1 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD DO
|
||||
SECTION QUESTION
|
||||
cname.example.com. IN A
|
||||
ENTRY_END
|
||||
|
||||
; recursion happens here.
|
||||
STEP 10 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RD RA AD NOERROR
|
||||
SECTION QUESTION
|
||||
cname.example.com. IN A
|
||||
SECTION ANSWER
|
||||
cname.example.com. 3600 IN CNAME www.example.com.
|
||||
cname.example.com. 3600 IN RRSIG CNAME 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFBhJC8qi+g+EOYqzT2q6RxE8Im09AhUAotz8NFnpY+cpEDNBKjM940a74/E= ;{id = 2854}
|
||||
SECTION AUTHORITY
|
||||
example.com. IN SOA ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000
|
||||
example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFCNGZ+/OfElYQMCZ77O9Lw9rhk7PAhUAmDcvTAst6Bq83qPq3r6c/Dm1nFc= ;{id = 2854}
|
||||
example.com. IN NSEC abc.example.com. SOA NS DNSKEY NSEC RRSIG
|
||||
example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFHV2IBWyTmDJvZ+sT+WsGrJX0op/AhQkAijjnjPAtx/tNub2FAGqcexJSg== ;{id = 2854}
|
||||
wab.example.com. IN NSEC wzz.example.com. A NSEC RRSIG
|
||||
wab.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFG5DZSEIZC088rjcB1e6sQx8nQz4AhUAtQ09tP1YYLJkhL/Wg1KV2pW4Ivk= ;{id = 2854}
|
||||
SECTION ADDITIONAL
|
||||
ENTRY_END
|
||||
|
||||
SCENARIO_END
|
||||
Vendored
+183
@@ -0,0 +1,183 @@
|
||||
; config options
|
||||
; The island of trust is at example.com
|
||||
server:
|
||||
trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
|
||||
trust-anchor: "example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}"
|
||||
val-override-date: "20070916134226"
|
||||
|
||||
stub-zone:
|
||||
name: "."
|
||||
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
|
||||
CONFIG_END
|
||||
|
||||
SCENARIO_BEGIN Test validator with cname-nxdomain with rcode nxdomain
|
||||
|
||||
; K.ROOT-SERVERS.NET.
|
||||
RANGE_BEGIN 0 100
|
||||
ADDRESS 193.0.14.129
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
. IN NS
|
||||
SECTION ANSWER
|
||||
. IN NS K.ROOT-SERVERS.NET.
|
||||
SECTION ADDITIONAL
|
||||
K.ROOT-SERVERS.NET. IN A 193.0.14.129
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
SECTION AUTHORITY
|
||||
com. IN NS a.gtld-servers.net.
|
||||
SECTION ADDITIONAL
|
||||
a.gtld-servers.net. IN A 192.5.6.30
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
www.example.net. IN A
|
||||
SECTION AUTHORITY
|
||||
net. IN NS a.gtld-servers.net.
|
||||
SECTION ADDITIONAL
|
||||
a.gtld-servers.net. IN A 192.5.6.30
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
; a.gtld-servers.net.
|
||||
RANGE_BEGIN 0 100
|
||||
ADDRESS 192.5.6.30
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
SECTION AUTHORITY
|
||||
example.com. IN NS ns.example.com.
|
||||
SECTION ADDITIONAL
|
||||
ns.example.com. IN A 1.2.3.4
|
||||
ENTRY_END
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
www.example.net. IN A
|
||||
SECTION AUTHORITY
|
||||
example.net. IN NS ns.example.net.
|
||||
SECTION ADDITIONAL
|
||||
ns.example.net. IN A 1.2.3.5
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
; ns.example.com.
|
||||
RANGE_BEGIN 0 100
|
||||
ADDRESS 1.2.3.4
|
||||
|
||||
; response to DNSKEY priming query
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
example.com. IN DNSKEY
|
||||
SECTION ANSWER
|
||||
example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}
|
||||
example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854}
|
||||
SECTION AUTHORITY
|
||||
example.com. IN NS ns.example.com.
|
||||
example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
|
||||
SECTION ADDITIONAL
|
||||
ns.example.com. IN A 1.2.3.4
|
||||
ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
|
||||
ENTRY_END
|
||||
|
||||
; response to query of interest
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NXDOMAIN
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
SECTION ANSWER
|
||||
www.example.com. 3600 IN CNAME www.example.net.
|
||||
www.example.com. 3600 IN RRSIG CNAME 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFGtYzScyRnHV8U/jOIPYwrlI9t3oAhRF0PIf+IthUR7uCWIvskWp5CfReQ== ;{id = 2854}
|
||||
SECTION AUTHORITY
|
||||
SECTION ADDITIONAL
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
; ns.example.net.
|
||||
RANGE_BEGIN 0 100
|
||||
ADDRESS 1.2.3.5
|
||||
|
||||
; response to DNSKEY priming query
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
example.net. IN DNSKEY
|
||||
SECTION ANSWER
|
||||
example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}
|
||||
example.net. 3600 IN RRSIG DNSKEY RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. hiFzlQ8VoYgCuvIsfVuxC3mfJDqsTh0yc6abs5xMx5uEcIjb0dndFQx7INOM+imlzveEN73Hqp4OLFpFhsWLlw== ;{id = 30899}
|
||||
SECTION AUTHORITY
|
||||
example.net. IN NS ns.example.net.
|
||||
example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899}
|
||||
SECTION ADDITIONAL
|
||||
ns.example.net. IN A 1.2.3.5
|
||||
ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899}
|
||||
ENTRY_END
|
||||
|
||||
; response to query of interest
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NXDOMAIN
|
||||
SECTION QUESTION
|
||||
www.example.net. IN A
|
||||
SECTION ANSWER
|
||||
SECTION AUTHORITY
|
||||
example.net. IN NSEC abc.example.net. SOA NS DNSKEY NSEC RRSIG
|
||||
example.net. 3600 IN RRSIG NSEC 5 2 3600 20070926134150 20070829134150 30899 example.net. SEHthmjHyqGlzaOp3Dx6Jn5Fnvvtknw/IF6YSFY8NZLe+YSh1oRJbdEkQ8G92IT08n1jSN6jvKRsFBOUoFOQAw== ;{id = 30899}
|
||||
wab.example.net. IN NSEC wzz.example.net. A NSEC RRSIG
|
||||
wab.example.net. 3600 IN RRSIG NSEC 5 3 3600 20070926134150 20070829134150 30899 example.net. gl8vkI3xfSWx4Pyv5OdOthiewE6u/13kclY7UG9ptuFBddamdJO3RQqyxM6Xcmq+ToO4kMCCyaKijp01gTDoGg== ;{id = 30899}
|
||||
SECTION ADDITIONAL
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
STEP 1 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD DO
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
ENTRY_END
|
||||
|
||||
; recursion happens here.
|
||||
STEP 10 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RD RA AD NOERROR
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
SECTION ANSWER
|
||||
www.example.com. IN CNAME www.example.net.
|
||||
www.example.com. 3600 IN RRSIG CNAME 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFGtYzScyRnHV8U/jOIPYwrlI9t3oAhRF0PIf+IthUR7uCWIvskWp5CfReQ== ;{id = 2854}
|
||||
SECTION AUTHORITY
|
||||
example.net. IN NSEC abc.example.net. SOA NS DNSKEY NSEC RRSIG
|
||||
example.net. 3600 IN RRSIG NSEC 5 2 3600 20070926134150 20070829134150 30899 example.net. SEHthmjHyqGlzaOp3Dx6Jn5Fnvvtknw/IF6YSFY8NZLe+YSh1oRJbdEkQ8G92IT08n1jSN6jvKRsFBOUoFOQAw== ;{id = 30899}
|
||||
wab.example.net. IN NSEC wzz.example.net. A NSEC RRSIG
|
||||
wab.example.net. 3600 IN RRSIG NSEC 5 3 3600 20070926134150 20070829134150 30899 example.net. gl8vkI3xfSWx4Pyv5OdOthiewE6u/13kclY7UG9ptuFBddamdJO3RQqyxM6Xcmq+ToO4kMCCyaKijp01gTDoGg== ;{id = 30899}
|
||||
SECTION ADDITIONAL
|
||||
ENTRY_END
|
||||
|
||||
SCENARIO_END
|
||||
+39
-3
@@ -89,7 +89,7 @@ config_create()
|
||||
cfg->host_ttl = 900;
|
||||
cfg->lame_ttl = 900;
|
||||
cfg->bogus_ttl = 900;
|
||||
cfg->max_ttl = 3600 * 24 * 10;
|
||||
cfg->max_ttl = 3600 * 24;
|
||||
cfg->infra_cache_slabs = 4;
|
||||
cfg->infra_cache_numhosts = 10000;
|
||||
cfg->infra_cache_lame_size = 10240; /* easily 40 or more entries */
|
||||
@@ -110,6 +110,7 @@ config_create()
|
||||
cfg->out_ifs = NULL;
|
||||
cfg->stubs = NULL;
|
||||
cfg->forwards = NULL;
|
||||
cfg->acls = NULL;
|
||||
cfg->harden_short_bufsize = 0;
|
||||
cfg->harden_large_queries = 0;
|
||||
cfg->harden_glue = 1;
|
||||
@@ -126,6 +127,9 @@ config_create()
|
||||
cfg->val_permissive_mode = 0;
|
||||
cfg->key_cache_size = 4 * 1024 * 1024;
|
||||
cfg->key_cache_slabs = 4;
|
||||
cfg->local_zones = NULL;
|
||||
cfg->local_zones_nodefault = NULL;
|
||||
cfg->local_data = NULL;
|
||||
if(!(cfg->module_conf = strdup("validator iterator"))) goto error_exit;
|
||||
if(!(cfg->val_nsec3_key_iterations =
|
||||
strdup("1024 150 2048 500 4096 2500"))) goto error_exit;
|
||||
@@ -171,8 +175,7 @@ config_read(struct config_file* cfg, char* filename)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** delete config strlist */
|
||||
static void
|
||||
void
|
||||
config_delstrlist(struct config_strlist* p)
|
||||
{
|
||||
struct config_strlist *np;
|
||||
@@ -184,6 +187,19 @@ config_delstrlist(struct config_strlist* p)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
config_deldblstrlist(struct config_str2list* p)
|
||||
{
|
||||
struct config_str2list *np;
|
||||
while(p) {
|
||||
np = p->next;
|
||||
free(p->str);
|
||||
free(p->str2);
|
||||
free(p);
|
||||
p = np;
|
||||
}
|
||||
}
|
||||
|
||||
/** delete config stublist */
|
||||
static void
|
||||
config_delstubs(struct config_stub* p)
|
||||
@@ -231,7 +247,11 @@ config_delete(struct config_file* cfg)
|
||||
config_delstrlist(cfg->trust_anchor_file_list);
|
||||
config_delstrlist(cfg->trusted_keys_file_list);
|
||||
config_delstrlist(cfg->trust_anchor_list);
|
||||
config_deldblstrlist(cfg->acls);
|
||||
free(cfg->val_nsec3_key_iterations);
|
||||
config_deldblstrlist(cfg->local_zones);
|
||||
config_delstrlist(cfg->local_zones_nodefault);
|
||||
config_delstrlist(cfg->local_data);
|
||||
free(cfg);
|
||||
}
|
||||
|
||||
@@ -281,6 +301,22 @@ cfg_strlist_insert(struct config_strlist** head, char* item)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
cfg_str2list_insert(struct config_str2list** head, char* item, char* i2)
|
||||
{
|
||||
struct config_str2list *s;
|
||||
if(!item || !i2 || !head)
|
||||
return 0;
|
||||
s = (struct config_str2list*)calloc(1, sizeof(struct config_str2list));
|
||||
if(!s)
|
||||
return 0;
|
||||
s->str = item;
|
||||
s->str2 = i2;
|
||||
s->next = *head;
|
||||
*head = s;
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
cfg_convert_timeval(const char* str)
|
||||
{
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#define UTIL_CONFIG_FILE_H
|
||||
struct config_stub;
|
||||
struct config_strlist;
|
||||
struct config_str2list;
|
||||
|
||||
/**
|
||||
* The configuration options.
|
||||
@@ -120,6 +121,8 @@ struct config_file {
|
||||
struct config_stub* forwards;
|
||||
/** list of donotquery addresses, linked list */
|
||||
struct config_strlist* donotqueryaddrs;
|
||||
/** list of access control entries, linked list */
|
||||
struct config_str2list* acls;
|
||||
/** use default localhost donotqueryaddr entries */
|
||||
int donotquery_localhost;
|
||||
|
||||
@@ -183,6 +186,13 @@ struct config_file {
|
||||
/** slabs in the key cache. */
|
||||
size_t key_cache_slabs;
|
||||
|
||||
/** local zones config */
|
||||
struct config_str2list* local_zones;
|
||||
/** local zones nodefault list */
|
||||
struct config_strlist* local_zones_nodefault;
|
||||
/** local data RRs configged */
|
||||
struct config_strlist* local_data;
|
||||
|
||||
/** daemonize, i.e. fork into the background. */
|
||||
int do_daemonize;
|
||||
};
|
||||
@@ -211,6 +221,18 @@ struct config_strlist {
|
||||
char* str;
|
||||
};
|
||||
|
||||
/**
|
||||
* List of two strings for config options
|
||||
*/
|
||||
struct config_str2list {
|
||||
/** next item in list */
|
||||
struct config_str2list* next;
|
||||
/** first string */
|
||||
char* str;
|
||||
/** second string */
|
||||
char* str2;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create config file structure. Filled with default values.
|
||||
* @return: the new structure or NULL on memory error.
|
||||
@@ -245,6 +267,27 @@ void config_apply(struct config_file* config);
|
||||
*/
|
||||
int cfg_strlist_insert(struct config_strlist** head, char* item);
|
||||
|
||||
/**
|
||||
* Insert string into str2list.
|
||||
* @param head: pointer to str2list head variable.
|
||||
* @param item: new item. malloced by caller. If NULL the insertion fails.
|
||||
* @param i2: 2nd string, malloced by caller. If NULL the insertion fails.
|
||||
* @return: true on success.
|
||||
*/
|
||||
int cfg_str2list_insert(struct config_str2list** head, char* item, char* i2);
|
||||
|
||||
/**
|
||||
* Delete items in config string list.
|
||||
* @param list: list.
|
||||
*/
|
||||
void config_delstrlist(struct config_strlist* list);
|
||||
|
||||
/**
|
||||
* Delete items in config double string list.
|
||||
* @param list: list.
|
||||
*/
|
||||
void config_deldblstrlist(struct config_str2list* list);
|
||||
|
||||
/**
|
||||
* Convert 14digit to time value
|
||||
* @param str: string of 14 digits
|
||||
|
||||
+735
-646
File diff suppressed because it is too large
Load Diff
+27
-5
@@ -87,13 +87,14 @@ static void config_end_include(void)
|
||||
|
||||
SPACE [ \t]
|
||||
LETTER [a-zA-Z]
|
||||
UNQUOTEDLETTER [^\"\n\r \t\\]|\\.
|
||||
UNQUOTEDLETTER [^\'\"\n\r \t\\]|\\.
|
||||
NEWLINE [\r\n]
|
||||
COMMENT \#
|
||||
COLON \:
|
||||
ANY [^\"\n\r\\]|\\.
|
||||
DQANY [^\"\n\r\\]|\\.
|
||||
SQANY [^\'\n\r\\]|\\.
|
||||
|
||||
%x quotedstring include include_quoted
|
||||
%x quotedstring singlequotedstr include include_quoted
|
||||
|
||||
%%
|
||||
{SPACE}* { LEXOUT(("SP ")); /* ignore */ }
|
||||
@@ -144,6 +145,7 @@ 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;}
|
||||
do-not-query-localhost{COLON} { YDOUT; return VAR_DO_NOT_QUERY_LOCALHOST;}
|
||||
access-control{COLON} { YDOUT; return VAR_ACCESS_CONTROL;}
|
||||
hide-identity{COLON} { YDOUT; return VAR_HIDE_IDENTITY;}
|
||||
hide-version{COLON} { YDOUT; return VAR_HIDE_VERSION;}
|
||||
identity{COLON} { YDOUT; return VAR_IDENTITY;}
|
||||
@@ -160,6 +162,8 @@ key-cache-size{COLON} { YDOUT; return VAR_KEY_CACHE_SIZE;}
|
||||
key-cache-slabs{COLON} { YDOUT; return VAR_KEY_CACHE_SLABS;}
|
||||
val-nsec3-keysize-iterations{COLON} { YDOUT; return VAR_VAL_NSEC3_KEYSIZE_ITERATIONS;}
|
||||
use-syslog{COLON} { YDOUT; return VAR_USE_SYSLOG;}
|
||||
local-zone{COLON} { YDOUT; return VAR_LOCAL_ZONE;}
|
||||
local-data{COLON} { YDOUT; return VAR_LOCAL_DATA;}
|
||||
{NEWLINE} { LEXOUT(("NL\n")); cfg_parser->line++;}
|
||||
|
||||
/* Quoted strings. Strip leading and ending quotes */
|
||||
@@ -168,7 +172,7 @@ use-syslog{COLON} { YDOUT; return VAR_USE_SYSLOG;}
|
||||
yyerror("EOF inside quoted string");
|
||||
BEGIN(INITIAL);
|
||||
}
|
||||
<quotedstring>{ANY}* { LEXOUT(("STR(%s) ", yytext)); yymore(); }
|
||||
<quotedstring>{DQANY}* { LEXOUT(("STR(%s) ", yytext)); yymore(); }
|
||||
<quotedstring>\n { cfg_parser->line++; yymore(); }
|
||||
<quotedstring>\" {
|
||||
LEXOUT(("QE "));
|
||||
@@ -180,6 +184,24 @@ use-syslog{COLON} { YDOUT; return VAR_USE_SYSLOG;}
|
||||
return STRING;
|
||||
}
|
||||
|
||||
/* Single Quoted strings. Strip leading and ending quotes */
|
||||
\' { BEGIN(singlequotedstr); LEXOUT(("SQS ")); }
|
||||
<singlequotedstr><<EOF>> {
|
||||
yyerror("EOF inside quoted string");
|
||||
BEGIN(INITIAL);
|
||||
}
|
||||
<singlequotedstr>{SQANY}* { LEXOUT(("STR(%s) ", yytext)); yymore(); }
|
||||
<singlequotedstr>\n { cfg_parser->line++; yymore(); }
|
||||
<singlequotedstr>\' {
|
||||
LEXOUT(("SQE "));
|
||||
BEGIN(INITIAL);
|
||||
yytext[yyleng - 1] = '\0';
|
||||
yylval.str = strdup(yytext);
|
||||
if(!yylval.str)
|
||||
yyerror("out of memory");
|
||||
return STRING;
|
||||
}
|
||||
|
||||
/* include: directive */
|
||||
include{COLON} { LEXOUT(("v(%s) ", yytext)); BEGIN(include); }
|
||||
<include><<EOF>> {
|
||||
@@ -198,7 +220,7 @@ include{COLON} { LEXOUT(("v(%s) ", yytext)); BEGIN(include); }
|
||||
yyerror("EOF inside quoted string");
|
||||
BEGIN(INITIAL);
|
||||
}
|
||||
<include_quoted>{ANY}* { LEXOUT(("ISTR(%s) ", yytext)); yymore(); }
|
||||
<include_quoted>{DQANY}* { LEXOUT(("ISTR(%s) ", yytext)); yymore(); }
|
||||
<include_quoted>{NEWLINE} { cfg_parser->line++; yymore(); }
|
||||
<include_quoted>\" {
|
||||
LEXOUT(("IQE "));
|
||||
|
||||
+338
-272
File diff suppressed because it is too large
Load Diff
+8
-2
@@ -108,7 +108,10 @@
|
||||
VAR_ROOT_HINTS = 324,
|
||||
VAR_DO_NOT_QUERY_LOCALHOST = 325,
|
||||
VAR_CACHE_MAX_TTL = 326,
|
||||
VAR_HARDEN_DNNSEC_STRIPPED = 327
|
||||
VAR_HARDEN_DNNSEC_STRIPPED = 327,
|
||||
VAR_ACCESS_CONTROL = 328,
|
||||
VAR_LOCAL_ZONE = 329,
|
||||
VAR_LOCAL_DATA = 330
|
||||
};
|
||||
#endif
|
||||
/* Tokens. */
|
||||
@@ -182,6 +185,9 @@
|
||||
#define VAR_DO_NOT_QUERY_LOCALHOST 325
|
||||
#define VAR_CACHE_MAX_TTL 326
|
||||
#define VAR_HARDEN_DNNSEC_STRIPPED 327
|
||||
#define VAR_ACCESS_CONTROL 328
|
||||
#define VAR_LOCAL_ZONE 329
|
||||
#define VAR_LOCAL_DATA 330
|
||||
|
||||
|
||||
|
||||
@@ -193,7 +199,7 @@ typedef union YYSTYPE
|
||||
char* str;
|
||||
}
|
||||
/* Line 1489 of yacc.c. */
|
||||
#line 197 "util/configparser.h"
|
||||
#line 203 "util/configparser.h"
|
||||
YYSTYPE;
|
||||
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
|
||||
# define YYSTYPE_IS_DECLARED 1
|
||||
|
||||
+43
-2
@@ -86,7 +86,8 @@ extern struct config_parser_state* cfg_parser;
|
||||
%token VAR_KEY_CACHE_SLABS VAR_TRUSTED_KEYS_FILE
|
||||
%token VAR_VAL_NSEC3_KEYSIZE_ITERATIONS VAR_USE_SYSLOG
|
||||
%token VAR_OUTGOING_INTERFACE VAR_ROOT_HINTS VAR_DO_NOT_QUERY_LOCALHOST
|
||||
%token VAR_CACHE_MAX_TTL VAR_HARDEN_DNNSEC_STRIPPED
|
||||
%token VAR_CACHE_MAX_TTL VAR_HARDEN_DNNSEC_STRIPPED VAR_ACCESS_CONTROL
|
||||
%token VAR_LOCAL_ZONE VAR_LOCAL_DATA
|
||||
|
||||
%%
|
||||
toplevelvars: /* empty */ | toplevelvars toplevelvar ;
|
||||
@@ -124,7 +125,8 @@ content_server: server_num_threads | server_verbosity | server_port |
|
||||
server_trusted_keys_file | server_val_nsec3_keysize_iterations |
|
||||
server_use_syslog | server_outgoing_interface | server_root_hints |
|
||||
server_do_not_query_localhost | server_cache_max_ttl |
|
||||
server_harden_dnssec_stripped
|
||||
server_harden_dnssec_stripped | server_access_control |
|
||||
server_local_zone | server_local_data
|
||||
;
|
||||
stubstart: VAR_STUB_ZONE
|
||||
{
|
||||
@@ -574,6 +576,19 @@ server_do_not_query_localhost: VAR_DO_NOT_QUERY_LOCALHOST STRING
|
||||
free($2);
|
||||
}
|
||||
;
|
||||
server_access_control: VAR_ACCESS_CONTROL STRING STRING
|
||||
{
|
||||
OUTYY(("P(server_access_control:%s %s)\n", $2, $3));
|
||||
if(strcmp($3, "deny")!=0 && strcmp($3, "refuse")!=0 &&
|
||||
strcmp($3, "allow")!=0) {
|
||||
yyerror("expected deny, refuse or allow in "
|
||||
"access control action");
|
||||
} else {
|
||||
if(!cfg_str2list_insert(&cfg_parser->cfg->acls, $2, $3))
|
||||
fatal_exit("out of memory adding acl");
|
||||
}
|
||||
}
|
||||
;
|
||||
server_module_conf: VAR_MODULE_CONF STRING
|
||||
{
|
||||
OUTYY(("P(server_module_conf:%s)\n", $2));
|
||||
@@ -666,6 +681,32 @@ server_key_cache_slabs: VAR_KEY_CACHE_SLABS STRING
|
||||
free($2);
|
||||
}
|
||||
;
|
||||
server_local_zone: VAR_LOCAL_ZONE STRING STRING
|
||||
{
|
||||
OUTYY(("P(server_local_zone:%s %s)\n", $2, $3));
|
||||
if(strcmp($3, "static")!=0 && strcmp($3, "deny")!=0 &&
|
||||
strcmp($3, "refuse")!=0 && strcmp($3, "redirect")!=0 &&
|
||||
strcmp($3, "transparent")!=0 && strcmp($3, "nodefault")!=0)
|
||||
yyerror("local-zone type: expected static, deny, "
|
||||
"refuse, redirect, transparent or nodefault");
|
||||
else if(strcmp($3, "nodefault")==0) {
|
||||
if(!cfg_strlist_insert(&cfg_parser->cfg->
|
||||
local_zones_nodefault, $2))
|
||||
fatal_exit("out of memory adding local-zone");
|
||||
} else {
|
||||
if(!cfg_str2list_insert(&cfg_parser->cfg->local_zones,
|
||||
$2, $3))
|
||||
fatal_exit("out of memory adding local-zone");
|
||||
}
|
||||
}
|
||||
;
|
||||
server_local_data: VAR_LOCAL_DATA STRING
|
||||
{
|
||||
OUTYY(("P(server_local_data:%s)\n", $2));
|
||||
if(!cfg_strlist_insert(&cfg_parser->cfg->local_data, $2))
|
||||
fatal_exit("out of memory adding local-data");
|
||||
}
|
||||
;
|
||||
stub_name: VAR_NAME STRING
|
||||
{
|
||||
OUTYY(("P(name:%s)\n", $2));
|
||||
|
||||
@@ -68,7 +68,7 @@ struct rr_parse;
|
||||
struct regional;
|
||||
|
||||
/** number of buckets in parse rrset hash table. Must be power of 2. */
|
||||
#define PARSE_TABLE_SIZE 1024
|
||||
#define PARSE_TABLE_SIZE 32
|
||||
/** Maximum TTL that is allowed. */
|
||||
extern uint32_t MAX_TTL;
|
||||
/** Negative cache time (for entries without any RRs.) */
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
#include "daemon/worker.h"
|
||||
#include "services/outside_network.h"
|
||||
#include "services/mesh.h"
|
||||
#include "services/localzone.h"
|
||||
#include "services/cache/infra.h"
|
||||
#include "iterator/iterator.h"
|
||||
#include "iterator/iter_donotq.h"
|
||||
@@ -64,6 +65,7 @@
|
||||
#include "util/storage/slabhash.h"
|
||||
#include "util/locks.h"
|
||||
#include "testcode/checklocks.h"
|
||||
#include "daemon/acl_list.h"
|
||||
|
||||
int
|
||||
fptr_whitelist_comm_point(comm_point_callback_t *fptr)
|
||||
@@ -130,6 +132,9 @@ fptr_whitelist_rbtree_cmp(int (*fptr) (const void *, const void *))
|
||||
{
|
||||
if(fptr == &mesh_state_compare) return 1;
|
||||
else if(fptr == &mesh_state_ref_compare) return 1;
|
||||
else if(fptr == &acl_list_cmp) return 1;
|
||||
else if(fptr == &local_zone_cmp) return 1;
|
||||
else if(fptr == &local_data_cmp) return 1;
|
||||
else if(fptr == &donotq_cmp) return 1;
|
||||
else if(fptr == &fwd_cmp) return 1;
|
||||
else if(fptr == &stub_cmp) return 1;
|
||||
|
||||
+140
-51
@@ -58,25 +58,25 @@ str_is_ip6(const char* str)
|
||||
int
|
||||
write_socket(int s, const void *buf, size_t size)
|
||||
{
|
||||
const char* data = (const char*)buf;
|
||||
size_t total_count = 0;
|
||||
const char* data = (const char*)buf;
|
||||
size_t total_count = 0;
|
||||
|
||||
fd_set_block(s);
|
||||
while (total_count < size) {
|
||||
ssize_t count
|
||||
= write(s, data + total_count, size - total_count);
|
||||
if (count == -1) {
|
||||
if (errno != EAGAIN && errno != EINTR) {
|
||||
while (total_count < size) {
|
||||
ssize_t count
|
||||
= write(s, data + total_count, size - total_count);
|
||||
if (count == -1) {
|
||||
if (errno != EAGAIN && errno != EINTR) {
|
||||
fd_set_nonblock(s);
|
||||
return 0;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
total_count += count;
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
total_count += count;
|
||||
}
|
||||
fd_set_nonblock(s);
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
@@ -149,27 +149,27 @@ void
|
||||
log_addr(enum verbosity_value v, const char* str,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen)
|
||||
{
|
||||
uint16_t port;
|
||||
const char* family = "unknown";
|
||||
char dest[100];
|
||||
int af = (int)((struct sockaddr_in*)addr)->sin_family;
|
||||
void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr;
|
||||
uint16_t port;
|
||||
const char* family = "unknown";
|
||||
char dest[100];
|
||||
int af = (int)((struct sockaddr_in*)addr)->sin_family;
|
||||
void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr;
|
||||
if(verbosity < v)
|
||||
return;
|
||||
switch(af) {
|
||||
case AF_INET: family="ip4"; break;
|
||||
case AF_INET6: family="ip6";
|
||||
sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr;
|
||||
break;
|
||||
case AF_UNIX: family="unix"; break;
|
||||
default: break;
|
||||
}
|
||||
if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) {
|
||||
strncpy(dest, "(inet_ntop error)", sizeof(dest));
|
||||
}
|
||||
switch(af) {
|
||||
case AF_INET: family="ip4"; break;
|
||||
case AF_INET6: family="ip6";
|
||||
sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr;
|
||||
break;
|
||||
case AF_UNIX: family="unix"; break;
|
||||
default: break;
|
||||
}
|
||||
if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) {
|
||||
strncpy(dest, "(inet_ntop error)", sizeof(dest));
|
||||
}
|
||||
dest[sizeof(dest)-1] = 0;
|
||||
port = ntohs(((struct sockaddr_in*)addr)->sin_port);
|
||||
log_info("%s %s %s %d (len %d)", str, family, dest, (int)port,
|
||||
port = ntohs(((struct sockaddr_in*)addr)->sin_port);
|
||||
log_info("%s %s %s %d (len %d)", str, family, dest, (int)port,
|
||||
(int)addrlen);
|
||||
}
|
||||
|
||||
@@ -229,6 +229,39 @@ ipstrtoaddr(const char* ip, int port, struct sockaddr_storage* addr,
|
||||
return 1;
|
||||
}
|
||||
|
||||
int netblockstrtoaddr(const char* str, int port, struct sockaddr_storage* addr,
|
||||
socklen_t* addrlen, int* net)
|
||||
{
|
||||
char* s = NULL;
|
||||
*net = (str_is_ip6(str)?128:32);
|
||||
if((s=strchr(str, '/'))) {
|
||||
if(atoi(s+1) > *net) {
|
||||
log_err("netblock too large: %s", str);
|
||||
return 0;
|
||||
}
|
||||
*net = atoi(s+1);
|
||||
if(net == 0 && strcmp(s+1, "0") != 0) {
|
||||
log_err("cannot parse netblock: '%s'", str);
|
||||
return 0;
|
||||
}
|
||||
if(!(s = strdup(str))) {
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
*strchr(s, '/') = '\0';
|
||||
}
|
||||
if(!ipstrtoaddr(s?s:str, port, addr, addrlen)) {
|
||||
free(s);
|
||||
log_err("cannot parse ip address: '%s'", str);
|
||||
return 0;
|
||||
}
|
||||
if(s) {
|
||||
free(s);
|
||||
addr_mask(addr, *addrlen, *net);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
log_nametypeclass(enum verbosity_value v, const char* str, uint8_t* name,
|
||||
uint16_t type, uint16_t dclass)
|
||||
@@ -264,32 +297,32 @@ log_nametypeclass(enum verbosity_value v, const char* str, uint8_t* name,
|
||||
void log_name_addr(enum verbosity_value v, const char* str, uint8_t* zone,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen)
|
||||
{
|
||||
uint16_t port;
|
||||
const char* family = "unknown_family ";
|
||||
uint16_t port;
|
||||
const char* family = "unknown_family ";
|
||||
char namebuf[LDNS_MAX_DOMAINLEN+1];
|
||||
char dest[100];
|
||||
int af = (int)((struct sockaddr_in*)addr)->sin_family;
|
||||
void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr;
|
||||
char dest[100];
|
||||
int af = (int)((struct sockaddr_in*)addr)->sin_family;
|
||||
void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr;
|
||||
if(verbosity < v)
|
||||
return;
|
||||
switch(af) {
|
||||
case AF_INET: family=""; break;
|
||||
case AF_INET6: family="";
|
||||
sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr;
|
||||
break;
|
||||
case AF_UNIX: family="unix_family "; break;
|
||||
default: break;
|
||||
}
|
||||
if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) {
|
||||
strncpy(dest, "(inet_ntop error)", sizeof(dest));
|
||||
}
|
||||
switch(af) {
|
||||
case AF_INET: family=""; break;
|
||||
case AF_INET6: family="";
|
||||
sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr;
|
||||
break;
|
||||
case AF_UNIX: family="unix_family "; break;
|
||||
default: break;
|
||||
}
|
||||
if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) {
|
||||
strncpy(dest, "(inet_ntop error)", sizeof(dest));
|
||||
}
|
||||
dest[sizeof(dest)-1] = 0;
|
||||
port = ntohs(((struct sockaddr_in*)addr)->sin_port);
|
||||
port = ntohs(((struct sockaddr_in*)addr)->sin_port);
|
||||
dname_str(zone, namebuf);
|
||||
if(af != AF_INET && af != AF_INET6)
|
||||
verbose(VERB_DETAIL, "%s <%s> %s%s#%d (addrlen %d)",
|
||||
str, namebuf, family, dest, (int)port, (int)addrlen);
|
||||
else verbose(VERB_DETAIL, "%s <%s> %s%s#%d",
|
||||
else verbose(VERB_DETAIL, "%s <%s> %s%s#%d",
|
||||
str, namebuf, family, dest, (int)port);
|
||||
}
|
||||
|
||||
@@ -373,3 +406,59 @@ addr_is_ip6(struct sockaddr_storage* addr, socklen_t len)
|
||||
return 1;
|
||||
else return 0;
|
||||
}
|
||||
|
||||
void
|
||||
addr_mask(struct sockaddr_storage* addr, socklen_t len, int net)
|
||||
{
|
||||
uint8_t mask[8] = {0x0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe};
|
||||
int i, max;
|
||||
uint8_t* s;
|
||||
if(addr_is_ip6(addr, len)) {
|
||||
s = (uint8_t*)&((struct sockaddr_in6*)addr)->sin6_addr;
|
||||
max = 128;
|
||||
} else {
|
||||
s = (uint8_t*)&((struct sockaddr_in*)addr)->sin_addr;
|
||||
max = 32;
|
||||
}
|
||||
if(net >= max)
|
||||
return;
|
||||
for(i=net/8+1; i<max/8; i++) {
|
||||
s[i] = 0;
|
||||
}
|
||||
s[net/8] &= mask[net&0x7];
|
||||
}
|
||||
|
||||
int
|
||||
addr_in_common(struct sockaddr_storage* addr1, int net1,
|
||||
struct sockaddr_storage* addr2, int net2, socklen_t addrlen)
|
||||
{
|
||||
int min = (net1<net2)?net1:net2;
|
||||
int i, to;
|
||||
int match = 0;
|
||||
uint8_t* s1, *s2;
|
||||
if(addr_is_ip6(addr1, addrlen)) {
|
||||
s1 = (uint8_t*)&((struct sockaddr_in6*)addr1)->sin6_addr;
|
||||
s2 = (uint8_t*)&((struct sockaddr_in6*)addr2)->sin6_addr;
|
||||
to = 16;
|
||||
} else {
|
||||
s1 = (uint8_t*)&((struct sockaddr_in*)addr1)->sin_addr;
|
||||
s2 = (uint8_t*)&((struct sockaddr_in*)addr2)->sin_addr;
|
||||
to = 4;
|
||||
}
|
||||
/* match = bits_in_common(s1, s2, to); */
|
||||
for(i=0; i<to; i++) {
|
||||
if(s1[i] == s2[i]) {
|
||||
match += 8;
|
||||
} else {
|
||||
uint8_t z = s1[i]^s2[i];
|
||||
log_assert(z);
|
||||
while(!(z&0x80)) {
|
||||
match++;
|
||||
z<<=1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(match > min) match = min;
|
||||
return match;
|
||||
}
|
||||
|
||||
@@ -186,6 +186,19 @@ int extstrtoaddr(const char* str, struct sockaddr_storage* addr,
|
||||
int ipstrtoaddr(const char* ip, int port, struct sockaddr_storage* addr,
|
||||
socklen_t* addrlen);
|
||||
|
||||
/**
|
||||
* Convert ip netblock (ip/netsize) string and port to sockaddr.
|
||||
* *SLOW*, does a malloc internally to avoid writing over 'ip' string.
|
||||
* @param ip: ip4 or ip6 address string.
|
||||
* @param port: port number, host format.
|
||||
* @param addr: where to store sockaddr.
|
||||
* @param addrlen: length of stored sockaddr is returned.
|
||||
* @param net: netblock size is returned.
|
||||
* @return 0 on error.
|
||||
*/
|
||||
int netblockstrtoaddr(const char* ip, int port, struct sockaddr_storage* addr,
|
||||
socklen_t* addrlen, int* net);
|
||||
|
||||
/**
|
||||
* Print string with neat domain name, type and class.
|
||||
* @param v: at what verbosity level to print this.
|
||||
@@ -228,4 +241,27 @@ int sockaddr_cmp_addr(struct sockaddr_storage* addr1, socklen_t len1,
|
||||
*/
|
||||
int addr_is_ip6(struct sockaddr_storage* addr, socklen_t len);
|
||||
|
||||
/**
|
||||
* Make sure the sockaddr ends in zeroes. For tree insertion and subsequent
|
||||
* comparison.
|
||||
* @param addr: the ip4 or ip6 addr.
|
||||
* @Param len: lentgh of addr.
|
||||
* @param net: number of bits to leave untouched, the rest of the netblock
|
||||
* address is zeroed.
|
||||
*/
|
||||
void addr_mask(struct sockaddr_storage* addr, socklen_t len, int net);
|
||||
|
||||
/**
|
||||
* See how many bits are shared, equal, between two addrs.
|
||||
* @param addr1: first addr.
|
||||
* @param net1: netblock size of first addr.
|
||||
* @param addr2: second addr.
|
||||
* @param net2: netblock size of second addr.
|
||||
* @param addrlen: length of first addr and of second addr.
|
||||
* They must be of the same length (i.e. same type IP4, IP6).
|
||||
* @return: number of bits the same.
|
||||
*/
|
||||
int addr_in_common(struct sockaddr_storage* addr1, int net1,
|
||||
struct sockaddr_storage* addr2, int net2, socklen_t addrlen);
|
||||
|
||||
#endif /* NET_HELP_H */
|
||||
|
||||
+13
-16
@@ -229,18 +229,23 @@ void
|
||||
comm_point_tcp_accept_callback(int fd, short event, void* arg)
|
||||
{
|
||||
struct comm_point* c = (struct comm_point*)arg, *c_hdl;
|
||||
struct comm_reply rep;
|
||||
int new_fd;
|
||||
log_assert(c->type == comm_tcp_accept);
|
||||
if(!(event & EV_READ)) {
|
||||
log_info("ignoring tcp accept event %d", (int)event);
|
||||
return;
|
||||
}
|
||||
/* find free tcp handler. */
|
||||
if(!c->tcp_free) {
|
||||
log_warn("accepted too many tcp, connections full");
|
||||
return;
|
||||
}
|
||||
/* accept incoming connection. */
|
||||
rep.c = NULL;
|
||||
rep.addrlen = (socklen_t)sizeof(rep.addr);
|
||||
c_hdl = c->tcp_free;
|
||||
c_hdl->repinfo.addrlen = (socklen_t)sizeof(c_hdl->repinfo.addr);
|
||||
log_assert(fd != -1);
|
||||
new_fd = accept(fd, (struct sockaddr*)&rep.addr, &rep.addrlen);
|
||||
new_fd = accept(fd, (struct sockaddr*)&c_hdl->repinfo.addr,
|
||||
&c_hdl->repinfo.addrlen);
|
||||
if(new_fd == -1) {
|
||||
/* EINTR is signal interrupt. others are closed connection. */
|
||||
if( errno != EINTR
|
||||
@@ -254,14 +259,7 @@ comm_point_tcp_accept_callback(int fd, short event, void* arg)
|
||||
log_err("accept failed: %s", strerror(errno));
|
||||
return;
|
||||
}
|
||||
/* find free tcp handler. */
|
||||
if(!c->tcp_free) {
|
||||
log_err("accepted too many tcp, connections full");
|
||||
close(new_fd);
|
||||
return;
|
||||
}
|
||||
/* grab it */
|
||||
c_hdl = c->tcp_free;
|
||||
/* grab the tcp handler buffers */
|
||||
c->tcp_free = c_hdl->tcp_free;
|
||||
if(!c->tcp_free) {
|
||||
/* stop accepting incoming queries for now. */
|
||||
@@ -307,7 +305,6 @@ tcp_callback_writer(struct comm_point* c)
|
||||
static void
|
||||
tcp_callback_reader(struct comm_point* c)
|
||||
{
|
||||
struct comm_reply rep;
|
||||
log_assert(c->type == comm_tcp || c->type == comm_local);
|
||||
ldns_buffer_flip(c->buffer);
|
||||
if(c->tcp_do_toggle_rw)
|
||||
@@ -315,10 +312,8 @@ tcp_callback_reader(struct comm_point* c)
|
||||
c->tcp_byte_count = 0;
|
||||
if(c->type == comm_tcp)
|
||||
comm_point_stop_listening(c);
|
||||
rep.c = c;
|
||||
rep.addrlen = 0;
|
||||
log_assert(fptr_whitelist_comm_point(c->callback));
|
||||
if( (*c->callback)(c, c->cb_arg, NETEVENT_NOERROR, &rep) ) {
|
||||
if( (*c->callback)(c, c->cb_arg, NETEVENT_NOERROR, &c->repinfo) ) {
|
||||
comm_point_start_listening(c, -1, TCP_QUERY_TIMEOUT);
|
||||
}
|
||||
}
|
||||
@@ -608,6 +603,7 @@ comm_point_create_tcp_handler(struct comm_base *base,
|
||||
c->do_not_close = 0;
|
||||
c->tcp_do_toggle_rw = 1;
|
||||
c->tcp_check_nb_connect = 0;
|
||||
c->repinfo.c = c;
|
||||
c->callback = callback;
|
||||
c->cb_arg = callback_arg;
|
||||
/* add to parent free list */
|
||||
@@ -724,6 +720,7 @@ comm_point_create_tcp_out(struct comm_base *base, size_t bufsize,
|
||||
c->do_not_close = 0;
|
||||
c->tcp_do_toggle_rw = 1;
|
||||
c->tcp_check_nb_connect = 1;
|
||||
c->repinfo.c = c;
|
||||
c->callback = callback;
|
||||
c->cb_arg = callback_arg;
|
||||
evbits = EV_PERSIST | EV_WRITE;
|
||||
|
||||
+14
-12
@@ -88,6 +88,18 @@ struct comm_base {
|
||||
struct internal_base* eb;
|
||||
};
|
||||
|
||||
/**
|
||||
* Reply information for a communication point.
|
||||
*/
|
||||
struct comm_reply {
|
||||
/** the comm_point with fd to send reply on to. */
|
||||
struct comm_point* c;
|
||||
/** the address (for UDP based communication) */
|
||||
struct sockaddr_storage addr;
|
||||
/** length of address */
|
||||
socklen_t addrlen;
|
||||
};
|
||||
|
||||
/**
|
||||
* Communication point to the network
|
||||
* These behaviours can be accomplished by setting the flags
|
||||
@@ -117,6 +129,8 @@ struct comm_point {
|
||||
size_t tcp_byte_count;
|
||||
/** parent communication point (for TCP sockets) */
|
||||
struct comm_point* tcp_parent;
|
||||
/** sockaddr from peer, for TCP handlers */
|
||||
struct comm_reply repinfo;
|
||||
|
||||
/* -------- TCP Accept -------- */
|
||||
/** the number of TCP handlers for this tcp-accept socket */
|
||||
@@ -187,18 +201,6 @@ struct comm_point {
|
||||
void *cb_arg;
|
||||
};
|
||||
|
||||
/**
|
||||
* Reply information for a communication point.
|
||||
*/
|
||||
struct comm_reply {
|
||||
/** the comm_point with fd to send reply on to. */
|
||||
struct comm_point* c;
|
||||
/** the address (for UDP based communication) */
|
||||
struct sockaddr_storage addr;
|
||||
/** length of address */
|
||||
socklen_t addrlen;
|
||||
};
|
||||
|
||||
/**
|
||||
* Structure only for making timeout events.
|
||||
*/
|
||||
|
||||
+18
-3
@@ -64,9 +64,24 @@ val_classify_response(uint16_t query_flags, struct query_info* qinf,
|
||||
if(rcode == LDNS_RCODE_NXDOMAIN && rep->an_numrrsets == 0)
|
||||
return VAL_CLASS_NAMEERROR;
|
||||
|
||||
/* check for referral: nonRD query */
|
||||
if(!(query_flags&BIT_RD))
|
||||
return VAL_CLASS_REFERRAL;
|
||||
/* check for referral: nonRD query and it looks like a nodata */
|
||||
if(!(query_flags&BIT_RD) && rep->an_numrrsets == 0 &&
|
||||
rcode == LDNS_RCODE_NOERROR) {
|
||||
/* SOA record in auth indicates it is NODATA instead.
|
||||
* All validation requiring NODATA messages have SOA in
|
||||
* authority section. */
|
||||
/* uses fact that answer section is empty */
|
||||
int saw_ns = 0;
|
||||
for(i=0; i<rep->ns_numrrsets; i++) {
|
||||
if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_SOA)
|
||||
return VAL_CLASS_NODATA;
|
||||
if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_DS)
|
||||
return VAL_CLASS_REFERRAL;
|
||||
if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_NS)
|
||||
saw_ns = 1;
|
||||
}
|
||||
return saw_ns?VAL_CLASS_REFERRAL:VAL_CLASS_NODATA;
|
||||
}
|
||||
|
||||
/* dump bad messages */
|
||||
if(rcode != LDNS_RCODE_NOERROR)
|
||||
|
||||
Reference in New Issue
Block a user