Compare commits

..
Author SHA1 Message Date
Wouter Wijngaards 8b2807799e tag 0.2
git-svn-id: file:///svn/unbound/tags/release-0.2@228 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-04-03 14:17:42 +00:00
133 changed files with 965 additions and 102626 deletions
+21 -54
View File
@@ -20,14 +20,12 @@ exec_prefix=@exec_prefix@
bindir=@bindir@
mandir=@mandir@
libdir=@libdir@
# datarootdir is here to please some checkers, use datadir.
datarootdir=@datarootdir@
datadir=@datadir@
includedir=@includedir@
doxygen=@doxygen@
libtool=@libtool@
ldnsdir=@ldnsdir@
staticexe=@staticexe@
YACC=@YACC@
LEX=@LEX@
@@ -46,37 +44,28 @@ endif
BUILD=build/
LINT=splint
LINTFLAGS=+quiet -weak -warnposix -unrecog -Din_addr_t=uint32_t -Du_int=unsigned -Du_char=uint8_t -preproc -Drlimit=rlimit64
LINTFLAGS=+quiet -weak -warnposix -unrecog -Din_addr_t=uint32_t -Du_int=unsigned -Du_char=uint8_t -preproc
# compat with openssl linux edition.
LINTFLAGS+="-DBN_ULONG=unsigned long" -Dkrb5_int32=int "-Dkrb5_ui_4=unsigned int" -DPQ_64BIT=uint64_t
INSTALL=$(srcdir)/install-sh
INSTALL=$(srcdir)/install-sh
COMMON_SRC=$(wildcard services/*.c services/cache/*.c util/*.c \
util/data/*.c util/storage/*.c iterator/*.c) util/configparser.c \
util/configlexer.c testcode/checklocks.c
COMMON_SRC=$(wildcard services/*.c util/*.c util/data/*.c util/storage/*.c) util/configparser.c util/configlexer.c testcode/checklocks.c
COMMON_OBJ=$(addprefix $(BUILD),$(COMMON_SRC:.c=.o))
COMPAT_OBJ=$(addprefix $(BUILD)compat/,$(LIBOBJS))
UNITTEST_SRC=$(wildcard testcode/unit*.c) testcode/readhex.c $(COMMON_SRC)
UNITTEST_SRC=$(wildcard testcode/unit*.c) $(COMMON_SRC)
UNITTEST_OBJ=$(addprefix $(BUILD),$(UNITTEST_SRC:.c=.o)) $(COMPAT_OBJ)
DAEMON_SRC=$(wildcard daemon/*.c) $(COMMON_SRC)
DAEMON_OBJ=$(addprefix $(BUILD),$(DAEMON_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 \
services/listen_dnsport.c services/outside_network.c, $(COMMON_SRC))
TESTBOUND_SRC=testcode/testbound.c testcode/ldns-testpkts.c daemon/worker.c daemon/daemon.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 $(COMMON_SRC)
LOCKVERIFY_OBJ=$(addprefix $(BUILD),$(LOCKVERIFY_SRC:.c=.o)) $(COMPAT_OBJ)
PKTVIEW_SRC=testcode/pktview.c testcode/readhex.c $(COMMON_SRC)
PKTVIEW_OBJ=$(addprefix $(BUILD),$(PKTVIEW_SRC:.c=.o)) $(COMPAT_OBJ)
ALL_SRC=$(COMMON_SRC) $(UNITTEST_SRC) $(DAEMON_SRC) \
$(TESTBOUND_SRC) $(LOCKVERIFY_SRC)
ALL_OBJ=$(addprefix $(BUILD),$(ALL_SRC:.c=.o) \
$(addprefix compat/,$(LIBOBJS))) $(COMPAT_OBJ)
ALL_SRC=$(COMMON_SRC) $(UNITTEST_SRC) $(DAEMON_SRC) $(TESTBOUND_SRC) $(LOCKVERIFY_SRC)
ALL_OBJ=$(addprefix $(BUILD),$(ALL_SRC:.c=.o) $(addprefix compat/,$(LIBOBJS))) $(COMPAT_OBJ)
COMPILE=$(LIBTOOL) --tag=CC --mode=compile $(CC) $(CPPFLAGS) $(CFLAGS)
LINK=$(LIBTOOL) --tag=CC --mode=link $(CC) $(staticexe) $(CFLAGS) $(LDFLAGS)
LINK=$(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) $(LDFLAGS)
LINK_LIB=$(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) $(LDFLAGS) -release $(VERSION)
$(BUILD)%.o: $(srcdir)/%.c
@@ -84,9 +73,9 @@ $(BUILD)%.o: $(srcdir)/%.c
@if test ! -d $(dir $@); then $(INSTALL) -d $(patsubst %/,%,$(dir $@)); fi
$Q$(COMPILE) -c $< -o $@
.PHONY: clean realclean doc lint all install uninstall
.PHONY: clean realclean doc lint all
all: $(COMMON_OBJ) unbound unittest testbound lock-verify pktview
all: $(COMMON_OBJ) unbound unittest testbound lock-verify
unbound: $(DAEMON_OBJ)
$(INFO) Link $@
@@ -104,21 +93,17 @@ lock-verify: $(LOCKVERIFY_OBJ)
$(INFO) Link $@
$Q$(LINK) -o $@ $^ $(LIBS)
pktview: $(PKTVIEW_OBJ)
$(INFO) Link $@
$Q$(LINK) -o $@ $^ $(LIBS)
#testcode/ldns-testpkts.c: $(ldnsdir)/examples/ldns-testpkts.c \
# $(ldnsdir)/examples/ldns-testpkts.h
# cp $(ldnsdir)/examples/ldns-testpkts.c testcode/ldns-testpkts.c
# cp $(ldnsdir)/examples/ldns-testpkts.h testcode/ldns-testpkts.h
testcode/ldns-testpkts.c: $(ldnsdir)/examples/ldns-testpkts.c \
$(ldnsdir)/examples/ldns-testpkts.h
cp $(ldnsdir)/examples/ldns-testpkts.c testcode/ldns-testpkts.c
cp $(ldnsdir)/examples/ldns-testpkts.h testcode/ldns-testpkts.h
util/config_file.c: util/configparser.h
util/configlexer.c: $(srcdir)/util/configlexer.lex util/configparser.h
$(INFO) Lex $<
@if test ! -d util; then $(INSTALL) -d util; fi
$Qecho "#include \"util/configyyrename.h\"" > $@
$Q$(LEX) -t $< >> $@
$Q$(LEX) -i -t $< >> $@
util/configparser.c util/configparser.h: $(srcdir)/util/configparser.y
$(INFO) Yacc $<
@@ -135,13 +120,12 @@ realclean: clean
rm -f util/configlexer.c util/configparser.c util/configparser.h
rm -f Makefile
$(BUILD)%.lint: $(srcdir)/%.c
$(INFO) Lint $<
@if test ! -d $(dir $@); then $(INSTALL) -d $(patsubst %/,%,$(dir $@)); fi
$Q$(LINT) $(LINTFLAGS) -I. -I$(srcdir) -I$(ldnsdir)/include $<
$Qtouch $@
lint: $(addprefix $(BUILD),$(filter-out util/configparser.lint,$(filter-out util/configlexer.lint,$(sort $(ALL_SRC:.c=.lint)))))
lint:
$Qfor i in $(filter-out util/configparser.c,$(filter-out util/configlexer.c,$(sort $(ALL_SRC)))); do \
echo lint $$i; \
$(LINT) $(LINTFLAGS) -I. -I$(srcdir) -I$(ldnsdir)/include $(srcdir)/$$i ; \
if [ $$? -ne 0 ] ; then exit 1 ; fi ; \
done
tags: $(srcdir)/*.[ch] $(srcdir)/*/*.[ch]
ctags -f $(srcdir)/tags $(srcdir)/*.[ch] $(srcdir)/*/*.[ch]
@@ -151,19 +135,6 @@ ifdef doxygen
$(doxygen) $(srcdir)/doc/unbound.doxygen
endif
install:
$(INSTALL) -d $(bindir)
$(INSTALL) -d $(mandir)
$(INSTALL) -d $(mandir)/man8
$(INSTALL) -d $(mandir)/man5
$(LIBTOOL) --mode=install cp unbound $(bindir)/unbound
$(INSTALL) -c -m 644 $(srcdir)/doc/unbound.8 $(mandir)/man8
$(INSTALL) -c -m 644 $(srcdir)/doc/unbound.conf.5 $(mandir)/man5
uninstall:
rm -f -- $(bindir)/unbound
rm -f -- $(mandir)/man8/unbound.8 $(mandir)/man5/unbound.conf.5
# Automatic dependencies.
$(BUILD)%.d: $(srcdir)/%.c
$(INFO) Depend $<
@@ -172,8 +143,4 @@ $(BUILD)%.d: $(srcdir)/%.c
| sed '\''s!\(.*\)\.o[ :]*!$(dir $@)\1.o $@ : !g'\'' > $@; \
[ -s $@ ] || rm -f $@'
ifneq ($(MAKECMDGOALS),clean)
ifneq ($(MAKECMDGOALS),realclean)
-include $(addprefix $(BUILD),$(ALL_SRC:.c=.d))
endif
endif
Vendored
+3 -5
View File
@@ -1,7 +1,7 @@
# generated automatically by aclocal 1.10 -*- Autoconf -*-
# generated automatically by aclocal 1.9.6 -*- Autoconf -*-
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
# 2005, 2006 Free Software Foundation, Inc.
# 2005 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
@@ -1597,7 +1597,7 @@ linux*)
# Append ld.so.conf contents to the search path
if test -f /etc/ld.so.conf; then
lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/^[ ]*//;s/#.*//;/^[^\/]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
sys_lib_dlsearch_path_spec="/lib${libsuff} /usr/lib${libsuff} $lt_ld_extra"
fi
@@ -6370,7 +6370,6 @@ do
done
done
done
IFS=$as_save_IFS
lt_ac_max=0
lt_ac_count=0
# Add /usr/xpg4/bin/sed as it is typically found on Solaris
@@ -6403,7 +6402,6 @@ for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do
done
])
SED=$lt_cv_path_SED
AC_SUBST([SED])
AC_MSG_RESULT([$SED])
])
+1 -31
View File
@@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.57)
AC_INIT(unbound, 0.4, wouter@nlnetlabs.nl, unbound)
AC_INIT(unbound, 0.2, wouter@nlnetlabs.nl, unbound)
CFLAGS=
AC_AIX
@@ -336,26 +336,6 @@ cv_msgiovlen_type="int" ],
AC_MSG_RESULT($cv_msgiovlen_type)
AC_DEFINE_UNQUOTED([TYPE_MSGIOVLEN], $cv_msgiovlen_type, [Define to 'int' or type of struct msghdr.msg_iovlen.])
# Check for yyunput
AC_DEFUN([CHECK_YYUNPUT],
[AC_MSG_CHECKING(whether lex can not generate yyunput)
AC_CACHE_VAL(ac_cv_c_yy_unput,
[ac_cv_c_yy_unput=no
if $LEX --nounput -h 2>&1 | grep "do not generate" 2>&1 >/dev/null; then
ac_cv_c_yy_unput="yes"
else
ac_cv_c_yy_unput="no"
fi
])
AC_MSG_RESULT($ac_cv_c_yy_unput)
if test $ac_cv_c_yy_unput = yes; then
LEX="$LEX --nounput"
fi
])dnl
CHECK_YYUNPUT
# Checks for libraries.
AC_ARG_WITH(ssl, AC_HELP_STRING([--with-ssl=pathname],
[enable SSL (will check /usr/local/ssl
@@ -469,16 +449,6 @@ else
AC_DEFINE(USE_MINI_EVENT, 1, [Define if you want to use internal select based events])
fi
# set static linking if requested
AC_SUBST(staticexe)
staticexe=""
AC_ARG_ENABLE(staticexe, AC_HELP_STRING([--enable-static-exe],
[ enable to compile executables statically against event, ldns libs, for debug purposes ]),
, )
if test x_$enable_static_exe = x_yes; then
staticexe="-static"
fi
# check to see if libraries are needed for these functions.
AC_CHECK_LIB(socket, socket)
AC_CHECK_LIB(nsl, inet_pton)
+8 -70
View File
@@ -50,10 +50,6 @@
#include "util/data/msgreply.h"
#include "util/storage/slabhash.h"
#include "services/listen_dnsport.h"
#include "services/cache/rrset.h"
#include "services/cache/infra.h"
#include "util/module.h"
#include "iterator/iterator.h"
#include <signal.h>
/** How many quit requests happened. */
@@ -62,10 +58,7 @@ static int sig_record_quit = 0;
static int sig_record_reload = 0;
/** used when no other sighandling happens, so we don't die
* when multiple signals in quick succession are sent to us.
* @param sig: signal number.
* @return signal handler return type (void or int).
*/
* when multiple signals in quick succession are sent to us. */
static RETSIGTYPE record_sigh(int sig)
{
#ifdef LIBEVENT_SIGNAL_PROBLEM
@@ -125,13 +118,15 @@ daemon_init()
signal_handling_record();
checklock_start();
daemon->need_to_exit = 0;
daemon->num_modules = 0;
if(!(daemon->env = (struct module_env*)calloc(1,
sizeof(*daemon->env)))) {
daemon->msg_cache = slabhash_create(HASH_DEFAULT_SLABS,
HASH_DEFAULT_STARTARRAY, HASH_DEFAULT_MAXMEM,
msgreply_sizefunc, query_info_compare,
query_entry_delete, reply_info_delete, NULL);
if(!daemon->msg_cache) {
free(daemon);
return NULL;
}
alloc_init(&daemon->superalloc, NULL, 0);
alloc_init(&daemon->superalloc, NULL);
return daemon;
}
@@ -148,53 +143,6 @@ daemon_open_shared_ports(struct daemon* daemon)
return 1;
}
/**
* Desetup the modules, deinit, delete.
* @param daemon: the daemon.
*/
static void
daemon_desetup_modules(struct daemon* daemon)
{
int i;
for(i=0; i<daemon->num_modules; i++) {
(*daemon->modfunc[i]->deinit)(daemon->env, i);
}
daemon->num_modules = 0;
free(daemon->modfunc);
daemon->modfunc = 0;
}
/**
* Setup modules. Assigns ids and calls module_init.
* @param daemon: the daemon
*/
static void daemon_setup_modules(struct daemon* daemon)
{
int i;
if(daemon->num_modules != 0)
daemon_desetup_modules(daemon);
/* fixed setup of the modules */
daemon->num_modules = 1;
daemon->modfunc = (struct module_func_block**)calloc((size_t)
daemon->num_modules, sizeof(struct module_func_block*));
if(!daemon->modfunc) {
fatal_exit("malloc failure allocating function callbacks");
}
daemon->modfunc[0] = iter_get_funcblock();
daemon->env->cfg = daemon->cfg;
daemon->env->alloc = &daemon->superalloc;
daemon->env->worker = NULL;
daemon->env->send_packet = &worker_send_packet;
daemon->env->send_query = &worker_send_query;
for(i=0; i<daemon->num_modules; i++) {
log_info("init module %d: %s", i, daemon->modfunc[i]->name);
if(!(*daemon->modfunc[i]->init)(daemon->env, i)) {
fatal_exit("module init for module %s failed",
daemon->modfunc[i]->name);
}
}
}
/**
* Allocate empty worker structures. With backptr and thread-number,
* from 0..numthread initialised. Used as user arguments to new threads.
@@ -311,10 +259,6 @@ void
daemon_fork(struct daemon* daemon)
{
log_assert(daemon);
/* setup modules */
daemon_setup_modules(daemon);
/* first create all the worker structures, so we can pass
* them to the newly created threads.
*/
@@ -367,17 +311,11 @@ daemon_delete(struct daemon* daemon)
{
if(!daemon)
return;
daemon_desetup_modules(daemon);
listening_ports_free(daemon->ports);
if(daemon->env) {
slabhash_delete(daemon->env->msg_cache);
rrset_cache_delete(daemon->env->rrset_cache);
infra_delete(daemon->env->infra_cache);
}
slabhash_delete(daemon->msg_cache);
alloc_clear(&daemon->superalloc);
free(daemon->cwd);
free(daemon->pidfile);
free(daemon->env);
free(daemon);
checklock_stop();
}
+2 -8
View File
@@ -48,8 +48,6 @@ struct config_file;
struct worker;
struct listen_port;
struct slabhash;
struct module_env;
struct rrset_cache;
/**
* Structure holding worker list.
@@ -74,12 +72,8 @@ struct daemon {
int need_to_exit;
/** master allocation cache */
struct alloc_cache superalloc;
/** the module environment master value, copied and changed by threads*/
struct module_env* env;
/** number of modules active, ids from 0 to num-1. */
int num_modules;
/** the module callbacks, array of num_modules length */
struct module_func_block** modfunc;
/** the message cache, content is struct msgreply_entry* */
struct slabhash* msg_cache;
};
/**
-72
View File
@@ -1,72 +0,0 @@
/*
* daemon/stats.c - collect runtime performance indicators.
*
* 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 describes the data structure used to collect runtime performance
* numbers. These 'statistics' may be of interest to the operator.
*/
#include "config.h"
#include "daemon/stats.h"
#include "daemon/worker.h"
#include "services/mesh.h"
void server_stats_init(struct server_stats* stats)
{
memset(stats, 0, sizeof(stats));
}
void server_stats_querymiss(struct server_stats* stats, struct worker* worker)
{
stats->num_queries_missed_cache++;
stats->sum_query_list_size += worker->env.mesh->all.count;
if(worker->env.mesh->all.count > stats->max_query_list_size)
stats->max_query_list_size = worker->env.mesh->all.count;
}
void server_stats_log(struct server_stats* stats, int threadnum)
{
log_info("server stats for thread %d: %u queries, %u from cache",
threadnum, (unsigned)stats->num_queries,
(unsigned)(stats->num_queries -
stats->num_queries_missed_cache));
log_info("server stats for thread %d: requestlist max %u avg %g "
"exceeded %u", threadnum, (unsigned)stats->max_query_list_size,
stats->num_queries_missed_cache?
(double)stats->sum_query_list_size/
stats->num_queries_missed_cache : 0.0,
(unsigned)stats->num_query_list_exceeded);
}
-77
View File
@@ -1,77 +0,0 @@
/*
* daemon/stats.h - collect runtime performance indicators.
*
* 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 describes the data structure used to collect runtime performance
* numbers. These 'statistics' may be of interest to the operator.
*/
#ifndef DAEMON_STATS_H
#define DAEMON_STATS_H
struct worker;
/** per worker statistics */
struct server_stats {
/** number of queries from clients received. */
size_t num_queries;
/** number of queries that had a cache-miss. */
size_t num_queries_missed_cache;
/**
* Sum of the querylistsize of the worker for
* every query that missed cache. To calculate average.
*/
size_t sum_query_list_size;
/** max value of query list size reached. */
size_t max_query_list_size;
/** number of times that the query_list_size was insufficient */
size_t num_query_list_exceeded;
};
/**
* Initialize server stats to 0.
* @param stats: what to init (this is alloced by the caller).
*/
void server_stats_init(struct server_stats* stats);
/** add query if it missed the cache */
void server_stats_querymiss(struct server_stats* stats, struct worker* worker);
/** display the stats to the log */
void server_stats_log(struct server_stats* stats, int threadnum);
#endif /* DAEMON_STATS_H */
+7 -62
View File
@@ -45,15 +45,10 @@
#include "daemon/daemon.h"
#include "util/config_file.h"
#include "util/storage/slabhash.h"
#include "services/listen_dnsport.h"
#include "services/cache/rrset.h"
#include "services/cache/infra.h"
#include "util/data/msgreply.h"
#include "util/module.h"
#include <signal.h>
#include <fcntl.h>
#include <pwd.h>
#include <sys/resource.h>
/** print usage. */
static void usage()
@@ -69,42 +64,6 @@ static void usage()
printf("Report bugs to %s\n", PACKAGE_BUGREPORT);
}
/** check file descriptor count */
static void
checkrlimits(struct config_file* cfg)
{
int list = ((cfg->do_ip4?1:0) + (cfg->do_ip6?1:0)) *
((cfg->do_udp?1:0) + (cfg->do_tcp?1 + TCP_ACCEPT_COUNT:0));
size_t ifs = (size_t)(cfg->num_ifs==0?1:cfg->num_ifs);
size_t listen_num = list*ifs;
size_t outnum = cfg->outgoing_num_ports*ifs + cfg->outgoing_num_tcp;
size_t misc = 4; /* logfile, pidfile, stdout... */
size_t perthread = listen_num + outnum + 2/*cmdpipe*/ + 2/*libevent*/
+ misc;
#if !defined(HAVE_PTHREAD) && !defined(HAVE_SOLARIS_THREADS)
int numthread = 1; /* it forks */
#else
int numthread = cfg->num_threads;
#endif
size_t total = numthread * perthread + misc;
struct rlimit rlim;
if(getrlimit(RLIMIT_NOFILE, &rlim) < 0) {
log_warn("getrlimit: %s", strerror(errno));
return;
}
if(rlim.rlim_cur == (rlim_t)RLIM_INFINITY)
return;
if((size_t)rlim.rlim_cur < total) {
log_err("Not enough sockets available. Increase "
"ulimit(open files).");
log_err("or decrease number of threads, outgoing num ports, "
"outgoing num tcp or number of interfaces");
log_err("estimate %u fds high mark, %u available",
(unsigned)total, (unsigned)rlim.rlim_cur);
fatal_exit("Not enough file descriptors available");
}
}
/** to changedir, logfile */
static void
apply_dir(struct daemon* daemon, struct config_file* cfg, int cmdline_verbose)
@@ -123,31 +82,20 @@ apply_dir(struct daemon* daemon, struct config_file* cfg, int cmdline_verbose)
log_err("cwd: malloc failed");
}
}
if(!daemon->env->msg_cache ||
cfg->msg_cache_size != slabhash_get_size(daemon->env->msg_cache) ||
cfg->msg_cache_slabs != daemon->env->msg_cache->size) {
slabhash_delete(daemon->env->msg_cache);
daemon->env->msg_cache = slabhash_create(cfg->msg_cache_slabs,
if(cfg->msg_cache_size != slabhash_get_size(daemon->msg_cache) ||
cfg->msg_cache_slabs != daemon->msg_cache->size) {
slabhash_delete(daemon->msg_cache);
daemon->msg_cache = slabhash_create(cfg->msg_cache_slabs,
HASH_DEFAULT_STARTARRAY, cfg->msg_cache_size,
msgreply_sizefunc, query_info_compare,
query_entry_delete, reply_info_delete, NULL);
if(!daemon->env->msg_cache) {
if(!daemon->msg_cache) {
fatal_exit("malloc failure updating config settings");
}
}
if((daemon->env->rrset_cache = rrset_cache_adjust(
daemon->env->rrset_cache, cfg, &daemon->superalloc)) == 0)
fatal_exit("malloc failure updating config settings");
if((daemon->env->infra_cache = infra_adjust(daemon->env->infra_cache,
cfg))==0)
fatal_exit("malloc failure updating config settings");
checkrlimits(cfg);
}
/** Read existing pid from pidfile.
* @param file: file name of pid file.
* @return: the pid from the file or -1 if none.
*/
/** Read existing pid from pidfile. */
static pid_t
readpid (const char* file)
{
@@ -187,10 +135,7 @@ readpid (const char* file)
return pid;
}
/** write pid to file.
* @param pidfile: file name of pid file.
* @param pid: pid to write to file.
*/
/** write pid to file. */
static void
writepid (const char* pidfile, pid_t pid)
{
+221 -433
View File
@@ -47,18 +47,9 @@
#include "daemon/daemon.h"
#include "util/netevent.h"
#include "util/config_file.h"
#include "util/module.h"
#include "util/region-allocator.h"
#include "util/storage/slabhash.h"
#include "services/listen_dnsport.h"
#include "services/outside_network.h"
#include "services/outbound_list.h"
#include "services/cache/rrset.h"
#include "services/cache/infra.h"
#include "services/mesh.h"
#include "util/data/msgparse.h"
#include "util/data/msgencode.h"
#include "util/data/dname.h"
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
@@ -66,36 +57,10 @@
#include <netdb.h>
#include <signal.h>
/** Size of an UDP datagram */
#define NORMAL_UDP_SIZE 512 /* bytes */
/** Report on memory usage by this thread and global */
static void
worker_mem_report(struct worker* worker)
{
size_t total, front, back, mesh, msg, rrset, infra, ac, superac;
size_t me;
if(verbosity < VERB_ALGO)
return;
front = listen_get_mem(worker->front);
back = outnet_get_mem(worker->back);
msg = slabhash_get_mem(worker->env.msg_cache);
rrset = slabhash_get_mem(&worker->env.rrset_cache->table);
infra = slabhash_get_mem(worker->env.infra_cache->hosts);
mesh = mesh_get_mem(worker->env.mesh);
ac = alloc_get_mem(&worker->alloc);
superac = alloc_get_mem(&worker->daemon->superalloc);
me = sizeof(*worker) + sizeof(*worker->base) + sizeof(*worker->comsig)
+ comm_point_get_mem(worker->cmd_com) +
sizeof(worker->rndstate) + region_get_mem(worker->scratchpad);
total = front+back+mesh+msg+rrset+infra+ac+superac+me;
log_info("Memory conditions: %u front=%u back=%u mesh=%u msg=%u "
"rrset=%u infra=%u alloccache=%u globalalloccache=%u me=%u",
(unsigned)total, (unsigned)front, (unsigned)back,
(unsigned)mesh, (unsigned)msg, (unsigned)rrset,
(unsigned)infra, (unsigned)ac, (unsigned)superac,
(unsigned)me);
}
/** size of ID+FLAGS in a DNS message */
#define DNS_ID_AND_FLAGS 4
/** timeout in seconds for UDP queries to auth servers. TODO: proper rtt */
#define UDP_QUERY_TIMEOUT 4
void
worker_send_cmd(struct worker* worker, ldns_buffer* buffer,
@@ -111,85 +76,126 @@ worker_send_cmd(struct worker* worker, ldns_buffer* buffer,
log_err("write socket: %s", strerror(errno));
}
/** release workrequest back to the freelist,
* note that the w->qinfo still needs to be cleared after this.
*/
static void
req_release(struct work_query* w)
{
if(w->worker->num_requests == w->worker->request_size) {
/* no longer at max, start accepting again. */
listen_resume(w->worker->front);
}
log_assert(w->worker->num_requests >= 1);
w->worker->num_requests --;
w->next = w->worker->free_queries;
w->worker->free_queries = w;
}
/** reply to query with given error code */
static void
replyerror(int r, struct work_query* w)
{
ldns_buffer* buf = w->query_reply.c->buffer;
uint16_t flags;
verbose(VERB_DETAIL, "reply with error");
ldns_buffer_clear(buf);
ldns_buffer_write(buf, &w->query_id, sizeof(uint16_t));
flags = (uint16_t)(BIT_QR | r); /* QR and retcode*/
flags |= (w->query_flags & (BIT_RD|BIT_CD)); /* copy RD and CD bit */
ldns_buffer_write_u16(buf, flags);
flags = 1;
ldns_buffer_write_u16(buf, flags);
flags = 0;
ldns_buffer_write(buf, &flags, sizeof(uint16_t));
ldns_buffer_write(buf, &flags, sizeof(uint16_t));
ldns_buffer_write(buf, &flags, sizeof(uint16_t));
ldns_buffer_write(buf, w->qinfo.qname, w->qinfo.qnamesize);
ldns_buffer_write_u16(buf, w->qinfo.qtype);
ldns_buffer_write_u16(buf, w->qinfo.qclass);
ldns_buffer_flip(buf);
comm_point_send_reply(&w->query_reply);
req_release(w);
query_info_clear(&w->qinfo);
}
/** process incoming replies from the network */
static int
worker_handle_reply(struct comm_point* c, void* arg, int error,
struct comm_reply* reply_info)
struct comm_reply* ATTR_UNUSED(reply_info))
{
struct module_qstate* q = (struct module_qstate*)arg;
struct worker* worker = q->env->worker;
struct outbound_entry e;
e.qstate = q;
e.qsent = NULL;
struct work_query* w = (struct work_query*)arg;
struct reply_info* rep;
struct msgreply_entry* e;
verbose(VERB_DETAIL, "reply to query with stored ID %d",
ntohs(w->query_id)); /* byteswapped so same as dig prints */
if(error != 0) {
mesh_report_reply(worker->env.mesh, &e, 0, reply_info);
worker_mem_report(worker);
replyerror(LDNS_RCODE_SERVFAIL, w);
return 0;
}
/* sanity check. */
if(!LDNS_QR_WIRE(ldns_buffer_begin(c->buffer))
|| LDNS_OPCODE_WIRE(ldns_buffer_begin(c->buffer)) !=
LDNS_PACKET_QUERY
|| LDNS_QDCOUNT(ldns_buffer_begin(c->buffer)) > 1) {
/* error becomes timeout for the module as if this reply
* never arrived. */
mesh_report_reply(worker->env.mesh, &e, 0, reply_info);
worker_mem_report(worker);
if(!LDNS_QR_WIRE(ldns_buffer_begin(c->buffer)))
return 0; /* not a reply. */
if(LDNS_OPCODE_WIRE(ldns_buffer_begin(c->buffer)) != LDNS_PACKET_QUERY)
return 0; /* not a reply to a query. */
if(LDNS_QDCOUNT(ldns_buffer_begin(c->buffer)) > 1)
return 0; /* too much in the query section */
/* woohoo a reply! */
rep = (struct reply_info*)malloc(sizeof(struct reply_info));
if(!rep) {
log_err("out of memory");
replyerror(LDNS_RCODE_SERVFAIL, w);
return 0;
}
mesh_report_reply(worker->env.mesh, &e, 1, reply_info);
worker_mem_report(worker);
rep->flags = ldns_buffer_read_u16_at(c->buffer, 2);
rep->replysize = ldns_buffer_limit(c->buffer) - DNS_ID_AND_FLAGS;
log_info("got reply of size %u", (unsigned)rep->replysize);
rep->reply = (uint8_t*)malloc(rep->replysize);
if(!rep->reply) {
free(rep);
log_err("out of memory");
replyerror(LDNS_RCODE_SERVFAIL, w);
return 0;
}
memcpy(rep->reply, ldns_buffer_at(c->buffer, DNS_ID_AND_FLAGS),
rep->replysize);
reply_info_answer_iov(rep, w->query_id, w->query_flags,
&w->query_reply, 0);
req_release(w);
/* store or update reply in the cache */
if(!(e = query_info_entrysetup(&w->qinfo, rep, w->query_hash))) {
free(rep->reply);
free(rep);
log_err("out of memory");
return 0;
}
slabhash_insert(w->worker->daemon->msg_cache, w->query_hash,
&e->entry, rep);
return 0;
}
/** process incoming serviced query replies from the network */
static int
worker_handle_service_reply(struct comm_point* c, void* arg, int error,
struct comm_reply* reply_info)
/** process incoming request */
static void
worker_process_query(struct worker* worker, struct work_query* w)
{
struct outbound_entry* e = (struct outbound_entry*)arg;
struct worker* worker = e->qstate->env->worker;
verbose(VERB_ALGO, "worker scvd callback for qstate %p", e->qstate);
if(error != 0) {
mesh_report_reply(worker->env.mesh, e, 0, reply_info);
worker_mem_report(worker);
return 0;
}
/* sanity check. */
if(!LDNS_QR_WIRE(ldns_buffer_begin(c->buffer))
|| LDNS_OPCODE_WIRE(ldns_buffer_begin(c->buffer)) !=
LDNS_PACKET_QUERY
|| LDNS_QDCOUNT(ldns_buffer_begin(c->buffer)) > 1) {
/* error becomes timeout for the module as if this reply
* never arrived. */
verbose(VERB_ALGO, "worker: bad reply handled as timeout");
mesh_report_reply(worker->env.mesh, e, 0, reply_info);
worker_mem_report(worker);
return 0;
}
mesh_report_reply(worker->env.mesh, e, 1, reply_info);
worker_mem_report(worker);
return 0;
/* query the forwarding address */
verbose(VERB_DETAIL, "process_query ID %d", ntohs(w->query_id));
pending_udp_query(worker->back, w->query_reply.c->buffer,
&worker->fwd_addr, worker->fwd_addrlen, UDP_QUERY_TIMEOUT,
worker_handle_reply, w, worker->rndstate);
}
/** check request sanity. Returns error code, 0 OK, or -1 discard.
* @param pkt: the wire packet to examine for sanity.
* @param worker: parameters for checking.
*/
static int
worker_check_request(ldns_buffer* pkt, struct worker* worker)
worker_check_request(ldns_buffer* pkt)
{
if(ldns_buffer_limit(pkt) < LDNS_HEADER_SIZE) {
verbose(VERB_DETAIL, "request too short, discarded");
return -1;
}
if(ldns_buffer_limit(pkt) > NORMAL_UDP_SIZE &&
worker->daemon->cfg->harden_large_queries) {
verbose(VERB_DETAIL, "request too large, discarded");
return -1;
}
if(LDNS_QR_WIRE(ldns_buffer_begin(pkt))) {
verbose(VERB_DETAIL, "request has QR bit on, discarded");
return -1;
@@ -214,7 +220,7 @@ worker_check_request(ldns_buffer* pkt, struct worker* worker)
LDNS_NSCOUNT(ldns_buffer_begin(pkt)));
return LDNS_RCODE_FORMERR;
}
if(LDNS_ARCOUNT(ldns_buffer_begin(pkt)) > 1) {
if(LDNS_ARCOUNT(ldns_buffer_begin(pkt)) != 0) {
verbose(VERB_DETAIL, "request wrong nr ar=%d",
LDNS_ARCOUNT(ldns_buffer_begin(pkt)));
return LDNS_RCODE_FORMERR;
@@ -222,12 +228,7 @@ worker_check_request(ldns_buffer* pkt, struct worker* worker)
return 0;
}
/** process control messages from the main thread.
* @param c: comm point to read from.
* @param arg: worker.
* @param error: error status of comm point.
* @param reply_info: not used.
*/
/** process control messages from the main thread. */
static int
worker_handle_control_cmd(struct comm_point* c, void* arg, int error,
struct comm_reply* ATTR_UNUSED(reply_info))
@@ -257,169 +258,6 @@ worker_handle_control_cmd(struct comm_point* c, void* arg, int error,
return 0;
}
/** check cname chain in cache reply */
static int
check_cache_chain(struct reply_info* rep) {
/* check only answer section rrs for matching cname chain.
* the cache may return changed rdata, but owner names are untouched.*/
size_t i;
uint8_t* sname = rep->rrsets[0]->rk.dname;
size_t snamelen = rep->rrsets[0]->rk.dname_len;
for(i=0; i<rep->an_numrrsets; i++) {
uint16_t t = ntohs(rep->rrsets[i]->rk.type);
if(t == LDNS_RR_TYPE_DNAME)
continue; /* skip dnames; note TTL 0 not cached */
/* verify that owner matches current sname */
if(query_dname_compare(sname, rep->rrsets[i]->rk.dname) != 0){
/* cname chain broken */
return 0;
}
/* if this is a cname; move on */
if(t == LDNS_RR_TYPE_CNAME) {
get_cname_target(rep->rrsets[i], &sname, &snamelen);
}
}
return 1;
}
/** answer query from the cache */
static int
answer_from_cache(struct worker* worker, struct lruhash_entry* e, uint16_t id,
uint16_t flags, struct comm_reply* repinfo, struct edns_data* edns)
{
struct msgreply_entry* mrentry = (struct msgreply_entry*)e->key;
struct reply_info* rep = (struct reply_info*)e->data;
uint32_t timenow = time(0);
uint16_t udpsize = edns->udp_size;
/* see if it is possible */
if(rep->ttl <= timenow) {
/* the rrsets may have been updated in the meantime.
* we will refetch the message format from the
* authoritative server
*/
return 0;
}
edns->edns_version = EDNS_ADVERTISED_VERSION;
edns->udp_size = EDNS_ADVERTISED_SIZE;
edns->ext_rcode = 0;
edns->bits &= EDNS_DO;
if(!rrset_array_lock(rep->ref, rep->rrset_count, timenow))
return 0;
/* locked and ids and ttls are OK. */
/* check CNAME chain (if any) */
if(rep->an_numrrsets > 0 && (rep->rrsets[0]->rk.type ==
htons(LDNS_RR_TYPE_CNAME) || rep->rrsets[0]->rk.type ==
htons(LDNS_RR_TYPE_DNAME))) {
if(!check_cache_chain(rep)) {
rrset_array_unlock_touch(worker->env.rrset_cache,
worker->scratchpad, rep->ref, rep->rrset_count);
region_free_all(worker->scratchpad);
return 0;
}
}
if(!reply_info_answer_encode(&mrentry->key, rep, id, flags,
repinfo->c->buffer, timenow, 1, worker->scratchpad,
udpsize, edns, (int)(edns->bits & EDNS_DO) )) {
error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
&mrentry->key, id, flags, edns);
}
/* cannot send the reply right now, because blocking network syscall
* is bad while holding locks. */
rrset_array_unlock_touch(worker->env.rrset_cache, worker->scratchpad,
rep->ref, rep->rrset_count);
region_free_all(worker->scratchpad);
/* go and return this buffer to the client */
return 1;
}
/**
* Fill CH class answer into buffer. Keeps query.
* @param pkt: buffer
* @param str: string to put into text record (<255).
* @param edns: edns reply information.
*/
static void
chaos_replystr(ldns_buffer* pkt, const char* str, struct edns_data* edns)
{
size_t len = strlen(str);
unsigned int rd = LDNS_RD_WIRE(ldns_buffer_begin(pkt));
unsigned int cd = LDNS_CD_WIRE(ldns_buffer_begin(pkt));
if(len>255) len=255; /* cap size of TXT record */
ldns_buffer_clear(pkt);
ldns_buffer_skip(pkt, (ssize_t)sizeof(uint16_t)); /* skip id */
ldns_buffer_write_u16(pkt, (uint16_t)(BIT_QR|BIT_RA));
if(rd) LDNS_RD_SET(ldns_buffer_begin(pkt));
if(cd) LDNS_CD_SET(ldns_buffer_begin(pkt));
ldns_buffer_write_u16(pkt, 1); /* qdcount */
ldns_buffer_write_u16(pkt, 1); /* ancount */
ldns_buffer_write_u16(pkt, 0); /* nscount */
ldns_buffer_write_u16(pkt, 0); /* arcount */
(void)query_dname_len(pkt); /* skip qname */
ldns_buffer_skip(pkt, (ssize_t)sizeof(uint16_t)); /* skip qtype */
ldns_buffer_skip(pkt, (ssize_t)sizeof(uint16_t)); /* skip qclass */
ldns_buffer_write_u16(pkt, 0xc00c); /* compr ptr to query */
ldns_buffer_write_u16(pkt, LDNS_RR_TYPE_TXT);
ldns_buffer_write_u16(pkt, LDNS_RR_CLASS_CH);
ldns_buffer_write_u32(pkt, 0); /* TTL */
ldns_buffer_write_u16(pkt, sizeof(uint8_t) + len);
ldns_buffer_write_u8(pkt, len);
ldns_buffer_write(pkt, str, len);
ldns_buffer_flip(pkt);
edns->edns_version = EDNS_ADVERTISED_VERSION;
edns->udp_size = EDNS_ADVERTISED_SIZE;
edns->bits &= EDNS_DO;
attach_edns_record(pkt, edns);
}
/**
* Answer CH class queries.
* @param w: worker
* @param qinfo: query info. Pointer into packet buffer.
* @param edns: edns info from query.
* @param pkt: packet buffer.
* @return: true if a reply is to be sent.
*/
static int
answer_chaos(struct worker* w, struct query_info* qinfo,
struct edns_data* edns, ldns_buffer* pkt)
{
struct config_file* cfg = w->env.cfg;
if(qinfo->qtype != LDNS_RR_TYPE_ANY && qinfo->qtype != LDNS_RR_TYPE_TXT)
return 0;
if(query_dname_compare(qinfo->qname,
(uint8_t*)"\002id\006server") == 0 ||
query_dname_compare(qinfo->qname,
(uint8_t*)"\010hostname\004bind") == 0)
{
if(cfg->hide_identity)
return 0;
if(cfg->identity==NULL || cfg->identity[0]==0) {
char buf[MAXHOSTNAMELEN];
if (gethostname(buf, MAXHOSTNAMELEN) == 0)
chaos_replystr(pkt, buf, edns);
else {
log_err("gethostname: %s", strerror(errno));
chaos_replystr(pkt, "no hostname", edns);
}
}
else chaos_replystr(pkt, cfg->identity, edns);
return 1;
}
if(query_dname_compare(qinfo->qname,
(uint8_t*)"\007version\006server") == 0 ||
query_dname_compare(qinfo->qname,
(uint8_t*)"\007version\004bind") == 0)
{
if(cfg->hide_version)
return 0;
if(cfg->version==NULL || cfg->version[0]==0)
chaos_replystr(pkt, PACKAGE_STRING, edns);
else chaos_replystr(pkt, cfg->version, edns);
return 1;
}
return 0;
}
/** handles callbacks from listening event interface */
static int
worker_handle_request(struct comm_point* c, void* arg, int error,
@@ -430,14 +268,14 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
hashvalue_t h;
struct lruhash_entry* e;
struct query_info qinfo;
struct edns_data edns;
struct work_query* w;
verbose(VERB_DETAIL, "worker handle request");
if(error != NETEVENT_NOERROR) {
log_err("handle request called with err=%d", error);
log_err("called with err=%d", error);
return 0;
}
if((ret=worker_check_request(c->buffer, worker)) != 0) {
verbose(VERB_ALGO, "worker check request: bad query.");
if((ret=worker_check_request(c->buffer)) != 0) {
if(ret != -1) {
LDNS_QR_SET(ldns_buffer_begin(c->buffer));
LDNS_RCODE_SET(ldns_buffer_begin(c->buffer), ret);
@@ -446,103 +284,59 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
comm_point_drop_reply(repinfo);
return 0;
}
worker->stats.num_queries++;
/* see if query is in the cache */
if(!query_info_parse(&qinfo, c->buffer)) {
verbose(VERB_ALGO, "worker parse request: formerror.");
LDNS_QR_SET(ldns_buffer_begin(c->buffer));
LDNS_RCODE_SET(ldns_buffer_begin(c->buffer),
LDNS_RCODE_FORMERR);
return 1;
}
if(qinfo.qtype == LDNS_RR_TYPE_AXFR ||
qinfo.qtype == LDNS_RR_TYPE_IXFR) {
verbose(VERB_ALGO, "worker request: refused zone transfer.");
LDNS_QR_SET(ldns_buffer_begin(c->buffer));
LDNS_RCODE_SET(ldns_buffer_begin(c->buffer),
LDNS_RCODE_REFUSED);
return 1;
}
if((ret=parse_edns_from_pkt(c->buffer, &edns)) != 0) {
verbose(VERB_ALGO, "worker parse edns: formerror.");
LDNS_QR_SET(ldns_buffer_begin(c->buffer));
LDNS_RCODE_SET(ldns_buffer_begin(c->buffer), ret);
return 1;
}
if(edns.edns_present && edns.edns_version != 0) {
edns.ext_rcode = (uint8_t)(EDNS_RCODE_BADVERS>>4);
edns.edns_version = EDNS_ADVERTISED_VERSION;
edns.udp_size = EDNS_ADVERTISED_SIZE;
edns.bits &= EDNS_DO;
verbose(VERB_ALGO, "query with bad edns version.");
error_encode(c->buffer, EDNS_RCODE_BADVERS&0xf, &qinfo,
*(uint16_t*)ldns_buffer_begin(c->buffer),
ldns_buffer_read_u16_at(c->buffer, 2), NULL);
attach_edns_record(c->buffer, &edns);
return 1;
}
if(edns.edns_present && edns.udp_size < NORMAL_UDP_SIZE &&
worker->daemon->cfg->harden_short_bufsize) {
verbose(VERB_DETAIL, "worker request: EDNS bufsize %d ignored",
(int)edns.udp_size);
edns.udp_size = NORMAL_UDP_SIZE;
}
if(edns.edns_present && edns.udp_size < LDNS_HEADER_SIZE) {
verbose(VERB_ALGO, "worker request: edns is too small.");
LDNS_QR_SET(ldns_buffer_begin(c->buffer));
LDNS_TC_SET(ldns_buffer_begin(c->buffer));
LDNS_RCODE_SET(ldns_buffer_begin(c->buffer),
LDNS_RCODE_SERVFAIL);
ldns_buffer_set_position(c->buffer, LDNS_HEADER_SIZE);
ldns_buffer_flip(c->buffer);
return 1;
}
if(c->type != comm_udp)
edns.udp_size = 65535; /* max size for TCP replies */
if(qinfo.qclass == LDNS_RR_CLASS_CH && answer_chaos(worker, &qinfo,
&edns, c->buffer)) {
verbose(VERB_ALGO, "class CH reply");
return 1;
}
h = query_info_hash(&qinfo);
if((e=slabhash_lookup(worker->env.msg_cache, h, &qinfo, 0))) {
if((e=slabhash_lookup(worker->daemon->msg_cache, h, &qinfo, 0))) {
/* answer from cache - we have acquired a readlock on it */
if(answer_from_cache(worker, e,
*(uint16_t*)ldns_buffer_begin(c->buffer),
ldns_buffer_read_u16_at(c->buffer, 2), repinfo,
&edns)) {
lock_rw_unlock(&e->lock);
return 1;
}
verbose(VERB_DETAIL, "answer from the cache -- data has timed out");
uint16_t id;
log_info("answer from the cache");
memcpy(&id, ldns_buffer_begin(c->buffer), sizeof(uint16_t));
reply_info_answer_iov((struct reply_info*)e->data, id,
ldns_buffer_read_u16_at(c->buffer, 2), repinfo, 1);
lock_rw_unlock(&e->lock);
return 0;
}
ldns_buffer_rewind(c->buffer);
server_stats_querymiss(&worker->stats, worker);
/* perform memory allocation(s) */
if(!query_info_allocqname(&qinfo)) {
comm_point_drop_reply(repinfo);
return 0;
}
/* grab a work request structure for this new request */
if(worker->env.mesh->all.count > worker->request_size) {
if(!(w = worker->free_queries)) {
/* we could get this due to a slow tcp incoming query,
that started before we performed listen_pushback */
verbose(VERB_DETAIL, "worker: too many incoming requests "
"active. dropping incoming query.");
verbose(VERB_ALGO, "currently servicing %d of %d queries",
(int)worker->env.mesh->all.count,
(int)worker->request_size);
worker->stats.num_query_list_exceeded++;
comm_point_drop_reply(repinfo);
query_info_clear(&qinfo);
return 0;
}
mesh_new_client(worker->env.mesh, &qinfo,
ldns_buffer_read_u16_at(c->buffer, 2),
&edns, repinfo, *(uint16_t*)ldns_buffer_begin(c->buffer));
if(worker->env.mesh->all.count == worker->request_size) {
worker->free_queries = w->next;
worker->num_requests ++;
log_assert(worker->num_requests <= worker->request_size);
if(worker->num_requests == worker->request_size) {
/* the max request number has been reached, stop accepting */
listen_pushback(worker->front);
}
worker_mem_report(worker);
/* init request */
w->next = NULL;
w->query_hash = h;
memcpy(&w->query_reply, repinfo, sizeof(struct comm_reply));
memcpy(&w->qinfo, &qinfo, sizeof(struct query_info));
memcpy(&w->query_id, ldns_buffer_begin(c->buffer), sizeof(uint16_t));
w->query_flags = ldns_buffer_read_u16_at(c->buffer, 2);
/* answer it */
worker_process_query(worker, w);
return 0;
}
@@ -610,6 +404,40 @@ worker_create(struct daemon* daemon, int id)
return worker;
}
/** create request handling structures */
static int
reqs_init(struct worker* worker)
{
size_t i;
for(i=0; i<worker->request_size; i++) {
struct work_query* q = (struct work_query*)calloc(1,
sizeof(struct work_query));
if(!q) return 0;
q->worker = worker;
q->next = worker->free_queries;
worker->free_queries = q;
q->all_next = worker->all_queries;
worker->all_queries = q;
}
return 1;
}
/** delete request list */
static void
reqs_delete(struct worker* worker)
{
struct work_query* q = worker->all_queries;
struct work_query* n;
while(q) {
n = q->all_next;
log_assert(q->worker == worker);
/* comm_reply closed in outside_network_delete */
query_info_clear(&q->qinfo);
free(q);
q = n;
}
}
int
worker_init(struct worker* worker, struct config_file *cfg,
struct listen_port* ports, size_t buffer_size, int do_sigs)
@@ -643,21 +471,6 @@ worker_init(struct worker* worker, struct config_file *cfg,
} else { /* !do_sigs */
worker->comsig = 0;
}
/* init random(), large table size. */
if(!(worker->rndstate = (struct ub_randstate*)calloc(1,
sizeof(struct ub_randstate)))) {
log_err("malloc rndtable failed.");
worker_delete(worker);
return 0;
}
seed = (unsigned int)time(NULL) ^ (unsigned int)getpid() ^
(((unsigned int)worker->thread_num)<<17);
/* shift thread_num so it does not match out pid bits */
if(!ub_initstate(seed, worker->rndstate, RND_STATE_SIZE)) {
log_err("could not init random numbers.");
worker_delete(worker);
return 0;
}
worker->front = listen_create(worker->base, ports,
buffer_size, worker_handle_request, worker);
if(!worker->front) {
@@ -669,16 +482,26 @@ worker_init(struct worker* worker, struct config_file *cfg,
cfg->outgoing_num_ports * worker->thread_num;
worker->back = outside_network_create(worker->base,
buffer_size, (size_t)cfg->outgoing_num_ports, cfg->ifs,
cfg->num_ifs, cfg->do_ip4, cfg->do_ip6, startport,
cfg->do_tcp?cfg->outgoing_num_tcp:0,
worker->daemon->env->infra_cache, worker->rndstate);
cfg->num_ifs, cfg->do_ip4, cfg->do_ip6, startport);
if(!worker->back) {
log_err("could not create outgoing sockets");
worker_delete(worker);
return 0;
}
outside_network_set_secondary_buffer(worker->back,
worker->front->udp_buff);
/* init random(), large table size. */
if(!(worker->rndstate = (struct ub_randstate*)calloc(1,
sizeof(struct ub_randstate)))) {
log_err("malloc rndtable failed.");
worker_delete(worker);
return 0;
}
seed = (unsigned int)time(NULL) ^ (unsigned int)getpid() ^
(unsigned int)worker->thread_num;
if(!ub_initstate(seed, worker->rndstate, RND_STATE_SIZE)) {
log_err("could not init random numbers.");
worker_delete(worker);
return 0;
}
if(worker->thread_num != 0) {
/* start listening to commands */
if(!(worker->cmd_com=comm_point_create_local(worker->base,
@@ -689,36 +512,20 @@ worker_init(struct worker* worker, struct config_file *cfg,
return 0;
}
}
worker->scratchpad = region_create_custom(malloc, free,
65536, 8192, 32, 1);
if(!worker->scratchpad) {
log_err("malloc failure");
worker_delete(worker);
return 0;
}
worker->request_size = cfg->num_queries_per_thread;
server_stats_init(&worker->stats);
alloc_init(&worker->alloc, &worker->daemon->superalloc,
worker->thread_num);
worker->env = *worker->daemon->env;
worker->env.worker = worker;
worker->env.alloc = &worker->alloc;
worker->env.rnd = worker->rndstate;
worker->env.scratch = worker->scratchpad;
worker->env.mesh = mesh_create(worker->daemon->num_modules,
worker->daemon->modfunc, &worker->env);
worker->env.detach_subs = &mesh_detach_subs;
worker->env.attach_sub = &mesh_attach_sub;
worker->env.kill_sub = &mesh_state_delete;
worker->env.query_done = &mesh_query_done;
worker->env.walk_supers = &mesh_walk_supers;
worker->env.detect_cycle = &mesh_detect_cycle;
if(!worker->env.mesh) {
if(!reqs_init(worker)) {
worker_delete(worker);
return 0;
}
worker_mem_report(worker);
/* set forwarder address */
if(cfg->fwd_address && cfg->fwd_address[0]) {
if(!worker_set_fwd(worker, cfg->fwd_address, cfg->fwd_port)) {
worker_delete(worker);
fatal_exit("could not set forwarder address");
}
}
alloc_init(&worker->alloc, &worker->daemon->superalloc);
return 1;
}
@@ -733,10 +540,7 @@ worker_delete(struct worker* worker)
{
if(!worker)
return;
mesh_stats(worker->env.mesh, "mesh has");
server_stats_log(&worker->stats, worker->thread_num);
worker_mem_report(worker);
mesh_delete(worker->env.mesh);
reqs_delete(worker);
listen_delete(worker->front);
outside_network_delete(worker->back);
comm_signal_delete(worker->comsig);
@@ -753,54 +557,38 @@ worker_delete(struct worker* worker)
close(worker->cmd_recv_fd);
worker->cmd_recv_fd = -1;
alloc_clear(&worker->alloc);
region_destroy(worker->scratchpad);
free(worker);
}
int
worker_send_packet(ldns_buffer* pkt, struct sockaddr_storage* addr,
socklen_t addrlen, int timeout, struct module_qstate* q, int use_tcp)
worker_set_fwd(struct worker* worker, const char* ip, int port)
{
struct worker* worker = q->env->worker;
if(use_tcp) {
return pending_tcp_query(worker->back, pkt, addr, addrlen,
timeout, worker_handle_reply, q,
worker->rndstate) != 0;
uint16_t p;
log_assert(worker && ip);
p = (uint16_t) port;
if(str_is_ip6(ip)) {
struct sockaddr_in6* sa =
(struct sockaddr_in6*)&worker->fwd_addr;
worker->fwd_addrlen = (socklen_t)sizeof(struct sockaddr_in6);
memset(sa, 0, worker->fwd_addrlen);
sa->sin6_family = AF_INET6;
sa->sin6_port = (in_port_t)htons(p);
if(inet_pton((int)sa->sin6_family, ip, &sa->sin6_addr) <= 0) {
log_err("Bad ip6 address %s", ip);
return 0;
}
} else { /* ip4 */
struct sockaddr_in* sa =
(struct sockaddr_in*)&worker->fwd_addr;
worker->fwd_addrlen = (socklen_t)sizeof(struct sockaddr_in);
memset(sa, 0, worker->fwd_addrlen);
sa->sin_family = AF_INET;
sa->sin_port = (in_port_t)htons(p);
if(inet_pton((int)sa->sin_family, ip, &sa->sin_addr) <= 0) {
log_err("Bad ip4 address %s", ip);
return 0;
}
}
return pending_udp_query(worker->back, pkt, addr, addrlen,
timeout*1000, worker_handle_reply, q,
worker->rndstate) != 0;
}
/** compare outbound entry qstates */
static int
outbound_entry_compare(void* a, void* b)
{
struct outbound_entry* e1 = (struct outbound_entry*)a;
struct outbound_entry* e2 = (struct outbound_entry*)b;
if(e1->qstate == e2->qstate)
return 1;
return 0;
}
struct outbound_entry*
worker_send_query(uint8_t* qname, size_t qnamelen, uint16_t qtype,
uint16_t qclass, uint16_t flags, int dnssec,
struct sockaddr_storage* addr, socklen_t addrlen,
struct module_qstate* q)
{
struct worker* worker = q->env->worker;
struct outbound_entry* e = (struct outbound_entry*)malloc(sizeof(*e));
if(!e)
return NULL;
e->qstate = q;
e->qsent = outnet_serviced_query(worker->back, qname,
qnamelen, qtype, qclass, flags, dnssec, addr, addrlen,
worker_handle_service_reply, e, worker->back->udp_buff,
&outbound_entry_compare);
if(!e->qsent) {
free(e);
return NULL;
}
return e;
verbose(VERB_ALGO, "fwd queries to: %s %d", ip, p);
return 1;
}
+40 -44
View File
@@ -48,16 +48,12 @@
#include "util/locks.h"
#include "util/alloc.h"
#include "util/data/msgreply.h"
#include "util/data/msgparse.h"
#include "daemon/stats.h"
#include "util/module.h"
struct listen_dnsport;
struct outside_network;
struct config_file;
struct daemon;
struct listen_port;
struct ub_randstate;
struct region;
/** size of table used for random numbers. large to be more secure. */
#define RND_STATE_SIZE 256
@@ -68,6 +64,26 @@ enum worker_commands {
worker_cmd_quit
};
/** information per query that is in processing */
struct work_query {
/** next query in freelist */
struct work_query* next;
/** the worker for this query */
struct worker* worker;
/** the query reply destination, packet buffer and where to send. */
struct comm_reply query_reply;
/** the query_info structure from the query */
struct query_info qinfo;
/** hash value of the query qinfo */
hashvalue_t query_hash;
/** next query in all-list */
struct work_query* all_next;
/** id of query, in network byteorder. */
uint16_t query_id;
/** flags uint16 from query */
uint16_t query_flags;
};
/**
* Structure holding working information for unbound.
* Holds globally visible information.
@@ -94,8 +110,19 @@ struct worker {
/** commpoint to listen to commands. */
struct comm_point* cmd_com;
/** number of requests currently active */
size_t num_requests;
/** number of requests that can be handled by this worker */
size_t request_size;
/** the free working queries */
struct work_query* free_queries;
/** list of all working queries */
struct work_query* all_queries;
/** address to forward to */
struct sockaddr_storage fwd_addr;
/** length of fwd_addr */
socklen_t fwd_addrlen;
/** random() table for this worker. */
struct ub_randstate* rndstate;
@@ -103,13 +130,6 @@ struct worker {
int need_to_restart;
/** allocation cache for this thread */
struct alloc_cache alloc;
/** per thread statistics */
struct server_stats stats;
/** thread scratch region */
struct region* scratchpad;
/** module environment passed to modules, changed for this thread */
struct module_env env;
};
/**
@@ -144,6 +164,15 @@ void worker_work(struct worker* worker);
*/
void worker_delete(struct worker* worker);
/**
* Set forwarder
* @param worker: the worker to modify.
* @param ip: the server name.
* @param port: port on server or NULL for default 53.
* @return: false on error.
*/
int worker_set_fwd(struct worker* worker, const char* ip, int port);
/**
* Send a command to a worker. Uses blocking writes.
* @param worker: worker to send command to.
@@ -160,37 +189,4 @@ void worker_send_cmd(struct worker* worker, ldns_buffer* buffer,
*/
void worker_sighandler(int sig, void* arg);
/**
* Worker service routine to send udp messages for modules.
* @param pkt: packet to send.
* @param addr: where to.
* @param addrlen: length of addr.
* @param timeout: seconds to wait until timeout.
* @param q: wich query state to reactivate upon return.
* @param use_tcp: true to use TCP, false for UDP.
* @return: false on failure (memory or socket related). no query was
* sent.
*/
int worker_send_packet(ldns_buffer* pkt, struct sockaddr_storage* addr,
socklen_t addrlen, int timeout, struct module_qstate* q, int use_tcp);
/**
* Worker service routine to send serviced queries to authoritative servers.
* @param qname: query name. (host order)
* @param qnamelen: length in bytes of qname, including trailing 0.
* @param qtype: query type. (host order)
* @param qclass: query class. (host order)
* @param flags: host order flags word, with opcode and CD bit.
* @param dnssec: if set, EDNS record will have DO bit set.
* @param addr: where to.
* @param addrlen: length of addr.
* @param q: wich query state to reactivate upon return.
* @return: false on failure (memory or socket related). no query was
* sent.
*/
struct outbound_entry* worker_send_query(uint8_t* qname, size_t qnamelen,
uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec,
struct sockaddr_storage* addr, socklen_t addrlen,
struct module_qstate* q);
#endif /* DAEMON_WORKER_H */
-7
View File
@@ -1,7 +0,0 @@
Unbound was developed at NLnet Labs by Wouter Wijngaards.
Unbound was devised by Bill Manning, David Blacka, and Matt Larson
from the University of California and from Verisign. The Java prototype
was made in further cooperation with Geoff Sisson and Roy Arends from Nominet.
At NLnet Labs, Jelte Jansen and Mark Santcroos reviewed the unbound C sources.
-479
View File
@@ -1,482 +1,3 @@
31 July 2007: Wouter
- updated plan
30 July 2007: Wouter
- changed random state init, so that sequential process IDs are not
cancelled out by sequential thread-ids in the random number seed.
- the fwd_three test, which sends three queries to unbound, and
unbound is kept waiting by ldns-testns for 3 seconds, failed
because the retry timeout for default by unbound is 3 seconds too,
it would hit that timeout and fail the test. Changed so that unbound
is kept waiting for 2 seconds instead.
27 July 2007: Wouter
- removed useless -C debug option. It did not work.
- text edit of documentation.
- added doc/CREDITS file, referred to by the manpages.
- updated planning.
26 July 2007: Wouter
- cycle detection, for query state dependencies. Will attempt to
circumvent the cycle, but if no other targets available fails.
- unit test for AXFR, IXFR response.
- test for cycle detection.
25 July 2007: Wouter
- testbound read ADDRESS and check it.
- test for version.bind and friends.
- test for iterator chaining through several referrals.
- test and fixup for refetch for glue. Refetch fails if glue
is still not provided.
24 July 2007: Wouter
- Example section in config manual.
- Addr stored for range and moment in replay.
20 July 2007: Wouter
- Check CNAME chain before returning cache entry with CNAMEs.
- Option harden-glue, default is on. It will discard out of zone
data. If disabled, performance is faster, but spoofing attempts
become a possibility. Note that still normalize scrubbing is done,
and that the potentially spoofed data is used for infrastructure
and not returned to the client.
- if glue times out, refetch by asking parent of delegation again.
Much like asking for DS at the parent side.
- TODO items from forgery-resilience draft.
and on memory handling improvements.
- renamed module_event_timeout to module_event_noreply.
- memory reporting code; reports on memory usage after handling
a network packet (not on cache replies).
19 July 2007: Wouter
- shuffle NS selection when getting nameserver target addresses.
- fixup of deadlock warnings, yield cpu in checklock code so that
freebsd scheduler selects correct process to run.
- added identity and version config options and replies.
- store cname messages complete answers.
18 July 2007: Wouter
- do not query addresses, 127.0.0.1, and ::1 by default.
17 July 2007: Wouter
- forward zone options in config file.
- forward per zone in iterator. takes precendence over stubs.
- fixup commithooks.
- removed forward-to and forward-to-port features, subsumed by
new forward zones.
- fix parser to handle absent server: clause.
- change untrusted rrset test to account for scrubber that is now
applied during the test (which removes the poison, by the way).
- feature, addresses can be specified with @portnumber, like nsd.conf.
- test config files changed over to new forwarder syntax.
27 June 2007: Wouter
- delete of mesh does a postorder traverse of the tree.
- found and fixed a memory leak. For TTL=0 messages, that would
not be cached, instead the msg-replyinfo structure was leaked.
- changed server selection so it will filter out hosts that are
unresponsive. This is defined as a host with the maximum rto value.
This means that unbound tried the host for retries up to 120 secs.
The rto value will time out after host-ttl seconds from the cache.
This keeps such unresolvable queries from taking up resources.
- utility for keeping histogram.
26 June 2007: Wouter
- mesh is called by worker, and iterator uses it.
This removes the hierarchical code.
QueryTargets state and Finished state are merged for iterator.
- forwarder mode no longer sets AA bit on first reply.
- rcode in walk_supers is not needed.
25 June 2007: Wouter
- more mesh work.
- error encode routine for ease.
22 June 2007: Wouter
- removed unused _node iterator value from rbtree_t. Takes up space.
- iterator can handle querytargets state without a delegation point
set, so that a priming(stub) subquery error can be handled.
- iterator stores if it is priming or not.
- log_query_info() neater logging.
- changed iterator so that it does not alter module_qstate.qinfo
but keeps a chase query info. Also query_flags are not altered,
the iterator uses chase_flags.
- fixup crash in case no ports for the family exist.
21 June 2007: Wouter
- Fixup secondary buffer in case of error callback.
- cleanup slumber list of runnable states.
- module_subreq_depth fails to work in slumber list.
- fixup query release for cached results to sub targets.
- neater error for tcp connection failure, shows addr in verbose.
- rbtree_init so that it can be used with preallocated memory.
20 June 2007: Wouter
- new -C option to enable coredumps after forking away.
- doc update.
- fixup CNAME generation by scrubber, and memory allocation of it.
- fixup deletion of serviced queries when all callbacks delete too.
- set num target queries to 0 when you move them to slumber list.
- typo in check caused subquery errors to be ignored, fixed.
- make lint happy about rlim_t.
- freeup of modules after freeup of module-states.
- duplicate replies work, this uses secondary udp buffer in outnet.
19 June 2007: Wouter
- nicer layout in stats.c, review 0.3 change.
- spelling improvement, review 0.3 change.
- uncapped timeout for server selection, so that very fast or slow
servers will stand out from the rest.
- target-fetch-policy: "3 2 1 0 0" config setting.
- fixup queries answered without RD bit (for root prime results).
- refuse AXFR and IXFR requests.
- fixup RD flag in error reply from iterator. fixup RA flag from
worker error reply.
- fixup encoding of very short edns buffer sizes, now sets TC bit.
- config options harden-short-bufsize and harden-large-queries.
18 June 2007: Wouter
- same, move subqueries to slumber list when first has resolved.
- fixup last fix for duplicate callbacks.
- another offbyone in targetcounter. Also in Java prototype by the way.
15 June 2007: Wouter
- if a query asks to be notified of the same serviced query result
multiple times, this will succeed. Only one callback will happen;
multiple outbound-list entries result (but the double cleanup of it
will not matter).
- when iterator moves on due to CNAME or referral, it will remove
the subqueries (for other targets). These are put on the slumber
list.
- state module wait subq is OK with no new subqs, an old one may have
stopped, with an error, and it is still waiting for other ones.
- if a query loops, halt entire query (easy way to clean up properly).
14 June 2007: Wouter
- num query targets was > 0 , not >= 0 compared, so that fetch
policy of 0 did nothing.
13 June 2007: Wouter
- debug option: configure --enable-static-exe for compile where
ldns and libevent are linked statically. Default is off.
- make install and make uninstall. Works with static-exe and without.
installation of unbound binary and manual pages.
- alignement problem fix on solaris 64.
- fixup address in case of TCP error.
12 June 2007: Wouter
- num target queries was set to 0 at a bad time. Default it to 0 and
increase as target queries are done.
- synthesize CNAME and DNAME responses from the cache.
- Updated doxygen config for doxygen 1.5.
- aclocal newer version.
- doxygen 1.5 fixes for comments (for the strict check on docs).
11 June 2007: Wouter
- replies on TCP queries have the address field set in replyinfo,
for serviced queries, because the initiator does not know that
a TCP fallback has occured.
- omit DNSSEC types from nonDO replies, except if qtype is ANY or
if qtype directly queries for the type (and then only show that
'unknown type' in the answer section).
- fixed message parsing where rrsigs on their own would be put
in the signature list over the rrsig type.
7 June 2007: Wouter
- fixup error in double linked list insertion for subqueries and
for outbound list of serviced queries for iterator module.
- nicer printout of outgoing port selection.
- fixup cname target readout.
- nicer debug output.
- fixup rrset counts when prepending CNAMEs to the answer.
- fixup rrset TTL for prepended CNAMEs.
- process better check for looping modules, and which submodule to
run next.
- subreq insertion code fixup for slumber list.
- VERB_DETAIL, verbosity: 2 level gives short but readable output.
VERB_ALGO, verbosity: 3 gives extensive output.
- fixup RA bit in cached replies.
- fixup CNAME responses from the cache no longer partial response.
- error in network send handled without leakage.
- enable ip6 from config, and try ip6 addresses if available,
if ip6 is not connected, skips to next server.
5 June 2007: Wouter
- iterator state finished.
- subrequests without parent store in cache and stop.
- worker slumber list for ongoing promiscuous queries.
- subrequest error handling.
- priming failure returns SERVFAIL.
- priming gives LAME result, returns SERVFAIL.
- debug routine to print dns_msg as handled by iterator.
- memleak in config file stubs fixup.
- more small bugs, in scrubber, query compare no ID for lookup,
in dname validation for NS targets.
- sets entry.key for new special allocs.
- lognametypeclass can display unknown types and classes.
4 June 2007: Wouter
- random selection of equally preferred nameserver targets.
- reply info copy routine. Reuses existing code.
- cache lameness in response handling.
- do not touch qstate after worker_process_query because it may have
been deleted by that routine.
- Prime response state.
- Process target response state.
- some memcmp changed to dname_compare for case preservation.
1 June 2007: Wouter
- normalize incoming messages. Like unbound-java, with CNAME chain
checked, DNAME checked, CNAME's synthesized, glue checked.
- sanitize incoming messages.
- split msgreply encode functions into own file msgencode.c.
- msg_parse to queryinfo/replyinfo conversion more versatile.
- process_response, classify response, delegpt_from_message.
31 May 2007: Wouter
- querytargets state.
- dname_subdomain_c() routine.
- server selection, based on RTT. ip6 is filtered out if not available,
and lameness is checked too.
- delegation point copy routine.
30 May 2007: Wouter
- removed FLAG_CD from message and rrset caches. This was useful for
an agnostic forwarder, but not for a sophisticated (trust value per
rrset enabled) cache.
- iterator reponse typing.
- iterator cname handle.
- iterator prime start.
- subquery work.
- processInitRequest and processInitRequest2.
- cache synthesizes referral messages, with DS and NSEC.
- processInitRequest3.
- if a request creates multiple subrequests these are all activated.
29 May 2007: Wouter
- routines to lock and unlock array of rrsets moved to cache/rrset.
- lookup message from msg cache (and copy to region).
- fixed cast error in dns msg lookup.
- message with duplicate rrset does not increase its TTLs twice.
- 'qnamesize' changed to 'qname_len' for similar naming scheme.
25 May 2007: Wouter
- Acknowledge use of unbound-java code in iterator. Nicer readme.
- services/cache/dns.c DNS Cache. Hybrid cache uses msgcache and
rrset cache from module environment.
- packed rrset key has type and class as easily accessable struct
members. They are still kept in network format for fast msg encode.
- dns cache find_delegation routine.
- iterator main functions setup.
- dns cache lookup setup.
24 May 2007: Wouter
- small changes to prepare for subqueries.
- iterator forwarder feature separated out.
- iterator hints stub code, config file stub code, so that first
testing can proceed locally.
- replay tests now have config option to enable forwarding mode.
23 May 2007: Wouter
- outside network does precise timers for roundtrip estimates for rtt
and for setting timeout for UDP. Pending_udp takes milliseconds.
- cleaner iterator sockaddr conversion of forwarder address.
- iterator/iter_utils and iter_delegpt setup.
- root hints.
22 May 2007: Wouter
- outbound query list for modules and support to callback with the
outbound entry to the module.
- testbound support for new serviced queries.
- test for retry to TCP cannot use testbound any longer.
- testns test for EDNS fallback, test for TCP fallback already exists.
- fixes for no-locking compile.
- mini_event timer precision and fix for change in timeouts during
timeout callback. Fix for fwd_three tests, performed nonexit query.
21 May 2007: Wouter
- small comment on hash table locking.
- outside network serviced queries, contain edns and tcp fallback,
and udp retries and rtt timing.
16 May 2007: Wouter
- lruhash_touch() would cause locking order problems. Fixup in
lock-verify in case locking cycle is found.
- services/cache/rrset.c for rrset cache code.
- special rrset_cache LRU updating function that uses the rrset id.
- no dependencies calculation when make clean is called.
- config settings for infra cache.
- daemon code slightly cleaner, only creates caches once.
15 May 2007: Wouter
- host cache code.
- unit test for host cache.
14 May 2007: Wouter
- Port to OS/X and Dec Alpha. Printf format and alignment fixes.
- extensive lock debug report on join timeout.
- proper RTT calculation, in utility code.
- setup of services/cache/infra, host cache.
11 May 2007: Wouter
- iterator/iterator.c module.
- fixup to pass reply_info in testcode and in netevent.
10 May 2007: Wouter
- created release-0.3 svn tag.
- util/module.h
- fixed compression - no longer compresses root name.
9 May 2007: Wouter
- outside network cleans up waiting tcp queries on exit.
- fallback to TCP.
- testbound replay with retry in TCP mode.
- tpkg test for retry in TCP mode, against ldns-testns server.
- daemon checks max number of open files and complains if not enough.
- test where data expires in the cache.
- compiletests: fixed empty body ifstatements in alloc.c, in case
locks are disabled.
8 May 2007: Wouter
- outgoing network keeps list of available tcp buffers for outgoing
tcp queries.
- outgoing-num-tcp config option.
- outgoing network keeps waiting list of queries waiting for buffer.
- netevent supports outgoing tcp commpoints, nonblocking connects.
7 May 2007: Wouter
- EDNS read from query, used to make reply smaller.
- advertised edns value constants.
- EDNS BADVERS response, if asked for too high edns version.
- EDNS extended error reponses once the EDNS record from the query
has successfully been parsed.
4 May 2007: Wouter
- msgreply sizefunc is more accurate.
- config settings for rrset cache size and slabs.
- hashtable insert takes argument so that a thread can use its own
alloc cache to store released keys.
- alloc cache special_release() locks if necessary.
- rrset trustworthiness type added.
- thread keeps a scratchpad region for handling messages.
- writev used in netevent to write tcp length and data after another.
This saves a roundtrip on tcp replies.
- test for one rrset updated in the cache.
- test for one rrset which is not updated, as it is not deemed
trustworthy enough.
- test for TTL refreshed in rrset.
3 May 2007: Wouter
- fill refs. Use new parse and encode to answer queries.
- stores rrsets in cache.
- uses new msgreply format in cache.
2 May 2007: Wouter
- dname unit tests in own file and spread out neatly in functions.
- more dname unit tests.
- message encoding creates truncated TC flagged messages if they do
not fit, and will leave out (whole)rrsets from additional if needed.
1 May 2007: Wouter
- decompress query section, extremely lenient acceptance.
But only for answers from other servers, not for plain queries.
- compression and decompression test cases.
- some stats added.
- example.conf interface: line is changed from 127.0.0.1 which leads
to problems if used (restricting communication to the localhost),
to a documentation and test address.
27 April 2007: Wouter
- removed iov usage, it is not good for dns message encoding.
- owner name compression more optimal.
- rrsig owner name compression.
- rdata domain name compression.
26 April 2007: Wouter
- floating point exception fix in lock-verify.
- lint uses make dependency
- fixup lint in dname owner domain name compression code.
- define for offset range that can be compressed to.
25 April 2007: Wouter
- prettier code; parse_rrset->type kept in host byte order.
- datatype used for hashvalue of converted rrsig structure.
- unit test compares edns section data too.
24 April 2007: Wouter
- ttl per RR, for RRSIG rrsets and others.
- dname_print debug function.
- if type is not known, size calc will skip DNAME decompression.
- RRSIG parsing and storing and putting in messages.
- dnssec enabled unit tests (from nlnetlabs.nl and se queries).
- EDNS extraction routine.
20 April 2007: Wouter
- code comes through all of the unit tests now.
- disabled warning about spurious extra data.
- documented the RRSIG parse plan in msgparse.h.
- rrsig reading and outputting.
19 April 2007: Wouter
- fix unit test to actually to tests.
- fix write iov helper, and fakevent code.
- extra builtin testcase (small packet).
- ttl converted to network format in packets.
- flags converted correctly
- rdatalen off by 2 error fixup.
- uses less iov space for header.
18 April 2007: Wouter
- review of msgparse code.
- smaller test cases.
17 April 2007: Wouter
- copy and decompress dnames.
- store calculated hash value too.
- routine to create message out of stored information.
- util/data/msgparse.c for message parsing code.
- unit test, and first fixes because of test.
* forgot rrset_count addition.
* did & of ptr on stack for memory position calculation.
* dname_pkt_copy forgot to read next label length.
- test from file and fixes
* double frees fixed in error conditions.
* types with less than full rdata allowed by parser.
Some dynamic update packets seem to use it.
16 April 2007: Wouter
- following a small change in LDNS, parsing code calculates the
memory size to allocate for rrs.
- code to handle ID creation.
13 April 2007: Wouter
- parse routines. Code that parses rrsets, rrs.
12 April 2007: Wouter
- dname compare routine that preserves case, with unit tests.
11 April 2007: Wouter
- parse work - dname packet parse, msgparse, querysection parse,
start of sectionparse.
10 April 2007: Wouter
- Improved alignment of reply_info packet, nice for 32 and 64 bit.
- Put RRset counts in reply_info, because the number of RRs can change
due to RRset updates.
- import of region-allocator code from nsd.
- set alloc special type to ub_packed_rrset_key.
Uses lruhash entry overflow chain next pointer in alloc cache.
- doxygen documentation for region-allocator.
- setup for parse scratch data.
5 April 2007: Wouter
- discussed packed rrset with Jelte.
4 April 2007: Wouter
- moved to version 0.3.
- added util/data/dname.c
- layout of memory for rrsets.
3 April 2007: Wouter
- detect sign of msghdr.msg_iovlen so that the cast to that type
in netevent (which is there to please lint) can be correct.
+6 -26
View File
@@ -4,30 +4,19 @@ http://unbound.net
This software is under BSD license, see LICENSE for details.
* Download the latest version of this software from
http://unbound.net
or get a beta version from the svn repository at
http://unbound.net/svn/
* Needs the following libraries
* ldns http://www.nlnetlabs.nl/ldns/ (BSD license)
* libevent http://www.monkey.org/~provos/libevent/ (BSD license)
* Create build environment
* run libtoolize -c if config.sub is missing.
* autoreconf (autoheader && autoconf), if ./configure is missing.
* Make and install: ./configure; make; make install
* Make and install: ./configure; make
* --with-ldns=/path/to/ldns
* --with-libevent=/path/to/libevent
Can be set to either the system install or the build directory.
--with-libevent=no gives a builtin alternative implementation.
* --without-pthreads
This disables pthreads, and uses Solaris thr library or no threading.
Without this option the pthreads library is detected automatically.
* --enable-static-exe
This enables a debug option to statically link, against ldns and
libevent libraries.
--with-libevent=no gives an alternative to libevent (based on select).
* Create build environment
* run libtoolize -c if config.sub is missing.
* autoreconf (autoheader && autoconf), if ./configure is missing.
Known issues
------------
@@ -36,13 +25,4 @@ o If libevent is older (1.3 and before), unbound will exit instead of reload
printed. Perform ./configure --with-libevent=no or update libevent, rerun
configure and recompile unbound to make sighup work correctly.
Acknowledgements
----------------
o Thanks to David Blacka and Matt Larson (Verisign) for the unbound-java
prototype. Design and code from that prototype has been used to create
this program. Such as the iterator state machine and the cache design.
o Other code origins are from the NSD (NLnet Labs) and LDNS (NLnet Labs)
projects. Such as buffer, region-allocator and red-black tree code.
o See Credits file for contributors.
* mailto:wouter@nlnetlabs.nl
-25
View File
@@ -3,28 +3,3 @@ o use real entropy to make random (ID, port) numbers more random.
o in production mode, do not free memory on exit. In debug mode, test leaks.
o profile memory allocation, and if performance issues, use special memory
allocator. For example, with caches per thread.
o #define BIT_... different on bigendian and smallendian systems so that
the htons on flags is not needed to send a message from the cache.
o speed up pkt domain name decompression loop detection using counter perhaps.
o detect OS/400 pthreads implementation that allows upgrading to writelock
on pthreads rwlocks and use it to examine-rd before storing-wr rrset cache.
o understand synthesized DNAMEs, so those TTL=0 packets are cached properly.
o understand NSEC/NSEC3, aggressive negative caching, so that updates to
NSEC/NSEC3 will result in proper negative responses.
o fallback without EDNS if result is NOTIMPL, now only on FORMERR like in java.
o scrubber has slow pkt_subdomain and pkt_strict_subdomain functions.
o get serverselection algorithm out of local optimum.
make subtargets to get rtt info for a couple of targets, like fetch-policy.
or send out multiple queries to multiple servers.
o donotqueryaddresses allow specification of subnets, use trie to store.
extend default list to contain illegal ip4 and ip6 addresses.
o memory profile; and if needed put serviced queries under qstate->region
and special purpose region code, reuse blocks, shrink if too big.
o check query, option to enforce presence of qdsection in noerror answers.
o configuration option where port 53 is used for send and receive, no other
ports are used.
o prime sequence in multiple queries, if glue missing from prime sequence.
o (option) to not send replies to clients after a timeout of (say 5 secs) has
passed, but keep task active for later retries by client.
o private TTL feature
o pretend-dnssec-unaware, and pretend-edns-unaware modes for debug/workshops.
+10 -97
View File
@@ -20,10 +20,7 @@ server:
# specify the interfaces to answer queries from by ip-address.
# If you give none the default (all) interface is used.
# specify every interface on a new 'interface:' labelled line.
# interface: 192.0.2.153
# interface: 192.0.2.154
# interface: 2001:DB8::5
# interface: 127.0.0.1
# port to answer queries from
# port: 53
@@ -39,48 +36,17 @@ server:
# But also takes more system resources (for open sockets).
# outgoing-range: 16
# number of outgoing simultaneous tcp buffers to hold per thread.
# outgoing-num-tcp: 10
# the amount of memory to use for the message cache.
# in bytes. default is 4 Mb
# msg-cache-size: 4194304
# the number of slabs to use for the message cache.
# the number of slabs must be a power of 2.
# more slabs reduce lock contention, but fragment memory usage.
# more slabs reduce lock contention, but fracture memory usage.
# msg-cache-slabs: 4
# the number of queries that a thread gets to service.
# num-queries-per-thread: 1024
# the amount of memory to use for the RRset cache.
# in bytes. default is 4 Mb
# rrset-cache-size: 4194304
# the number of slabs to use for the RRset cache.
# the number of slabs must be a power of 2.
# more slabs reduce lock contention, but fragment memory usage.
# rrset-cache-slabs: 4
# the time to live (TTL) value for cached roundtrip times and
# EDNS version information for hosts. In seconds.
# infra-host-ttl: 900
# the time to live (TTL) value for cached lame delegations. In sec.
# infra-lame-ttl: 900
# the number of slabs to use for the Infrastructure cache.
# the number of slabs must be a power of 2.
# more slabs reduce lock contention, but fragment memory usage.
# infra-cache-slabs: 4
# the maximum number of hosts that are cached (roundtrip times, EDNS).
# infra-cache-numhosts: 1000
# the maximum number of lame zones per host that are cached.
# infra-cache-numlame: 1000
# Enable IPv4, "yes" or "no".
# do-ip4: yes
@@ -93,6 +59,14 @@ server:
# Enable TCP, "yes" or "no".
# do-tcp: yes
# Set this to configure unbound to act as a forwarder. All queries are
# sent to the remote nameserver that will resolve them.
# Set to "" to disable forwarding, or give ip-address to enable.
# forward-to: ""
# The port number to send forwarded queries to.
# forward-to-port: 53
# 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.
@@ -110,64 +84,3 @@ server:
# the pid file.
# pidfile: "unbound.pid"
# enable to not answer id.server and hostname.bind queries.
# hide-identity: no
# enable to not answer version.server and version.bind queries.
# hide-version: no
# the identity to report. Leave "" or default to return hostname.
# identity: ""
# the version to report. Leave "" or default to return package version.
# version: ""
# the target fetch policy.
# series of integers describing the policy per dependency depth.
# The number of values in the list determines the maximum dependency
# depth the recursor will pursue before giving up. Each integer means:
# -1 : fetch all targets opportunistically,
# 0: fetch on demand,
# positive value: fetch that many targets opportunistically.
# Enclose the list of numbers between quotes ("").
# target-fetch-policy: "3 2 1 0 0"
# Harden against very small EDNS buffer sizes.
# harden-short-bufsize: no
# Harden against unseemly large queries.
# harden-large-queries: no
# Harden against out of zone rrsets, to avoid spoofing attempts.
# harden-glue: yes
# Do not query the following addresses. No DNS queries are sent there.
# List one address per entry. To block other ports than the default
# DNS port, use "1.2.3.4@123" to block port 123 for 1.2.3.4.
# do-not-query-address: 127.0.0.1
# do-not-query-address: ::1
# Stub zones.
# Create entries like below, to make all queries for 'example.com' and
# 'example.org' go to the given list of nameservers. list zero or more
# nameservers by hostname or by ipaddress.
# stub-zone:
# name: "example.com"
# stub-addr: 192.0.2.68
# stub-zone:
# name: "example.org"
# stub-host: ns.example.com.
# Forward zones
# Create entries like below, to make all queries for 'example.com' and
# 'example.org' go to the given list of servers. These servers have to handle
# recursion to other nameservers. List zero or more nameservers by hostname
# or by ipaddress. Use an entry with name "." to forward all queries.
# forward-zone:
# name: "example.com"
# forward-addr: 192.0.2.68
# forward-addr: 192.0.2.73@5355 # forward to port 5355.
# forward-zone:
# name: "example.org"
# forward-host: fwd.example.com
+8 -37
View File
@@ -29,23 +29,14 @@ Roughly the boxes are as follows:
This stage takes longer, due to complexity in the iterator module.
Twice as long; one box for module layout, one box for iterator module.
0.5 Validator - validator module.
0.6 Bigger and better - Operational useful features (config, log, memory)
0.6 Bigger and better - good syslog, compressed packets, port ranges,
config file format with config checker.
0.7 Local zones feature - localzones stubzones fwdzones, no leak rfc1918.
views support; for selective recursive service.
0.8 Library use - resolver validator lib (and test apps)
0.9 Corner cases - be able to resolve in the wild. Run fuzzers.
Run as many tests as we can think of.
Go through logs and check for long, unresolved cases
Use profiler.
0.10 Beta release. Run shadow for a resolver in production for several
weeks.
0.11 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, option to enforce qdsection checking (forgery-resilience).
NSID support.
Be able to prime roots using several queries (only NS on first).
For boxes 0.5-1.0 the planning is to be revised, at the 0.5 stage external
coders are welcome. Since the project is bigger, there is room for them.
@@ -124,7 +115,7 @@ Styleguide:
* Speed test of caching forwarder.
*** Basic Resolver
* Create module interface and module caller algorithm.
* Create module interfacce and module caller algorithm.
* Daemon config to use modules. Test the module caller.
* Create basic iterator and scrubber modules.
* Test every state of the iterator by passing test data into
@@ -143,18 +134,19 @@ Styleguide:
* Speed test.
*** Bigger and Better
* DNS packet compression of output.
* test packet compression (that it compresses.)
* config option to compress yes/no
* speed test with and without compression.
* Config file syntax checker program. Tests on checker.
* Use a huge number of random outgoing ports.
* Logging first class feature with config options.
* donotqueryaddresses with trie for blocking entire netblocks.
* Memory overhaul, special allocators for hashtable caches, and mesh qstates.
* read root hints from file.
*** Local zones feature.
* Build in local zone features. First the total stop for1912.
* Then 'local content' for minimal serving of localhost.localdomain,
and so on.
* Remember jakob's diagram.
* views support, selective recursive service
* Forward-local-zone to NSD.
- include in package, autoforkexec on localhost to do so.
* forward local zone to remote server.
@@ -177,27 +169,6 @@ Styleguide:
* Try to setup corner cases of (mis)configured DNS service/websites.
* Resolve msoft, google, yahoo, etc weird websites.
* Try to resolve many many different queries, perhaps compared with bind.
* create module testers, specific for the modules
* read a file with cache contents and settings, provide fake
environment for module-handle-state-X functions, then check
resulting module state structure to correct answer.
*** Beta release.
* Run shadow for a resolver in production for several weeks.
* Check logs for errors, long queries.
* Run in valgrind, speed profiling (as production shadow).
*** 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.
* Be able to prime roots using several queries (like, get only NS first).
* Nicer statistics
* private TTL, dTLS features.
treeshrew/
validator/ *.c *.h
+35 -8
View File
@@ -1,11 +1,38 @@
.\"
.\" unbound.8 -- unbound manual
.\"
.\" Copyright (c) 2007, NLnet Labs. All rights reserved.
.\"
.\" See LICENSE for the license.
.\"
.\"
.ig
unbound.8 -- unbound manual
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.
..
.Dd @date@
.Dt unbound 8
.Sh NAME
+8 -128
View File
@@ -24,31 +24,6 @@ The notation is: attribute: value.
Comments start with # and last to the end of line. Empty lines are
ignored as is whitespace at the beginning of a line.
.El
.Sh EXAMPLE
An example config file is shown below. Copy this to /etc/unbound/unbound.conf
and start the server with:
.nf
$ unbound -c /etc/unbound/unbound.conf
.fi
Most settings are the defaults. Stop the server with:
.nf
$ kill `cat /etc/unbound/unbound.pid`
.fi
Below is a minimal config file. The source distribution contains an extensive
example.conf file with all the options.
.nf
# unbound.conf(5) config file for unbound(8).
server:
directory: "/etc/unbound"
username: unbound # make sure it can write to pidfile, logfile.
chroot: "/etc/unbound"
logfile: "/etc/unbound/unbound.log"
pidfile: "/etc/unbound/unbound.pid"
# verbosity: 1 # uncomment and increase to get more logging.
.fi
.El
.Sh FILE FORMAT
There must be whitespace between keywords. Attribute keywords end with a colon ':'. An attribute
@@ -88,9 +63,6 @@ Number of ports to open. This number is opened per thread for every outgoing
query interface. Must be at least 1. Default is 16.
Larger numbers give more protection against spoofing attempts, but need
extra resources from the operating system.
.It \fBoutgoing-num-tcp:\fR <number>
Number of outgoing TCP buffers to allocate per thread. Default is 10. If set
to 0, or if do_tcp is "no", no TCP queries to authoritative servers are done.
.It \fBmsg-cache-size:\fR <number>
Number of bytes size of the message cache. Default is 4 megabytes.
.It \fBmsg-cache-slabs:\fR <number>
@@ -99,23 +71,6 @@ Must be set to a power of 2. Setting (close) to the number of cpus is a
reasonable guess.
.It \fBnum-queries-per-thread:\fR <number>
The number of queries that every thread will service simultaneously.
.It \fBrrset-cache-size:\fR <number>
Number of bytes size of the RRset cache. Default is 4 megabytes.
.It \fBrrset-cache-slabs:\fR <number>
Number of slabs in the RRset cache. Slabs reduce lock contention by threads.
Must be set to a power of 2.
.It \fBinfra-host-ttl:\fR <seconds>
Time to live for entries in the host cache. The host cache contains
roundtrip timing and EDNS support information. Default is 900.
.It \fBinfra-lame-ttl:\fR <seconds>
The time to live when a delegation is discovered to be lame. Default is 900.
.It \fBinfra-cache-slabs:\fR <number>
Number of slabs in the infrastructure cache. Slabs reduce lock contention
by threads. Must be set to a power of 2.
.It \fBinfra-cache-numhosts:\fR <number>
Number of hosts for which information is cached. Default is 1000.
.It \fBinfra-cache-numlame:\fR <number>
Number of zones per host for which lameness is cached. Default is 1000.
.It \fBdo-ip4:\fR <yes or no>
Enable or disable whether ip4 queries are answered. Default is yes.
.It \fBdo-ip6:\fR <yes or no>
@@ -124,16 +79,20 @@ 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 \fBforward-to:\fR <ip address>
If set (not "") then forwarder mode is enabled. Default is "" (disabled).
The ip address is used to forward all DNS queries to.
.It \fBforward-to-port:\fR <port number>
The port on which the remote server is running that answers forwarded queries.
Default is 53.
.It \fBchroot:\fR <directory>
If given a chroot is done to the given directory. The default is none ("").
.It \fBusername:\fR <name>
If given, after binding the port the user privileges are dropped. Default is
not to change user, username: "".
If this user is not capable of binding the
not to change user, username: "". If this user is not capable of binding the
port, reloads (by signal HUP) will still retain the opened ports.
If you change the port number in the config file, and that new port number
requires privileges, then a reload will fail; a restart is needed.
requires privileges, then a restart is needed.
.It \fBdirectory:\fR <directory>
Sets the working directory for the program.
.It \fBlogfile:\fR <filename>
@@ -144,90 +103,11 @@ The logfile is appended to, in the following format:
The process id is written to the file. Default is "unbound.pid". So,
kill -HUP `cat /etc/unbound/unbound.pid` will trigger a reload,
kill -QUIT `cat /etc/unbound/unbound.pid` will gracefully terminate.
.It \fBhide-identity:\fR <yes or no>
If enabled id.server and hostname.bind queries are refused.
.It \fBidentity:\fR <string>
Set the identity to report. If set to "", the default, then the hostname
of the server is returned.
.It \fBhide-version:\fR <yes or no>
If enabled version.server and version.bind queries are refused.
.It \fBversion:\fR <string>
Set the version to report. If set to "", the default, then the package
version is returned.
.It \fBtarget-fetch-policy:\fR <"list of numbers">
Set the target fetch policy used by unbound to determine if it should fetch
nameserver target addresses opportunistically. The policy is described per
dependency depth.
The number of values determines the maximum dependency depth
that unbound will pursue in answering a query.
A value of -1 means to fetch all targets opportunistically for that dependency
depth. A value of 0 means to fetch on demand only. A positive value fetches
that many targets opportunistically.
Enclose the list between quotes ("") and put spaces between numbers.
The default is "3 2 1 0 0". Setting all zeroes, "0 0 0 0 0" gives behaviour
closer to that of BIND 9, while setting "-1 -1 -1 -1 -1" gives behaviour
rumoured to be closer to that of BIND 8.
.It \fBharden-short-bufsize:\fR <yes or no>
Very small EDNS buffer sizes from queries are ignored. Default is off, since
it is legal protocol wise to send these, and unbound tries to give very
small answers to these queries, where possible.
.It \fBharden-large-queries:\fR <yes or no>
Very large queries are ignored. Default is off, since it is legal protocol
wise to send these, and could be necessary for operation if TSIG or EDNS
payload is very large.
.It \fBharden-glue:\fR <yes or no>
Will trust glue only if it is within the servers authority. Default is on.
.It \fBdo-not-query-address:\fR <IP address>
Do not query the given IP address. Can be IP4 or IP6. By default the
DNS port is blocked for that address. Appending the character '@' and then
the portnumber will block other port numbers.
.El
.Ss Stub Zone Options
There may be multiple
.Ic stub-zone:
clauses. Each with a name: and zero or more hostnames or IP addresses.
For the stub zone this list of nameservers is used. Class IN is assumed.
.Bl -tag -width indent
.It \fBname:\fR <domain name>
Name of the stub zone.
.It \fBstub-host:\fR <domain name>
Name of stub zone nameserver. Is itself resolved before it is used.
.It \fBstub-addr:\fR <IP address>
IP address of stub zone nameserver. Can be IP 4 or IP 6.
To use a nondefault port for DNS communication append '@' with the port number.
.El
.Ss Forward Zone Options
There may be multiple
.Ic forward-zone:
clauses. Each with a name: and zero or more hostnames or IP addresses.
For the forward zone this list of nameservers is used to forward the queries
to. The servers have to handle further recursion for the query. Class IN is
assumed. A forward-zone entry with name "." and a forward-addr target will
forward all queries to that other server (unless it can answer from the cache).
.Bl -tag -width indent
.It \fBname:\fR <domain name>
Name of the forward zone.
.It \fBforward-host:\fR <domain name>
Name of server to forward to. Is itself resolved before it is used.
.It \fBforward-addr:\fR <IP address>
IP address of server to forward to. Can be IP 4 or IP 6.
To use a nondefault port for DNS communication append '@' with the port number.
.El
.Sh FILES
.Bl -tag -width indent
.It Pa /etc/unbound
default unbound working directory
.It Pa unbound.conf
unbound configuration file.
.It Pa unbound.pid
default unbound pidfile with process ID of the running daemon.
.It Pa unbound.log
unbound log file.
.El
.Sh SEE ALSO
.Xr unbound 8
+45 -70
View File
@@ -1,4 +1,4 @@
# Doxyfile 1.5.2
# Doxyfile 1.4.6
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project
@@ -14,14 +14,6 @@
# Project related configuration options
#---------------------------------------------------------------------------
# This tag specifies the encoding used for all characters in the config file that
# follow. The default is UTF-8 which is also the encoding used for all text before
# the first occurrence of this tag. Doxygen uses libiconv (or the iconv built into
# libc) for the transcoding. See http://www.gnu.org/software/libiconv for the list of
# possible encodings.
# DOXYFILE_ENCODING = UTF-8
# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
# by quotes) that should identify the project.
@@ -53,14 +45,24 @@ CREATE_SUBDIRS = NO
# documentation generated by doxygen is written. Doxygen will use this
# information to generate all constant output in the proper language.
# The default language is English, other supported languages are:
# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
# Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian,
# Italian, Japanese, Japanese-en (Japanese with English messages), Korean,
# Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian,
# Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian.
# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish,
# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese,
# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian,
# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish,
# Swedish, and Ukrainian.
OUTPUT_LANGUAGE = English
# This tag can be used to specify the encoding used in the generated output.
# The encoding is not always determined by the language that is chosen,
# but also whether or not the output is meant for Windows or non-Windows users.
# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES
# forces the Windows encoding (this is the default for the Windows binary),
# whereas setting the tag to NO uses a Unix-style encoding (the default for
# all platforms other than Windows).
USE_WINDOWS_ENCODING = NO
# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
# include brief member descriptions after the members that are listed in
# the file and class documentation (similar to JavaDoc).
@@ -202,11 +204,6 @@ OPTIMIZE_OUTPUT_JAVA = NO
BUILTIN_STL_SUPPORT = NO
# If you use Microsoft's C++/CLI language, you should set this option to YES to
# enable parsing support.
# CPP_CLI_SUPPORT = NO
# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
# tag is set to YES, then doxygen will reuse the documentation of the first
# member in the group (if any) for the other members of the group. By default
@@ -462,14 +459,7 @@ WARN_LOGFILE =
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
INPUT = .
# This tag can be used to specify the character encoding of the source files that
# doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default
# input encoding. Doxygen uses libiconv (or the iconv built into libc) for the transcoding.
# See http://www.gnu.org/software/libiconv for the list of possible encodings.
# INPUT_ENCODING = UTF-8
INPUT = .
# If the value of the INPUT tag contains directories, you can use the
# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
@@ -478,7 +468,7 @@ INPUT = .
# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py
FILE_PATTERNS =
#FILE_PATTERNS = *.h *.c *.dox
# The RECURSIVE tag can be used to turn specify whether or not subdirectories
# should be searched for input files as well. Possible values are YES and NO.
@@ -490,12 +480,7 @@ RECURSIVE = YES
# excluded from the INPUT source files. This way you can easily exclude a
# subdirectory from a directory tree whose root is specified with the INPUT tag.
EXCLUDE = ./build \
./compat \
util/configparser.c \
util/configparser.h \
util/configlexer.c \
util/locks.h
EXCLUDE = ./build ./compat util/configparser.c util/configparser.h util/configlexer.c util/locks.h
# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
# directories that are symbolic links (a Unix filesystem feature) are excluded
@@ -511,13 +496,6 @@ EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS =
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
# (namespaces, classes, functions, etc.) that should be excluded from the output.
# The symbol name can be a fully qualified name, a word, or if the wildcard * is used,
# a substring. Examples: ANamespace, AClass, AClass::ANamespace, ANamespace::*Test
# EXCLUDE_SYMBOLS =
# The EXAMPLE_PATH tag can be used to specify one or more files or
# directories that contain example code fragments that are included (see
# the \include command).
@@ -603,13 +581,6 @@ REFERENCED_BY_RELATION = YES
REFERENCES_RELATION = YES
# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
# link to the source code. Otherwise they will link to the documentstion.
# REFERENCES_LINK_SOURCE = YES
# If the USE_HTAGS tag is set to YES then the references to source code
# will point to the HTML generated by the htags(1) tool instead of doxygen
# built-in source browser. The htags tool is part of GNU's global source
@@ -1107,14 +1078,6 @@ PERL_PATH = /usr/bin/perl
CLASS_DIAGRAMS = YES
# You can define message sequence charts within doxygen comments using the \msc
# command. Doxygen will then run the mscgen tool (see http://www.mcternan.me.uk/mscgen/) to
# produce the chart and insert it in the documentation. The MSCGEN_PATH tag allows you to
# specify the directory where the mscgen tool resides. If left empty the tool is assumed to
# be found in the default search path.
# MSCGEN_PATH =
# If set to YES, the inheritance and collaboration graphs will hide
# inheritance and usage relations if the target is undocumented
# or is not a class.
@@ -1180,14 +1143,6 @@ INCLUDED_BY_GRAPH = YES
CALL_GRAPH = NO
# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then doxygen will
# generate a caller dependency graph for every global function or class method.
# Note that enabling this option will significantly increase the time of a run.
# So in most cases it will be better to enable caller graphs for selected
# functions only using the \callergraph command.
# CALLER_GRAPH = NO
# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
# will graphical hierarchy of all classes instead of a textual one.
@@ -1217,13 +1172,33 @@ DOT_PATH =
DOTFILE_DIRS =
# The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
# nodes that will be shown in the graph. If the number of nodes in a graph
# becomes larger than this value, doxygen will truncate the graph, which is
# visualized by representing a node as a red box. Note that doxygen will always
# show the root nodes and its direct children regardless of this setting.
# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
# (in pixels) of the graphs generated by dot. If a graph becomes larger than
# this value, doxygen will try to truncate the graph, so that it fits within
# the specified constraint. Beware that most browsers cannot cope with very
# large images.
# DOT_GRAPH_MAX_NODES = 50
MAX_DOT_GRAPH_WIDTH = 1024
# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
# (in pixels) of the graphs generated by dot. If a graph becomes larger than
# this value, doxygen will try to truncate the graph, so that it fits within
# the specified constraint. Beware that most browsers cannot cope with very
# large images.
MAX_DOT_GRAPH_HEIGHT = 1024
# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
# graphs generated by dot. A depth value of 3 means that only nodes reachable
# from the root by following a path via at most 3 edges will be shown. Nodes
# that lay further from the root node will be omitted. Note that setting this
# option to 1 or 2 may greatly reduce the computation time needed for large
# code bases. Also note that a graph may be further truncated if the graph's
# image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH
# and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default),
# the graph is not depth-constrained.
MAX_DOT_GRAPH_DEPTH = 0
# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
# background. This is disabled by default, which results in a white background.
-376
View File
@@ -1,376 +0,0 @@
/*
* iterator/iter_delegpt.c - delegation point with NS and address information.
*
* 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 implements the Delegation Point. It contains a list of name servers
* and their addresses if known.
*/
#include "config.h"
#include "iterator/iter_delegpt.h"
#include "services/cache/dns.h"
#include "util/region-allocator.h"
#include "util/data/dname.h"
#include "util/data/packed_rrset.h"
#include "util/data/msgreply.h"
#include "util/net_help.h"
struct delegpt*
delegpt_create(struct region* region)
{
struct delegpt* dp=(struct delegpt*)region_alloc(region, sizeof(*dp));
if(!dp)
return NULL;
memset(dp, 0, sizeof(*dp));
return dp;
}
struct delegpt* delegpt_copy(struct delegpt* dp, struct region* region)
{
struct delegpt* copy = delegpt_create(region);
struct delegpt_ns* ns;
struct delegpt_addr* a;
if(!copy)
return NULL;
if(!delegpt_set_name(copy, region, dp->name))
return NULL;
for(ns = dp->nslist; ns; ns = ns->next) {
if(!delegpt_add_ns(copy, region, ns->name))
return NULL;
copy->nslist->resolved = ns->resolved;
}
for(a = dp->target_list; a; a = a->next_target) {
if(!delegpt_add_addr(copy, region, &a->addr, a->addrlen))
return NULL;
}
return copy;
}
int
delegpt_set_name(struct delegpt* dp, struct region* region, uint8_t* name)
{
dp->namelabs = dname_count_size_labels(name, &dp->namelen);
dp->name = region_alloc_init(region, name, dp->namelen);
return dp->name != 0;
}
int
delegpt_add_ns(struct delegpt* dp, struct region* region, uint8_t* name)
{
struct delegpt_ns* ns = (struct delegpt_ns*)region_alloc(region,
sizeof(struct delegpt_ns));
if(!ns)
return 0;
ns->next = dp->nslist;
dp->nslist = ns;
(void)dname_count_size_labels(name, &ns->namelen);
ns->name = region_alloc_init(region, name, ns->namelen);
ns->resolved = 0;
return 1;
}
struct delegpt_ns*
delegpt_find_ns(struct delegpt* dp, uint8_t* name, size_t namelen)
{
struct delegpt_ns* p = dp->nslist;
while(p) {
if(namelen == p->namelen &&
query_dname_compare(name, p->name) == 0) {
return p;
}
p = p->next;
}
return NULL;
}
int
delegpt_add_target(struct delegpt* dp, struct region* region,
uint8_t* name, size_t namelen, struct sockaddr_storage* addr,
socklen_t addrlen)
{
struct delegpt_ns* ns = delegpt_find_ns(dp, name, namelen);
if(!ns) {
/* ignore it */
return 1;
}
ns->resolved = 1;
return delegpt_add_addr(dp, region, addr, addrlen);
}
int
delegpt_add_addr(struct delegpt* dp, struct region* region,
struct sockaddr_storage* addr, socklen_t addrlen)
{
struct delegpt_addr* a = (struct delegpt_addr*)region_alloc(region,
sizeof(struct delegpt_addr));
if(!a)
return 0;
a->next_target = dp->target_list;
dp->target_list = a;
a->next_result = 0;
a->next_usable = dp->usable_list;
dp->usable_list = a;
memcpy(&a->addr, addr, addrlen);
a->addrlen = addrlen;
return 1;
}
/** count NS and number missing */
static void
delegpt_count_ns(struct delegpt* dp, size_t* numns, size_t* missing)
{
struct delegpt_ns* ns;
*numns = 0;
*missing = 0;
for(ns = dp->nslist; ns; ns = ns->next) {
(*numns)++;
if(!ns->resolved)
(*missing)++;
}
}
/** count addresses, and number in result and available lists */
static void
delegpt_count_addr(struct delegpt* dp, size_t* numaddr, size_t* numres,
size_t* numavail)
{
struct delegpt_addr* a;
*numaddr = 0;
*numres = 0;
*numavail = 0;
for(a = dp->target_list; a; a = a->next_target) {
(*numaddr)++;
}
for(a = dp->result_list; a; a = a->next_result) {
(*numres)++;
}
for(a = dp->usable_list; a; a = a->next_usable) {
(*numavail)++;
}
}
void delegpt_log(struct delegpt* dp)
{
char buf[LDNS_MAX_DOMAINLEN+1];
struct delegpt_ns* ns;
struct delegpt_addr* a;
size_t missing=0, numns=0, numaddr=0, numres=0, numavail=0;
dname_str(dp->name, buf);
if(dp->nslist == NULL && dp->target_list == NULL) {
log_info("DelegationPoint<%s>: empty", buf);
return;
}
delegpt_count_ns(dp, &numns, &missing);
delegpt_count_addr(dp, &numaddr, &numres, &numavail);
log_info("DelegationPoint<%s>: %u names (%u missing), "
"%u addrs (%u result, %u avail)",
buf, (unsigned)numns, (unsigned)missing,
(unsigned)numaddr, (unsigned)numres, (unsigned)numavail);
if(verbosity >= VERB_ALGO) {
for(ns = dp->nslist; ns; ns = ns->next) {
dname_str(ns->name, buf);
log_info(" %s%s", buf, (ns->resolved?"*":""));
}
for(a = dp->target_list; a; a = a->next_target) {
log_addr(" ", &a->addr, a->addrlen);
}
}
}
void
delegpt_add_unused_targets(struct delegpt* dp)
{
struct delegpt_addr* usa = dp->usable_list;
dp->usable_list = NULL;
while(usa) {
usa->next_result = dp->result_list;
dp->result_list = usa;
usa = usa->next_usable;
}
}
size_t
delegpt_count_missing_targets(struct delegpt* dp)
{
struct delegpt_ns* ns;
size_t n = 0;
for(ns = dp->nslist; ns; ns = ns->next)
if(!ns->resolved)
n++;
return n;
}
/** find NS rrset in given list */
static struct ub_packed_rrset_key*
find_NS(struct reply_info* rep, size_t from, size_t to)
{
size_t i;
for(i=from; i<to; i++) {
if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_NS)
return rep->rrsets[i];
}
return NULL;
}
struct delegpt*
delegpt_from_message(struct dns_msg* msg, struct region* region)
{
struct ub_packed_rrset_key* ns_rrset = NULL;
struct delegpt* dp;
size_t i;
/* look for NS records in the authority section... */
ns_rrset = find_NS(msg->rep, msg->rep->an_numrrsets,
msg->rep->an_numrrsets+msg->rep->ns_numrrsets);
/* In some cases (even legitimate, perfectly legal cases), the
* NS set for the "referral" might be in the answer section. */
if(!ns_rrset)
ns_rrset = find_NS(msg->rep, 0, msg->rep->an_numrrsets);
/* If there was no NS rrset in the authority section, then this
* wasn't a referral message. (It might not actually be a
* referral message anyway) */
if(!ns_rrset)
return NULL;
/* If we found any, then Yay! we have a delegation point. */
dp = delegpt_create(region);
if(!dp)
return NULL;
if(!delegpt_set_name(dp, region, ns_rrset->rk.dname))
return NULL;
if(!delegpt_rrset_add_ns(dp, region, ns_rrset))
return NULL;
/* add glue, A and AAAA in answer and additional section */
for(i=0; i<msg->rep->rrset_count; i++) {
struct ub_packed_rrset_key* s = msg->rep->rrsets[i];
/* skip auth section. FIXME really needed?*/
if(msg->rep->an_numrrsets <= i &&
i < (msg->rep->an_numrrsets+msg->rep->ns_numrrsets))
continue;
if(ntohs(s->rk.type) == LDNS_RR_TYPE_A) {
if(!delegpt_add_rrset_A(dp, region, s))
return NULL;
} else if(ntohs(s->rk.type) == LDNS_RR_TYPE_AAAA) {
if(!delegpt_add_rrset_AAAA(dp, region, s))
return NULL;
}
}
return dp;
}
int
delegpt_rrset_add_ns(struct delegpt* dp, struct region* region,
struct ub_packed_rrset_key* ns_rrset)
{
struct packed_rrset_data* nsdata = (struct packed_rrset_data*)
ns_rrset->entry.data;
size_t i;
for(i=0; i<nsdata->count; i++) {
if(nsdata->rr_len[i] < 2+1) continue; /* len + root label */
if(dname_valid(nsdata->rr_data[i]+2, nsdata->rr_len[i]-2) !=
(size_t)ldns_read_uint16(nsdata->rr_data[i]))
continue; /* bad format */
/* add rdata of NS (= wirefmt dname), skip rdatalen bytes */
if(!delegpt_add_ns(dp, region, nsdata->rr_data[i]+2))
return 0;
}
return 1;
}
int
delegpt_add_rrset_A(struct delegpt* dp, struct region* region,
struct ub_packed_rrset_key* ak)
{
struct packed_rrset_data* d=(struct packed_rrset_data*)ak->entry.data;
size_t i;
struct sockaddr_in sa;
socklen_t len = (socklen_t)sizeof(sa);
memset(&sa, 0, len);
sa.sin_family = AF_INET;
sa.sin_port = (in_port_t)htons(UNBOUND_DNS_PORT);
for(i=0; i<d->count; i++) {
if(d->rr_len[i] != 2 + INET_SIZE)
continue;
memmove(&sa.sin_addr, d->rr_data[i]+2, INET_SIZE);
if(!delegpt_add_target(dp, region, ak->rk.dname,
ak->rk.dname_len, (struct sockaddr_storage*)&sa,
len))
return 0;
}
return 1;
}
int
delegpt_add_rrset_AAAA(struct delegpt* dp, struct region* region,
struct ub_packed_rrset_key* ak)
{
struct packed_rrset_data* d=(struct packed_rrset_data*)ak->entry.data;
size_t i;
struct sockaddr_in6 sa;
socklen_t len = (socklen_t)sizeof(sa);
memset(&sa, 0, len);
sa.sin6_family = AF_INET6;
sa.sin6_port = (in_port_t)htons(UNBOUND_DNS_PORT);
for(i=0; i<d->count; i++) {
if(d->rr_len[i] != 2 + INET6_SIZE) /* rdatalen + len of IP6 */
continue;
memmove(&sa.sin6_addr, d->rr_data[i]+2, INET6_SIZE);
if(!delegpt_add_target(dp, region, ak->rk.dname,
ak->rk.dname_len, (struct sockaddr_storage*)&sa,
len))
return 0;
}
return 1;
}
int
delegpt_add_rrset(struct delegpt* dp, struct region* region,
struct ub_packed_rrset_key* rrset)
{
if(!rrset)
return 1;
if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_NS)
return delegpt_rrset_add_ns(dp, region, rrset);
else if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_A)
return delegpt_add_rrset_A(dp, region, rrset);
else if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_AAAA)
return delegpt_add_rrset_AAAA(dp, region, rrset);
log_warn("Unknown rrset type added to delegpt");
return 1;
}
-257
View File
@@ -1,257 +0,0 @@
/*
* iterator/iter_delegpt.h - delegation point with NS and address information.
*
* 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 implements the Delegation Point. It contains a list of name servers
* and their addresses if known.
*/
#ifndef ITERATOR_ITER_DELEGPT_H
#define ITERATOR_ITER_DELEGPT_H
struct region;
struct delegpt_ns;
struct delegpt_addr;
struct dns_msg;
struct ub_packed_rrset_key;
/**
* Delegation Point.
* For a domain name, the NS rrset, and the A and AAAA records for those.
*/
struct delegpt {
/** the domain name of the delegation point. */
uint8_t* name;
/** length of the delegation point name */
size_t namelen;
/** number of labels in delegation point */
int namelabs;
/** the nameservers, names from the NS RRset rdata. */
struct delegpt_ns* nslist;
/** the target addresses for delegation */
struct delegpt_addr* target_list;
/** the list of usable targets; subset of target_list
* the items in this list are not part of the result list. */
struct delegpt_addr* usable_list;
/** the list of returned targets; subset of target_list */
struct delegpt_addr* result_list;
};
/**
* Nameservers for a delegation point.
*/
struct delegpt_ns {
/** next in list */
struct delegpt_ns* next;
/** name of nameserver */
uint8_t* name;
/** length of name */
size_t namelen;
/**
* If the name has been resolved. false if not queried for yet.
* true if the address is known, or marked true if failed.
*/
int resolved;
};
/**
* Address of target nameserver in delegation point.
*/
struct delegpt_addr {
/** next delegation point in results */
struct delegpt_addr* next_result;
/** next delegation point in usable list */
struct delegpt_addr* next_usable;
/** next delegation point in all targets list */
struct delegpt_addr* next_target;
/** delegation point address */
struct sockaddr_storage addr;
/** length of addr */
socklen_t addrlen;
};
/**
* Create new delegation point.
* @param region: where to allocate it.
* @return new delegation point or NULL on error.
*/
struct delegpt* delegpt_create(struct region* region);
/**
* Create a copy of a delegation point.
* @param dp: delegation point to copy.
* @param region: where to allocate it.
* @return new delegation point or NULL on error.
*/
struct delegpt* delegpt_copy(struct delegpt* dp, struct region* region);
/**
* Set name of delegation point.
* @param dp: delegation point.
* @param region: where to allocate the name copy.
* @param name: name to use.
* @return false on error.
*/
int delegpt_set_name(struct delegpt* dp, struct region* region, uint8_t* name);
/**
* Add a name to the delegation point.
* @param dp: delegation point.
* @param region: where to allocate the info.
* @param name: domain name in wire format.
* @return false on error.
*/
int delegpt_add_ns(struct delegpt* dp, struct region* region, uint8_t* name);
/**
* Add NS rrset; calls add_ns repeatedly.
* @param dp: delegation point.
* @param region: where to allocate the info.
* @param ns_rrset: NS rrset.
* return 0 on alloc error.
*/
int delegpt_rrset_add_ns(struct delegpt* dp, struct region* region,
struct ub_packed_rrset_key* ns_rrset);
/**
* Add target address to the delegation point.
* @param dp: delegation point.
* @param region: where to allocate the info.
* @param name: name for which target was found (must be in nslist).
* This name is marked resolved.
* @param namelen: length of name.
* @param addr: the address.
* @param addrlen: the length of addr.
* @return false on error.
*/
int delegpt_add_target(struct delegpt* dp, struct region* region,
uint8_t* name, size_t namelen, struct sockaddr_storage* addr,
socklen_t addrlen);
/**
* Add A RRset to delegpt.
* @param dp: delegation point.
* @param region: where to allocate the info.
* @param rrset: RRset A to add.
* @return 0 on alloc error.
*/
int delegpt_add_rrset_A(struct delegpt* dp, struct region* region,
struct ub_packed_rrset_key* rrset);
/**
* Add AAAA RRset to delegpt.
* @param dp: delegation point.
* @param region: where to allocate the info.
* @param rrset: RRset AAAA to add.
* @return 0 on alloc error.
*/
int delegpt_add_rrset_AAAA(struct delegpt* dp, struct region* region,
struct ub_packed_rrset_key* rrset);
/**
* Add any RRset to delegpt.
* @param dp: delegation point.
* @param region: where to allocate the info.
* @param rrset: RRset to add, NS, A, AAAA.
* @return 0 on alloc error.
*/
int delegpt_add_rrset(struct delegpt* dp, struct region* region,
struct ub_packed_rrset_key* rrset);
/**
* Add address to the delegation point. No servername is associated or checked.
* @param dp: delegation point.
* @param region: where to allocate the info.
* @param addr: the address.
* @param addrlen: the length of addr.
* @return false on error.
*/
int delegpt_add_addr(struct delegpt* dp, struct region* region,
struct sockaddr_storage* addr, socklen_t addrlen);
/**
* Find NS record in name list of delegation point.
* @param dp: delegation point.
* @param name: name of nameserver to look for, uncompressed wireformat.
* @param namelen: length of name.
* @return the ns structure or NULL if not found.
*/
struct delegpt_ns* delegpt_find_ns(struct delegpt* dp, uint8_t* name,
size_t namelen);
/**
* Print the delegation point to the log. For debugging.
* @param dp: delegation point.
*/
void delegpt_log(struct delegpt* dp);
/**
* Add all usable targets to the result list.
* @param dp: delegation point.
*/
void delegpt_add_unused_targets(struct delegpt* dp);
/**
* Count number of missing targets. These are ns names with no resolved flag.
* @param dp: delegation point.
* @return number of missing targets (or 0).
*/
size_t delegpt_count_missing_targets(struct delegpt* dp);
/**
* Create new delegation point from a dns message
*
* Note that this method does not actually test to see if the message is an
* actual referral. It really is just checking to see if it can construct a
* delegation point, so the message could be of some other type (some ANSWER
* messages, some CNAME messages, generally.) Note that the resulting
* DelegationPoint will contain targets for all "relevant" glue (i.e.,
* address records whose ownernames match the target of one of the NS
* records), so if policy dictates that some glue should be discarded beyond
* that, discard it before calling this method. Note that this method will
* find "glue" in either the ADDITIONAL section or the ANSWER section.
*
* @param msg: the dns message, referral.
* @param region: where to allocate delegation point.
* @return new delegation point or NULL on alloc error, or if the
* message was not appropriate.
*/
struct delegpt* delegpt_from_message(struct dns_msg* msg,
struct region* region);
#endif /* ITERATOR_ITER_DELEGPT_H */
-149
View File
@@ -1,149 +0,0 @@
/*
* iterator/iter_donotq.c - iterative resolver donotqueryaddresses storage.
*
* Copyright (c) 2007, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file
*
* This file contains functions to assist the iterator module.
* The donotqueryaddresses are stored and looked up. These addresses
* (like 127.0.0.1) must not be used to send queries to, and can be
* discarded immediately from the server selection.
*/
#include "config.h"
#include "iterator/iter_donotq.h"
#include "util/region-allocator.h"
#include "util/log.h"
#include "util/config_file.h"
#include "util/net_help.h"
/** compare two donotq entries */
static int
donotq_cmp(const void* k1, const void* k2)
{
struct iter_donotq_addr* n1 = (struct iter_donotq_addr*)k1;
struct iter_donotq_addr* n2 = (struct iter_donotq_addr*)k2;
return sockaddr_cmp(&n1->addr, n1->addrlen, &n2->addr, n2->addrlen);
}
struct iter_donotq*
donotq_create()
{
struct iter_donotq* dq = (struct iter_donotq*)calloc(1,
sizeof(struct iter_donotq));
if(!dq)
return NULL;
dq->region = region_create(malloc, free);
if(!dq->region) {
donotq_delete(dq);
return NULL;
}
return dq;
}
void
donotq_delete(struct iter_donotq* dq)
{
if(!dq)
return;
region_destroy(dq->region);
free(dq->tree);
free(dq);
}
/** insert new address into donotq structure */
static int
donotq_insert(struct iter_donotq* dq, struct sockaddr_storage* addr,
socklen_t addrlen)
{
struct iter_donotq_addr* node = region_alloc(dq->region,
sizeof(struct iter_donotq_addr));
if(!node)
return 0;
node->node.key = node;
memcpy(&node->addr, addr, addrlen);
node->addrlen = addrlen;
if(!rbtree_insert(dq->tree, &node->node)) {
log_warn("duplicate donotquery address ignored.");
}
return 1;
}
/** read donotq config */
static int
read_donotq(struct iter_donotq* dq, struct config_file* cfg)
{
struct config_strlist* p;
struct sockaddr_storage addr;
socklen_t addrlen;
for(p = cfg->donotqueryaddrs; p; p = p->next) {
log_assert(p->str);
if(!extstrtoaddr(p->str, &addr, &addrlen)) {
log_err("cannot parse donotquery ip address: '%s'",
p->str);
return 0;
}
if(!donotq_insert(dq, &addr, addrlen)) {
log_err("out of memory");
return 0;
}
}
return 1;
}
int
donotq_apply_cfg(struct iter_donotq* dq, struct config_file* cfg)
{
free(dq->tree);
dq->tree = rbtree_create(donotq_cmp);
if(!dq->tree)
return 0;
if(!read_donotq(dq, cfg))
return 0;
return 1;
}
int
donotq_lookup(struct iter_donotq* donotq, struct sockaddr_storage* addr,
socklen_t addrlen)
{
/* lookup in the tree */
struct iter_donotq_addr key;
key.node.key = &key;
memcpy(&key.addr, addr, addrlen);
key.addrlen = addrlen;
if(rbtree_search(donotq->tree, &key))
return 1;
return 0;
}
-106
View File
@@ -1,106 +0,0 @@
/*
* iterator/iter_donotq.h - iterative resolver donotqueryaddresses storage.
*
* Copyright (c) 2007, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file
*
* This file contains functions to assist the iterator module.
* Keep track of the donotquery addresses and lookup fast.
*/
#ifndef ITERATOR_ITER_DONOTQ_H
#define ITERATOR_ITER_DONOTQ_H
#include "util/rbtree.h"
struct iter_env;
struct config_file;
struct region;
/**
* Iterator donotqueryaddresses structure
*/
struct iter_donotq {
/** region for allocation */
struct region* region;
/**
* Tree of the single addresses that are blocked.
* contents of type iter_donotq_addr.
*/
rbtree_t* tree;
};
/**
* Iterator donotquery address.
* A single address that must not be used to send queries to.
*/
struct iter_donotq_addr {
/** redblacktree node, key is this structure: addr and addrlen */
rbnode_t node;
/** address */
struct sockaddr_storage addr;
/** length of addr */
socklen_t addrlen;
};
/**
* Create donotqueryaddresses structure
* @return new structure or NULL on error.
*/
struct iter_donotq* donotq_create();
/**
* Delete donotqueryaddresses structure.
* @param donotq: to delete.
*/
void donotq_delete(struct iter_donotq* donotq);
/**
* Process donotqueryaddresses config.
* @param donotq: where to store.
* @param cfg: config options.
* @return 0 on error.
*/
int donotq_apply_cfg(struct iter_donotq* donotq, struct config_file* cfg);
/**
* See if an address is blocked.
* @param donotq: structure for address storage.
* @param addr: address to check
* @param addrlen: length of addr.
* @return: true if the address must not be queried. false if unlisted.
*/
int donotq_lookup(struct iter_donotq* donotq, struct sockaddr_storage* addr,
socklen_t addrlen);
#endif /* ITERATOR_ITER_DONOTQ_H */
-285
View File
@@ -1,285 +0,0 @@
/*
* iterator/iter_fwd.c - iterative resolver module forward zones.
*
* Copyright (c) 2007, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file
*
* This file contains functions to assist the iterator module.
* Keep track of forward zones and config settings.
*/
#include "config.h"
#include "iterator/iter_fwd.h"
#include "iterator/iter_delegpt.h"
#include "util/region-allocator.h"
#include "util/log.h"
#include "util/config_file.h"
#include "util/net_help.h"
#include "util/data/dname.h"
/** compare two fwd entries */
static int
fwd_cmp(const void* k1, const void* k2)
{
int m;
struct iter_forward_zone* n1 = (struct iter_forward_zone*)k1;
struct iter_forward_zone* n2 = (struct iter_forward_zone*)k2;
if(n1->dclass != n2->dclass) {
if(n1->dclass < n2->dclass)
return -1;
return 1;
}
return dname_lab_cmp(n1->name, n1->namelabs, n2->name, n2->namelabs,
&m);
}
struct iter_forwards*
forwards_create()
{
struct iter_forwards* fwd = (struct iter_forwards*)calloc(1,
sizeof(struct iter_forwards));
if(!fwd)
return NULL;
fwd->region = region_create(malloc, free);
if(!fwd->region) {
forwards_delete(fwd);
return NULL;
}
return fwd;
}
void
forwards_delete(struct iter_forwards* fwd)
{
if(!fwd)
return;
region_destroy(fwd->region);
free(fwd->tree);
free(fwd);
}
/** insert new info into forward structure */
static int
forwards_insert(struct iter_forwards* fwd, uint16_t c, struct delegpt* dp)
{
struct iter_forward_zone* node = region_alloc(fwd->region,
sizeof(struct iter_forward_zone));
if(!node)
return 0;
node->node.key = node;
node->dclass = c;
node->name = region_alloc_init(fwd->region, dp->name, dp->namelen);
if(!node->name)
return 0;
node->namelen = dp->namelen;
node->namelabs = dp->namelabs;
node->dp = dp;
if(!rbtree_insert(fwd->tree, &node->node)) {
log_err("duplicate forward zone ignored.");
}
return 1;
}
/** initialise parent pointers in the tree */
static void
fwd_init_parents(struct iter_forwards* fwd)
{
struct iter_forward_zone* node, *prev = NULL, *p;
int m;
RBTREE_FOR(node, struct iter_forward_zone*, fwd->tree) {
node->parent = NULL;
if(!prev || prev->dclass != node->dclass) {
prev = node;
continue;
}
(void)dname_lab_cmp(prev->name, prev->namelabs, node->name,
node->namelabs, &m); /* we know prev is smaller */
/* sort order like: . com. bla.com. zwb.com. net. */
/* find the previous, or parent-parent-parent */
for(p = prev; p; p = p->parent)
/* looking for name with few labels, a parent */
if(p->namelabs <= m) {
/* ==: since prev matched m, this is closest*/
/* <: prev matches more, but is not a parent,
* this one is a (grand)parent */
node->parent = p;
break;
}
prev = node;
}
}
/** set zone name */
static int
read_fwds_name(struct iter_forwards* fwd, struct config_stub* s,
struct delegpt* dp)
{
ldns_rdf* rdf;
if(!s->name) {
log_err("forward zone without a name (use name \".\" to forward everything)");
return 0;
}
rdf = ldns_dname_new_frm_str(s->name);
if(!rdf) {
log_err("cannot parse forward zone name %s", s->name);
return 0;
}
if(!delegpt_set_name(dp, fwd->region, ldns_rdf_data(rdf))) {
ldns_rdf_deep_free(rdf);
log_err("out of memory");
return 0;
}
ldns_rdf_deep_free(rdf);
return 1;
}
/** set fwd host names */
static int
read_fwds_host(struct iter_forwards* fwd, struct config_stub* s,
struct delegpt* dp)
{
struct config_strlist* p;
ldns_rdf* rdf;
for(p = s->hosts; p; p = p->next) {
log_assert(p->str);
rdf = ldns_dname_new_frm_str(p->str);
if(!rdf) {
log_err("cannot parse forward %s server name: '%s'",
s->name, p->str);
return 0;
}
if(!delegpt_add_ns(dp, fwd->region, ldns_rdf_data(rdf))) {
ldns_rdf_deep_free(rdf);
log_err("out of memory");
return 0;
}
ldns_rdf_deep_free(rdf);
}
return 1;
}
/** set fwd server addresses */
static int
read_fwds_addr(struct iter_forwards* fwd, struct config_stub* s,
struct delegpt* dp)
{
struct config_strlist* p;
struct sockaddr_storage addr;
socklen_t addrlen;
for(p = s->addrs; p; p = p->next) {
log_assert(p->str);
if(!extstrtoaddr(p->str, &addr, &addrlen)) {
log_err("cannot parse forward %s ip address: '%s'",
s->name, p->str);
return 0;
}
if(!delegpt_add_addr(dp, fwd->region, &addr, addrlen)) {
log_err("out of memory");
return 0;
}
}
return 1;
}
/** read forwards config */
static int
read_forwards(struct iter_forwards* fwd, struct config_file* cfg)
{
struct config_stub* s;
for(s = cfg->forwards; s; s = s->next) {
struct delegpt* dp = delegpt_create(fwd->region);
if(!dp) {
log_err("out of memory");
return 0;
}
if(!read_fwds_name(fwd, s, dp) ||
!read_fwds_host(fwd, s, dp) ||
!read_fwds_addr(fwd, s, dp))
return 0;
if(!forwards_insert(fwd, LDNS_RR_CLASS_IN, dp))
return 0;
log_info("Forward zone server list:");
delegpt_log(dp);
}
return 1;
}
int
forwards_apply_cfg(struct iter_forwards* fwd, struct config_file* cfg)
{
free(fwd->tree);
fwd->tree = rbtree_create(fwd_cmp);
if(!fwd->tree)
return 0;
/* read forward zones */
if(!read_forwards(fwd, cfg))
return 0;
fwd_init_parents(fwd);
return 1;
}
struct delegpt*
forwards_lookup(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass)
{
/* lookup the forward zone in the tree */
rbnode_t* res = NULL;
struct iter_forward_zone *result;
struct iter_forward_zone key;
key.node.key = &key;
key.dclass = qclass;
key.name = qname;
key.namelabs = dname_count_size_labels(qname, &key.namelen);
if(rbtree_find_less_equal(fwd->tree, &key, &res)) {
/* exact */
result = (struct iter_forward_zone*)res;
} else {
/* smaller element (or no element) */
int m;
result = (struct iter_forward_zone*)res;
if(!result || result->dclass != qclass)
return NULL;
/* count number of labels matched */
(void)dname_lab_cmp(result->name, result->namelabs, key.name,
key.namelabs, &m);
while(result) { /* go up until qname is subdomain of stub */
if(result->namelabs <= m)
break;
result = result->parent;
}
}
if(result)
return result->dp;
return NULL;
}
-121
View File
@@ -1,121 +0,0 @@
/*
* iterator/iter_fwd.h - iterative resolver module forward zones.
*
* Copyright (c) 2007, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file
*
* This file contains functions to assist the iterator module.
* Keep track of forward zones, and read those from config.
*/
#ifndef ITERATOR_ITER_FWD_H
#define ITERATOR_ITER_FWD_H
#include "util/rbtree.h"
struct iter_env;
struct config_file;
struct delegpt;
struct region;
/**
* Iterator forward zones structure
*/
struct iter_forwards {
/** region where forward zone server addresses are allocated */
struct region* region;
/**
* Zones are stored in this tree. Sort order is specially chosen.
* first sorted on qtype. Then on dname in nsec-like order, so that
* a lookup on class, name will return an exact match or the closest
* match which gives the ancestor needed.
* contents of type iter_forward_zone.
*/
rbtree_t* tree;
};
/**
* Iterator forward servers for a particular zone.
*/
struct iter_forward_zone {
/** redblacktree node, key is this structure: class and name */
rbnode_t node;
/** name */
uint8_t* name;
/** length of name */
size_t namelen;
/** number of labels in name */
int namelabs;
/** delegation point with forward server information for this zone. */
struct delegpt* dp;
/** pointer to parent in tree (or NULL if none) */
struct iter_forward_zone* parent;
/** class. host order. */
uint16_t dclass;
};
/**
* Create forwards
* @return new forwards or NULL on error.
*/
struct iter_forwards* forwards_create();
/**
* Delete forwards.
* @param fwd: to delete.
*/
void forwards_delete(struct iter_forwards* fwd);
/**
* Process forwards config.
* @param fwd: where to store.
* @param cfg: config options.
* @return 0 on error.
*/
int forwards_apply_cfg(struct iter_forwards* fwd, struct config_file* cfg);
/**
* Find forward zone information
* For this qname/qclass find forward zone information, returns delegation
* point with server names and addresses, or NULL if no forwarding is needed.
*
* @param fwd: forward storage.
* @param qname: The qname of the query.
* @param qclass: The qclass of the query.
* @return: A delegation point if the query has to be forwarded to that list,
* otherwise null.
*/
struct delegpt* forwards_lookup(struct iter_forwards* fwd,
uint8_t* qname, uint16_t qclass);
#endif /* ITERATOR_ITER_FWD_H */
-377
View File
@@ -1,377 +0,0 @@
/*
* iterator/iter_hints.c - iterative resolver module stub and root hints.
*
* Copyright (c) 2007, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file
*
* This file contains functions to assist the iterator module.
* Keep track of stub and root hints, and read those from config.
*/
#include "config.h"
#include "iterator/iter_hints.h"
#include "iterator/iter_delegpt.h"
#include "util/region-allocator.h"
#include "util/log.h"
#include "util/config_file.h"
#include "util/net_help.h"
#include "util/data/dname.h"
/** compare two hint entries */
static int
stub_cmp(const void* k1, const void* k2)
{
int m;
struct iter_hints_stub* n1 = (struct iter_hints_stub*)k1;
struct iter_hints_stub* n2 = (struct iter_hints_stub*)k2;
if(n1->hint_class != n2->hint_class) {
if(n1->hint_class < n2->hint_class)
return -1;
return 1;
}
return dname_lab_cmp(n1->name, n1->namelabs, n2->name, n2->namelabs,
&m);
}
struct iter_hints*
hints_create()
{
struct iter_hints* hints = (struct iter_hints*)calloc(1,
sizeof(struct iter_hints));
if(!hints)
return NULL;
hints->region = region_create(malloc, free);
if(!hints->region) {
hints_delete(hints);
return NULL;
}
return hints;
}
void
hints_delete(struct iter_hints* hints)
{
if(!hints)
return;
region_destroy(hints->region);
free(hints->tree);
free(hints);
}
/** add hint to delegation hints */
static int
ah(struct delegpt* dp, struct region* r, const char* sv, const char* ip)
{
struct sockaddr_storage addr;
socklen_t addrlen;
ldns_rdf* rdf = ldns_dname_new_frm_str(sv);
if(!rdf) {
log_err("could not parse %s", sv);
return 0;
}
if(!delegpt_add_ns(dp, r, ldns_rdf_data(rdf)) ||
!extstrtoaddr(ip, &addr, &addrlen) ||
!delegpt_add_target(dp, r, ldns_rdf_data(rdf), ldns_rdf_size(rdf),
&addr, addrlen)) {
ldns_rdf_deep_free(rdf);
return 0;
}
ldns_rdf_deep_free(rdf);
return 1;
}
/** obtain compiletime provided root hints */
static struct delegpt*
compile_time_root_prime(struct region* r)
{
/* from:
; This file is made available by InterNIC
; under anonymous FTP as
; file /domain/named.cache
; on server FTP.INTERNIC.NET
; -OR- RS.INTERNIC.NET
;
; last update: Jan 29, 2004
; related version of root zone: 2004012900
*/
struct delegpt* dp = delegpt_create(r);
if(!dp)
return NULL;
if(!delegpt_set_name(dp, r, (uint8_t*)"\000"))
return NULL;
if(!ah(dp, r, "A.ROOT-SERVERS.NET.", "198.41.0.4")) return 0;
if(!ah(dp, r, "B.ROOT-SERVERS.NET.", "192.228.79.201")) return 0;
if(!ah(dp, r, "C.ROOT-SERVERS.NET.", "192.33.4.12")) return 0;
if(!ah(dp, r, "D.ROOT-SERVERS.NET.", "128.8.10.90")) return 0;
if(!ah(dp, r, "E.ROOT-SERVERS.NET.", "192.203.230.10")) return 0;
if(!ah(dp, r, "F.ROOT-SERVERS.NET.", "192.5.5.241")) return 0;
if(!ah(dp, r, "G.ROOT-SERVERS.NET.", "192.112.36.4")) return 0;
if(!ah(dp, r, "H.ROOT-SERVERS.NET.", "128.63.2.53")) return 0;
if(!ah(dp, r, "I.ROOT-SERVERS.NET.", "192.36.148.17")) return 0;
if(!ah(dp, r, "J.ROOT-SERVERS.NET.", "192.58.128.30")) return 0;
if(!ah(dp, r, "K.ROOT-SERVERS.NET.", "193.0.14.129")) return 0;
if(!ah(dp, r, "L.ROOT-SERVERS.NET.", "198.32.64.12")) return 0;
if(!ah(dp, r, "M.ROOT-SERVERS.NET.", "202.12.27.33")) return 0;
return dp;
}
/** insert new hint info into hint structure */
static int
hints_insert(struct iter_hints* hints, uint16_t c, struct delegpt* dp)
{
struct iter_hints_stub* node = region_alloc(hints->region,
sizeof(struct iter_hints_stub));
if(!node)
return 0;
node->node.key = node;
node->hint_class = c;
node->name = region_alloc_init(hints->region, dp->name, dp->namelen);
if(!node->name)
return 0;
node->namelen = dp->namelen;
node->namelabs = dp->namelabs;
node->dp = dp;
if(!rbtree_insert(hints->tree, &node->node)) {
log_err("second hints ignored.");
}
return 1;
}
/** initialise parent pointers in the tree */
static void
init_parents(struct iter_hints* hints)
{
struct iter_hints_stub* node, *prev = NULL, *p;
int m;
RBTREE_FOR(node, struct iter_hints_stub*, hints->tree) {
node->parent = NULL;
if(!prev || prev->hint_class != node->hint_class) {
prev = node;
continue;
}
(void)dname_lab_cmp(prev->name, prev->namelabs, node->name,
node->namelabs, &m); /* we know prev is smaller */
/* sort order like: . com. bla.com. zwb.com. net. */
/* find the previous, or parent-parent-parent */
for(p = prev; p; p = p->parent)
/* looking for name with few labels, a parent */
if(p->namelabs <= m) {
/* ==: since prev matched m, this is closest*/
/* <: prev matches more, but is not a parent,
* this one is a (grand)parent */
node->parent = p;
break;
}
prev = node;
}
}
/** set stub name */
static int
read_stubs_name(struct iter_hints* hints, struct config_stub* s,
struct delegpt* dp)
{
ldns_rdf* rdf;
if(!s->name) {
log_err("stub zone without a name");
return 0;
}
rdf = ldns_dname_new_frm_str(s->name);
if(!rdf) {
log_err("cannot parse stub zone name %s", s->name);
return 0;
}
if(!delegpt_set_name(dp, hints->region, ldns_rdf_data(rdf))) {
ldns_rdf_deep_free(rdf);
log_err("out of memory");
return 0;
}
ldns_rdf_deep_free(rdf);
return 1;
}
/** set stub host names */
static int
read_stubs_host(struct iter_hints* hints, struct config_stub* s,
struct delegpt* dp)
{
struct config_strlist* p;
ldns_rdf* rdf;
for(p = s->hosts; p; p = p->next) {
log_assert(p->str);
rdf = ldns_dname_new_frm_str(p->str);
if(!rdf) {
log_err("cannot parse stub %s nameserver name: '%s'",
s->name, p->str);
return 0;
}
if(!delegpt_add_ns(dp, hints->region, ldns_rdf_data(rdf))) {
ldns_rdf_deep_free(rdf);
log_err("out of memory");
return 0;
}
ldns_rdf_deep_free(rdf);
}
return 1;
}
/** set stub server addresses */
static int
read_stubs_addr(struct iter_hints* hints, struct config_stub* s,
struct delegpt* dp)
{
struct config_strlist* p;
struct sockaddr_storage addr;
socklen_t addrlen;
for(p = s->addrs; p; p = p->next) {
log_assert(p->str);
if(!extstrtoaddr(p->str, &addr, &addrlen)) {
log_err("cannot parse stub %s ip address: '%s'",
s->name, p->str);
return 0;
}
if(!delegpt_add_addr(dp, hints->region, &addr, addrlen)) {
log_err("out of memory");
return 0;
}
}
return 1;
}
/** read stubs config */
static int
read_stubs(struct iter_hints* hints, struct config_file* cfg)
{
struct config_stub* s;
for(s = cfg->stubs; s; s = s->next) {
struct delegpt* dp = delegpt_create(hints->region);
if(!dp) {
log_err("out of memory");
return 0;
}
if(!read_stubs_name(hints, s, dp) ||
!read_stubs_host(hints, s, dp) ||
!read_stubs_addr(hints, s, dp))
return 0;
if(!hints_insert(hints, LDNS_RR_CLASS_IN, dp))
return 0;
delegpt_log(dp);
}
return 1;
}
int
hints_apply_cfg(struct iter_hints* hints, struct config_file* cfg)
{
free(hints->tree);
hints->tree = rbtree_create(stub_cmp);
if(!hints->tree)
return 0;
/* TODO: read root hints from file named in cfg */
/* read stub hints */
if(!read_stubs(hints, cfg))
return 0;
/* use fallback compiletime root hints */
if(!hints_lookup_root(hints, LDNS_RR_CLASS_IN)) {
struct delegpt* dp = compile_time_root_prime(hints->region);
verbose(VERB_ALGO, "no config, using builtin root hints.");
if(!dp)
return 0;
if(!hints_insert(hints, LDNS_RR_CLASS_IN, dp))
return 0;
delegpt_log(dp);
}
init_parents(hints);
return 1;
}
struct delegpt*
hints_lookup_root(struct iter_hints* hints, uint16_t qclass)
{
uint8_t rootlab = 0;
struct iter_hints_stub key, *stub;
key.node.key = &key;
key.hint_class = qclass;
key.name = &rootlab;
key.namelen = 1;
key.namelabs = 1;
stub = (struct iter_hints_stub*)rbtree_search(hints->tree, &key);
if(!stub)
return NULL;
return stub->dp;
}
struct delegpt*
hints_lookup_stub(struct iter_hints* hints, uint8_t* qname,
uint16_t qclass, struct delegpt* cache_dp)
{
/* first lookup the stub */
rbnode_t* res = NULL;
struct iter_hints_stub *result;
struct iter_hints_stub key;
key.node.key = &key;
key.hint_class = qclass;
key.name = qname;
key.namelabs = dname_count_size_labels(qname, &key.namelen);
if(rbtree_find_less_equal(hints->tree, &key, &res)) {
/* exact */
result = (struct iter_hints_stub*)res;
} else {
/* smaller element (or no element) */
int m;
result = (struct iter_hints_stub*)res;
if(!result || result->hint_class != qclass)
return NULL;
/* count number of labels matched */
(void)dname_lab_cmp(result->name, result->namelabs, key.name,
key.namelabs, &m);
while(result) { /* go up until qname is subdomain of stub */
if(result->namelabs <= m)
break;
result = result->parent;
}
if(!result)
return NULL;
}
/*
* If our cached delegation point is above the hint, we need to prime.
*/
if(dname_strict_subdomain(result->dp->name, result->dp->namelabs,
cache_dp->name, cache_dp->namelabs))
return result->dp; /* need to prime this stub */
return NULL;
}
-130
View File
@@ -1,130 +0,0 @@
/*
* iterator/iter_hints.h - iterative resolver module stub and root hints.
*
* Copyright (c) 2007, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file
*
* This file contains functions to assist the iterator module.
* Keep track of stub and root hints, and read those from config.
*/
#ifndef ITERATOR_ITER_HINTS_H
#define ITERATOR_ITER_HINTS_H
#include "util/rbtree.h"
struct iter_env;
struct config_file;
struct delegpt;
struct region;
/**
* Iterator hints structure
*/
struct iter_hints {
/** region where hints are allocated */
struct region* region;
/**
* Hints are stored in this tree. Sort order is specially chosen.
* first sorted on qtype. Then on dname in nsec-like order, so that
* a lookup on class, name will return an exact match or the closest
* match which gives the ancestor needed.
* contents of type iter_hints_stub. The class IN root is in here.
*/
rbtree_t* tree;
};
/**
* Iterator hints for a particular stub.
*/
struct iter_hints_stub {
/** redblacktree node, key is this structure: class and name */
rbnode_t node;
/** name */
uint8_t* name;
/** length of name */
size_t namelen;
/** number of labels in name */
int namelabs;
/** delegation point with hint information for this stub. */
struct delegpt* dp;
/** pointer to parent in stub hint tree (or NULL if none) */
struct iter_hints_stub* parent;
/** class of hints. host order. */
uint16_t hint_class;
};
/**
* Create hints
* @return new hints or NULL on error.
*/
struct iter_hints* hints_create();
/**
* Delete hints.
* @param hints: to delete.
*/
void hints_delete(struct iter_hints* hints);
/**
* Process hints config. Sets default values for root hints if no config.
* @param hints: where to store.
* @param cfg: config options.
* @return 0 on error.
*/
int hints_apply_cfg(struct iter_hints* hints, struct config_file* cfg);
/**
* Find root hints for the given class.
* @param hints: hint storage.
* @param qclass: class for which root hints are requested. host order.
* @return: NULL if no hints, or a ptr to stored hints.
*/
struct delegpt* hints_lookup_root(struct iter_hints* hints, uint16_t qclass);
/**
* Given a qname/qclass combination, and the delegation point from the cache
* for this qname/qclass, determine if this combination indicates that a
* stub hint exists and must be primed.
*
* @param hints: hint storage.
* @param qname: The qname that generated the delegation point.
* @param qclass: The qclass that generated the delegation point.
* @param dp: The cache generated delegation point.
* @return: A priming delegation point if there is a stub hint that must
* be primed, otherwise null.
*/
struct delegpt* hints_lookup_stub(struct iter_hints* hints,
uint8_t* qname, uint16_t qclass, struct delegpt* dp);
#endif /* ITERATOR_ITER_HINTS_H */
-223
View File
@@ -1,223 +0,0 @@
/*
* iterator/iter_resptype.c - response type information and classification.
*
* 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 defines the response type. DNS Responses can be classified as
* one of the response types.
*/
#include "config.h"
#include "iterator/iter_resptype.h"
#include "iterator/iter_delegpt.h"
#include "services/cache/dns.h"
#include "util/net_help.h"
#include "util/data/dname.h"
enum response_type
response_type_from_cache(struct dns_msg* msg,
struct query_info* request)
{
/* If the message is NXDOMAIN, then it is an ANSWER. */
if(FLAGS_GET_RCODE(msg->rep->flags) == LDNS_RCODE_NXDOMAIN)
return RESPONSE_TYPE_ANSWER;
/* First we look at the answer section. This can tell us if this is
* CNAME or positive ANSWER. */
if(msg->rep->an_numrrsets > 0) {
/* Now look at the answer section first. 3 states:
* o our answer is there directly,
* o our answer is there after a cname,
* o or there is just a cname. */
uint8_t* mname = request->qname;
size_t mname_len = request->qname_len;
size_t i;
for(i=0; i<msg->rep->an_numrrsets; i++) {
struct ub_packed_rrset_key* s = msg->rep->rrsets[i];
/* If we have encountered an answer (before or
* after a CNAME), then we are done! Note that
* if qtype == CNAME then this will be noted as
* an ANSWER before it gets treated as a CNAME,
* as it should */
if(ntohs(s->rk.type) == request->qtype &&
ntohs(s->rk.rrset_class) == request->qclass &&
query_dname_compare(mname, s->rk.dname) == 0) {
return RESPONSE_TYPE_ANSWER;
}
/* If we have encountered a CNAME, make sure that
* it is relevant. */
if(ntohs(s->rk.type) == LDNS_RR_TYPE_CNAME &&
query_dname_compare(mname, s->rk.dname) == 0) {
get_cname_target(s, &mname, &mname_len);
}
}
/* if we encountered a CNAME (or a bunch of CNAMEs), and
* still got to here, then it is a CNAME response. (i.e.,
* the CNAME chain didn't terminate in an answer rrset.) */
if(mname != request->qname) {
return RESPONSE_TYPE_CNAME;
}
}
/* At this point, since we don't need to detect REFERRAL or LAME
* messages, it can only be an ANSWER. */
return RESPONSE_TYPE_ANSWER;
}
enum response_type
response_type_from_server(struct dns_msg* msg, struct query_info* request,
struct delegpt* dp)
{
uint8_t* origzone = (uint8_t*)"\000"; /* the default */
size_t origzonelen = 1;
size_t i;
if(!msg || !request)
return RESPONSE_TYPE_THROWAWAY;
/* If the message is NXDOMAIN, then it answers the question. */
if(FLAGS_GET_RCODE(msg->rep->flags) == LDNS_RCODE_NXDOMAIN)
return RESPONSE_TYPE_ANSWER;
/* Other response codes mean (so far) to throw the response away as
* meaningless and move on to the next nameserver. */
if(FLAGS_GET_RCODE(msg->rep->flags) != LDNS_RCODE_NOERROR)
return RESPONSE_TYPE_THROWAWAY;
/* Note: TC bit has already been handled */
if(dp) {
origzone = dp->name;
origzonelen = dp->namelen;
}
/* First we look at the answer section. This can tell us if this is a
* CNAME or ANSWER or (provisional) ANSWER. */
if(msg->rep->an_numrrsets > 0) {
uint8_t* mname = request->qname;
size_t mname_len = request->qname_len;
/* Now look at the answer section first. 3 states: our
* answer is there directly, our answer is there after
* a cname, or there is just a cname. */
for(i=0; i<msg->rep->an_numrrsets; i++) {
struct ub_packed_rrset_key* s = msg->rep->rrsets[i];
/* If we have encountered an answer (before or
* after a CNAME), then we are done! Note that
* if qtype == CNAME then this will be noted as an
* ANSWER before it gets treated as a CNAME, as
* it should. */
if(ntohs(s->rk.type) == request->qtype &&
ntohs(s->rk.rrset_class) == request->qclass &&
query_dname_compare(mname, s->rk.dname) == 0) {
if((msg->rep->flags&BIT_AA))
return RESPONSE_TYPE_ANSWER;
/* If the AA bit isn't on, and we've seen
* the answer, we only provisionally say
* 'ANSWER' -- it very well could be a
* REFERRAL. */
break;
}
/* If we have encountered a CNAME, make sure that
* it is relevant. */
if(ntohs(s->rk.type) == LDNS_RR_TYPE_CNAME &&
query_dname_compare(mname, s->rk.dname) == 0) {
get_cname_target(s, &mname, &mname_len);
}
}
/* if we encountered a CNAME (or a bunch of CNAMEs), and
* still got to here, then it is a CNAME response.
* (This is regardless of the AA bit at this point) */
if(mname != request->qname) {
return RESPONSE_TYPE_CNAME;
}
}
/* Looking at the authority section, we just look and see if
* there is a delegation NS set, turning it into a delegation.
* Otherwise, we will have to conclude ANSWER (either it is
* NOERROR/NODATA, or an non-authoritative answer). */
for(i = msg->rep->an_numrrsets; i < (msg->rep->an_numrrsets +
msg->rep->ns_numrrsets); i++) {
struct ub_packed_rrset_key* s = msg->rep->rrsets[i];
/* The normal way of detecting NOERROR/NODATA. */
if(ntohs(s->rk.type) == LDNS_RR_TYPE_SOA &&
dname_subdomain_c(request->qname, s->rk.dname)) {
return RESPONSE_TYPE_ANSWER;
}
/* Detect REFERRAL/LAME/ANSWER based on the relationship
* of the NS set to the originating zone name. */
if(ntohs(s->rk.type) == LDNS_RR_TYPE_NS) {
/* If we are getting an NS set for the zone we
* thought we were contacting, then it is an answer.*/
/* FIXME: is this correct? */
if(query_dname_compare(s->rk.dname, origzone) == 0) {
return RESPONSE_TYPE_ANSWER;
}
/* If we are getting a referral upwards (or to
* the same zone), then the server is 'lame'. */
if(dname_subdomain_c(origzone, s->rk.dname)) {
return RESPONSE_TYPE_LAME;
}
/* If the NS set is below the delegation point we
* are on, and it is non-authoritative, then it is
* a referral, otherwise it is an answer. */
if(dname_subdomain_c(s->rk.dname, origzone)) {
/* NOTE: I no longer remember in what case
* we would like this to be an answer.
* NODATA should have a SOA or nothing,
* not an NS rrset.
* True, referrals should not have the AA
* bit set, but... */
/* if((msg->rep->flags&BIT_AA))
return RESPONSE_TYPE_ANSWER; */
return RESPONSE_TYPE_REFERRAL;
}
/* Otherwise, the NS set is irrelevant. */
}
}
/* If we've gotten this far, this is NOERROR/NODATA (which could
* be an entirely empty message) */
return RESPONSE_TYPE_ANSWER;
}
-119
View File
@@ -1,119 +0,0 @@
/*
* iterator/iter_resptype.h - response type information and classification.
*
* 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 defines the response type. DNS Responses can be classified as
* one of the response types.
*/
#ifndef ITERATOR_ITER_RESPTYPE_H
#define ITERATOR_ITER_RESPTYPE_H
struct dns_msg;
struct query_info;
struct delegpt;
/**
* The response type is used to interpret the response.
*/
enum response_type {
/**
* 'untyped' means that the type of this response hasn't been
* assigned.
*/
RESPONSE_TYPE_UNTYPED = 0,
/**
* 'answer' means that the response terminates the resolution
* process.
*/
RESPONSE_TYPE_ANSWER,
/** 'delegation' means that the response is a delegation. */
RESPONSE_TYPE_REFERRAL,
/**
* 'cname' means that the response is a cname without the final
* answer, and thus must be restarted.
*/
RESPONSE_TYPE_CNAME,
/**
* 'throwaway' means that this particular response should be
* discarded and the next nameserver should be contacted
*/
RESPONSE_TYPE_THROWAWAY,
/**
* 'lame' means that this particular response indicates that
* the nameserver knew nothing about the question.
*/
RESPONSE_TYPE_LAME
};
/**
* Classifies a response message from cache based on the current request.
* Note that this routine assumes that THROWAWAY or LAME responses will not
* occur. Also, it will not detect REFERRAL type messages, since those are
* (currently) automatically classified based on how they came from the
* cache (findDelegation() instead of lookup()).
*
* @param msg: the message from the cache.
* @param request: the request that generated the response.
* @return the response type (CNAME or ANSWER).
*/
enum response_type response_type_from_cache(struct dns_msg* msg,
struct query_info* request);
/**
* Classifies a response message (from the wire) based on the current
* request.
*
* NOTE: currently this routine uses the AA bit in the response to help
* distinguish between some non-standard referrals and answers. It also
* relies somewhat on the originating zone to be accurate (for lameness
* detection, mostly).
*
* @param msg: the message from the cache.
* @param request: the request that generated the response.
* @param dp: The delegation point that was being queried
* when the response was returned.
* @return the response type (CNAME or ANSWER).
*/
enum response_type response_type_from_server(struct dns_msg* msg,
struct query_info* request, struct delegpt* dp);
#endif /* ITERATOR_ITER_RESPTYPE_H */
-565
View File
@@ -1,565 +0,0 @@
/*
* iterator/iter_scrub.c - scrubbing, normalization, sanitization of DNS msgs.
*
* 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 has routine(s) for cleaning up incoming DNS messages from
* possible useless or malicious junk in it.
*/
#include "config.h"
#include "iterator/iter_scrub.h"
#include "services/cache/rrset.h"
#include "util/log.h"
#include "util/net_help.h"
#include "util/region-allocator.h"
#include "util/config_file.h"
#include "util/module.h"
#include "util/data/msgparse.h"
#include "util/data/dname.h"
#include "util/data/msgreply.h"
#include "util/alloc.h"
/** RRset flag used during scrubbing. The RRset is OK. */
#define RRSET_SCRUB_OK 0x80
/** remove rrset, update loop variables */
static void
remove_rrset(const char* str, ldns_buffer* pkt, struct msg_parse* msg,
struct rrset_parse* prev, struct rrset_parse** rrset)
{
if(verbosity >= VERB_DETAIL
&& (*rrset)->dname_len <= LDNS_MAX_DOMAINLEN) {
uint8_t buf[LDNS_MAX_DOMAINLEN+1];
dname_pkt_copy(pkt, buf, (*rrset)->dname);
log_nametypeclass(VERB_DETAIL, str, buf,
(*rrset)->type, ntohs((*rrset)->rrset_class));
}
if(prev)
prev->rrset_all_next = (*rrset)->rrset_all_next;
else msg->rrset_first = (*rrset)->rrset_all_next;
if(msg->rrset_last == *rrset)
msg->rrset_last = prev;
msg->rrset_count --;
switch((*rrset)->section) {
case LDNS_SECTION_ANSWER: msg->an_rrsets--; break;
case LDNS_SECTION_AUTHORITY: msg->ns_rrsets--; break;
case LDNS_SECTION_ADDITIONAL: msg->ar_rrsets--; break;
default: log_assert(0);
}
msgparse_bucket_remove(msg, *rrset);
*rrset = (*rrset)->rrset_all_next;
}
/** return true if rr type has additional names in it */
static int
has_additional(uint16_t t)
{
switch(t) {
case LDNS_RR_TYPE_MB:
case LDNS_RR_TYPE_MD:
case LDNS_RR_TYPE_MF:
case LDNS_RR_TYPE_NS:
case LDNS_RR_TYPE_MX:
case LDNS_RR_TYPE_KX:
case LDNS_RR_TYPE_SRV:
return 1;
case LDNS_RR_TYPE_NAPTR:
/* TODO: NAPTR not supported, glue stripped off */
return 0;
default:
return 0;
}
return 0;
}
/** get additional name from rrset RR, return false if no name present */
static int
get_additional_name(struct rrset_parse* rrset, struct rr_parse* rr,
uint8_t** nm, size_t* nmlen, ldns_buffer* pkt)
{
size_t offset = 0;
size_t len, oldpos;
switch(rrset->type) {
case LDNS_RR_TYPE_MB:
case LDNS_RR_TYPE_MD:
case LDNS_RR_TYPE_MF:
case LDNS_RR_TYPE_NS:
offset = 0;
break;
case LDNS_RR_TYPE_MX:
case LDNS_RR_TYPE_KX:
offset = 2;
break;
case LDNS_RR_TYPE_SRV:
offset = 6;
break;
case LDNS_RR_TYPE_NAPTR:
/* TODO: NAPTR not supported, glue stripped off */
return 0;
default:
return 0;
}
len = ldns_read_uint16(rr->ttl_data+sizeof(uint32_t));
if(len < offset+1)
return 0; /* rdata field too small */
*nm = rr->ttl_data+sizeof(uint32_t)+sizeof(uint16_t)+offset;
oldpos = ldns_buffer_position(pkt);
ldns_buffer_set_position(pkt, (size_t)(*nm - ldns_buffer_begin(pkt)));
*nmlen = pkt_dname_len(pkt);
ldns_buffer_set_position(pkt, oldpos);
if(*nmlen == 0)
return 0;
return 1;
}
/** Place mark on rrsets in additional section they are OK */
static void
mark_additional_rrset(ldns_buffer* pkt, struct msg_parse* msg,
struct rrset_parse* rrset)
{
/* Mark A and AAAA for NS as appropriate additional section info. */
uint8_t* nm = NULL;
size_t nmlen = 0;
struct rr_parse* rr;
if(!has_additional(rrset->type))
return;
for(rr = rrset->rr_first; rr; rr = rr->next) {
if(get_additional_name(rrset, rr, &nm, &nmlen, pkt)) {
/* mark A */
hashvalue_t h = pkt_hash_rrset(pkt, nm, LDNS_RR_TYPE_A,
rrset->rrset_class, 0);
struct rrset_parse* r = msgparse_hashtable_lookup(
msg, pkt, h, 0, nm, nmlen,
LDNS_RR_TYPE_A, rrset->rrset_class);
if(r && r->section == LDNS_SECTION_ADDITIONAL) {
r->flags |= RRSET_SCRUB_OK;
}
/* mark AAAA */
h = pkt_hash_rrset(pkt, nm, LDNS_RR_TYPE_AAAA,
rrset->rrset_class, 0);
r = msgparse_hashtable_lookup(msg, pkt, h, 0, nm,
nmlen, LDNS_RR_TYPE_AAAA, rrset->rrset_class);
if(r && r->section == LDNS_SECTION_ADDITIONAL) {
r->flags |= RRSET_SCRUB_OK;
}
}
}
}
/** Get target name of a CNAME */
static int
parse_get_cname_target(struct rrset_parse* rrset, uint8_t** sname,
size_t* snamelen)
{
if(rrset->rr_count != 1) {
verbose(VERB_ALGO, "Found CNAME rrset with "
"size > 1: %u", (unsigned)rrset->rr_count);
return 0;
}
if(rrset->rr_first->size < sizeof(uint16_t)+1)
return 0; /* CNAME rdata too small */
*sname = rrset->rr_first->ttl_data + sizeof(uint32_t)
+ sizeof(uint16_t); /* skip ttl, rdatalen */
*snamelen = rrset->rr_first->size - sizeof(uint16_t);
return 1;
}
/** Synthesize CNAME from DNAME, false if too long */
static int
synth_cname(uint8_t* qname, size_t qnamelen, struct rrset_parse* dname_rrset,
uint8_t* alias, size_t* aliaslen, ldns_buffer* pkt)
{
/* we already know that sname is a strict subdomain of DNAME owner */
uint8_t* dtarg = NULL;
size_t dtarglen;
if(!parse_get_cname_target(dname_rrset, &dtarg, &dtarglen))
return 0;
log_assert(qnamelen > dname_rrset->dname_len);
/* DNAME from com. to net. with qname example.com. -> example.net. */
/* so: \3com\0 to \3net\0 and qname \7example\3com\0 */
*aliaslen = qnamelen + dtarglen - dname_rrset->dname_len;
if(*aliaslen > LDNS_MAX_DOMAINLEN)
return 0; /* should have been RCODE YXDOMAIN */
/* decompress dnames into buffer, we know it fits */
dname_pkt_copy(pkt, alias, qname);
dname_pkt_copy(pkt, alias+(qnamelen-dname_rrset->dname_len), dtarg);
return 1;
}
/** synthesize a CNAME rrset */
static struct rrset_parse*
synth_cname_rrset(uint8_t** sname, size_t* snamelen, uint8_t* alias,
size_t aliaslen, struct region* region, struct msg_parse* msg,
struct rrset_parse* rrset, struct rrset_parse* prev,
struct rrset_parse* nx, ldns_buffer* pkt)
{
struct rrset_parse* cn = (struct rrset_parse*)region_alloc(region,
sizeof(struct rrset_parse));
if(!cn)
return NULL;
memset(cn, 0, sizeof(*cn));
cn->rr_first = (struct rr_parse*)region_alloc(region,
sizeof(struct rr_parse));
if(!cn->rr_first)
return NULL;
cn->rr_last = cn->rr_first;
/* CNAME from sname to alias */
cn->dname = (uint8_t*)region_alloc(region, *snamelen);
if(!cn->dname)
return NULL;
dname_pkt_copy(pkt, cn->dname, *sname);
cn->dname_len = *snamelen;
cn->type = LDNS_RR_TYPE_CNAME;
cn->section = rrset->section;
cn->rrset_class = rrset->rrset_class;
cn->rr_count = 1;
cn->size = sizeof(uint16_t) + aliaslen;
cn->hash=pkt_hash_rrset(pkt, cn->dname, cn->type, cn->rrset_class, 0);
/* allocate TTL + rdatalen + uncompressed dname */
memset(cn->rr_first, 0, sizeof(struct rr_parse));
cn->rr_first->outside_packet = 1;
cn->rr_first->ttl_data = (uint8_t*)region_alloc(region,
sizeof(uint32_t)+sizeof(uint16_t)+aliaslen);
if(!cn->rr_first->ttl_data)
return NULL;
ldns_write_uint32(cn->rr_first->ttl_data, 0); /* TTL = 0 */
ldns_write_uint16(cn->rr_first->ttl_data+4, aliaslen);
memmove(cn->rr_first->ttl_data+6, alias, aliaslen);
cn->rr_first->size = sizeof(uint16_t)+aliaslen;
/* link it in */
cn->rrset_all_next = nx;
if(prev)
prev->rrset_all_next = cn;
else msg->rrset_first = cn;
if(nx == NULL)
msg->rrset_last = cn;
msg->rrset_count ++;
msg->an_rrsets++;
/* it is not inserted in the msg hashtable. */
*sname = cn->rr_first->ttl_data + sizeof(uint32_t)+sizeof(uint16_t);
*snamelen = aliaslen;
return cn;
}
/** check if DNAME applies to a name */
static int
pkt_strict_sub(ldns_buffer* pkt, uint8_t* sname, uint8_t* dr)
{
uint8_t buf1[LDNS_MAX_DOMAINLEN+1];
uint8_t buf2[LDNS_MAX_DOMAINLEN+1];
/* decompress names */
dname_pkt_copy(pkt, buf1, sname);
dname_pkt_copy(pkt, buf2, dr);
return dname_strict_subdomain_c(buf1, buf2);
}
/** check subdomain with decompression */
static int
pkt_sub(ldns_buffer* pkt, uint8_t* comprname, uint8_t* zone)
{
uint8_t buf[LDNS_MAX_DOMAINLEN+1];
dname_pkt_copy(pkt, buf, comprname);
return dname_subdomain_c(buf, zone);
}
/**
* This routine normalizes a response. This includes removing "irrelevant"
* records from the answer and additional sections and (re)synthesizing
* CNAMEs from DNAMEs, if present.
*
* @param pkt: packet.
* @param msg: msg to normalize.
* @param qinfo: original query.
* @param region: where to allocate synthesized CNAMEs.
* @return 0 on error.
*/
static int
scrub_normalize(ldns_buffer* pkt, struct msg_parse* msg,
struct query_info* qinfo, struct region* region)
{
uint8_t* sname = qinfo->qname;
size_t snamelen = qinfo->qname_len;
struct rrset_parse* rrset, *prev;
if(FLAGS_GET_RCODE(msg->flags) != LDNS_RCODE_NOERROR &&
FLAGS_GET_RCODE(msg->flags) != LDNS_RCODE_NXDOMAIN)
return 1;
/* For the ANSWER section, remove all "irrelevant" records and add
* synthesized CNAMEs from DNAMEs
* This will strip out-of-order CNAMEs as well. */
/* walk through the parse packet rrset list, keep track of previous
* for insert and delete ease, and examine every RRset */
prev = NULL;
rrset = msg->rrset_first;
while(rrset && rrset->section == LDNS_SECTION_ANSWER) {
if(rrset->type == LDNS_RR_TYPE_DNAME &&
pkt_strict_sub(pkt, sname, rrset->dname)) {
/* check if next rrset is correct CNAME. else,
* synthesize a CNAME */
struct rrset_parse* nx = rrset->rrset_all_next;
uint8_t alias[LDNS_MAX_DOMAINLEN+1];
size_t aliaslen = 0;
if(rrset->rr_count != 1) {
verbose(VERB_ALGO, "Found DNAME rrset with "
"size > 1: %u",
(unsigned)rrset->rr_count);
return 0;
}
if(!synth_cname(sname, snamelen, rrset, alias,
&aliaslen, pkt)) {
verbose(VERB_ALGO, "synthesized CNAME "
"too long");
return 0;
}
if(nx && nx->type == LDNS_RR_TYPE_CNAME &&
dname_pkt_compare(pkt, sname, nx->dname) == 0) {
/* check next cname */
uint8_t* t = NULL;
size_t tlen = 0;
if(!parse_get_cname_target(rrset, &t, &tlen))
return 0;
if(dname_pkt_compare(pkt, alias, t) == 0) {
/* it's OK and better capitalized */
prev = rrset;
rrset = nx;
continue;
}
/* synth ourselves */
}
/* synth a CNAME rrset */
prev = synth_cname_rrset(&sname, &snamelen, alias,
aliaslen, region, msg, rrset, rrset, nx, pkt);
if(!prev) {
log_err("out of memory synthesizing CNAME");
return 0;
}
/* FIXME: resolve the conflict between synthesized
* CNAME ttls and the cache. */
rrset = nx;
continue;
}
/* The only records in the ANSWER section not allowed to */
if(dname_pkt_compare(pkt, sname, rrset->dname) != 0) {
remove_rrset("normalize: removing irrelevant RRset:",
pkt, msg, prev, &rrset);
continue;
}
/* Follow the CNAME chain. */
if(rrset->type == LDNS_RR_TYPE_CNAME) {
if(!parse_get_cname_target(rrset, &sname, &snamelen))
return 0;
prev = rrset;
rrset = rrset->rrset_all_next;
continue;
}
/* Otherwise, make sure that the RRset matches the qtype. */
if(qinfo->qtype != LDNS_RR_TYPE_ANY &&
qinfo->qtype != rrset->type) {
remove_rrset("normalize: removing irrelevant RRset:",
pkt, msg, prev, &rrset);
continue;
}
/* Mark the additional names from relevant rrset as OK. */
mark_additional_rrset(pkt, msg, rrset);
prev = rrset;
rrset = rrset->rrset_all_next;
}
/* Mark additional names from AUTHORITY */
while(rrset && rrset->section == LDNS_SECTION_AUTHORITY) {
mark_additional_rrset(pkt, msg, rrset);
prev = rrset;
rrset = rrset->rrset_all_next;
}
/* For each record in the additional section, remove it if it is an
* address record and not in the collection of additional names
* found in ANSWER and AUTHORITY. */
/* These records have not been marked OK previously */
while(rrset && rrset->section == LDNS_SECTION_ADDITIONAL) {
/* FIXME: what about other types? */
if(rrset->type==LDNS_RR_TYPE_A ||
rrset->type==LDNS_RR_TYPE_AAAA)
{
if((rrset->flags & RRSET_SCRUB_OK)) {
/* remove flag to clean up flags variable */
rrset->flags &= ~RRSET_SCRUB_OK;
} else {
remove_rrset("normalize: removing irrelevant "
"RRset:", pkt, msg, prev, &rrset);
continue;
}
}
prev = rrset;
rrset = rrset->rrset_all_next;
}
return 1;
}
/**
* Store potential poison in the cache (only if hardening disabled).
* The rrset is stored in the cache but removed from the message.
* So that it will be used for infrastructure purposes, but not be
* returned to the client.
* @param pkt: packet
* @param msg: message parsed
* @param env: environment with cache
* @param rrset: to store.
*/
static void
store_rrset(ldns_buffer* pkt, struct msg_parse* msg, struct module_env* env,
struct rrset_parse* rrset)
{
struct ub_packed_rrset_key* k;
struct packed_rrset_data* d;
struct rrset_ref ref;
uint32_t now = time(NULL);
k = alloc_special_obtain(env->alloc);
if(!k)
return;
k->entry.data = NULL;
if(!parse_copy_decompress_rrset(pkt, msg, rrset, NULL, k)) {
alloc_special_release(env->alloc, k);
return;
}
d = (struct packed_rrset_data*)k->entry.data;
packed_rrset_ttl_add(d, now);
ref.key = k;
ref.id = k->id;
/*ignore ret: it was in the cache, ref updated */
(void)rrset_cache_update(env->rrset_cache, &ref,
env->alloc, now);
}
/**
* Given a response event, remove suspect RRsets from the response.
* "Suspect" rrsets are potentially poison. Note that this routine expects
* the response to be in a "normalized" state -- that is, all "irrelevant"
* RRsets have already been removed, CNAMEs are in order, etc.
*
* @param pkt: packet.
* @param msg: msg to normalize.
* @param zonename: name of server zone.
* @param env: module environment with config and cache.
* @return 0 on error.
*/
static int
scrub_sanitize(ldns_buffer* pkt, struct msg_parse* msg, uint8_t* zonename,
struct module_env* env)
{
struct rrset_parse* rrset, *prev;
prev = NULL;
rrset = msg->rrset_first;
/* At this point, we brutally remove ALL rrsets that aren't
* children of the originating zone. The idea here is that,
* as far as we know, the server that we contacted is ONLY
* authoritative for the originating zone. It, of course, MAY
* be authoriative for any other zones, and of course, MAY
* NOT be authoritative for some subdomains of the originating
* zone. */
while(rrset) {
/* skip DNAME records -- they will always be followed by a
* synthesized CNAME, which will be relevant.
* FIXME: should this do something differently with DNAME
* rrsets NOT in Section.ANSWER? */
/* But since DNAME records are also subdomains of the zone,
* same check can be used */
if(!pkt_sub(pkt, rrset->dname, zonename)) {
if(!env->cfg->harden_glue) {
/* store in cache! Since it is relevant
* (from normalize) it will be picked up
* from the cache to be used later */
store_rrset(pkt, msg, env, rrset);
remove_rrset("sanitize: storing potential "
"poison RRset:", pkt, msg, prev, &rrset);
} else
remove_rrset("sanitize: removing potential "
"poison RRset:", pkt, msg, prev, &rrset);
continue;
}
prev = rrset;
rrset = rrset->rrset_all_next;
}
return 1;
}
int
scrub_message(ldns_buffer* pkt, struct msg_parse* msg,
struct query_info* qinfo, uint8_t* zonename, struct region* region,
struct module_env* env)
{
/* basic sanity checks */
log_nametypeclass(VERB_ALGO, "scrub for", zonename, LDNS_RR_TYPE_NS,
qinfo->qclass);
if(msg->qdcount > 1)
return 0;
if( !(msg->flags&BIT_QR) )
return 0;
/* if a query is echoed back, make sure it is correct. Otherwise,
* this may be not a reply to our query. */
if(msg->qdcount == 1) {
if(dname_pkt_compare(pkt, msg->qname, qinfo->qname) != 0)
return 0;
if(msg->qtype != qinfo->qtype || msg->qclass != qinfo->qclass)
return 0;
}
/* normalize the response, this cleans up the additional. */
if(!scrub_normalize(pkt, msg, qinfo, region))
return 0;
/* delete all out-of-zone information */
if(!scrub_sanitize(pkt, msg, zonename, env))
return 0;
return 1;
}
-66
View File
@@ -1,66 +0,0 @@
/*
* iterator/iter_scrub.h - scrubbing, normalization, sanitization of DNS msgs.
*
* 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 has routine(s) for cleaning up incoming DNS messages from
* possible useless or malicious junk in it.
*/
#ifndef ITERATOR_ITER_SCRUB_H
#define ITERATOR_ITER_SCRUB_H
struct msg_parse;
struct query_info;
struct region;
struct module_env;
/**
* Cleanup the passed dns message.
* @param pkt: the packet itself, for resolving name compression pointers.
* the packet buffer is unaltered.
* @param msg: the parsed packet, this structure is cleaned up.
* @param qinfo: the query info that was sent to the server. Checked.
* @param zonename: the name of the last delegation point.
* Used to determine out of bailiwick information.
* @param region: where to allocate (new) parts of the message.
* @param env: module environment with config settings and cache.
* @return: false if the message is total waste. true if scrubbed with success.
*/
int scrub_message(ldns_buffer* pkt, struct msg_parse* msg,
struct query_info* qinfo, uint8_t* zonename, struct region* region,
struct module_env* env);
#endif /* ITERATOR_ITER_SCRUB_H */
-390
View File
@@ -1,390 +0,0 @@
/*
* iterator/iter_utils.c - iterative resolver module utility functions.
*
* Copyright (c) 2007, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file
*
* This file contains functions to assist the iterator module.
* Configuration options. Forward zones.
*/
#include "config.h"
#include "iterator/iter_utils.h"
#include "iterator/iterator.h"
#include "iterator/iter_hints.h"
#include "iterator/iter_fwd.h"
#include "iterator/iter_donotq.h"
#include "iterator/iter_delegpt.h"
#include "services/cache/infra.h"
#include "services/cache/dns.h"
#include "services/cache/rrset.h"
#include "util/net_help.h"
#include "util/module.h"
#include "util/log.h"
#include "util/config_file.h"
#include "util/region-allocator.h"
#include "util/data/msgparse.h"
#include "util/random.h"
/** count number of integers in fetch policy string */
static int
fetch_count(const char* s)
{
/* format ::= (sp num)+ sp */
/* num ::= [-](0-9)+ */
/* sp ::= (space|tab)* */
int num = 0;
while(*s) {
while(*s && isspace(*s))
s++;
if(!*s) /* end of string */
break;
if(*s == '-')
s++;
if(!*s) /* only - not allowed */
return 0;
if(!isdigit(*s)) /* bad character */
return 0;
while(*s && isdigit(*s))
s++;
num++;
}
return num;
}
/** fillup fetch policy array */
static void
fetch_fill(struct iter_env* ie, const char* str)
{
char* s = (char*)str, *e;
int i;
for(i=0; i<ie->max_dependency_depth+1; i++) {
ie->target_fetch_policy[i] = strtol(s, &e, 10);
log_assert(s != e); /* parsed syntax already */
s = e;
}
}
/** Read config string that represents the target fetch policy */
static int
read_fetch_policy(struct iter_env* ie, const char* str)
{
int count = fetch_count(str);
if(count < 1) {
log_err("Cannot parse target fetch policy: \"%s\"", str);
return 0;
}
ie->max_dependency_depth = count - 1;
ie->target_fetch_policy = (int*)calloc(
(size_t)ie->max_dependency_depth+1, sizeof(int));
if(!ie->target_fetch_policy) {
log_err("alloc fetch policy: out of memory");
return 0;
}
fetch_fill(ie, str);
return 1;
}
int
iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
{
int i;
/* target fetch policy */
if(!read_fetch_policy(iter_env, cfg->target_fetch_policy))
return 0;
for(i=0; i<iter_env->max_dependency_depth+1; i++)
verbose(VERB_DETAIL, "target fetch policy for level %d is %d",
i, iter_env->target_fetch_policy[i]);
if(!iter_env->hints)
iter_env->hints = hints_create();
if(!iter_env->hints || !hints_apply_cfg(iter_env->hints, cfg)) {
log_err("Could not set root or stub hints");
return 0;
}
if(!iter_env->fwds)
iter_env->fwds = forwards_create();
if(!iter_env->fwds || !forwards_apply_cfg(iter_env->fwds, cfg)) {
log_err("Could not set forward zones");
return 0;
}
if(!iter_env->donotq)
iter_env->donotq = donotq_create();
if(!iter_env->donotq || !donotq_apply_cfg(iter_env->donotq, cfg)) {
log_err("Could not set donotqueryaddresses");
return 0;
}
iter_env->supports_ipv6 = cfg->do_ip6;
return 1;
}
/** filter out unsuitable targets, return rtt or -1 */
static int
iter_filter_unsuitable(struct iter_env* iter_env, struct module_env* env,
uint8_t* name, size_t namelen, time_t now, struct delegpt_addr* a)
{
int rtt;
int lame;
if(donotq_lookup(iter_env->donotq, &a->addr, a->addrlen)) {
return -1; /* server is on the donotquery list */
}
if(!iter_env->supports_ipv6 && addr_is_ip6(&a->addr)) {
return -1; /* there is no ip6 available */
}
/* check lameness - need zone , class info */
if(infra_get_lame_rtt(env->infra_cache, &a->addr, a->addrlen,
name, namelen, &lame, &rtt, now)) {
if(lame)
return -1; /* server is lame */
else if(rtt >= USEFUL_SERVER_TOP_TIMEOUT)
return -1; /* server is unresponsive */
else return rtt;
}
/* no server information present */
return UNKNOWN_SERVER_NICENESS;
}
/** filter the addres list, putting best targets at front,
* returns number of best targets (or 0, no suitable targets) */
static int
iter_filter_order(struct iter_env* iter_env, struct module_env* env,
uint8_t* name, size_t namelen, time_t now, struct delegpt* dp)
{
int got_num = 0, got_rtt = 0, thisrtt, swap_to_front;
struct delegpt_addr* a, *n, *prev=NULL;
a = dp->result_list;
while(a) {
/* filter out unsuitable targets */
thisrtt = iter_filter_unsuitable(iter_env, env, name, namelen,
now, a);
if(thisrtt == -1) {
prev = a;
a = a->next_result;
continue;
}
/* classify the server address and determine what to do */
swap_to_front = 0;
if(got_num == 0) {
got_rtt = thisrtt;
got_num = 1;
swap_to_front = 1;
} else if(thisrtt == got_rtt) {
got_num++;
swap_to_front = 1;
} else if(thisrtt < got_rtt) {
got_rtt = thisrtt;
got_num = 1; /* start back at count of 1 */
swap_to_front = 1;
}
/* swap to front if necessary, or move to next result */
if(swap_to_front && prev) {
n = a->next_result;
prev->next_result = n;
a->next_result = dp->result_list;
dp->result_list = a;
a = n;
} else {
prev = a;
a = a->next_result;
}
}
return got_num;
}
struct delegpt_addr*
iter_server_selection(struct iter_env* iter_env,
struct module_env* env, struct delegpt* dp,
uint8_t* name, size_t namelen)
{
time_t now = time(NULL);
int sel;
struct delegpt_addr* a, *prev;
int num = iter_filter_order(iter_env, env, name, namelen, now, dp);
if(num == 0)
return NULL;
if(num == 1) {
a = dp->result_list;
dp->result_list = a->next_result;
return a;
}
/* randomly select a target from the list */
log_assert(num > 1);
/* we do not need secure random numbers here, but
* we do need it to be threadsafe, so we use this */
sel = ub_random(env->rnd) % num;
a = dp->result_list;
prev = NULL;
while(sel > 0 && a) {
prev = a;
a = a->next_result;
sel--;
}
if(!a) /* robustness */
return NULL;
/* remove it from the delegation point result list */
if(prev)
prev->next_result = a->next_result;
else dp->result_list = a->next_result;
return a;
}
struct dns_msg*
dns_alloc_msg(ldns_buffer* pkt, struct msg_parse* msg, struct region* region)
{
struct dns_msg* m = (struct dns_msg*)region_alloc(region,
sizeof(struct dns_msg));
if(!m)
return NULL;
memset(m, 0, sizeof(*m));
if(!parse_create_msg(pkt, msg, NULL, &m->qinfo, &m->rep, region)) {
log_err("malloc failure: allocating incoming dns_msg");
return NULL;
}
return m;
}
struct dns_msg*
dns_copy_msg(struct dns_msg* from, struct region* region)
{
struct dns_msg* m = (struct dns_msg*)region_alloc(region,
sizeof(struct dns_msg));
if(!m)
return NULL;
m->qinfo = from->qinfo;
if(!(m->qinfo.qname = region_alloc_init(region, from->qinfo.qname,
from->qinfo.qname_len)))
return NULL;
if(!(m->rep = reply_info_copy(from->rep, NULL, region)))
return NULL;
return m;
}
int
iter_dns_store(struct module_env* env, struct query_info* msgqinf,
struct reply_info* msgrep, int is_referral)
{
struct reply_info* rep = NULL;
/* alloc, malloc properly (not in region, like msg is) */
rep = reply_info_copy(msgrep, env->alloc, NULL);
if(!rep)
return 0;
if(is_referral) {
/* store rrsets */
struct rrset_ref ref;
uint32_t now = time(NULL);
size_t i;
for(i=0; i<rep->rrset_count; i++) {
packed_rrset_ttl_add((struct packed_rrset_data*)
rep->rrsets[i]->entry.data, now);
ref.key = rep->rrsets[i];
ref.id = rep->rrsets[i]->id;
/*ignore ret: it was in the cache, ref updated */
(void)rrset_cache_update(env->rrset_cache, &ref,
env->alloc, now);
}
free(rep);
return 1;
} else {
/* store msg, and rrsets */
struct query_info qinf;
hashvalue_t h;
qinf = *msgqinf;
qinf.qname = memdup(msgqinf->qname, msgqinf->qname_len);
if(!qinf.qname) {
reply_info_parsedelete(rep, env->alloc);
return 0;
}
/* fixup flags to be sensible for a reply based on the cache */
/* this module means that RA is available. It is an answer QR.
* Not AA from cache. Not CD in cache (depends on client bit). */
rep->flags |= (BIT_RA | BIT_QR);
rep->flags &= ~(BIT_AA | BIT_CD);
h = query_info_hash(&qinf);
dns_cache_store_msg(env, &qinf, h, rep);
/* qname is used inside query_info_entrysetup, and set to
* NULL. If it has not been used, free it. free(0) is safe. */
free(qinf.qname);
}
return 1;
}
int
iter_ns_probability(struct ub_randstate* rnd, int n, int m)
{
int sel;
if(n == m) /* 100% chance */
return 1;
/* we do not need secure random numbers here, but
* we do need it to be threadsafe, so we use this */
sel = ub_random(rnd) % m;
return (sel < n);
}
/** detect dependency cycle for query and target */
static int
causes_cycle(struct module_qstate* qstate, uint8_t* name, size_t namelen,
uint16_t t, uint16_t c)
{
struct query_info qinf;
qinf.qname = name;
qinf.qname_len = namelen;
qinf.qtype = t;
qinf.qclass = c;
return (*qstate->env->detect_cycle)(qstate, &qinf);
}
void
iter_mark_cycle_targets(struct module_qstate* qstate, struct delegpt* dp)
{
struct delegpt_ns* ns;
for(ns = dp->nslist; ns; ns = ns->next) {
if(ns->resolved)
continue;
/* see if this ns as target causes dependency cycle */
if(causes_cycle(qstate, ns->name, ns->namelen,
LDNS_RR_TYPE_AAAA, qstate->qinfo.qclass) ||
causes_cycle(qstate, ns->name, ns->namelen,
LDNS_RR_TYPE_A, qstate->qinfo.qclass)) {
log_nametypeclass(VERB_DETAIL, "skipping target due "
"to dependency cycle (harden-glue: no may "
"fix this)", ns->name, LDNS_RR_TYPE_A,
qstate->qinfo.qclass);
ns->resolved = 1;
}
}
}
-131
View File
@@ -1,131 +0,0 @@
/*
* iterator/iter_utils.h - iterative resolver module utility functions.
*
* Copyright (c) 2007, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file
*
* This file contains functions to assist the iterator module.
* Configuration options. Forward zones.
*/
#ifndef ITERATOR_ITER_UTILS_H
#define ITERATOR_ITER_UTILS_H
struct iter_env;
struct config_file;
struct module_env;
struct delegpt_addr;
struct delegpt;
struct region;
struct msg_parse;
struct ub_randstate;
struct query_info;
struct reply_info;
struct module_qstate;
/**
* Process config options and set iterator module state.
* Sets default values if no config is found.
* @param iter_env: iterator module state.
* @param cfg: config options.
* @return 0 on error.
*/
int iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg);
/**
* Select a valid, nice target to send query to.
* Sorting and removing unsuitable targets is combined.
*
* @param iter_env: iterator module global state, with ip6 enabled and
* do-not-query-addresses.
* @param env: environment with infra cache (lameness, rtt info).
* @param dp: delegation point with result list.
* @param name: zone name (for lameness check).
* @param namelen: length of name.
* @return best target or NULL if no target.
* if not null, that target is removed from the result list in the dp.
*/
struct delegpt_addr* iter_server_selection(struct iter_env* iter_env,
struct module_env* env, struct delegpt* dp, uint8_t* name,
size_t namelen);
/**
* Allocate dns_msg from parsed msg, in region.
* @param pkt: packet.
* @param msg: parsed message (cleaned and ready for region allocation).
* @param region: region to use for allocation.
* @return newly allocated dns_msg, or NULL on memory error.
*/
struct dns_msg* dns_alloc_msg(ldns_buffer* pkt, struct msg_parse* msg,
struct region* region);
/**
* Copy a dns_msg to this region.
* @param from: dns message, also in region.
* @param region: region to use for allocation.
* @return newly allocated dns_msg, or NULL on memory error.
*/
struct dns_msg* dns_copy_msg(struct dns_msg* from, struct region* region);
/**
* Allocate a dns_msg with malloc/alloc structure and store in dns cache.
* @param env: environment, with alloc structure and dns cache.
* @param qinf: query info, the query for which answer is stored.
* @param rep: reply in dns_msg from dns_alloc_msg for example.
* @param is_referral: If true, then the given message to be stored is a
* referral. The cache implementation may use this as a hint.
* @return 0 on alloc error (out of memory).
*/
int iter_dns_store(struct module_env* env, struct query_info* qinf,
struct reply_info* rep, int is_referral);
/**
* Select randomly with n/m probability.
* For shuffle NS records for address fetching.
* @param rnd: random table
* @param n: probability.
* @param m: divisor for probability.
* @return true with n/m probability.
*/
int iter_ns_probability(struct ub_randstate* rnd, int n, int m);
/**
* Mark targets that result in a dependency cycle as done, so they
* will not get selected as targets.
* @param qstate: query state.
* @param dp: delegpt to mark ns in.
*/
void iter_mark_cycle_targets(struct module_qstate* qstate, struct delegpt* dp);
#endif /* ITERATOR_ITER_UTILS_H */
-1620
View File
File diff suppressed because it is too large Load Diff
-275
View File
@@ -1,275 +0,0 @@
/*
* iterator/iterator.h - iterative resolver DNS query response module
*
* 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 a module that performs recusive iterative DNS query
* processing.
*/
#ifndef ITERATOR_ITERATOR_H
#define ITERATOR_ITERATOR_H
#include "services/outbound_list.h"
#include "util/data/msgreply.h"
struct module_func_block;
struct delegpt;
struct iter_hints;
struct iter_forwards;
struct iter_donotq;
struct iter_prep_list;
/** max number of query restarts. Determines max number of CNAME chain. */
#define MAX_RESTART_COUNT 8
/** max number of referrals. Makes sure resolver does not run away */
#define MAX_REFERRAL_COUNT 30
/** how nice is a server without further information, in msec
* Equals rtt initial timeout value.
*/
#define UNKNOWN_SERVER_NICENESS 3000
/** maximum timeout before a host is deemed unsuitable, in msec.
* After host_ttl this will be timed out and the host will be tried again.
* Equals RTT_MAX_TIMEOUT
*/
#define USEFUL_SERVER_TOP_TIMEOUT 120000
/**
* Global state for the iterator.
*/
struct iter_env {
/**
* The hints -- these aren't stored in the cache because they don't
* expire. The hints are always used to "prime" the cache. Note
* that both root hints and stub zone "hints" are stored in this
* data structure.
*/
struct iter_hints* hints;
/** A flag to indicate whether or not we have an IPv6 route */
int supports_ipv6;
/** Mapping of forwarding zones to targets. */
struct iter_forwards* fwds;
/** A set of inetaddrs that should never be queried. */
struct iter_donotq* donotq;
/** The maximum dependency depth that this resolver will pursue. */
int max_dependency_depth;
/**
* The target fetch policy for each dependency level. This is
* described as a simple number (per dependency level):
* negative numbers (usually just -1) mean fetch-all,
* 0 means only fetch on demand, and
* positive numbers mean to fetch at most that many targets.
* array of max_dependency_depth+1 size.
*/
int* target_fetch_policy;
};
/**
* State of the iterator for a query.
*/
enum iter_state {
/**
* Externally generated queries start at this state. Query restarts are
* reset to this state.
*/
INIT_REQUEST_STATE = 0,
/**
* Root priming events reactivate here, most other events pass
* through this naturally as the 2nd part of the INIT_REQUEST_STATE.
*/
INIT_REQUEST_2_STATE,
/**
* Stub priming events reactivate here, most other events pass
* through this naturally as the 3rd part of the INIT_REQUEST_STATE.
*/
INIT_REQUEST_3_STATE,
/**
* Each time a delegation point changes for a given query or a
* query times out and/or wakes up, this state is (re)visited.
* This state is reponsible for iterating through a list of
* nameserver targets.
*/
QUERYTARGETS_STATE,
/**
* Responses to queries start at this state. This state handles
* the decision tree associated with handling responses.
*/
QUERY_RESP_STATE,
/** Responses to priming queries finish at this state. */
PRIME_RESP_STATE,
/** Responses that are to be returned upstream end at this state.
* As well as responses to target queries. */
FINISHED_STATE
};
/**
* Per query state for the iterator module.
*/
struct iter_qstate {
/**
* State of the iterator module.
* This is the state that event is in or should sent to -- all
* requests should start with the INIT_REQUEST_STATE. All
* responses should start with QUERY_RESP_STATE. Subsequent
* processing of the event will change this state.
*/
enum iter_state state;
/**
* Final state for the iterator module.
* This is the state that responses should be routed to once the
* response is final. For externally initiated queries, this
* will be FINISHED_STATE, locally initiated queries will have
* different final states.
*/
enum iter_state final_state;
/**
* The depth of this query, this means the depth of recursion.
* This address is needed for another query, which is an address
* needed for another query, etc. Original client query has depth 0.
*/
int depth;
/**
* The response
*/
struct dns_msg* response;
/**
* This is a list of RRsets that must be prepended to the
* ANSWER section of a response before being sent upstream.
*/
struct iter_prep_list* prepend_list;
/** Last element of the prepend list */
struct iter_prep_list* prepend_last;
/** query name used for chasing the results. Initially the same as
* the state qinfo, but after CNAMEs this will be different.
* The query info used to elicit the results needed. */
struct query_info qchase;
/** query flags to use when chasing the answer (i.e. RD flag) */
uint16_t chase_flags;
/**
* This is the current delegation point for an in-progress query. This
* object retains state as to which delegation targets need to be
* (sub)queried for vs which ones have already been visited.
*/
struct delegpt* dp;
/** Current delegation message - returned for non-RD queries */
struct dns_msg* deleg_msg;
/** number of outstanding target sub queries */
int num_target_queries;
/** outstanding direct queries */
int num_current_queries;
/** the number of times this query has been restarted. */
int query_restart_count;
/** the number of times this query as followed a referral. */
int referral_count;
/**
* This flag, if true, means that this event is a priming query.
* In that case priming stub may be set as well.
*/
int priming;
/**
* This is flag that, if true, means that this event is
* representing a stub priming query. It is meaningless unless
* the finalState is the PRIMING_RESP_STATE.
*/
int priming_stub;
/**
* This is a flag that, if true, means that this query is
* for (re)fetching glue from a zone. Since the address should
* have been glue, query again to the servers that should have
* been returning it as glue.
* The delegation point must be set to the one that should *not*
* be used when creating the state. A higher one will be attempted.
*/
int refetch_glue;
/** list of pending queries to authoritative servers. */
struct outbound_list outlist;
};
/**
* List of prepend items
*/
struct iter_prep_list {
/** next in list */
struct iter_prep_list* next;
/** rrset */
struct ub_packed_rrset_key* rrset;
};
/**
* Get the iterator function block.
* @return: function block with function pointers to iterator methods.
*/
struct module_func_block* iter_get_funcblock();
/**
* Get iterator state as a string
* @param state: to convert
* @return constant string that is printable.
*/
const char* iter_state_to_string(enum iter_state state);
/**
* See if iterator state is a response state
* @param s: to inspect
* @return true if response state.
*/
int iter_state_is_responsestate(enum iter_state s);
#endif /* ITERATOR_ITERATOR_H */
-587
View File
@@ -1,587 +0,0 @@
/*
* services/cache/dns.c - Cache services for DNS using msg and rrset caches.
*
* 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 the DNS cache.
*/
#include "config.h"
#include "iterator/iter_delegpt.h"
#include "services/cache/dns.h"
#include "services/cache/rrset.h"
#include "util/data/msgreply.h"
#include "util/data/packed_rrset.h"
#include "util/data/dname.h"
#include "util/module.h"
#include "util/net_help.h"
#include "util/region-allocator.h"
/** store rrsets in the rrset cache.
* @param env: module environment with caches.
* @param rep: contains list of rrsets to store.
* @param now: current time(NULL).
*/
static void
store_rrsets(struct module_env* env, struct reply_info* rep, uint32_t now)
{
size_t i;
/* see if rrset already exists in cache, if not insert it. */
for(i=0; i<rep->rrset_count; i++) {
rep->ref[i].key = rep->rrsets[i];
rep->ref[i].id = rep->rrsets[i]->id;
if(rrset_cache_update(env->rrset_cache, &rep->ref[i],
env->alloc, now)) /* it was in the cache */
rep->rrsets[i] = rep->ref[i].key;
}
}
void
dns_cache_store_msg(struct module_env* env, struct query_info* qinfo,
hashvalue_t hash, struct reply_info* rep)
{
struct msgreply_entry* e;
uint32_t now = time(NULL), ttl = rep->ttl;
size_t i;
/* store RRsets */
for(i=0; i<rep->rrset_count; i++) {
rep->ref[i].key = rep->rrsets[i];
rep->ref[i].id = rep->rrsets[i]->id;
}
reply_info_sortref(rep);
reply_info_set_ttls(rep, now);
store_rrsets(env, rep, now);
if(ttl == 0) {
/* we do not store the message, but we did store the RRs,
* which could be useful for delegation information */
verbose(VERB_ALGO, "TTL 0: dropped msg from cache");
free(rep);
return;
}
/* store msg in the cache */
reply_info_sortref(rep);
if(!(e = query_info_entrysetup(qinfo, rep, hash))) {
log_err("store_msg: malloc failed");
return;
}
slabhash_insert(env->msg_cache, hash, &e->entry, rep, env->alloc);
}
/** allocate rrset in region - no more locks needed */
static struct ub_packed_rrset_key*
copy_rrset(struct ub_packed_rrset_key* key, struct region* region,
uint32_t now)
{
struct ub_packed_rrset_key* ck = region_alloc(region,
sizeof(struct ub_packed_rrset_key));
struct packed_rrset_data* d;
struct packed_rrset_data* data = (struct packed_rrset_data*)
key->entry.data;
size_t dsize, i;
if(!ck)
return NULL;
ck->id = key->id;
memset(&ck->entry, 0, sizeof(ck->entry));
ck->entry.hash = key->entry.hash;
ck->entry.key = ck;
ck->rk = key->rk;
ck->rk.dname = region_alloc_init(region, key->rk.dname,
key->rk.dname_len);
if(!ck->rk.dname)
return NULL;
dsize = packed_rrset_sizeof(data);
d = (struct packed_rrset_data*)region_alloc_init(region, data, dsize);
if(!d)
return NULL;
ck->entry.data = d;
packed_rrset_ptr_fixup(d);
/* make TTLs relative - once per rrset */
for(i=0; i<d->count + d->rrsig_count; i++)
d->rr_ttl[i] -= now;
d->ttl -= now;
return ck;
}
/** find closest NS or DNAME and returns the rrset (locked) */
static struct ub_packed_rrset_key*
find_closest_of_type(struct module_env* env, uint8_t* qname, size_t qnamelen,
uint16_t qclass, uint32_t now, uint16_t searchtype)
{
struct ub_packed_rrset_key *rrset;
uint8_t lablen;
/* snip off front part of qname until the type is found */
while(qnamelen > 0) {
if((rrset = rrset_cache_lookup(env->rrset_cache, qname,
qnamelen, searchtype, qclass, 0, now, 0)))
return rrset;
/* snip off front label */
lablen = *qname;
qname += lablen + 1;
qnamelen -= lablen + 1;
}
return NULL;
}
/** add addr to additional section */
static void
addr_to_additional(struct ub_packed_rrset_key* rrset, struct region* region,
struct dns_msg* msg, uint32_t now)
{
if((msg->rep->rrsets[msg->rep->rrset_count] =
copy_rrset(rrset, region, now))) {
msg->rep->ar_numrrsets++;
msg->rep->rrset_count++;
}
}
/** find and add A and AAAA records for nameservers in delegpt */
static int
find_add_addrs(struct module_env* env, uint16_t qclass, struct region* region,
struct delegpt* dp, uint32_t now, struct dns_msg** msg)
{
struct delegpt_ns* ns;
struct ub_packed_rrset_key* akey;
for(ns = dp->nslist; ns; ns = ns->next) {
akey = rrset_cache_lookup(env->rrset_cache, ns->name,
ns->namelen, LDNS_RR_TYPE_A, qclass, 0, now, 0);
if(akey) {
if(!delegpt_add_rrset_A(dp, region, akey)) {
lock_rw_unlock(&akey->entry.lock);
return 0;
}
if(msg)
addr_to_additional(akey, region, *msg, now);
lock_rw_unlock(&akey->entry.lock);
}
akey = rrset_cache_lookup(env->rrset_cache, ns->name,
ns->namelen, LDNS_RR_TYPE_AAAA, qclass, 0, now, 0);
if(akey) {
if(!delegpt_add_rrset_AAAA(dp, region, akey)) {
lock_rw_unlock(&akey->entry.lock);
return 0;
}
if(msg)
addr_to_additional(akey, region, *msg, now);
lock_rw_unlock(&akey->entry.lock);
}
}
return 1;
}
/** find and add A and AAAA records for missing nameservers in delegpt */
int
cache_fill_missing(struct module_env* env, uint16_t qclass,
struct region* region, struct delegpt* dp)
{
struct delegpt_ns* ns;
struct ub_packed_rrset_key* akey;
uint32_t now = time(NULL);
for(ns = dp->nslist; ns; ns = ns->next) {
if(ns->resolved)
continue;
akey = rrset_cache_lookup(env->rrset_cache, ns->name,
ns->namelen, LDNS_RR_TYPE_A, qclass, 0, now, 0);
if(akey) {
if(!delegpt_add_rrset_A(dp, region, akey)) {
lock_rw_unlock(&akey->entry.lock);
return 0;
}
log_nametypeclass(VERB_ALGO, "found in cache",
ns->name, LDNS_RR_TYPE_A, qclass);
lock_rw_unlock(&akey->entry.lock);
}
akey = rrset_cache_lookup(env->rrset_cache, ns->name,
ns->namelen, LDNS_RR_TYPE_AAAA, qclass, 0, now, 0);
if(akey) {
if(!delegpt_add_rrset_AAAA(dp, region, akey)) {
lock_rw_unlock(&akey->entry.lock);
return 0;
}
log_nametypeclass(VERB_ALGO, "found in cache",
ns->name, LDNS_RR_TYPE_AAAA, qclass);
lock_rw_unlock(&akey->entry.lock);
}
}
return 1;
}
/** find and add DS or NSEC to delegation msg */
static void
find_add_ds(struct module_env* env, struct region* region,
struct dns_msg* msg, struct delegpt* dp, uint32_t now)
{
/* Lookup the DS or NSEC at the delegation point. */
struct ub_packed_rrset_key* rrset = rrset_cache_lookup(
env->rrset_cache, dp->name, dp->namelen, LDNS_RR_TYPE_DS,
msg->qinfo.qclass, 0, now, 0);
if(!rrset) {
/* NOTE: this won't work for alternate NSEC schemes
* (opt-in, NSEC3) */
rrset = rrset_cache_lookup(env->rrset_cache, dp->name,
dp->namelen, LDNS_RR_TYPE_NSEC, msg->qinfo.qclass,
0, now, 0);
/* Note: the PACKED_RRSET_NSEC_AT_APEX flag is not used.
* since this is a referral, we need the NSEC at the parent
* side of the zone cut, not the NSEC at apex side. */
}
if(rrset) {
/* add it to auth section. This is the second rrset. */
if((msg->rep->rrsets[msg->rep->rrset_count] =
copy_rrset(rrset, region, now))) {
msg->rep->ns_numrrsets++;
msg->rep->rrset_count++;
}
lock_rw_unlock(&rrset->entry.lock);
}
}
/** create referral message with NS and query */
static struct dns_msg*
create_msg(uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
struct region* region, struct ub_packed_rrset_key* nskey,
struct packed_rrset_data* nsdata, uint32_t now)
{
struct dns_msg* msg = (struct dns_msg*)region_alloc(region,
sizeof(struct dns_msg));
if(!msg)
return NULL;
msg->qinfo.qname = region_alloc_init(region, qname, qnamelen);
if(!msg->qinfo.qname)
return NULL;
msg->qinfo.qname_len = qnamelen;
msg->qinfo.qtype = qtype;
msg->qinfo.qclass = qclass;
/* non-packed reply_info, because it needs to grow the array */
msg->rep = (struct reply_info*)region_alloc(region,
sizeof(struct reply_info)-sizeof(struct rrset_ref));
if(!msg->rep)
return NULL;
memset(msg->rep, 0,
sizeof(struct reply_info)-sizeof(struct rrset_ref));
msg->rep->flags = BIT_QR; /* with QR, no AA */
msg->rep->qdcount = 1;
/* allocate the array to as much as we could need:
* NS rrset + DS/NSEC rrset +
* A rrset for every NS RR
* AAAA rrset for every NS RR
*/
msg->rep->rrsets = (struct ub_packed_rrset_key**)region_alloc(region,
(2 + nsdata->count*2)*sizeof(struct ub_packed_rrset_key*));
if(!msg->rep->rrsets)
return NULL;
msg->rep->rrsets[0] = copy_rrset(nskey, region, now);
if(!msg->rep->rrsets[0])
return NULL;
msg->rep->ns_numrrsets++;
msg->rep->rrset_count++;
return msg;
}
struct delegpt*
dns_cache_find_delegation(struct module_env* env, uint8_t* qname,
size_t qnamelen, uint16_t qtype, uint16_t qclass,
struct region* region, struct dns_msg** msg)
{
/* try to find closest NS rrset */
struct ub_packed_rrset_key* nskey;
struct packed_rrset_data* nsdata;
struct delegpt* dp;
uint32_t now = (uint32_t)time(NULL);
nskey = find_closest_of_type(env, qname, qnamelen, qclass, now,
LDNS_RR_TYPE_NS);
if(!nskey) /* hope the caller has hints to prime or something */
return NULL;
nsdata = (struct packed_rrset_data*)nskey->entry.data;
/* got the NS key, create delegation point */
dp = delegpt_create(region);
if(!dp || !delegpt_set_name(dp, region, nskey->rk.dname)) {
lock_rw_unlock(&nskey->entry.lock);
log_err("find_delegation: out of memory");
return NULL;
}
/* create referral message */
if(msg) {
*msg = create_msg(qname, qnamelen, qtype, qclass, region,
nskey, nsdata, now);
if(!*msg) {
lock_rw_unlock(&nskey->entry.lock);
log_err("find_delegation: out of memory");
return NULL;
}
}
if(!delegpt_rrset_add_ns(dp, region, nskey))
log_err("find_delegation: addns out of memory");
lock_rw_unlock(&nskey->entry.lock); /* first unlock before next lookup*/
/* find and add DS/NSEC (if any) */
if(msg)
find_add_ds(env, region, *msg, dp, now);
/* find and add A entries */
if(!find_add_addrs(env, qclass, region, dp, now, msg))
log_err("find_delegation: addrs out of memory");
log_info("dns_cache_find_delegation returns delegpt");
delegpt_log(dp);
return dp;
}
/** allocate dns_msg from query_info and reply_info */
static struct dns_msg*
gen_dns_msg(struct region* region, struct query_info* q, size_t num)
{
struct dns_msg* msg = (struct dns_msg*)region_alloc(region,
sizeof(struct dns_msg));
if(!msg)
return NULL;
memcpy(&msg->qinfo, q, sizeof(struct query_info));
msg->qinfo.qname = region_alloc_init(region, q->qname, q->qname_len);
if(!msg->qinfo.qname)
return NULL;
/* allocate replyinfo struct and rrset key array separately */
msg->rep = (struct reply_info*)region_alloc(region,
sizeof(struct reply_info) - sizeof(struct rrset_ref));
if(!msg->rep)
return NULL;
msg->rep->rrsets = (struct ub_packed_rrset_key**)region_alloc(region,
num * sizeof(struct ub_packed_rrset_key*));
if(!msg->rep->rrsets)
return NULL;
return msg;
}
/** generate dns_msg from cached message */
static struct dns_msg*
tomsg(struct module_env* env, struct msgreply_entry* e, struct reply_info* r,
struct region* region, uint32_t now, struct region* scratch)
{
struct dns_msg* msg;
size_t i;
if(now > r->ttl)
return NULL;
msg = gen_dns_msg(region, &e->key, r->rrset_count);
if(!msg)
return NULL;
msg->rep->flags = r->flags;
msg->rep->qdcount = r->qdcount;
msg->rep->ttl = r->ttl;
msg->rep->an_numrrsets = r->an_numrrsets;
msg->rep->ns_numrrsets = r->ns_numrrsets;
msg->rep->ar_numrrsets = r->ar_numrrsets;
msg->rep->rrset_count = r->rrset_count;
if(!rrset_array_lock(r->ref, r->rrset_count, now))
return NULL;
for(i=0; i<msg->rep->rrset_count; i++) {
msg->rep->rrsets[i] = copy_rrset(r->rrsets[i], region, now);
if(!msg->rep->rrsets[i]) {
rrset_array_unlock(r->ref, r->rrset_count);
return NULL;
}
}
rrset_array_unlock_touch(env->rrset_cache, scratch, r->ref,
r->rrset_count);
return msg;
}
/** synthesize CNAME response from cached CNAME item */
static struct dns_msg*
cname_msg(struct ub_packed_rrset_key* rrset, struct region* region,
uint32_t now, struct query_info* q)
{
struct dns_msg* msg;
struct packed_rrset_data* d = (struct packed_rrset_data*)
rrset->entry.data;
if(now > d->ttl)
return NULL;
msg = gen_dns_msg(region, q, 1); /* only the CNAME RRset */
if(!msg)
return NULL;
msg->rep->flags = BIT_QR; /* reply, no AA, no error */
msg->rep->qdcount = 1;
msg->rep->ttl = d->ttl - now;
msg->rep->an_numrrsets = 1;
msg->rep->ns_numrrsets = 0;
msg->rep->ar_numrrsets = 0;
msg->rep->rrset_count = 1;
msg->rep->rrsets[0] = copy_rrset(rrset, region, now);
if(!msg->rep->rrsets[0]) /* copy CNAME */
return NULL;
return msg;
}
/** synthesize DNAME+CNAME response from cached DNAME item */
static struct dns_msg*
synth_dname_msg(struct ub_packed_rrset_key* rrset, struct region* region,
uint32_t now, struct query_info* q)
{
struct dns_msg* msg;
struct ub_packed_rrset_key* ck;
struct packed_rrset_data* newd, *d = (struct packed_rrset_data*)
rrset->entry.data;
uint8_t* newname, *dtarg = NULL;
size_t newlen, dtarglen;
if(now > d->ttl)
return NULL;
msg = gen_dns_msg(region, q, 2); /* DNAME + CNAME RRset */
if(!msg)
return NULL;
msg->rep->flags = BIT_QR; /* reply, no AA, no error */
msg->rep->qdcount = 1;
msg->rep->ttl = d->ttl - now;
msg->rep->an_numrrsets = 1;
msg->rep->ns_numrrsets = 0;
msg->rep->ar_numrrsets = 0;
msg->rep->rrset_count = 1;
msg->rep->rrsets[0] = copy_rrset(rrset, region, now);
if(!msg->rep->rrsets[0]) /* copy DNAME */
return NULL;
/* synth CNAME rrset */
get_cname_target(rrset, &dtarg, &dtarglen);
if(!dtarg)
return NULL;
newlen = q->qname_len + dtarglen - rrset->rk.dname_len;
if(newlen > LDNS_MAX_DOMAINLEN) {
msg->rep->flags |= LDNS_RCODE_YXDOMAIN;
return msg;
}
newname = (uint8_t*)region_alloc(region, newlen);
if(!newname)
return NULL;
/* new name is concatenation of qname front (without DNAME owner)
* and DNAME target name */
memcpy(newname, q->qname, q->qname_len-rrset->rk.dname_len);
memmove(newname+(q->qname_len-rrset->rk.dname_len), dtarg, dtarglen);
/* create rest of CNAME rrset */
ck = (struct ub_packed_rrset_key*)region_alloc(region,
sizeof(struct ub_packed_rrset_key));
if(!ck)
return NULL;
memset(&ck->entry, 0, sizeof(ck->entry));
msg->rep->rrsets[1] = ck;
ck->entry.key = ck;
ck->rk.type = htons(LDNS_RR_TYPE_CNAME);
ck->rk.rrset_class = rrset->rk.rrset_class;
ck->rk.flags = 0;
ck->rk.dname = region_alloc_init(region, q->qname, q->qname_len);
if(!ck->rk.dname)
return NULL;
ck->rk.dname_len = q->qname_len;
ck->entry.hash = rrset_key_hash(&ck->rk);
newd = (struct packed_rrset_data*)region_alloc(region,
sizeof(struct packed_rrset_data) + sizeof(size_t) +
sizeof(uint8_t*) + sizeof(uint32_t) + sizeof(uint16_t)
+ newlen);
if(!newd)
return NULL;
ck->entry.data = newd;
newd->ttl = 0; /* 0 for synthesized CNAME TTL */
newd->count = 1;
newd->rrsig_count = 0;
newd->trust = rrset_trust_ans_noAA;
newd->rr_len = (size_t*)((uint8_t*)newd +
sizeof(struct packed_rrset_data));
newd->rr_len[0] = newlen + sizeof(uint16_t);
packed_rrset_ptr_fixup(newd);
newd->rr_ttl[0] = newd->ttl;
msg->rep->ttl = newd->ttl;
ldns_write_uint16(newd->rr_data[0], newlen);
memmove(newd->rr_data[0] + sizeof(uint16_t), newname, newlen);
msg->rep->an_numrrsets ++;
msg->rep->rrset_count ++;
return msg;
}
struct dns_msg*
dns_cache_lookup(struct module_env* env,
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
struct region* region, struct region* scratch)
{
struct lruhash_entry* e;
struct query_info k;
hashvalue_t h;
uint32_t now = (uint32_t)time(NULL);
struct ub_packed_rrset_key* rrset;
/* lookup first, this has both NXdomains and ANSWER responses */
k.qname = qname;
k.qname_len = qnamelen;
k.qtype = qtype;
k.qclass = qclass;
h = query_info_hash(&k);
e = slabhash_lookup(env->msg_cache, h, &k, 0);
if(e) {
struct msgreply_entry* key = (struct msgreply_entry*)e->key;
struct reply_info* data = (struct reply_info*)e->data;
struct dns_msg* msg = tomsg(env, key, data, region, now,
scratch);
if(msg) {
lock_rw_unlock(&e->lock);
return msg;
}
/* could be msg==NULL; due to TTL or not all rrsets available */
lock_rw_unlock(&e->lock);
}
/* see if a DNAME exists. Checked for first, to enforce that DNAMEs
* are more important, the CNAME is resynthesized and thus
* consistent with the DNAME */
if( (rrset=find_closest_of_type(env, qname, qnamelen, qclass, now,
LDNS_RR_TYPE_DNAME))) {
/* synthesize a DNAME+CNAME message based on this */
struct dns_msg* msg = synth_dname_msg(rrset, region, now, &k);
if(msg) {
lock_rw_unlock(&rrset->entry.lock);
return msg;
}
lock_rw_unlock(&rrset->entry.lock);
}
/* see if we have CNAME for this domain */
if( (rrset=rrset_cache_lookup(env->rrset_cache, qname, qnamelen,
LDNS_RR_TYPE_CNAME, qclass, 0, now, 0))) {
struct dns_msg* msg = cname_msg(rrset, region, now, &k);
if(msg) {
lock_rw_unlock(&rrset->entry.lock);
return msg;
}
lock_rw_unlock(&rrset->entry.lock);
}
/* construct DS, DNSKEY messages from rrset cache. TODO */
return NULL;
}
-123
View File
@@ -1,123 +0,0 @@
/*
* services/cache/dns.h - Cache services for DNS using msg and rrset caches.
*
* 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 the DNS cache.
*/
#ifndef SERVICES_CACHE_DNS_H
#define SERVICES_CACHE_DNS_H
#include "util/storage/lruhash.h"
#include "util/data/msgreply.h"
struct module_env;
struct query_info;
struct reply_info;
struct region;
struct delegpt;
/**
* Region allocated message reply
*/
struct dns_msg {
/** query info */
struct query_info qinfo;
/** reply info - ptr to packed repinfo structure */
struct reply_info *rep;
};
/**
* Store message in the cache. Stores in message cache and rrset cache.
* Both qinfo and rep should be malloced and are put in the cache.
* They should not be used after this call, as they are then in shared cache.
* Does not return errors, they are logged and only lead to less cache.
*
* @param env: module environment with the DNS cache.
* @param qinfo: query info
* @param hash: hash over qinfo.
* @param rep: reply info, together with qinfo makes up the message.
* Adjusts the reply info TTLs to absolute time.
*/
void dns_cache_store_msg(struct module_env* env, struct query_info* qinfo,
hashvalue_t hash, struct reply_info* rep);
/**
* Find a delegation from the cache.
* @param env: module environment with the DNS cache.
* @param qname: query name.
* @param qnamelen: length of qname.
* @param qtype: query type.
* @param qclass: query class.
* @param region: where to allocate result delegation.
* @param msg: if not NULL, delegation message is returned here, synthesized
* from the cache.
* @return new delegation or NULL on error or if not found in cache.
*/
struct delegpt* dns_cache_find_delegation(struct module_env* env,
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
struct region* region, struct dns_msg** msg);
/**
* Find cached message
* @param env: module environment with the DNS cache.
* @param qname: query name.
* @param qnamelen: length of qname.
* @param qtype: query type.
* @param qclass: query class.
* @param region: where to allocate result.
* @param scratch: where to allocate temporary data.
* @return new response message (alloced in region, rrsets do not have IDs).
* or NULL on error or if not found in cache.
* TTLs are made relative to the current time.
*/
struct dns_msg* dns_cache_lookup(struct module_env* env,
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
struct region* region, struct region* scratch);
/**
* find and add A and AAAA records for missing nameservers in delegpt
* @param env: module environment with rrset cache
* @param qclass: which class to look in.
* @param region: where to store new dp info.
* @param dp: delegation point to fill missing entries.
* @return false on alloc failure.
*/
int cache_fill_missing(struct module_env* env, uint16_t qclass,
struct region* region, struct delegpt* dp);
/** Find covering DNAME */
#endif /* SERVICES_CACHE_DNS_H */
-488
View File
@@ -1,488 +0,0 @@
/*
* services/cache/infra.c - infrastructure cache, server rtt and capabilities
*
* 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 the infrastructure cache.
*/
#include "config.h"
#include "services/cache/infra.h"
#include "util/storage/slabhash.h"
#include "util/storage/lookup3.h"
#include "util/data/dname.h"
#include "util/log.h"
#include "util/net_help.h"
#include "util/config_file.h"
/** calculate size for the hashtable, does not count size of lameness,
* so the hashtable is a fixed number of items */
static size_t
infra_host_sizefunc(void* ATTR_UNUSED(k), void* ATTR_UNUSED(d))
{
return sizeof(struct infra_host_key) + sizeof(struct infra_host_data);
}
/** compare two addresses, returns -1, 0, or +1 */
static int
infra_host_compfunc(void* key1, void* key2)
{
struct infra_host_key* k1 = (struct infra_host_key*)key1;
struct infra_host_key* k2 = (struct infra_host_key*)key2;
return sockaddr_cmp(&k1->addr, k1->addrlen, &k2->addr, k2->addrlen);
}
/** delete key, and destroy the lock */
static void
infra_host_delkeyfunc(void* k, void* ATTR_UNUSED(arg), int il)
{
struct infra_host_key* key = (struct infra_host_key*)k;
if(!key)
return;
if(il) { lock_rw_unlock(&key->entry.lock); }
lock_rw_destroy(&key->entry.lock);
free(key);
}
/** delete data and destroy the lameness hashtable */
static void
infra_host_deldatafunc(void* d, void* ATTR_UNUSED(arg))
{
struct infra_host_data* data = (struct infra_host_data*)d;
lruhash_delete(data->lameness);
free(data);
}
struct infra_cache*
infra_create(struct config_file* cfg)
{
struct infra_cache* infra = (struct infra_cache*)calloc(1,
sizeof(struct infra_cache));
/* the size of the lameness tables are not counted */
size_t maxmem = cfg->infra_cache_numhosts *
(sizeof(struct infra_host_key)+sizeof(struct infra_host_data));
infra->hosts = slabhash_create(cfg->infra_cache_slabs,
INFRA_HOST_STARTSIZE, maxmem, &infra_host_sizefunc,
&infra_host_compfunc, &infra_host_delkeyfunc,
&infra_host_deldatafunc, NULL);
if(!infra->hosts) {
free(infra);
return NULL;
}
infra->host_ttl = cfg->host_ttl;
infra->lame_ttl = cfg->lame_ttl;
infra->max_lame = cfg->infra_cache_numlame;
return infra;
}
void
infra_delete(struct infra_cache* infra)
{
if(!infra)
return;
slabhash_delete(infra->hosts);
free(infra);
}
struct infra_cache*
infra_adjust(struct infra_cache* infra, struct config_file* cfg)
{
size_t maxmem;
if(!infra)
return infra_create(cfg);
infra->host_ttl = cfg->host_ttl;
infra->lame_ttl = cfg->lame_ttl;
infra->max_lame = cfg->infra_cache_numlame;
maxmem = cfg->infra_cache_numhosts *
(sizeof(struct infra_host_key)+sizeof(struct infra_host_data));
if(maxmem != slabhash_get_size(infra->hosts) ||
cfg->infra_cache_slabs != infra->hosts->size) {
infra_delete(infra);
infra = infra_create(cfg);
}
return infra;
}
/** calculate the hash value for a host key */
static hashvalue_t
hash_addr(struct sockaddr_storage* addr, socklen_t addrlen)
{
hashvalue_t h = 0xab;
h = hashlittle(&addrlen, sizeof(addrlen), h);
h = hashlittle(addr, addrlen, h);
return h;
}
/** lookup version that does not check host ttl (you check it) */
static struct lruhash_entry*
infra_lookup_host_nottl(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen, int wr)
{
struct infra_host_key k;
k.addrlen = addrlen;
memcpy(&k.addr, addr, addrlen);
k.entry.hash = hash_addr(addr, addrlen);
k.entry.key = (void*)&k;
k.entry.data = NULL;
return slabhash_lookup(infra->hosts, k.entry.hash, &k, wr);
}
struct infra_host_data*
infra_lookup_host(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen, int wr,
time_t timenow, struct infra_host_key** key)
{
struct infra_host_data* data;
struct lruhash_entry* e = infra_lookup_host_nottl(infra, addr,
addrlen, wr);
*key = NULL;
if(!e)
return NULL;
/* check TTL */
data = (struct infra_host_data*)e->data;
if(data->ttl < timenow) {
lock_rw_unlock(&e->lock);
return NULL;
}
*key = (struct infra_host_key*)e->key;
return data;
}
/**
* Create and init a new entry for a host
* @param infra: infra structure with config parameters.
* @param addr: host address.
* @param addrlen: length of addr.
* @param tm: time now.
* @return: the new entry or NULL on malloc failure.
*/
static struct lruhash_entry*
new_host_entry(struct infra_cache* infra, struct sockaddr_storage* addr,
socklen_t addrlen, time_t tm)
{
struct infra_host_data* data;
struct infra_host_key* key = (struct infra_host_key*)malloc(
sizeof(struct infra_host_key));
if(!key)
return NULL;
data = (struct infra_host_data*)malloc(
sizeof(struct infra_host_data));
if(!data) {
free(key);
return NULL;
}
lock_rw_init(&key->entry.lock);
key->entry.hash = hash_addr(addr, addrlen);
key->entry.key = (void*)key;
key->entry.data = (void*)data;
key->addrlen = addrlen;
memcpy(&key->addr, addr, addrlen);
data->ttl = tm + infra->host_ttl;
data->lameness = NULL;
data->edns_version = 0;
rtt_init(&data->rtt);
return &key->entry;
}
int
infra_host(struct infra_cache* infra, struct sockaddr_storage* addr,
socklen_t addrlen, time_t timenow, int* edns_vs, int* to)
{
struct lruhash_entry* e = infra_lookup_host_nottl(infra, addr,
addrlen, 0);
struct infra_host_data* data;
if(e && ((struct infra_host_data*)e->data)->ttl < timenow) {
/* it expired, try to reuse existing entry */
lock_rw_unlock(&e->lock);
e = infra_lookup_host_nottl(infra, addr, addrlen, 1);
if(e) {
/* if its still there we have a writelock, init */
/* re-initialise */
data = (struct infra_host_data*)e->data;
data->ttl = timenow + infra->host_ttl;
rtt_init(&data->rtt);
/* do not touch lameness, it may be valid still */
data->edns_version = 0;
}
}
if(!e) {
/* insert new entry */
if(!(e = new_host_entry(infra, addr, addrlen, timenow)))
return 0;
data = (struct infra_host_data*)e->data;
*to = rtt_timeout(&data->rtt);
*edns_vs = data->edns_version;
slabhash_insert(infra->hosts, e->hash, e, data, NULL);
return 1;
}
/* use existing entry */
data = (struct infra_host_data*)e->data;
*to = rtt_timeout(&data->rtt);
*edns_vs = data->edns_version;
lock_rw_unlock(&e->lock);
return 1;
}
/** hash lameness key */
static hashvalue_t
hash_lameness(uint8_t* name, size_t namelen)
{
return hashlittle(name, namelen, 0xab);
}
int
infra_lookup_lame(struct infra_host_data* host,
uint8_t* name, size_t namelen, time_t timenow)
{
struct lruhash_entry* e;
struct infra_lame_key k;
struct infra_lame_data *d;
if(!host->lameness)
return 0;
k.entry.hash = hash_lameness(name, namelen);
k.zonename = name;
k.namelen = namelen;
k.entry.key = (void*)&k;
k.entry.data = NULL;
e = lruhash_lookup(host->lameness, k.entry.hash, &k, 0);
if(!e)
return 0;
d = (struct infra_lame_data*)e->data;
if(d->ttl < timenow) {
lock_rw_unlock(&e->lock);
return 0;
}
lock_rw_unlock(&e->lock);
return 1;
}
/** calculate size, which is fixed, zonename does not count so that
* a fixed number of items is stored */
static size_t
infra_lame_sizefunc(void* ATTR_UNUSED(k), void* ATTR_UNUSED(d))
{
return sizeof(struct infra_lame_key)+sizeof(struct infra_lame_data);
}
/** compare zone names, returns -1, 0, +1 */
static int
infra_lame_compfunc(void* key1, void* key2)
{
struct infra_lame_key* k1 = (struct infra_lame_key*)key1;
struct infra_lame_key* k2 = (struct infra_lame_key*)key2;
if(k1->namelen != k2->namelen) {
if(k1->namelen < k2->namelen)
return -1;
return 1;
}
return query_dname_compare(k1->zonename, k2->zonename);
}
/** free key, lock and zonename */
static void
infra_lame_delkeyfunc(void* k, void* ATTR_UNUSED(arg), int il)
{
struct infra_lame_key* key = (struct infra_lame_key*)k;
if(!key)
return;
if(il) { lock_rw_unlock(&key->entry.lock); }
lock_rw_destroy(&key->entry.lock);
free(key->zonename);
free(key);
}
/** free the lameness data */
static void
infra_lame_deldatafunc(void* d, void* ATTR_UNUSED(arg))
{
if(!d)
return;
free(d);
}
int
infra_set_lame(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen,
uint8_t* name, size_t namelen, time_t timenow)
{
struct infra_host_data* data;
struct lruhash_entry* e;
int needtoinsert = 0;
struct infra_lame_key* k;
struct infra_lame_data* d;
/* allocate at start, easier cleanup (no locks held) */
k = (struct infra_lame_key*)malloc(sizeof(*k));
if(!k) {
log_err("set_lame: malloc failure");
return 0;
}
d = (struct infra_lame_data*)malloc(sizeof(*d));
if(!d) {
free(k);
log_err("set_lame: malloc failure");
return 0;
}
k->zonename = memdup(name, namelen);
if(!k->zonename) {
free(d);
free(k);
log_err("set_lame: malloc failure");
return 0;
}
lock_rw_init(&k->entry.lock);
k->entry.hash = hash_lameness(name, namelen);
k->entry.key = (void*)k;
k->entry.data = (void*)d;
d->ttl = timenow + infra->lame_ttl;
k->namelen = namelen;
e = infra_lookup_host_nottl(infra, addr, addrlen, 1);
if(!e) {
/* insert it */
if(!(e = new_host_entry(infra, addr, addrlen, timenow))) {
free(k->zonename);
free(k);
free(d);
log_err("set_lame: malloc failure");
return 0;
}
needtoinsert = 1;
}
/* got an entry, now set the zone lame */
data = (struct infra_host_data*)e->data;
if(!data->lameness) {
/* create hash table if not there already */
data->lameness = lruhash_create(INFRA_LAME_STARTSIZE,
infra->max_lame*(sizeof(struct infra_lame_key)+
sizeof(struct infra_lame_data)), infra_lame_sizefunc,
infra_lame_compfunc, infra_lame_delkeyfunc,
infra_lame_deldatafunc, NULL);
if(!data->lameness) {
log_err("set_lame: malloc failure");
if(needtoinsert) slabhash_insert(infra->hosts,
e->hash, e, e->data, NULL);
else { lock_rw_unlock(&e->lock); }
free(k->zonename);
free(k);
free(d);
return 0;
}
}
/* inserts new entry, or updates TTL of older entry */
lruhash_insert(data->lameness, k->entry.hash, &k->entry, d, NULL);
if(needtoinsert)
slabhash_insert(infra->hosts, e->hash, e, e->data, NULL);
else { lock_rw_unlock(&e->lock); }
return 1;
}
int
infra_rtt_update(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen,
int roundtrip, time_t timenow)
{
struct lruhash_entry* e = infra_lookup_host_nottl(infra, addr,
addrlen, 1);
struct infra_host_data* data;
int needtoinsert = 0;
if(!e) {
if(!(e = new_host_entry(infra, addr, addrlen, timenow)))
return 0;
needtoinsert = 1;
}
/* have an entry, update the rtt, and the ttl */
data = (struct infra_host_data*)e->data;
data->ttl = timenow + infra->host_ttl;
if(roundtrip == -1)
rtt_lost(&data->rtt);
else rtt_update(&data->rtt, roundtrip);
if(needtoinsert)
slabhash_insert(infra->hosts, e->hash, e, e->data, NULL);
else { lock_rw_unlock(&e->lock); }
return 1;
}
int
infra_edns_update(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen,
int edns_version, time_t timenow)
{
struct lruhash_entry* e = infra_lookup_host_nottl(infra, addr,
addrlen, 1);
struct infra_host_data* data;
int needtoinsert = 0;
if(!e) {
if(!(e = new_host_entry(infra, addr, addrlen, timenow)))
return 0;
needtoinsert = 1;
}
/* have an entry, update the rtt, and the ttl */
data = (struct infra_host_data*)e->data;
data->ttl = timenow + infra->host_ttl;
data->edns_version = edns_version;
if(needtoinsert)
slabhash_insert(infra->hosts, e->hash, e, e->data, NULL);
else { lock_rw_unlock(&e->lock); }
return 1;
}
int
infra_get_lame_rtt(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen,
uint8_t* name, size_t namelen, int* lame, int* rtt, time_t timenow)
{
struct infra_host_data* host;
struct lruhash_entry* e = infra_lookup_host_nottl(infra, addr,
addrlen, 0);
if(!e)
return 0;
host = (struct infra_host_data*)e->data;
*rtt = rtt_unclamped(&host->rtt);
/* check lameness first, if so, ttl on host does not matter anymore */
if(infra_lookup_lame(host, name, namelen, timenow)) {
lock_rw_unlock(&e->lock);
*lame = 1;
return 1;
}
*lame = 0;
if(timenow > host->ttl) {
lock_rw_unlock(&e->lock);
return 0;
}
lock_rw_unlock(&e->lock);
return 1;
}
-238
View File
@@ -1,238 +0,0 @@
/*
* services/cache/infra.h - infrastructure cache, server rtt and capabilities
*
* 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 the infrastructure cache.
*/
#ifndef SERVICES_CACHE_INFRA_H
#define SERVICES_CACHE_INFRA_H
#include "util/storage/lruhash.h"
#include "util/rtt.h"
struct slabhash;
struct config_file;
/**
* Host information kept for every server.
*/
struct infra_host_key {
/** the host address. */
struct sockaddr_storage addr;
/** length of addr. */
socklen_t addrlen;
/** hash table entry, data of type infra_host_data. */
struct lruhash_entry entry;
};
/**
* Host information encompasses host capabilities and retransmission timeouts.
*/
struct infra_host_data {
/** TTL value for this entry. absolute time. */
time_t ttl;
/** round trip times for timeout calculation */
struct rtt_info rtt;
/** Names of the zones that are lame. NULL=no lame zones. */
struct lruhash* lameness;
/** edns version that the host supports, -1 means no EDNS */
int edns_version;
};
/**
* Lameness information, per host, per zone.
*/
struct infra_lame_key {
/** key is zone name in wireformat */
uint8_t* zonename;
/** length of zonename */
size_t namelen;
/** lruhash entry */
struct lruhash_entry entry;
};
/**
* Lameness information. Expires.
* This host is lame because it is in the cache.
*/
struct infra_lame_data {
/** TTL of this entry. absolute time. */
time_t ttl;
};
/**
* Infra cache
*/
struct infra_cache {
/** The hash table with hosts */
struct slabhash* hosts;
/** TTL value for host information, in seconds */
int host_ttl;
/** TTL for Lameness information, in seconds */
int lame_ttl;
/** infra lame cache max memory per host, for this many entries */
size_t max_lame;
};
/** infra host cache default hash lookup size */
#define INFRA_HOST_STARTSIZE 32
/** infra lame cache default hash lookup size */
#define INFRA_LAME_STARTSIZE 2
/**
* Create infra cache.
* @param cfg: config parameters or NULL for defaults.
* @return: new infra cache, or NULL.
*/
struct infra_cache* infra_create(struct config_file* cfg);
/**
* Delete infra cache.
* @param infra: infrastructure cache to delete.
*/
void infra_delete(struct infra_cache* infra);
/**
* Adjust infra cache to use updated configuration settings.
* This may clean the cache. Operates a bit like realloc.
* There may be no threading or use by other threads.
* @param infra: existing cache. If NULL a new infra cache is returned.
* @param cfg: config options.
* @return the new infra cache pointer or NULL on error.
*/
struct infra_cache* infra_adjust(struct infra_cache* infra,
struct config_file* cfg);
/**
* Lookup host data
* @param infra: infrastructure cache.
* @param addr: host address.
* @param addrlen: length of addr.
* @param wr: set to true to get a writelock on the entry.
* @param timenow: what time it is now.
* @param key: the key for the host, returned so caller can unlock when done.
* @return: host data or NULL if not found or expired.
*/
struct infra_host_data* infra_lookup_host(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen, int wr,
time_t timenow, struct infra_host_key** key);
/**
* Find host information to send a packet. Creates new entry if not found.
* Lameness is empty. EDNS is 0 (try with first), and rtt is returned for
* the first message to it.
* @param infra: infrastructure cache.
* @param addr: host address.
* @param addrlen: length of addr.
* @param timenow: what time it is now.
* @param edns_vs: edns version it supports, is returned.
* @param to: timeout to use, is returned.
* @return: 0 on error.
*/
int infra_host(struct infra_cache* infra, struct sockaddr_storage* addr,
socklen_t addrlen, time_t timenow, int* edns_vs, int* to);
/**
* Check for lameness of this server for a particular zone.
* You must have a lock on the host structure.
* @param host: infrastructure cache data for the host. Caller holds lock.
* @param name: domain name of zone apex.
* @param namelen: length of domain name.
* @param timenow: what time it is now.
* @return: 0 if not lame or unknown or timed out, true if lame.
*/
int infra_lookup_lame(struct infra_host_data* host,
uint8_t* name, size_t namelen, time_t timenow);
/**
* Set a host to be lame for the given zone.
* @param infra: infrastructure cache.
* @param addr: host address.
* @param addrlen: length of addr.
* @param name: domain name of zone apex.
* @param namelen: length of domain name.
* @param timenow: what time it is now.
* @return: 0 on error.
*/
int infra_set_lame(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen,
uint8_t* name, size_t namelen, time_t timenow);
/**
* Update rtt information for the host.
* @param infra: infrastructure cache.
* @param addr: host address.
* @param addrlen: length of addr.
* @param roundtrip: estimate of roundtrip time in milliseconds or -1 for
* timeout.
* @param timenow: what time it is now.
* @return: 0 on error.
*/
int infra_rtt_update(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen,
int roundtrip, time_t timenow);
/**
* Update edns information for the host.
* @param infra: infrastructure cache.
* @param addr: host address.
* @param addrlen: length of addr.
* @param edns_version: the version that it publishes.
* @param timenow: what time it is now.
* @return: 0 on error.
*/
int infra_edns_update(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen,
int edns_version, time_t timenow);
/**
* Get Lameness information and average RTT if host is in the cache.
* @param infra: infrastructure cache.
* @param addr: host address.
* @param addrlen: length of addr.
* @param name: zone name.
* @param namelen: zone name length.
* @param lame: if function returns true, this returns lameness of the zone.
* @param rtt: if function returns true, this returns avg rtt of the server.
* The rtt value is unclamped and reflects recent timeouts.
* @param timenow: what time it is now.
* @return if found in cache, or false if not (or TTL bad).
*/
int infra_get_lame_rtt(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen,
uint8_t* name, size_t namelen, int* lame, int* rtt, time_t timenow);
#endif /* SERVICES_CACHE_INFRA_H */
-267
View File
@@ -1,267 +0,0 @@
/*
* services/cache/rrset.c - Resource record set cache.
*
* 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 the rrset cache.
*/
#include "config.h"
#include "services/cache/rrset.h"
#include "util/storage/slabhash.h"
#include "util/config_file.h"
#include "util/data/packed_rrset.h"
#include "util/data/msgreply.h"
#include "util/region-allocator.h"
struct rrset_cache* rrset_cache_create(struct config_file* cfg,
struct alloc_cache* alloc)
{
size_t slabs = (cfg?cfg->rrset_cache_slabs:HASH_DEFAULT_SLABS);
size_t startarray = HASH_DEFAULT_STARTARRAY;
size_t maxmem = (cfg?cfg->rrset_cache_size:HASH_DEFAULT_MAXMEM);
struct rrset_cache *r = (struct rrset_cache*)slabhash_create(slabs,
startarray, maxmem, ub_rrset_sizefunc, ub_rrset_compare,
ub_rrset_key_delete, rrset_data_delete, alloc);
return r;
}
void rrset_cache_delete(struct rrset_cache* r)
{
if(!r)
return;
slabhash_delete(&r->table);
}
struct rrset_cache* rrset_cache_adjust(struct rrset_cache *r,
struct config_file* cfg, struct alloc_cache* alloc)
{
if(!r || !cfg || cfg->rrset_cache_slabs != r->table.size ||
cfg->rrset_cache_size != slabhash_get_size(&r->table))
{
rrset_cache_delete(r);
r = rrset_cache_create(cfg, alloc);
}
return r;
}
void
rrset_cache_touch(struct rrset_cache* r, struct ub_packed_rrset_key* key,
hashvalue_t hash, rrset_id_t id)
{
struct lruhash* table = slabhash_gettable(&r->table, hash);
/*
* This leads to locking problems, deadlocks, if the caller is
* holding any other rrset lock.
* Because a lookup through the hashtable does:
* tablelock -> entrylock (for that entry caller holds)
* And this would do
* entrylock(already held) -> tablelock
* And if two threads do this, it results in deadlock.
* So, the caller must not hold entrylock.
*/
lock_quick_lock(&table->lock);
/* we have locked the hash table, the item can still be deleted.
* because it could already have been reclaimed, but not yet set id=0.
* This is because some lruhash routines have lazy deletion.
* so, we must acquire a lock on the item to verify the id != 0.
* also, with hash not changed, we are using the right slab.
*/
lock_rw_rdlock(&key->entry.lock);
if(key->id == id && key->entry.hash == hash) {
lru_touch(table, &key->entry);
}
lock_rw_unlock(&key->entry.lock);
lock_quick_unlock(&table->lock);
}
/** see if rrset needs to be updated in the cache */
static int
need_to_update_rrset(void* nd, void* cd, uint32_t timenow)
{
struct packed_rrset_data* newd = (struct packed_rrset_data*)nd;
struct packed_rrset_data* cached = (struct packed_rrset_data*)cd;
/* o if current RRset is more trustworthy - insert it */
if( newd->trust > cached->trust )
return 1;
/* o item in cache has expired */
if( cached->ttl < timenow )
return 1;
/* o same trust, but different in data - insert it */
if( newd->trust == cached->trust &&
!rrsetdata_equal(newd, cached))
return 1;
/* o see if TTL is better than TTL in cache. */
/* if so, see if rrset+rdata is the same */
/* if so, update TTL in cache, even if trust is worse. */
if( newd->ttl > cached->ttl &&
rrsetdata_equal(newd, cached)) {
/* since all else is the same, use the best trust value */
if(newd->trust < cached->trust)
newd->trust = cached->trust;
return 1;
}
return 0;
}
int
rrset_cache_update(struct rrset_cache* r, struct rrset_ref* ref,
struct alloc_cache* alloc, uint32_t timenow)
{
struct lruhash_entry* e;
struct ub_packed_rrset_key* k = ref->key;
hashvalue_t h = k->entry.hash;
/* looks up item with a readlock - no editing! */
if((e=slabhash_lookup(&r->table, h, k, 0)) != 0) {
/* return id and key as they will be used in the cache
* since the lruhash_insert, if item already exists, deallocs
* the passed key in favor of the already stored key.
* because of the small gap (see below) this key ptr and id
* may prove later to be already deleted, which is no problem
* as it only makes a cache miss.
*/
ref->key = (struct ub_packed_rrset_key*)e->key;
ref->id = ref->key->id;
if(!need_to_update_rrset(k->entry.data, e->data, timenow)) {
/* cache is superior, return that value */
lock_rw_unlock(&e->lock);
ub_packed_rrset_parsedelete(k, alloc);
return 1;
}
lock_rw_unlock(&e->lock);
/* Go on and insert the passed item.
* small gap here, where entry is not locked.
* possibly entry is updated with something else.
* we then overwrite that with our data.
* this is just too bad, its cache anyway. */
/* use insert to update entry to manage lruhash
* cache size values nicely. */
}
slabhash_insert(&r->table, h, &k->entry, k->entry.data, alloc);
if(e)
return 1;
return 0;
}
struct ub_packed_rrset_key*
rrset_cache_lookup(struct rrset_cache* r, uint8_t* qname, size_t qnamelen,
uint16_t qtype, uint16_t qclass, uint32_t flags, uint32_t timenow,
int wr)
{
struct lruhash_entry* e;
struct ub_packed_rrset_key key;
key.entry.key = &key;
key.entry.data = NULL;
key.rk.dname = qname;
key.rk.dname_len = qnamelen;
key.rk.type = htons(qtype);
key.rk.rrset_class = htons(qclass);
key.rk.flags = flags;
key.entry.hash = rrset_key_hash(&key.rk);
if((e = slabhash_lookup(&r->table, key.entry.hash, &key, wr))) {
/* check TTL */
struct packed_rrset_data* data =
(struct packed_rrset_data*)e->data;
if(timenow > data->ttl) {
lock_rw_unlock(&e->lock);
return NULL;
}
/* we're done */
return (struct ub_packed_rrset_key*)e->key;
}
return NULL;
}
int
rrset_array_lock(struct rrset_ref* ref, size_t count, uint32_t timenow)
{
size_t i;
for(i=0; i<count; i++) {
if(i>0 && ref[i].key == ref[i-1].key)
continue; /* only lock items once */
lock_rw_rdlock(&ref[i].key->entry.lock);
if(ref[i].id != ref[i].key->id || timenow >
((struct packed_rrset_data*)(ref[i].key->entry.data))
->ttl) {
/* failure! rollback our readlocks */
rrset_array_unlock(ref, i+1);
return 0;
}
}
return 1;
}
void
rrset_array_unlock(struct rrset_ref* ref, size_t count)
{
size_t i;
for(i=0; i<count; i++) {
if(i>0 && ref[i].key == ref[i-1].key)
continue; /* only unlock items once */
lock_rw_unlock(&ref[i].key->entry.lock);
}
}
void
rrset_array_unlock_touch(struct rrset_cache* r, struct region* scratch,
struct rrset_ref* ref, size_t count)
{
hashvalue_t* h;
size_t i;
if(!(h = (hashvalue_t*)region_alloc(scratch,
sizeof(hashvalue_t)*count)))
log_warn("rrset LRU: memory allocation failed");
else /* store hash values */
for(i=0; i<count; i++)
h[i] = ref[i].key->entry.hash;
/* unlock */
for(i=0; i<count; i++) {
if(i>0 && ref[i].key == ref[i-1].key)
continue; /* only unlock items once */
lock_rw_unlock(&ref[i].key->entry.lock);
}
if(h) {
/* LRU touch, with no rrset locks held */
for(i=0; i<count; i++) {
if(i>0 && ref[i].key == ref[i-1].key)
continue; /* only touch items once */
rrset_cache_touch(r, ref[i].key, h[i], ref[i].id);
}
}
}
-187
View File
@@ -1,187 +0,0 @@
/*
* services/cache/rrset.h - Resource record set cache.
*
* 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 the rrset cache.
*/
#ifndef SERVICES_CACHE_RRSET_H
#define SERVICES_CACHE_RRSET_H
#include "util/storage/lruhash.h"
#include "util/storage/slabhash.h"
#include "util/data/packed_rrset.h"
struct config_file;
struct alloc_cache;
struct rrset_ref;
struct region;
/**
* The rrset cache
* Thin wrapper around hashtable, like a typedef.
*/
struct rrset_cache {
/** uses partitioned hash table */
struct slabhash table;
};
/**
* Create rrset cache
* @param cfg: config settings or NULL for defaults.
* @param alloc: initial default rrset key allocation.
* @return: NULL on error.
*/
struct rrset_cache* rrset_cache_create(struct config_file* cfg,
struct alloc_cache* alloc);
/**
* Delete rrset cache
* @param r: rrset cache to delete.
*/
void rrset_cache_delete(struct rrset_cache* r);
/**
* Adjust settings of the cache to settings from the config file.
* May purge the cache. May recreate the cache.
* There may be no threading or use by other threads.
* @param r: rrset cache to adjust (like realloc).
* @param cfg: config settings or NULL for defaults.
* @param alloc: initial default rrset key allocation.
* @return 0 on error, or new rrset cache pointer on success.
*/
struct rrset_cache* rrset_cache_adjust(struct rrset_cache* r,
struct config_file* cfg, struct alloc_cache* alloc);
/**
* Touch rrset, with given pointer and id.
* Caller may not hold a lock on ANY rrset, this could give deadlock.
*
* This routine is faster than a hashtable lookup:
* o no bin_lock is acquired.
* o no walk through the bin-overflow-list.
* o no comparison of the entry key to find it.
*
* @param r: rrset cache.
* @param key: rrset key. Marked recently used (if it was not deleted
* before the lock is acquired, in that case nothing happens).
* @param hash: hash value of the item. Please read it from the key when
* you have it locked. Used to find slab from slabhash.
* @param id: used to check that the item is unchanged and not deleted.
*/
void rrset_cache_touch(struct rrset_cache* r, struct ub_packed_rrset_key* key,
hashvalue_t hash, rrset_id_t id);
/**
* Update an rrset in the rrset cache. Stores the information for later use.
* Will lookup if the rrset is in the cache and perform an update if necessary.
* If the item was present, and superior, references are returned to that.
* The passed item is then deallocated with rrset_parsedelete.
*
* A superior rrset is:
* o rrset with better trust value.
* o same trust value, different rdata, newly passed rrset is inserted.
* If rdata is the same, TTL in the cache is updated.
*
* @param r: the rrset cache.
* @param ref: reference (ptr and id) to the rrset. Pass reference setup for
* the new rrset. The reference may be changed if the cached rrset is
* superior.
* Before calling the rrset is presumed newly allocated and changeable.
* Afer calling you do not hold a lock, and the rrset is inserted in
* the hashtable so you need a lock to change it.
* @param alloc: how to allocate (and deallocate) the special rrset key.
* @param timenow: current time (to see if ttl in cache is expired).
* @return: true if the passed reference is updated, false if it is unchanged.
*/
int rrset_cache_update(struct rrset_cache* r, struct rrset_ref* ref,
struct alloc_cache* alloc, uint32_t timenow);
/**
* Lookup rrset. You obtain read/write lock. You must unlock before lookup
* anything of else.
* @param r: the rrset cache.
* @param qname: name of rrset to lookup.
* @param qnamelen: length of name of rrset to lookup.
* @param qtype: type of rrset to lookup (host order).
* @param qclass: class of rrset to lookup (host order).
* @param flags: rrset flags, or 0.
* @param timenow: used to compare with TTL.
* @param wr: set true to get writelock.
* @return packed rrset key pointer. Remember to unlock the key.entry.lock.
* or NULL if could not be found or it was timed out.
*/
struct ub_packed_rrset_key* rrset_cache_lookup(struct rrset_cache* r,
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
uint32_t flags, uint32_t timenow, int wr);
/**
* Obtain readlock on a (sorted) list of rrset references.
* Checks TTLs and IDs of the rrsets and rollbacks locking if not Ok.
* @param ref: array of rrset references (key pointer and ID value).
* duplicate references are allowed and handled.
* @param count: size of array.
* @param timenow: used to compare with TTL.
* @return true on success, false on a failure, which can be that some
* RRsets have timed out, or that they do not exist any more, the
* RRsets have been purged from the cache.
* If true, you hold readlocks on all the ref items.
*/
int rrset_array_lock(struct rrset_ref* ref, size_t count, uint32_t timenow);
/**
* Unlock array (sorted) of rrset references.
* @param ref: array of rrset references (key pointer and ID value).
* duplicate references are allowed and handled.
* @param count: size of array.
*/
void rrset_array_unlock(struct rrset_ref* ref, size_t count);
/**
* Unlock array (sorted) of rrset references and at the same time
* touch LRU on the rrsets. It needs the scratch region for temporary
* storage as it uses the initial locks to obtain hash values.
* @param r: the rrset cache. In this cache LRU is updated.
* @param scratch: region for temporary storage of hash values.
* if memory allocation fails, the lru touch fails silently,
* but locks are released. memory errors are logged.
* @param ref: array of rrset references (key pointer and ID value).
* duplicate references are allowed and handled.
* @param count: size of array.
*/
void rrset_array_unlock_touch(struct rrset_cache* r, struct region* scratch,
struct rrset_ref* ref, size_t count);
#endif /* SERVICES_CACHE_RRSET_H */
+3 -14
View File
@@ -54,6 +54,8 @@
/** number of queued TCP connections for listen() */
#define TCP_BACKLOG 5
/** number of simultaneous open TCP connections for queries */
#define TCP_COUNT 10
/**
* Debug print of the getaddrinfo returned address.
@@ -308,7 +310,7 @@ listen_create(struct comm_base* base, struct listen_port* ports,
cp = comm_point_create_udp(base, ports->fd,
front->udp_buff, cb, cb_arg);
else cp = comm_point_create_tcp(base, ports->fd,
TCP_ACCEPT_COUNT, bufsize, cb, cb_arg);
TCP_COUNT, bufsize, cb, cb_arg);
if(!cp) {
log_err("can't create commpoint");
listen_delete(front);
@@ -452,16 +454,3 @@ void listening_ports_free(struct listen_port* list)
list = nx;
}
}
size_t listen_get_mem(struct listen_dnsport* listen)
{
size_t s = sizeof(*listen) + sizeof(*listen->base) +
sizeof(*listen->udp_buff) +
ldns_buffer_capacity(listen->udp_buff);
struct listen_list* p;
for(p = listen->cps; p; p = p->next) {
s += sizeof(*p);
s += comm_point_get_mem(p->com);
}
return s;
}
-11
View File
@@ -48,9 +48,6 @@ struct listen_list;
struct addrinfo;
struct config_file;
/** number of simultaneous open TCP connections for queries */
#define TCP_ACCEPT_COUNT 10
/**
* Listening for queries structure.
* Contains list of query-listen sockets.
@@ -141,17 +138,9 @@ void listen_resume(struct listen_dnsport* listen);
/**
* delete the listening structure
* @param listen: listening structure.
*/
void listen_delete(struct listen_dnsport* listen);
/**
* get memory size used by the listening structs
* @param listen: listening structure.
* @return: size in bytes.
*/
size_t listen_get_mem(struct listen_dnsport* listen);
/**
* Create and bind nonblocking UDP socket
* @param addr: address info ready to make socket.
-615
View File
@@ -1,615 +0,0 @@
/*
* services/mesh.c - deal with mesh of query states and handle events for that.
*
* Copyright (c) 2007, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file
*
* This file contains functions to assist in dealing with a mesh of
* query states. This mesh is supposed to be thread-specific.
* It consists of query states (per qname, qtype, qclass) and connections
* between query states and the super and subquery states, and replies to
* send back to clients.
*/
#include "config.h"
#include "services/mesh.h"
#include "services/outbound_list.h"
#include "util/log.h"
#include "util/net_help.h"
#include "util/module.h"
#include "util/region-allocator.h"
#include "util/data/msgencode.h"
#include "util/timehist.h"
/** compare two mesh_states */
static int
mesh_state_compare(const void* ap, const void* bp)
{
struct mesh_state* a = (struct mesh_state*)ap;
struct mesh_state* b = (struct mesh_state*)bp;
if(a->is_priming && !b->is_priming)
return -1;
if(!a->is_priming && b->is_priming)
return 1;
if((a->s.query_flags&BIT_RD) && !(b->s.query_flags&BIT_RD))
return -1;
if(!(a->s.query_flags&BIT_RD) && (b->s.query_flags&BIT_RD))
return 1;
return query_info_compare(&a->s.qinfo, &b->s.qinfo);
}
/** compare two mesh references */
static int
mesh_state_ref_compare(const void* ap, const void* bp)
{
struct mesh_state_ref* a = (struct mesh_state_ref*)ap;
struct mesh_state_ref* b = (struct mesh_state_ref*)bp;
return mesh_state_compare(a->s, b->s);
}
struct mesh_area*
mesh_create(int num_modules, struct module_func_block** modfunc,
struct module_env* env)
{
struct mesh_area* mesh = calloc(1, sizeof(struct mesh_area));
if(!mesh) {
log_err("mesh area alloc: out of memory");
return NULL;
}
mesh->histogram = timehist_setup();
if(!mesh->histogram) {
free(mesh);
log_err("mesh area alloc: out of memory");
return NULL;
}
mesh->num_modules = num_modules;
mesh->modfunc = modfunc;
mesh->env = env;
rbtree_init(&mesh->run, &mesh_state_compare);
rbtree_init(&mesh->all, &mesh_state_compare);
mesh->num_reply_addrs = 0;
mesh->num_reply_states = 0;
mesh->num_detached_states = 0;
return mesh;
}
/** help mesh delete delete mesh states */
static void
mesh_delete_helper(rbnode_t* n, void* ATTR_UNUSED(arg))
{
struct mesh_state* mstate = (struct mesh_state*)n->key;
mesh_state_cleanup(mstate);
}
void
mesh_delete(struct mesh_area* mesh)
{
if(!mesh)
return;
/* free all query states */
traverse_postorder(&mesh->all, &mesh_delete_helper, NULL);
timehist_delete(mesh->histogram);
free(mesh);
}
void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
uint16_t qflags, struct edns_data* edns, struct comm_reply* rep,
uint16_t qid)
{
struct mesh_state* s = mesh_area_find(mesh, qinfo, qflags, 0);
int was_detached = 0;
int was_noreply = 0;
int added = 0;
/* see if it already exists, if not, create one */
if(!s) {
struct rbnode_t* n;
s = mesh_state_create(mesh->env,qinfo, qflags, 0);
if(!s) {
log_err("mesh_state_create: out of memory; SERVFAIL");
error_encode(rep->c->buffer, LDNS_RCODE_SERVFAIL,
qinfo, qid, qflags, edns);
comm_point_send_reply(rep);
return;
}
n = rbtree_insert(&mesh->all, &s->node);
log_assert(n != NULL);
/* set detached (it is now) */
mesh->num_detached_states++;
added = 1;
}
if(!s->reply_list && s->super_set.count == 0)
was_detached = 1;
if(!s->reply_list)
was_noreply = 1;
/* add reply to s */
if(!mesh_state_add_reply(s, edns, rep, qid, qflags)) {
log_err("mesh_new_client: out of memory; SERVFAIL");
error_encode(rep->c->buffer, LDNS_RCODE_SERVFAIL,
qinfo, qid, qflags, edns);
comm_point_send_reply(rep);
if(added)
mesh_state_delete(&s->s);
return;
}
/* update statistics */
if(was_detached) {
log_assert(mesh->num_detached_states > 0);
mesh->num_detached_states--;
}
if(was_noreply) {
mesh->num_reply_states ++;
}
mesh->num_reply_addrs++;
if(added)
mesh_run(mesh, s, module_event_new, NULL);
}
void mesh_report_reply(struct mesh_area* mesh, struct outbound_entry* e,
int is_ok, struct comm_reply* reply)
{
e->qstate->reply = reply;
mesh_run(mesh, e->qstate->mesh_info,
is_ok?module_event_reply:module_event_noreply, e);
}
struct mesh_state*
mesh_state_create(struct module_env* env, struct query_info* qinfo,
uint16_t qflags, int prime)
{
region_type* region = region_create(malloc, free);
struct mesh_state* mstate;
int i;
if(!region)
return NULL;
mstate = (struct mesh_state*)region_alloc(region,
sizeof(struct mesh_state));
if(!mstate) {
region_destroy(region);
return NULL;
}
memset(mstate, 0, sizeof(*mstate));
mstate->node = *RBTREE_NULL;
mstate->run_node = *RBTREE_NULL;
mstate->node.key = mstate;
mstate->run_node.key = mstate;
mstate->debug_flags = 0;
mstate->is_priming = prime;
mstate->reply_list = NULL;
rbtree_init(&mstate->super_set, &mesh_state_ref_compare);
rbtree_init(&mstate->sub_set, &mesh_state_ref_compare);
/* init module qstate */
mstate->s.qinfo.qtype = qinfo->qtype;
mstate->s.qinfo.qclass = qinfo->qclass;
mstate->s.qinfo.qname_len = qinfo->qname_len;
mstate->s.qinfo.qname = region_alloc_init(region, qinfo->qname,
qinfo->qname_len);
if(!mstate->s.qinfo.qname) {
region_destroy(region);
return NULL;
}
/* remove all weird bits from qflags */
mstate->s.query_flags = (qflags & BIT_RD);
mstate->s.reply = NULL;
mstate->s.region = region;
mstate->s.curmod = 0;
mstate->s.env = env;
mstate->s.mesh_info = mstate;
/* init modules */
for(i=0; i<env->mesh->num_modules; i++) {
mstate->s.minfo[i] = NULL;
mstate->s.ext_state[i] = module_state_initial;
}
return mstate;
}
void
mesh_state_cleanup(struct mesh_state* mstate)
{
struct mesh_area* mesh;
int i;
if(!mstate)
return;
/* de-init modules */
mesh = mstate->s.env->mesh;
for(i=0; i<mesh->num_modules; i++) {
(*mesh->modfunc[i]->clear)(&mstate->s, i);
mstate->s.minfo[i] = NULL;
mstate->s.ext_state[i] = module_finished;
}
region_destroy(mstate->s.region);
}
void
mesh_state_delete(struct module_qstate* qstate)
{
struct mesh_area* mesh;
struct mesh_state_ref* super, ref;
struct mesh_state* mstate;
if(!qstate)
return;
mstate = qstate->mesh_info;
mesh = mstate->s.env->mesh;
mesh_detach_subs(&mstate->s);
if(!mstate->reply_list && mstate->super_set.count == 0) {
log_assert(mesh->num_detached_states > 0);
mesh->num_detached_states--;
}
if(mstate->reply_list) {
log_assert(mesh->num_reply_states > 0);
mesh->num_reply_states--;
}
ref.node.key = &ref;
ref.s = mstate;
RBTREE_FOR(super, struct mesh_state_ref*, &mstate->super_set) {
(void)rbtree_delete(&super->s->sub_set, &ref);
}
(void)rbtree_delete(&mesh->run, mstate);
(void)rbtree_delete(&mesh->all, mstate);
mesh_state_cleanup(mstate);
}
void mesh_detach_subs(struct module_qstate* qstate)
{
struct mesh_area* mesh = qstate->env->mesh;
struct mesh_state_ref* ref, lookup;
struct rbnode_t* n;
lookup.node.key = &lookup;
lookup.s = qstate->mesh_info;
RBTREE_FOR(ref, struct mesh_state_ref*, &qstate->mesh_info->sub_set) {
n = rbtree_delete(&ref->s->super_set, &lookup);
log_assert(n != NULL); /* must have been present */
if(!ref->s->reply_list && ref->s->super_set.count == 0) {
mesh->num_detached_states++;
log_assert(mesh->num_detached_states +
mesh->num_reply_states <= mesh->all.count);
}
}
rbtree_init(&qstate->mesh_info->sub_set, &mesh_state_ref_compare);
}
int mesh_attach_sub(struct module_qstate* qstate, struct query_info* qinfo,
uint16_t qflags, int prime, struct module_qstate** newq)
{
/* find it, if not, create it */
struct mesh_area* mesh = qstate->env->mesh;
struct mesh_state* sub = mesh_area_find(mesh, qinfo, qflags, prime);
if(!sub) {
struct rbnode_t* n;
/* create a new one */
sub = mesh_state_create(qstate->env, qinfo, qflags, prime);
if(!sub) {
log_err("mesh_attach_sub: out of memory");
return 0;
}
n = rbtree_insert(&mesh->all, &sub->node);
log_assert(n != NULL);
/* set detached (it is now) */
mesh->num_detached_states++;
/* set new query state to run */
n = rbtree_insert(&mesh->run, &sub->run_node);
log_assert(n != NULL);
*newq = &sub->s;
} else
*newq = NULL;
if(!mesh_state_attachment(qstate->mesh_info, sub))
return 0;
if(!sub->reply_list && sub->super_set.count == 1) {
/* it used to be detached, before this one got added */
log_assert(mesh->num_detached_states > 0);
mesh->num_detached_states--;
}
/* *newq will be run when inited after the current module stops */
return 1;
}
int mesh_state_attachment(struct mesh_state* super, struct mesh_state* sub)
{
struct rbnode_t* n;
struct mesh_state_ref* subref; /* points to sub, inserted in super */
struct mesh_state_ref* superref; /* points to super, inserted in sub */
if( !(subref = region_alloc(super->s.region,
sizeof(struct mesh_state_ref))) ||
!(superref = region_alloc(sub->s.region,
sizeof(struct mesh_state_ref))) ) {
log_err("mesh_state_attachment: out of memory");
return 0;
}
superref->node.key = superref;
superref->s = super;
subref->node.key = subref;
subref->s = sub;
n = rbtree_insert(&sub->super_set, &superref->node);
log_assert(n != NULL);
n = rbtree_insert(&super->sub_set, &subref->node);
log_assert(n != NULL);
return 1;
}
/** subtract timers and the values do not overflow or become negative */
static void
timeval_subtract(struct timeval* d, struct timeval* end, struct timeval* start)
{
#ifndef S_SPLINT_S
d->tv_sec = end->tv_sec - start->tv_sec;
while(end->tv_usec < start->tv_usec) {
end->tv_usec += 1000000;
d->tv_sec--;
}
d->tv_usec = end->tv_usec - start->tv_usec;
#endif
}
/** add timers and the values do not overflow or become negative */
static void
timeval_add(struct timeval* d, struct timeval* add)
{
#ifndef S_SPLINT_S
d->tv_sec += add->tv_sec;
d->tv_usec += add->tv_usec;
while(d->tv_usec > 1000000 ) {
d->tv_usec -= 1000000;
d->tv_sec++;
}
#endif
}
/** divide sum of timers to get average */
static void
timeval_divide(struct timeval* avg, struct timeval* sum, size_t d)
{
#ifndef S_SPLINT_S
size_t leftover;
if(d == 0) {
avg->tv_sec = 0;
avg->tv_usec = 0;
return;
}
avg->tv_sec = sum->tv_sec / d;
avg->tv_usec = sum->tv_usec / d;
/* handle fraction from seconds divide */
leftover = sum->tv_sec - avg->tv_sec*d;
avg->tv_usec += (leftover*1000000)/d;
#endif
}
/**
* Send reply to mesh reply entry
* @param m: mesh state to send it for.
* @param rcode: if not 0, error code.
* @param rep: reply to send (or NULL if rcode is set).
* @param r: reply entry
*/
static void
mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
struct mesh_reply* r)
{
struct timeval end_time;
/* send the reply */
if(rcode) {
error_encode(r->query_reply.c->buffer, rcode, &m->s.qinfo,
r->qid, r->qflags, &r->edns);
comm_point_send_reply(&r->query_reply);
} else {
size_t udp_size = r->edns.udp_size;
r->edns.edns_version = EDNS_ADVERTISED_VERSION;
r->edns.udp_size = EDNS_ADVERTISED_SIZE;
r->edns.ext_rcode = 0;
r->edns.bits &= EDNS_DO;
if(!reply_info_answer_encode(&m->s.qinfo, rep, r->qid,
r->qflags, r->query_reply.c->buffer, 0, 1,
m->s.env->scratch, udp_size, &r->edns,
(int)(r->edns.bits & EDNS_DO)))
{
error_encode(r->query_reply.c->buffer,
LDNS_RCODE_SERVFAIL, &m->s.qinfo, r->qid,
r->qflags, &r->edns);
}
comm_point_send_reply(&r->query_reply);
}
/* account */
m->s.env->mesh->num_reply_addrs--;
if(gettimeofday(&end_time, NULL) < 0) {
log_err("gettimeofday: %s", strerror(errno));
return;
} else {
struct timeval duration;
timeval_subtract(&duration, &end_time, &r->start_time);
verbose(VERB_ALGO, "query took %d.%6.6d sec",
(int)duration.tv_sec, (int)duration.tv_usec);
m->s.env->mesh->replies_sent++;
timeval_add(&m->s.env->mesh->replies_sum_wait, &duration);
timehist_insert(m->s.env->mesh->histogram, &duration);
}
}
void mesh_query_done(struct module_qstate* qstate, int rcode,
struct reply_info* rep)
{
struct mesh_state* m = qstate->mesh_info;
struct mesh_reply* r;
log_assert(!(m->debug_flags&1)); /* not twice! */
m->debug_flags |= 1;
for(r = m->reply_list; r; r = r->next) {
mesh_send_reply(m, rcode, rep, r);
}
}
void mesh_walk_supers(struct module_qstate* qstate, int id,
void (*cb)(struct module_qstate*, int, struct module_qstate*))
{
struct mesh_state* m = qstate->mesh_info;
struct mesh_area* mesh = m->s.env->mesh;
struct mesh_state_ref* ref;
log_assert(!(m->debug_flags&2)); /* not twice! */
m->debug_flags |= 2;
RBTREE_FOR(ref, struct mesh_state_ref*, &qstate->mesh_info->super_set)
{
/* make super runnable */
(void)rbtree_insert(&mesh->run, &ref->s->run_node);
/* callback */
(*cb)(qstate, id, &ref->s->s);
}
}
struct mesh_state* mesh_area_find(struct mesh_area* mesh,
struct query_info* qinfo, uint16_t qflags, int prime)
{
struct mesh_state key;
struct mesh_state* result;
key.node.key = &key;
key.is_priming = prime;
key.s.qinfo = *qinfo;
key.s.query_flags = qflags;
result = (struct mesh_state*)rbtree_search(&mesh->all, &key);
return result;
}
int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns,
struct comm_reply* rep, uint16_t qid, uint16_t qflags)
{
struct mesh_reply* r = region_alloc(s->s.region,
sizeof(struct mesh_reply));
if(!r)
return 0;
r->query_reply = *rep;
r->edns = *edns;
r->qid = qid;
r->qflags = qflags;
if(gettimeofday(&r->start_time, NULL) < 0) {
log_err("addrep: gettimeofday: %s", strerror(errno));
memset(&r->start_time, 0, sizeof(r->start_time));
}
r->next = s->reply_list;
s->reply_list = r;
return 1;
}
void mesh_run(struct mesh_area* mesh, struct mesh_state* mstate,
enum module_ev ev, struct outbound_entry* e)
{
enum module_ext_state s;
verbose(VERB_ALGO, "mesh_run: start");
while(mstate) {
/* run the module */
(*mesh->modfunc[mstate->s.curmod]->operate)
(&mstate->s, ev, mstate->s.curmod, e);
/* examine results */
mstate->s.reply = NULL;
region_free_all(mstate->s.env->scratch);
s = mstate->s.ext_state[mstate->s.curmod];
verbose(VERB_ALGO, "mesh_run: %s module exit state is %s",
mesh->modfunc[mstate->s.curmod]->name, strextstate(s));
if(s == module_error || s == module_finished) {
/* must have called _done and _supers */
log_assert(mstate->debug_flags == 3);
mesh_state_delete(&mstate->s);
}
/* run more modules */
ev = module_event_pass;
e = NULL;
if(mesh->run.count > 0) {
/* pop random element off the runnable tree */
mstate = (struct mesh_state*)mesh->run.root->key;
(void)rbtree_delete(&mesh->run, mstate);
} else mstate = NULL;
}
if(verbosity >= VERB_ALGO)
mesh_stats(mesh, "mesh_run: end");
}
void
mesh_stats(struct mesh_area* mesh, const char* str)
{
log_info("%s %u states (%u with reply, %u detached), "
"%u waiting replies", str, (unsigned)mesh->all.count,
(unsigned)mesh->num_reply_states,
(unsigned)mesh->num_detached_states,
(unsigned)mesh->num_reply_addrs);
if(mesh->replies_sent > 0) {
struct timeval avg;
timeval_divide(&avg, &mesh->replies_sum_wait,
mesh->replies_sent);
log_info("sent %u replies, with average wait "
"of %d.%6.6d sec", (unsigned)mesh->replies_sent,
(int)avg.tv_sec, (int)avg.tv_usec);
log_info("histogram of reply wait times");
timehist_log(mesh->histogram);
}
}
size_t
mesh_get_mem(struct mesh_area* mesh)
{
struct mesh_state* m;
size_t s = sizeof(*mesh) + sizeof(struct timehist) +
sizeof(struct th_buck)*mesh->histogram->num;
RBTREE_FOR(m, struct mesh_state*, &mesh->all) {
/* all, including m itself allocated in qstate region */
s += region_get_mem(m->s.region);
}
return s;
}
/** helper recursive rbtree find routine */
static int
find_in_subsub(struct mesh_state* m, struct mesh_state* tofind)
{
struct mesh_state_ref* r;
RBTREE_FOR(r, struct mesh_state_ref*, &m->sub_set) {
if(r->s == tofind || find_in_subsub(r->s, tofind))
return 1;
}
return 0;
}
int
mesh_detect_cycle(struct module_qstate* qstate, struct query_info* qinfo)
{
struct mesh_area* mesh = qstate->env->mesh;
struct mesh_state* cyc_m = qstate->mesh_info;
struct mesh_state* dep_m = mesh_area_find(mesh, qinfo, BIT_RD, 0);
if(!dep_m)
return 0;
if(dep_m == cyc_m || find_in_subsub(dep_m, cyc_m))
return 1;
return 0;
}
-371
View File
@@ -1,371 +0,0 @@
/*
* services/mesh.h - deal with mesh of query states and handle events for that.
*
* Copyright (c) 2007, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file
*
* This file contains functions to assist in dealing with a mesh of
* query states. This mesh is supposed to be thread-specific.
* It consists of query states (per qname, qtype, qclass) and connections
* between query states and the super and subquery states, and replies to
* send back to clients.
*/
#ifndef SERVICES_MESH_H
#define SERVICES_MESH_H
#include "util/rbtree.h"
#include "util/netevent.h"
#include "util/data/msgparse.h"
#include "util/module.h"
struct mesh_state;
struct mesh_reply;
struct query_info;
struct reply_info;
struct outbound_entry;
struct timehist;
/**
* Mesh of query states
*/
struct mesh_area {
/** the number of modules */
int num_modules;
/** the module callbacks, array of num_modules length (ref only) */
struct module_func_block** modfunc;
/** environment for new states */
struct module_env* env;
/** set of runnable queries (mesh_state.run_node) */
rbtree_t run;
/** rbtree of all current queries (mesh_state.node)*/
rbtree_t all;
/** count of the total number of mesh_reply entries */
size_t num_reply_addrs;
/** count of the number of mesh_states that have mesh_replies
* Because a state can send results to multiple reply addresses,
* this number must be equal or lower than num_reply_addrs. */
size_t num_reply_states;
/** number of mesh_states that have no mesh_replies, and also
* an empty set of super-states, thus are 'toplevel' or detached
* internal opportunistic queries */
size_t num_detached_states;
/** number of replies sent */
size_t replies_sent;
/** sum of waiting times for the replies */
struct timeval replies_sum_wait;
/** histogram of time values */
struct timehist* histogram;
};
/**
* A mesh query state
* Unique per qname, qtype, qclass (from the qstate).
* And RD flag; in case a client turns it off.
* And priming queries are different from ordinary queries (because of hints).
*
* The entire structure is allocated in a region, this region is the qstate
* region. All parts (rbtree nodes etc) are also allocated in the region.
*/
struct mesh_state {
/** node in mesh_area all tree, key is this struct. Must be first. */
rbnode_t node;
/** node in mesh_area runnable tree, key is this struct */
rbnode_t run_node;
/** if this is a (stub or root) priming query (with hints) */
int is_priming;
/** the query state. Note that the qinfo and query_flags
* may not change. */
struct module_qstate s;
/** the list of replies to clients for the results */
struct mesh_reply* reply_list;
/** debug flags */
int debug_flags;
/** set of superstates (that want this state's result)
* contains struct mesh_state_ref* */
rbtree_t super_set;
/** set of substates (that this state needs to continue)
* contains struct mesh_state_ref* */
rbtree_t sub_set;
};
/**
* Rbtree reference to a mesh_state.
* Used in super_set and sub_set.
*/
struct mesh_state_ref {
/** node in rbtree for set, key is this structure */
rbnode_t node;
/** the mesh state */
struct mesh_state* s;
};
/**
* Reply to a client
*/
struct mesh_reply {
/** next in reply list */
struct mesh_reply* next;
/** the query reply destination, packet buffer and where to send. */
struct comm_reply query_reply;
/** edns data from query */
struct edns_data edns;
/** the time when request was entered */
struct timeval start_time;
/** id of query, in network byteorder. */
uint16_t qid;
/** flags of query, for reply flags */
uint16_t qflags;
};
/* ------------------- Functions for worker -------------------- */
/**
* Allocate mesh, to empty.
* @param num_modules: number of modules that are present.
* @param modfunc: array passed (alloced and deleted by caller), that has
* num_modules function callbacks for the modules.
* @param env: environment for new queries.
* @return mesh: the new mesh or NULL on error.
*/
struct mesh_area* mesh_create(int num_modules,
struct module_func_block** modfunc, struct module_env* env);
/**
* Delete mesh, and all query states and replies in it.
* @param mesh: the mesh to delete.
*/
void mesh_delete(struct mesh_area* mesh);
/**
* New query incoming from clients. Create new query state if needed, and
* add mesh_reply to it. Returns error to client on malloc failures.
* Will run the mesh area queries to process if a new query state is created.
*
* @param mesh: the mesh.
* @param qinfo: query from client.
* @param qflags: flags from client query.
* @param edns: edns data from client query.
* @param rep: where to reply to.
* @param qid: query id to reply with.
*/
void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
uint16_t qflags, struct edns_data* edns, struct comm_reply* rep,
uint16_t qid);
/**
* Handle new event from the wire. A serviced query has returned.
* The query state will be made runnable, and the mesh_area will process
* query states until processing is complete.
*
* @param mesh: the query mesh.
* @param e: outbound entry, with query state to run and reply pointer.
* @param is_ok: if true, reply is OK, otherwise a timeout happened.
* @param reply: the comm point reply info.
*/
void mesh_report_reply(struct mesh_area* mesh, struct outbound_entry* e,
int is_ok, struct comm_reply* reply);
/* ------------------- Functions for module environment --------------- */
/**
* Detach-subqueries.
* Remove all sub-query references from this query state.
* Keeps super-references of those sub-queries correct.
* Updates stat items in mesh_area structure.
* @param qstate: used to find mesh state.
*/
void mesh_detach_subs(struct module_qstate* qstate);
/**
* Attach subquery.
* Creates it if it does not exist already.
* Keeps sub and super references correct.
* Updates stat items in mesh_area structure.
* Pass if it is priming query or not.
* return:
* o if error (malloc) happened.
* o need to initialise the new state (module init; it is a new state).
* so that the next run of the query with this module is successful.
* o no init needed, attachment successful.
*
* @param qstate: the state to find mesh state, and that wants to receive
* the results from the new subquery.
* @param qinfo: what to query for (copied).
* @param qflags: what flags to use (RD flag or not).
* @param prime: if it is a (stub) priming query.
* @param newq: If the new subquery needs initialisation, it is returned,
* otherwise NULL is returned.
* @return: false on error, true if success (and init may be needed).
*/
int mesh_attach_sub(struct module_qstate* qstate, struct query_info* qinfo,
uint16_t qflags, int prime, struct module_qstate** newq);
/**
* Query state is done, send messages to reply entries.
* Encode messages using reply entry values and the querystate (with original
* qinfo), using given reply_info.
* Pass errcode != 0 if an error reply is needed.
* If no reply entries, nothing is done.
* Must be called before a module can module_finished or return module_error.
* The module must handle the super query states itself as well.
*
* @param qstate: used for original query info. And to find mesh info.
* @param rcode: if not 0 (NOERROR) an error is sent back (and rep ignored).
* @param rep: reply to encode and send back to clients.
*/
void mesh_query_done(struct module_qstate* qstate, int rcode,
struct reply_info* rep);
/**
* Get a callback for the super query states that are interested in the
* results from this query state. These can then be changed for error
* or results.
* Must be called befor a module can module_finished or return module_error.
* After finishing or module error, the super query states become runnable
* with event module_event_pass.
*
* @param qstate: the state that has results, used to find mesh state.
* @param id: module id.
* @param cb: callback function. Called as
* cb(qstate, id, super_qstate) for every super query state.
*/
void mesh_walk_supers(struct module_qstate* qstate, int id,
void (*cb)(struct module_qstate*, int, struct module_qstate*));
/**
* Delete mesh state, cleanup and also rbtrees and so on.
* Will detach from all super/subnodes.
* @param qstate: to remove.
*/
void mesh_state_delete(struct module_qstate* qstate);
/* ------------------- Functions for mesh -------------------- */
/**
* Create and initialize a new mesh state and its query state
* Does not put the mesh state into rbtrees and so on.
* @param env: module environment to set.
* @param qinfo: query info that the mesh is for.
* @param qflags: flags for query (RD flag).
* @param prime: if true, it is a priming query, set is_priming on mesh state.
* @return: new mesh state or NULL on allocation error.
*/
struct mesh_state* mesh_state_create(struct module_env* env,
struct query_info* qinfo, uint16_t qflags, int prime);
/**
* Cleanup a mesh state and its query state. Does not do rbtree or
* reference cleanup.
* @param mstate: mesh state to cleanup. Its pointer may no longer be used
* afterwards. Cleanup rbtrees before calling this function.
*/
void mesh_state_cleanup(struct mesh_state* mstate);
/**
* Find a mesh state in the mesh area. Pass relevant flags.
*
* @param mesh: the mesh area to look in.
* @param qinfo: what query
* @param qflags: if RD bit is set or not.
* @param prime: if it is a priming query.
* @return: mesh state or NULL if not found.
*/
struct mesh_state* mesh_area_find(struct mesh_area* mesh,
struct query_info* qinfo, uint16_t qflags, int prime);
/**
* Setup attachment super/sub relation between super and sub mesh state.
* The relation must not be present when calling the function.
* Does not update stat items in mesh_area.
* @param super: super state.
* @param sub: sub state.
* @return: 0 on alloc error.
*/
int mesh_state_attachment(struct mesh_state* super, struct mesh_state* sub);
/**
* Create new reply structure and attach it to a mesh state.
* Does not update stat items in mesh area.
* @param s: the mesh state.
* @param edns: edns data for reply (bufsize).
* @param rep: comm point reply info.
* @param qid: ID of reply.
* @param qflags: original query flags.
* @return: 0 on alloc error.
*/
int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns,
struct comm_reply* rep, uint16_t qid, uint16_t qflags);
/**
* Run the mesh. Run all runnable mesh states. Which can create new
* runnable mesh states. Until completion. Automatically called by
* mesh_report_reply and mesh_new_client as needed.
* @param mesh: mesh area.
* @param mstate: first mesh state to run.
* @param ev: event the mstate. Others get event_pass.
* @param e: if a reply, its outbound entry.
*/
void mesh_run(struct mesh_area* mesh, struct mesh_state* mstate,
enum module_ev ev, struct outbound_entry* e);
/**
* Print some stats about the mesh to the log.
* @param mesh: the mesh to print it for.
* @param str: descriptive string to go with it.
*/
void mesh_stats(struct mesh_area* mesh, const char* str);
/**
* Calculate memory size in use by mesh and all queries inside it.
* @param mesh: the mesh to examine.
* @return size in bytes.
*/
size_t mesh_get_mem(struct mesh_area* mesh);
/**
* Find cycle; see if the given mesh is in the targets sub, or sub-sub, ...
* trees.
* @param qstate: given mesh querystate.
* @param qinfo: query info for dependency.
* @return true if the name,type,class exists and the given qstate mesh exists
* as a dependency of that name. Thus if qstate becomes dependent on
* name,type,class then a cycle is created.
*/
int mesh_detect_cycle(struct module_qstate* qstate, struct query_info* qinfo);
#endif /* SERVICES_MESH_H */
-88
View File
@@ -1,88 +0,0 @@
/*
* services/outbound_list.c - keep list of outbound serviced queries.
*
* 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 help a module keep track of the
* queries it has outstanding to authoritative servers.
*/
#include "config.h"
#include "services/outbound_list.h"
#include "services/outside_network.h"
void
outbound_list_init(struct outbound_list* list)
{
list->first = NULL;
}
void
outbound_list_clear(struct outbound_list* list)
{
struct outbound_entry *p, *np;
p = list->first;
while(p) {
np = p->next;
outnet_serviced_query_stop(p->qsent, p);
free(p);
p = np;
}
outbound_list_init(list);
}
void
outbound_list_insert(struct outbound_list* list, struct outbound_entry* e)
{
if(list->first)
list->first->prev = e;
e->next = list->first;
e->prev = NULL;
list->first = e;
}
void
outbound_list_remove(struct outbound_list* list, struct outbound_entry* e)
{
if(!e)
return;
outnet_serviced_query_stop(e->qsent, e);
if(e->next)
e->next->prev = e->prev;
if(e->prev)
e->prev->next = e->next;
else list->first = e->next;
free(e);
}
-105
View File
@@ -1,105 +0,0 @@
/*
* services/outbound_list.h - keep list of outbound serviced queries.
*
* 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 help a module keep track of the
* queries it has outstanding to authoritative servers.
*/
#ifndef SERVICES_OUTBOUND_LIST_H
#define SERVICES_OUTBOUND_LIST_H
struct outbound_entry;
struct serviced_query;
struct module_qstate;
/**
* The outbound list. This structure is part of the module specific query
* state.
*/
struct outbound_list {
/** The linked list of outbound query entries. */
struct outbound_entry* first;
};
/**
* Outbound list entry. A serviced query sent by a module processing the
* query from the qstate. Double linked list to aid removal.
*/
struct outbound_entry {
/** next in list */
struct outbound_entry* next;
/** prev in list */
struct outbound_entry* prev;
/** The query that was sent out */
struct serviced_query* qsent;
/** the module query state that sent it */
struct module_qstate* qstate;
};
/**
* Init the user allocated outbound list structure
* @param list: the list structure.
*/
void outbound_list_init(struct outbound_list* list);
/**
* Clear the user owner outbound list structure.
* Deletes serviced queries.
* @param list: the list structure. It is cleared, but the list struct itself
* is callers responsability to delete.
*/
void outbound_list_clear(struct outbound_list* list);
/**
* Insert new entry into the list. Caller must allocate the entry with malloc.
* qstate and qsent are set by caller.
* @param list: the list to add to.
* @param e: entry to add, it is only half initialised at call start, fully
* initialised at call end.
*/
void outbound_list_insert(struct outbound_list* list,
struct outbound_entry* e);
/**
* Remove an entry from the list, and deletes it.
* Deletes serviced query in the entry.
* @param list: the list to remove from.
* @param e: the entry to remove.
*/
void outbound_list_remove(struct outbound_list* list,
struct outbound_entry* e);
#endif /* SERVICES_OUTBOUND_LIST_H */
File diff suppressed because it is too large Load Diff
+12 -227
View File
@@ -49,9 +49,6 @@
struct pending;
struct pending_timeout;
struct ub_randstate;
struct pending_tcp;
struct waiting_tcp;
struct infra_cache;
/**
* Send queries to outside servers and wait for answers from servers.
@@ -65,51 +62,23 @@ struct outside_network {
datagram at any time. */
ldns_buffer* udp_buff;
/** buffer for storage. (buffer for incoming connections, since
* either an event to outside or incoming happens, but not both
* This buffer is used during callbacks, so that the datagram
* that just arrived does not collide with new datagrams sent out. */
ldns_buffer* udp_second;
/**
* Array of udp comm point* that are used to listen to pending events.
* Each is on a different port. This is for ip4 ports.
*/
struct comm_point** udp4_ports;
struct comm_point **udp4_ports;
/** number of udp4 ports */
size_t num_udp4;
/**
* The opened ip6 ports.
*/
struct comm_point** udp6_ports;
struct comm_point **udp6_ports;
/** number of udp6 ports */
size_t num_udp6;
/** pending udp answers. sorted by id, addr */
rbtree_t* pending;
/** serviced queries, sorted by qbuf, addr, dnssec */
rbtree_t* serviced;
/** host cache, pointer but not owned by outnet. */
struct infra_cache* infra;
/** where to get random numbers */
struct ub_randstate* rnd;
/**
* Array of tcp pending used for outgoing TCP connections.
* Each can be used to establish a TCP connection with a server.
* The file descriptors are -1 if they are free, and need to be
* opened for the tcp connection. Can be used for ip4 and ip6.
*/
struct pending_tcp **tcp_conns;
/** number of tcp communication points. */
size_t num_tcp;
/** list of tcp comm points that are free for use */
struct pending_tcp* tcp_free;
/** list of tcp queries waiting for a buffer */
struct waiting_tcp* tcp_wait_first;
/** last of waiting query list */
struct waiting_tcp* tcp_wait_last;
/** pending answers. sorted by id, addr */
rbtree_t *pending;
};
/**
@@ -136,113 +105,6 @@ struct pending {
struct outside_network* outnet;
};
/**
* Pending TCP query to server.
*/
struct pending_tcp {
/** next in list of free tcp comm points, or NULL. */
struct pending_tcp* next_free;
/** the ID for the query; checked in reply */
uint16_t id;
/** tcp comm point it was sent on (and reply must come back on). */
struct comm_point* c;
/** the query being serviced, NULL if the pending_tcp is unused. */
struct waiting_tcp* query;
};
/**
* Query waiting for TCP buffer.
*/
struct waiting_tcp {
/**
* next in waiting list.
* if pkt==0, this points to the pending_tcp structure.
*/
struct waiting_tcp* next_waiting;
/** timeout event; timer keeps running whether the query is
* waiting for a buffer or the tcp reply is pending */
struct comm_timer* timer;
/** the outside network it is part of */
struct outside_network* outnet;
/** remote address. */
struct sockaddr_storage addr;
/** length of addr field in use. */
socklen_t addrlen;
/**
* The query itself, the query packet to send.
* allocated after the waiting_tcp structure.
* set to NULL when the query is serviced and it part of pending_tcp.
* if this is NULL, the next_waiting points to the pending_tcp.
*/
uint8_t* pkt;
/** length of query packet. */
size_t pkt_len;
/** callback for the timeout, error or reply to the message */
comm_point_callback_t* cb;
/** callback user argument */
void* cb_arg;
};
/**
* Callback to party interested in serviced query results.
*/
struct service_callback {
/** next in callback list */
struct service_callback* next;
/** callback function */
comm_point_callback_t* cb;
/** user argument for callback function */
void* cb_arg;
};
/**
* Query service record.
* Contains query and destination. UDP, TCP, EDNS are all tried.
* complete with retries and timeouts. A number of interested parties can
* receive a callback.
*/
struct serviced_query {
/** The rbtree node, key is this record */
rbnode_t node;
/** The query that needs to be answered. Starts with flags u16,
* then qdcount, ..., including qname, qtype, qclass. Does not include
* EDNS record. */
uint8_t* qbuf;
/** length of qbuf. */
size_t qbuflen;
/** If an EDNS section is included, the DO bit will be turned on. */
int dnssec;
/** where to send it */
struct sockaddr_storage addr;
/** length of addr field in use. */
socklen_t addrlen;
/** current status */
enum serviced_query_status {
/** initial status */
serviced_initial,
/** UDP with EDNS sent */
serviced_query_UDP_EDNS,
/** UDP without EDNS sent */
serviced_query_UDP,
/** TCP with EDNS sent */
serviced_query_TCP_EDNS,
/** TCP without EDNS sent */
serviced_query_TCP
} status;
/** true if serviced_query is scheduled for deletion already */
int to_be_deleted;
/** number of UDP retries */
int retry;
/** time last UDP was sent */
struct timeval last_sent_time;
/** outside network this is part of */
struct outside_network* outnet;
/** list of interested parties that need callback on results. */
struct service_callback* cblist;
/** the UDP or TCP query that is pending, see status which */
void* pending;
};
/**
* Create outside_network structure with N udp ports.
* @param base: the communication base to use for event handling.
@@ -255,15 +117,11 @@ struct serviced_query {
* @param do_ip6: service IP6.
* @param port_base: if -1 system assigns ports, otherwise try to get
* the ports numbered from this starting number.
* @param num_tcp: number of outgoing tcp buffers to preallocate.
* @param infra: pointer to infra cached used for serviced queries.
* @param rnd: stored to create random numbers for serviced queries.
* @return: the new structure (with no pending answers) or NULL on error.
*/
struct outside_network* outside_network_create(struct comm_base* base,
size_t bufsize, size_t num_ports, char** ifs, int num_ifs,
int do_ip4, int do_ip6, int port_base, size_t num_tcp,
struct infra_cache* infra, struct ub_randstate* rnd);
int do_ip4, int do_ip6, int port_base);
/**
* Delete outside_network structure.
@@ -271,16 +129,6 @@ struct outside_network* outside_network_create(struct comm_base* base,
*/
void outside_network_delete(struct outside_network* outnet);
/**
* Set secondary UDP buffer. Make sure it is not used during outside network
* callbacks. Such as the incoming network UDP buffer. Caller responsible
* for deletion.
* @param outnet: outside network.
* @param buf: buffer to use as secondary buffer.
*/
void outside_network_set_secondary_buffer(struct outside_network* outnet,
ldns_buffer* buf);
/**
* Send UDP query, create pending answer.
* Changes the ID for the query to be random and unique for that destination.
@@ -288,36 +136,17 @@ void outside_network_set_secondary_buffer(struct outside_network* outnet,
* @param packet: wireformat query to send to destination.
* @param addr: address to send to.
* @param addrlen: length of addr.
* @param timeout: in milliseconds from now.
* @param timeout: in seconds from now.
* @param callback: function to call on error, timeout or reply.
* The routine does not return an error, instead it calls the callback,
* with an error code if an error happens.
* @param callback_arg: user argument for callback function.
* @param rnd: random state for generating ID and port.
* @return: NULL on error for malloc or socket. Else the pending query object.
*/
struct pending* pending_udp_query(struct outside_network* outnet,
ldns_buffer* packet, struct sockaddr_storage* addr,
socklen_t addrlen, int timeout, comm_point_callback_t* callback,
void* callback_arg, struct ub_randstate* rnd);
/**
* Send TCP query. May wait for TCP buffer. Selects ID to be random, and
* checks id.
* @param outnet: provides the event handling.
* @param packet: wireformat query to send to destination. copied from.
* @param addr: address to send to.
* @param addrlen: length of addr.
* @param timeout: in seconds from now.
* Timer starts running now. Timer may expire if all buffers are used,
* without any query been sent to the server yet.
* @param callback: function to call on error, timeout or reply.
* @param callback_arg: user argument for callback function.
* @param rnd: random state for generating ID.
* @return: false on error for malloc or socket. Else the pending TCP object.
*/
struct waiting_tcp* pending_tcp_query(struct outside_network* outnet,
ldns_buffer* packet, struct sockaddr_storage* addr,
socklen_t addrlen, int timeout, comm_point_callback_t* callback,
void* callback_arg, struct ub_randstate* rnd);
void pending_udp_query(struct outside_network* outnet, ldns_buffer* packet,
struct sockaddr_storage* addr, socklen_t addrlen, int timeout,
comm_point_callback_t* callback, void* callback_arg,
struct ub_randstate* rnd);
/**
* Delete pending answer.
@@ -327,48 +156,4 @@ struct waiting_tcp* pending_tcp_query(struct outside_network* outnet,
*/
void pending_delete(struct outside_network* outnet, struct pending* p);
/**
* Perform a serviced query to the authoritative servers.
* Duplicate efforts are detected, and EDNS, TCP and UDP retry is performed.
* @param outnet: outside network, with rbtree of serviced queries.
* @param qname: what qname to query.
* @param qnamelen: length of qname in octets including 0 root label.
* @param qtype: rrset type to query (host format)
* @param qclass: query class. (host format)
* @param flags: flags u16 (host format), includes opcode, CD bit.
* @param dnssec: if set, DO bit is set in EDNS queries.
* @param callback: callback function.
* @param callback_arg: user argument to callback function.
* @param addr: to which server to send the query.
* @param addrlen: length of addr.
* @param buff: scratch buffer to create query contents in. Empty on exit.
* @param arg_compare: function to compare callback args, return true if
* identical. It is given the callback_arg and args that are listed.
* @return 0 on error, or pointer to serviced query that is used to answer
* this serviced query may be shared with other callbacks as well.
*/
struct serviced_query* outnet_serviced_query(struct outside_network* outnet,
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
uint16_t flags, int dnssec, struct sockaddr_storage* addr,
socklen_t addrlen, comm_point_callback_t* callback,
void* callback_arg, ldns_buffer* buff,
int (*arg_compare)(void*,void*));
/**
* Remove service query callback.
* If that leads to zero callbacks, the query is completely cancelled.
* @param sq: serviced query to adjust.
* @param cb_arg: callback argument of callback that needs removal.
* same as the callback_arg to outnet_serviced_query().
*/
void outnet_serviced_query_stop(struct serviced_query* sq, void* cb_arg);
/**
* Get memory size in use by outside network.
* Counts buffers and outstanding query (serviced queries) malloced data.
* @param outnet: outside network structure.
* @return size in bytes.
*/
size_t outnet_get_mem(struct outside_network* outnet);
#endif /* OUTSIDE_NETWORK_H */
+10 -105
View File
@@ -52,7 +52,7 @@
#ifdef USE_THREAD_DEBUG
/** How long to wait before lock attempt is a failure. */
#define CHECK_LOCK_TIMEOUT 30 /* seconds */
#define CHECK_LOCK_TIMEOUT 15 /* seconds */
/** How long to wait before join attempt is a failure. */
#define CHECK_JOIN_TIMEOUT 120 /* seconds */
@@ -63,13 +63,10 @@ static ub_thread_key_t thr_debug_key;
/** the list of threads, so all threads can be examined. NULL if unused. */
static struct thr_check* thread_infos[THRDEBUG_MAX_THREADS];
/** do we check locking order */
int check_locking_order = 0;
int check_locking_order = 1;
/** the pid of this runset, reasonably unique. */
static pid_t check_lock_pid;
/** print all possible debug info on the state of the system */
static void total_debug_info();
/** print pretty lock error and exit */
static void lock_error(struct checked_lock* lock,
const char* func, const char* file, int line, const char* err)
@@ -85,8 +82,6 @@ static void lock_error(struct checked_lock* lock,
(lock->type==check_lock_mutex)?"mutex": (
(lock->type==check_lock_spinlock)?"spinlock": (
(lock->type==check_lock_rwlock)?"rwlock": "badtype")), err);
log_err("complete status display:");
total_debug_info();
fatal_exit("bailing out");
}
@@ -194,7 +189,7 @@ prot_check(struct checked_lock* lock,
}
}
/** Copy protected memory region */
/** Copy protected memory region. */
static void
prot_store(struct checked_lock* lock)
{
@@ -205,7 +200,7 @@ prot_store(struct checked_lock* lock)
}
}
/** write lock trace info to file, while you hold those locks */
/** write lock trace info to file, while you hold those locks. */
static void
ordercheck_locklock(struct thr_check* thr, struct checked_lock* lock)
{
@@ -225,7 +220,7 @@ ordercheck_locklock(struct thr_check* thr, struct checked_lock* lock)
log_err("fwrite: %s", strerror(errno));
}
/** write ordercheck lock creation details to file */
/** write ordercheck lock creation details to file. */
static void
ordercheck_lockcreate(struct thr_check* thr, struct checked_lock* lock)
{
@@ -365,7 +360,7 @@ checklock_destroy(enum check_lock_type type, struct checked_lock** lock,
free(e);
}
/** finish acquiring lock, shared between _(rd|wr||)lock() routines */
/** finish acquiring lock, shared between _(rd|wr||)lock() routines. */
static void
finish_acquire_lock(struct thr_check* thr, struct checked_lock* lock,
const char* func, const char* file, int line)
@@ -516,7 +511,6 @@ static int timed_spinlock(void* arg, struct timespec* to)
#ifndef S_SPLINT_S
if(time(NULL) >= to->tv_sec)
return ETIMEDOUT;
usleep(1000); /* in 1/1000000s of a second */
#endif
}
return err;
@@ -612,7 +606,7 @@ checklock_unlock(enum check_lock_type type, struct checked_lock* lock,
}
}
/** open order info debug file, thr->num must be valid */
/** open order info debug file, thr->num must be valid. */
static void
open_lockorder(struct thr_check* thr)
{
@@ -632,7 +626,7 @@ open_lockorder(struct thr_check* thr)
log_err("fwrite: %s", strerror(errno));
}
/** checklock thread main, Inits thread structure */
/** checklock thread main, Inits thread structure. */
static void* checklock_main(void* arg)
{
struct thr_check* thr = (struct thr_check*)arg;
@@ -705,102 +699,13 @@ checklock_thrcreate(pthread_t* id, void* (*func)(void*), void* arg)
LOCKRET(pthread_create(id, NULL, checklock_main, thr));
}
/** count number of thread infos */
static int
count_thread_infos()
{
int cnt = 0;
int i;
for(i=0; i<THRDEBUG_MAX_THREADS; i++)
if(thread_infos[i])
cnt++;
return cnt;
}
/** print lots of info on a lock */
static void
lock_debug_info(struct checked_lock* lock)
{
if(!lock) return;
log_info("+++ Lock %x, %d %d create %s %s %d", (int)lock,
lock->create_thread, lock->create_instance,
lock->create_func, lock->create_file, lock->create_line);
log_info("lock type: %s",
(lock->type==check_lock_mutex)?"mutex": (
(lock->type==check_lock_spinlock)?"spinlock": (
(lock->type==check_lock_rwlock)?"rwlock": "badtype")));
log_info("lock contention %u, history:%u, hold:%d, wait:%d",
(unsigned)lock->contention_count, (unsigned)lock->history_count,
lock->hold_count, lock->wait_count);
log_info("last touch %s %s %d", lock->holder_func, lock->holder_file,
lock->holder_line);
log_info("holder thread %d, writeholder thread %d",
lock->holder?lock->holder->num:-1,
lock->writeholder?lock->writeholder->num:-1);
}
/** print debug locks held by a thread */
static void
held_debug_info(struct thr_check* thr, struct checked_lock* lock)
{
if(!lock) return;
lock_debug_info(lock);
held_debug_info(thr, lock->next_held_lock[thr->num]);
}
/** print debug info for a thread */
static void
thread_debug_info(struct thr_check* thr)
{
struct checked_lock* w = NULL;
struct checked_lock* f = NULL;
struct checked_lock* l = NULL;
if(!thr) return;
log_info("pthread id is %x", (int)thr->id);
log_info("thread func is %x", (int)thr->func);
log_info("thread arg is %x (%d)", (int)thr->arg,
(thr->arg?*(int*)thr->arg:0));
log_info("thread num is %d", thr->num);
log_info("locks created %d", thr->locks_created);
log_info("open file for lockinfo: %s",
thr->order_info?"yes, flushing":"no");
fflush(thr->order_info);
w = thr->waiting;
f = thr->holding_first;
l = thr->holding_last;
log_info("thread waiting for a lock: %s %x", w?"yes":"no", (int)w);
lock_debug_info(w);
log_info("thread holding first: %s, last: %s", f?"yes":"no",
l?"yes":"no");
held_debug_info(thr, f);
}
static void
total_debug_info()
{
int i;
log_info("checklocks: supervising %d threads.",
count_thread_infos());
if(!key_created) {
log_info("No thread debug key created yet");
}
for(i=0; i<THRDEBUG_MAX_THREADS; i++) {
if(thread_infos[i]) {
log_info("*** Thread %d information: ***", i);
thread_debug_info(thread_infos[i]);
}
}
}
/** signal handler for join timeout, Exits */
/** signal handler for join timeout, Exits. */
static RETSIGTYPE joinalarm(int ATTR_UNUSED(sig))
{
log_err("join thread timeout. hangup or deadlock. Info follows.");
total_debug_info();
fatal_exit("join thread timeout. hangup or deadlock.");
}
/** wait for thread with a timeout */
/** wait for thread with a timeout. */
void
checklock_thrjoin(pthread_t thread)
{
+15 -230
View File
@@ -47,10 +47,6 @@
#include "config.h"
#include "testcode/fake_event.h"
#include "util/netevent.h"
#include "util/net_help.h"
#include "util/data/msgparse.h"
#include "util/data/msgreply.h"
#include "util/data/msgencode.h"
#include "services/listen_dnsport.h"
#include "services/outside_network.h"
#include "testcode/replay.h"
@@ -73,7 +69,7 @@ fake_event_cleanup()
saved_scenario = NULL;
}
/** helper function that logs a ldns_pkt packet to logfile */
/** helper function that logs a ldns_pkt packet to logfile. */
static void
log_pkt(const char* desc, ldns_pkt* pkt)
{
@@ -143,10 +139,6 @@ pending_matches_current(struct replay_runtime* runtime,
return 0;
/* see if any of the pending queries matches */
for(p = runtime->pending_list; p; p = p->next) {
if(runtime->now->addrlen != 0 &&
sockaddr_cmp(&p->addr, p->addrlen, &runtime->now->addr,
runtime->now->addrlen) != 0)
continue;
if((e=find_match(runtime->now->match, p->pkt, p->transport))) {
*entry = e;
*pend = p;
@@ -171,14 +163,10 @@ pending_find_match(struct replay_runtime* runtime, struct entry** entry,
struct replay_range* p = runtime->scenario->range_list;
while(p) {
if(p->start_step <= timenow && timenow <= p->end_step &&
(p->addrlen == 0 || sockaddr_cmp(&p->addr, p->addrlen,
&pend->addr, pend->addrlen) == 0) &&
(*entry = find_match(p->match, pend->pkt, pend->transport))) {
log_info("matched query time %d in range [%d, %d] "
"with entry line %d", timenow,
p->start_step, p->end_step, (*entry)->lineno);
if(p->addrlen != 0)
log_addr("matched ip", &p->addr, p->addrlen);
return 1;
}
p = p->next_range;
@@ -200,7 +188,6 @@ pending_matches_range(struct replay_runtime* runtime,
struct fake_pending* p = runtime->pending_list;
/* slow, O(N*N), but it works as advertised with weird matching */
while(p) {
log_info("check of pending");
if(pending_find_match(runtime, entry, p)) {
*pend = p;
return 1;
@@ -274,10 +261,6 @@ answer_callback_from_entry(struct replay_runtime* runtime,
struct entry* entry, struct fake_pending* pend)
{
struct comm_point c;
struct comm_reply repinfo;
void* cb_arg = pend->cb_arg;
comm_point_callback_t* cb = pend->callback;
memset(&c, 0, sizeof(c));
c.fd = -1;
c.buffer = ldns_buffer_new(runtime->bufsize);
@@ -285,15 +268,11 @@ answer_callback_from_entry(struct replay_runtime* runtime,
if(pend->transport == transport_tcp)
c.type = comm_tcp;
fill_buffer_with_reply(c.buffer, entry, pend->pkt);
repinfo.c = &c;
repinfo.addrlen = pend->addrlen;
memcpy(&repinfo.addr, &pend->addr, pend->addrlen);
if(!pend->serviced)
pending_list_delete(runtime, pend);
if((*cb)(&c, cb_arg, NETEVENT_NOERROR, &repinfo)) {
if((*pend->callback)(&c, pend->cb_arg, NETEVENT_NOERROR, NULL)) {
fatal_exit("testbound: unexpected: callback returned 1");
}
ldns_buffer_free(c.buffer);
pending_list_delete(runtime, pend);
}
/** Check the now moment answer check event */
@@ -308,10 +287,7 @@ answer_check_it(struct replay_runtime* runtime)
enum transport_type tr = transport_tcp;
if(ans->repinfo.c->type == comm_udp)
tr = transport_udp;
if((runtime->now->addrlen == 0 || sockaddr_cmp(
&runtime->now->addr, runtime->now->addrlen,
&ans->repinfo.addr, ans->repinfo.addrlen) == 0) &&
find_match(runtime->now->match, ans->pkt, tr)) {
if(find_match(runtime->now->match, ans->pkt, tr)) {
struct replay_answer *n = ans->next;
log_info("testbound matched event entry from line %d",
runtime->now->match->lineno);
@@ -346,10 +322,6 @@ fake_front_query(struct replay_runtime* runtime, struct replay_moment *todo)
memset(&repinfo, 0, sizeof(repinfo));
repinfo.c = (struct comm_point*)calloc(1, sizeof(struct comm_point));
repinfo.addrlen = (socklen_t)sizeof(struct sockaddr_in);
if(todo->addrlen != 0) {
repinfo.addrlen = todo->addrlen;
memcpy(&repinfo.addr, &todo->addr, todo->addrlen);
}
repinfo.c->fd = -1;
repinfo.c->ev = (struct internal_event*)runtime;
repinfo.c->buffer = ldns_buffer_new(runtime->bufsize);
@@ -374,7 +346,6 @@ fake_pending_callback(struct replay_runtime* runtime,
struct replay_moment* todo, int error)
{
struct fake_pending* p = runtime->pending_list;
struct comm_reply repinfo;
struct comm_point c;
memset(&c, 0, sizeof(c));
if(!p) fatal_exit("No pending queries.");
@@ -385,11 +356,8 @@ fake_pending_callback(struct replay_runtime* runtime,
c.type = comm_tcp;
if(todo->evt_type == repevt_back_reply && todo->match) {
fill_buffer_with_reply(c.buffer, todo->match, p->pkt);
}
repinfo.c = &c;
repinfo.addrlen = p->addrlen;
memcpy(&repinfo.addr, &p->addr, p->addrlen);
if((*p->callback)(&c, p->cb_arg, error, &repinfo)) {
}
if((*p->callback)(&c, p->cb_arg, error, NULL)) {
fatal_exit("unexpected: pending callback returned 1");
}
/* delete the pending item. */
@@ -504,10 +472,6 @@ run_scenario(struct replay_runtime* runtime)
} while(runtime->now);
if(runtime->pending_list) {
struct fake_pending* p;
log_err("testbound: there are still messages pending.");
for(p = runtime->pending_list; p; p=p->next)
log_pkt("pending msg", p->pkt);
fatal_exit("testbound: there are still messages pending.");
}
if(runtime->answer_list) {
@@ -649,8 +613,12 @@ void
comm_point_send_reply_iov(struct comm_reply* repinfo, struct iovec* iov,
size_t iovlen)
{
/* skip tcp len at [0]. */
write_iov_buffer(repinfo->c->buffer, iov+1, iovlen-1);
size_t i;
ldns_buffer_clear(repinfo->c->buffer);
for(i=1; i<iovlen; i++)
ldns_buffer_write(repinfo->c->buffer, iov[i].iov_base,
iov[i].iov_len);
ldns_buffer_flip(repinfo->c->buffer);
comm_point_send_reply(repinfo);
}
@@ -668,9 +636,7 @@ struct outside_network*
outside_network_create(struct comm_base* base, size_t bufsize,
size_t ATTR_UNUSED(num_ports), char** ATTR_UNUSED(ifs),
int ATTR_UNUSED(num_ifs), int ATTR_UNUSED(do_ip4),
int ATTR_UNUSED(do_ip6), int ATTR_UNUSED(port_base),
size_t ATTR_UNUSED(num_tcp), struct infra_cache* ATTR_UNUSED(infra),
struct ub_randstate* ATTR_UNUSED(rnd))
int ATTR_UNUSED(do_ip6), int ATTR_UNUSED(port_base))
{
struct outside_network* outnet = calloc(1,
sizeof(struct outside_network));
@@ -692,14 +658,7 @@ outside_network_delete(struct outside_network* outnet)
free(outnet);
}
void
outside_network_set_secondary_buffer(struct outside_network*
ATTR_UNUSED(outnet), ldns_buffer* ATTR_UNUSED(buf))
{
/* nothing to do */
}
struct pending*
void
pending_udp_query(struct outside_network* outnet, ldns_buffer* packet,
struct sockaddr_storage* addr, socklen_t addrlen, int timeout,
comm_point_callback_t* callback, void* callback_arg,
@@ -719,11 +678,9 @@ pending_udp_query(struct outside_network* outnet, ldns_buffer* packet,
pend->addrlen = addrlen;
pend->callback = callback;
pend->cb_arg = callback_arg;
pend->timeout = timeout/1000;
pend->timeout = timeout;
pend->transport = transport_udp;
pend->pkt = NULL;
pend->serviced = 0;
pend->runtime = runtime;
status = ldns_buffer2pkt_wire(&pend->pkt, packet);
if(status != LDNS_STATUS_OK) {
log_err("ldns error parsing udp output packet: %s",
@@ -734,9 +691,6 @@ pending_udp_query(struct outside_network* outnet, ldns_buffer* packet,
/* see if it matches the current moment */
if(runtime->now && runtime->now->evt_type == repevt_back_query &&
(runtime->now->addrlen == 0 || sockaddr_cmp(
&runtime->now->addr, runtime->now->addrlen,
&pend->addr, pend->addrlen) == 0) &&
find_match(runtime->now->match, pend->pkt, pend->transport)) {
log_info("testbound: matched pending to event. "
"advance time between events.");
@@ -749,160 +703,6 @@ pending_udp_query(struct outside_network* outnet, ldns_buffer* packet,
/* add to list */
pend->next = runtime->pending_list;
runtime->pending_list = pend;
return (struct pending*)pend;
}
struct waiting_tcp*
pending_tcp_query(struct outside_network* outnet, ldns_buffer* packet,
struct sockaddr_storage* addr, socklen_t addrlen, int timeout,
comm_point_callback_t* callback, void* callback_arg,
struct ub_randstate* ATTR_UNUSED(rnd))
{
struct replay_runtime* runtime = (struct replay_runtime*)outnet->base;
struct fake_pending* pend = (struct fake_pending*)calloc(1,
sizeof(struct fake_pending));
ldns_status status;
log_assert(pend);
pend->buffer = ldns_buffer_new(ldns_buffer_capacity(packet));
log_assert(pend->buffer);
ldns_buffer_write(pend->buffer, ldns_buffer_begin(packet),
ldns_buffer_limit(packet));
ldns_buffer_flip(pend->buffer);
memcpy(&pend->addr, addr, addrlen);
pend->addrlen = addrlen;
pend->callback = callback;
pend->cb_arg = callback_arg;
pend->timeout = timeout;
pend->transport = transport_tcp;
pend->pkt = NULL;
pend->runtime = runtime;
pend->serviced = 0;
status = ldns_buffer2pkt_wire(&pend->pkt, packet);
if(status != LDNS_STATUS_OK) {
log_err("ldns error parsing tcp output packet: %s",
ldns_get_errorstr_by_id(status));
fatal_exit("Sending unparseable DNS packets to servers!");
}
log_pkt("pending tcp pkt: ", pend->pkt);
/* see if it matches the current moment */
if(runtime->now && runtime->now->evt_type == repevt_back_query &&
(runtime->now->addrlen == 0 || sockaddr_cmp(
&runtime->now->addr, runtime->now->addrlen,
&pend->addr, pend->addrlen) == 0) &&
find_match(runtime->now->match, pend->pkt, pend->transport)) {
log_info("testbound: matched pending to event. "
"advance time between events.");
log_info("testbound: do STEP %d %s", runtime->now->time_step,
repevt_string(runtime->now->evt_type));
advance_moment(runtime);
/* still create the pending, because we need it to callback */
}
log_info("testbound: created fake pending");
/* add to list */
pend->next = runtime->pending_list;
runtime->pending_list = pend;
return (struct waiting_tcp*)pend;
}
struct serviced_query* outnet_serviced_query(struct outside_network* outnet,
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
uint16_t flags, int dnssec, struct sockaddr_storage* addr,
socklen_t addrlen, comm_point_callback_t* callback,
void* callback_arg, ldns_buffer* ATTR_UNUSED(buff),
int (*arg_compare)(void*,void*))
{
struct replay_runtime* runtime = (struct replay_runtime*)outnet->base;
struct fake_pending* pend = (struct fake_pending*)calloc(1,
sizeof(struct fake_pending));
ldns_status status;
(void)arg_compare;
log_assert(pend);
/* create packet with EDNS */
pend->buffer = ldns_buffer_new(512);
log_assert(pend->buffer);
ldns_buffer_write_u16(pend->buffer, 0); /* id */
ldns_buffer_write_u16(pend->buffer, flags);
ldns_buffer_write_u16(pend->buffer, 1); /* qdcount */
ldns_buffer_write_u16(pend->buffer, 0); /* ancount */
ldns_buffer_write_u16(pend->buffer, 0); /* nscount */
ldns_buffer_write_u16(pend->buffer, 0); /* arcount */
ldns_buffer_write(pend->buffer, qname, qnamelen);
ldns_buffer_write_u16(pend->buffer, qtype);
ldns_buffer_write_u16(pend->buffer, qclass);
ldns_buffer_flip(pend->buffer);
if(1) {
/* add edns */
struct edns_data edns;
edns.edns_present = 1;
edns.ext_rcode = 0;
edns.edns_version = EDNS_ADVERTISED_VERSION;
edns.udp_size = EDNS_ADVERTISED_SIZE;
edns.bits = 0;
if(dnssec)
edns.bits = EDNS_DO;
attach_edns_record(pend->buffer, &edns);
}
memcpy(&pend->addr, addr, addrlen);
pend->addrlen = addrlen;
pend->callback = callback;
pend->cb_arg = callback_arg;
pend->timeout = UDP_QUERY_TIMEOUT;
pend->transport = transport_udp; /* pretend UDP */
pend->pkt = NULL;
pend->runtime = runtime;
pend->serviced = 1;
status = ldns_buffer2pkt_wire(&pend->pkt, pend->buffer);
if(status != LDNS_STATUS_OK) {
log_err("ldns error parsing serviced output packet: %s",
ldns_get_errorstr_by_id(status));
fatal_exit("internal error");
}
log_pkt("pending serviced query: ", pend->pkt);
/* see if it matches the current moment */
if(runtime->now && runtime->now->evt_type == repevt_back_query &&
(runtime->now->addrlen == 0 || sockaddr_cmp(
&runtime->now->addr, runtime->now->addrlen,
&pend->addr, pend->addrlen) == 0) &&
find_match(runtime->now->match, pend->pkt, pend->transport)) {
log_info("testbound: matched pending to event. "
"advance time between events.");
log_info("testbound: do STEP %d %s", runtime->now->time_step,
repevt_string(runtime->now->evt_type));
advance_moment(runtime);
/* still create the pending, because we need it to callback */
}
log_info("testbound: created fake pending");
/* add to list */
pend->next = runtime->pending_list;
runtime->pending_list = pend;
return (struct serviced_query*)pend;
}
void outnet_serviced_query_stop(struct serviced_query* sq, void* cb_arg)
{
struct fake_pending* pend = (struct fake_pending*)sq;
struct replay_runtime* runtime = pend->runtime;
/* delete from the list */
struct fake_pending* p = runtime->pending_list, *prev=NULL;
while(p) {
if(p == pend) {
log_assert(p->cb_arg == cb_arg);
log_info("serviced pending delete");
if(prev)
prev->next = p->next;
else runtime->pending_list = p->next;
ldns_buffer_free(p->buffer);
ldns_pkt_free(p->pkt);
free(p);
return;
}
prev = p;
p = p->next;
}
log_info("double delete of pending serviced query");
}
struct listen_port* listening_ports_open(struct config_file* ATTR_UNUSED(cfg))
@@ -937,19 +737,4 @@ void comm_point_delete(struct comm_point* c)
free(c);
}
size_t listen_get_mem(struct listen_dnsport* ATTR_UNUSED(listen))
{
return 0;
}
size_t outnet_get_mem(struct outside_network* ATTR_UNUSED(outnet))
{
return 0;
}
size_t comm_point_get_mem(struct comm_point* ATTR_UNUSED(c))
{
return 0;
}
/*********** End of Dummy routines ***********/
+11 -28
View File
@@ -31,7 +31,7 @@ struct sockaddr_storage;
/** string to show in warnings and errors */
static const char* prog_name = "ldns-testpkts";
/** logging routine, provided by caller */
/** logging routine, provided by caller. */
void verbose(int lvl, const char* msg, ...);
/** print error and exit */
@@ -106,10 +106,6 @@ static void matchline(const char* line, struct entry* e)
e->match_qname = true;
} else if(str_keyword(&parse, "all")) {
e->match_all = true;
} else if(str_keyword(&parse, "ttl")) {
e->match_ttl = true;
} else if(str_keyword(&parse, "DO")) {
e->match_do = true;
} else if(str_keyword(&parse, "UDP")) {
e->match_transport = transport_udp;
} else if(str_keyword(&parse, "TCP")) {
@@ -157,8 +153,6 @@ static void replyline(const char* line, ldns_pkt *reply)
ldns_pkt_set_rcode(reply, LDNS_RCODE_NXDOMAIN);
} else if(str_keyword(&parse, "NOTIMPL")) {
ldns_pkt_set_rcode(reply, LDNS_RCODE_NOTIMPL);
} else if(str_keyword(&parse, "REFUSED")) {
ldns_pkt_set_rcode(reply, LDNS_RCODE_REFUSED);
} else if(str_keyword(&parse, "YXDOMAIN")) {
ldns_pkt_set_rcode(reply, LDNS_RCODE_YXDOMAIN);
} else if(str_keyword(&parse, "YXRRSET")) {
@@ -223,8 +217,6 @@ static struct entry* new_entry()
e->match_qtype = false;
e->match_qname = false;
e->match_all = false;
e->match_ttl = false;
e->match_do = false;
e->match_serial = false;
e->ixfr_soa_serial = 0;
e->match_transport = transport_any;
@@ -399,7 +391,7 @@ get_origin(const char* name, int lineno, ldns_rdf** origin, char* parse)
/* Reads one entry from file. Returns entry or NULL on error. */
struct entry*
read_entry(FILE* in, const char* name, int *lineno, uint32_t* default_ttl,
read_entry(FILE* in, const char* name, int *lineno, uint16_t* default_ttl,
ldns_rdf** origin, ldns_rdf** prev_rr)
{
struct entry* current = NULL;
@@ -433,7 +425,7 @@ read_entry(FILE* in, const char* name, int *lineno, uint32_t* default_ttl,
get_origin(name, *lineno, origin, (char*)parse);
continue;
} else if(str_keyword(&parse, "$TTL")) {
*default_ttl = (uint32_t)atoi(parse);
*default_ttl = (uint16_t)atoi(parse);
continue;
}
@@ -507,7 +499,7 @@ read_datafile(const char* name)
struct entry* current = NULL;
FILE *in;
int lineno = 0;
uint32_t default_ttl = 0;
uint16_t default_ttl = 0;
ldns_rdf* origin = NULL;
ldns_rdf* prev_rr = NULL;
int entry_num = 0;
@@ -563,7 +555,7 @@ static uint32_t get_serial(ldns_pkt* p)
/** match two rr lists */
static int
match_list(ldns_rr_list* q, ldns_rr_list *p, bool mttl)
match_list(ldns_rr_list* q, ldns_rr_list *p)
{
size_t i;
if(ldns_rr_list_rr_count(q) != ldns_rr_list_rr_count(p))
@@ -575,11 +567,6 @@ match_list(ldns_rr_list* q, ldns_rr_list *p, bool mttl)
verbose(3, "rr %d different", i);
return 0;
}
if(mttl && ldns_rr_ttl(ldns_rr_list_rr(q, i)) !=
ldns_rr_ttl(ldns_rr_list_rr(p, i))) {
verbose(3, "rr %d ttl different", i);
return 0;
}
}
return 1;
}
@@ -596,7 +583,7 @@ cmp_bool(int x, int y)
/** match all of the packet */
static int
match_all(ldns_pkt* q, ldns_pkt* p, bool mttl)
match_all(ldns_pkt* q, ldns_pkt* p)
{
if(ldns_pkt_get_opcode(q) != ldns_pkt_get_opcode(p))
{ verbose(3, "allmatch: opcode different"); return 0;}
@@ -626,13 +613,13 @@ match_all(ldns_pkt* q, ldns_pkt* p, bool mttl)
{ verbose(3, "allmatch: nscount different"); return 0;}
if(ldns_pkt_arcount(q) != ldns_pkt_arcount(p))
{ verbose(3, "allmatch: arcount different"); return 0;}
if(!match_list(ldns_pkt_question(q), ldns_pkt_question(p), mttl))
if(!match_list(ldns_pkt_question(q), ldns_pkt_question(p)))
{ verbose(3, "allmatch: qd section different"); return 0;}
if(!match_list(ldns_pkt_answer(q), ldns_pkt_answer(p), mttl))
if(!match_list(ldns_pkt_answer(q), ldns_pkt_answer(p)))
{ verbose(3, "allmatch: an section different"); return 0;}
if(!match_list(ldns_pkt_authority(q), ldns_pkt_authority(p), mttl))
if(!match_list(ldns_pkt_authority(q), ldns_pkt_authority(p)))
{ verbose(3, "allmatch: ar section different"); return 0;}
if(!match_list(ldns_pkt_additional(q), ldns_pkt_additional(p), mttl))
if(!match_list(ldns_pkt_additional(q), ldns_pkt_additional(p)))
{ verbose(3, "allmatch: ns section different"); return 0;}
return 1;
}
@@ -668,15 +655,11 @@ find_match(struct entry* entries, ldns_pkt* query_pkt,
verbose(3, "bad serial\n");
continue;
}
if(p->match_do && !ldns_pkt_edns_do(query_pkt)) {
verbose(3, "no DO bit set\n");
continue;
}
if(p->match_transport != transport_any && p->match_transport != transport) {
verbose(3, "bad transport\n");
continue;
}
if(p->match_all && !match_all(query_pkt, reply, p->match_ttl)) {
if(p->match_all && !match_all(query_pkt, reply)) {
verbose(3, "bad allmatch\n");
continue;
}
+3 -9
View File
@@ -44,10 +44,8 @@
; 'qname' makes the query match the qname from the reply
; 'serial=1023' makes the query match if ixfr serial is 1023.
; 'all' has to match header byte for byte and all rrs in packet.
; 'ttl' used with all, rrs in packet must also have matching TTLs.
; 'DO' will match only queries with DO bit set.
MATCH [opcode] [qtype] [qname] [serial=<value>] [all] [ttl]
MATCH [UDP|TCP] DO
MATCH [opcode] [qtype] [qname] [serial=<value>] [all]
MATCH [UDP|TCP]
MATCH ...
; Then the REPLY header is specified.
REPLY opcode, rcode or flags.
@@ -159,10 +157,6 @@ struct entry {
bool match_serial;
/** match all of the packet */
bool match_all;
/** match ttls in the packet */
bool match_ttl;
/** match DO bit */
bool match_do;
/** match query serial with this value. */
uint32_t ixfr_soa_serial;
/** match on UDP/TCP */
@@ -210,7 +204,7 @@ void delete_entry(struct entry* list);
* @return: The entry read (malloced) or NULL if no entry could be read.
*/
struct entry* read_entry(FILE* in, const char* name, int *lineno,
uint32_t* default_ttl, ldns_rdf** origin, ldns_rdf** prev_rr);
uint16_t* default_ttl, ldns_rdf** origin, ldns_rdf** prev_rr);
/**
* finds entry in list, or returns NULL.
+3 -7
View File
@@ -139,9 +139,6 @@ read_header(FILE* in)
the_time = t;
the_pid = p;
memset(threads, 0, 256*sizeof(int));
if(thrno >= 256) {
fatal_exit("Thread number too big. %d", thrno);
}
threads[thrno] = 1;
have_values = 1;
printf(" trace %d from pid %u on %s", thrno,
@@ -309,7 +306,7 @@ static void found_cycle(struct lock_ref* visit, int level)
}
}
/** Detect cycle by comparing visited now with all (unvisited) bigger nodes */
/** Detect cycle by comparing visited now with all (unvisited) bigger nodes. */
static int detect_cycle(struct lock_ref* visit, struct lock_ref* from)
{
struct lock_ref* p = from;
@@ -335,7 +332,7 @@ static void search_cycle(struct lock_ref* visit, int level,
/* check for cycle */
if(detect_cycle(visit, from) && level != 0) {
found_cycle(visit, level);
fatal_exit("found lock order cycle");
return;
}
/* recurse */
if(!visit->lock->visited)
@@ -383,8 +380,7 @@ static void check_order(rbtree_t* all_locks)
i, (int)all_locks->count,
lock->id.thr, lock->id.instance,
lock->create_file, lock->create_line);
else if (i % ((all_locks->count/75)<1?1:all_locks->count/75)
== 0)
else if (i % (all_locks->count/75) == 0)
fprintf(stderr, ".");
i++;
check_order_lock(lock);
-192
View File
@@ -1,192 +0,0 @@
/*
* testcode/pktview.c - debug program to disassemble a DNS packet.
*
* 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 program shows a dns packet wire format.
*/
#include "config.h"
#include "util/log.h"
#include "util/data/dname.h"
#include "util/data/msgparse.h"
#include "testcode/unitmain.h"
#include "testcode/readhex.h"
/** usage information for pktview */
void usage(char* argv[])
{
printf("usage: %s\n", argv[0]);
printf("present hex packet on stdin.\n");
exit(1);
}
/** read hex input */
void read_input(ldns_buffer* pkt, FILE* in)
{
char buf[102400];
char* np = buf;
while(fgets(np, (int)sizeof(buf) - (np-buf), in)) {
if(buf[0] == ';') /* comment */
continue;
np = &np[strlen(np)];
}
hex_to_buf(pkt, buf);
}
/** analyze domain name in packet, possibly compressed */
void analyze_dname(ldns_buffer* pkt)
{
size_t oldpos = ldns_buffer_position(pkt);
size_t len;
printf("[pos %d] dname: ", (int)oldpos);
dname_print(stdout, pkt, ldns_buffer_current(pkt));
len = pkt_dname_len(pkt);
printf(" len=%d", (int)len);
if(ldns_buffer_position(pkt)-oldpos != len)
printf(" comprlen=%d\n",
(int)(ldns_buffer_position(pkt)-oldpos));
else printf("\n");
}
/** analyze rdata in packet */
void analyze_rdata(ldns_buffer*pkt, const ldns_rr_descriptor* desc,
uint16_t rdlen)
{
int rdf = 0;
int count = (int)desc->_dname_count;
size_t len, oldpos;
while(rdlen > 0 && count) {
switch(desc->_wireformat[rdf]) {
case LDNS_RDF_TYPE_DNAME:
oldpos = ldns_buffer_position(pkt);
analyze_dname(pkt);
rdlen -= ldns_buffer_position(pkt)-oldpos;
count --;
len = 0;
break;
case LDNS_RDF_TYPE_STR:
len = ldns_buffer_current(pkt)[0] + 1;
break;
default:
len = get_rdf_size(desc->_wireformat[rdf]);
}
if(len) {
printf(" wf[%d]", (int)len);
ldns_buffer_skip(pkt, (ssize_t)len);
rdlen -= len;
}
rdf++;
}
if(rdlen)
printf(" remain[%d]\n", (int)rdlen);
else printf("\n");
ldns_buffer_skip(pkt, (ssize_t)rdlen);
}
/** analyze rr in packet */
void analyze_rr(ldns_buffer* pkt, int q)
{
uint16_t type, dclass, len;
uint32_t ttl;
analyze_dname(pkt);
type = ldns_buffer_read_u16(pkt);
dclass = ldns_buffer_read_u16(pkt);
printf("type %s(%d)", ldns_rr_descript(type)?
ldns_rr_descript(type)->_name: "??" , (int)type);
printf(" class %s(%d) ", ldns_lookup_by_id(ldns_rr_classes,
(int)dclass)?ldns_lookup_by_id( ldns_rr_classes,
(int)dclass)->name:"??", (int)dclass);
if(q) {
printf("\n");
} else {
ttl = ldns_buffer_read_u32(pkt);
printf(" ttl %d (0x%x)", ttl, ttl);
len = ldns_buffer_read_u16(pkt);
printf(" rdata len %d:\n", len);
if(ldns_rr_descript(type))
analyze_rdata(pkt, ldns_rr_descript(type), len);
else ldns_buffer_skip(pkt, (ssize_t)len);
}
}
/** analyse pkt */
void analyze(ldns_buffer* pkt)
{
uint16_t i, f, qd, an, ns, ar;
int rrnum = 0;
printf("packet length %d\n", (int)ldns_buffer_limit(pkt));
if(ldns_buffer_limit(pkt) < 12) return;
i = ldns_buffer_read_u16(pkt);
printf("id (hostorder): %d (0x%x)\n", i, i);
f = ldns_buffer_read_u16(pkt);
printf("flags: 0x%x\n", f);
qd = ldns_buffer_read_u16(pkt);
printf("qdcount: %d\n", qd);
an = ldns_buffer_read_u16(pkt);
printf("ancount: %d\n", an);
ns = ldns_buffer_read_u16(pkt);
printf("nscount: %d\n", ns);
ar = ldns_buffer_read_u16(pkt);
printf("arcount: %d\n", ar);
printf(";-- query section\n");
while(ldns_buffer_remaining(pkt) > 0) {
if(rrnum == qd) printf(";-- answer section\n");
if(rrnum == qd+an) printf(";-- authority section\n");
if(rrnum == qd+an+ns) printf(";-- additional section\n");
printf("rr %d ", rrnum);
analyze_rr(pkt, rrnum < qd);
rrnum++;
}
}
/** main program for pktview */
int main(int argc, char* argv[])
{
ldns_buffer* pkt = ldns_buffer_new(65553);
if(argc != 1) {
usage(argv);
}
if(!pkt) fatal_exit("out of memory");
read_input(pkt, stdin);
analyze(pkt);
ldns_buffer_free(pkt);
return 0;
}
-82
View File
@@ -1,82 +0,0 @@
/*
* testcode/readhex.c - read hex data.
*
* 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
* Declarations useful for the unit tests.
*/
#include "config.h"
#include "testcode/readhex.h"
#include "util/log.h"
/** skip whitespace */
static void
skip_whites(const char** p)
{
while(1) {
while(isspace(**p))
(*p)++;
if(**p == ';') {
/* comment, skip until newline */
while(**p && **p != '\n')
(*p)++;
if(**p == '\n')
(*p)++;
} else return;
}
}
/** takes a hex string and puts into buffer */
void hex_to_buf(ldns_buffer* pkt, const char* hex)
{
const char* p = hex;
int val;
ldns_buffer_clear(pkt);
while(*p) {
skip_whites(&p);
if(ldns_buffer_position(pkt) == ldns_buffer_limit(pkt))
fatal_exit("hex_to_buf: buffer too small");
if(!isalnum(*p))
break;
val = ldns_hexdigit_to_int(*p++) << 4;
skip_whites(&p);
log_assert(*p && isalnum(*p));
val |= ldns_hexdigit_to_int(*p++);
ldns_buffer_write_u8(pkt, (uint8_t)val);
skip_whites(&p);
}
ldns_buffer_flip(pkt);
}
-47
View File
@@ -1,47 +0,0 @@
/*
* testcode/readhex.h - read hex data.
*
* 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
* Declarations useful for the unit tests.
*/
#ifndef TESTCODE_READHEX_H
#define TESTCODE_READHEX_H
/** helper to convert hex string to packet buffer */
void hex_to_buf(ldns_buffer* pkt, const char* hex);
#endif /* TESTCODE_READHEX_H */
+4 -40
View File
@@ -41,7 +41,6 @@
#include "config.h"
#include "util/log.h"
#include "util/net_help.h"
#include "testcode/replay.h"
#include "testcode/ldns-testpkts.h"
@@ -86,18 +85,6 @@ replay_range_delete(struct replay_range* rng)
free(rng);
}
/** strip whitespace from end of string */
static void
strip_end_white(char* p)
{
size_t i;
for(i = strlen(p); i > 0; i--) {
if(isspace(p[i-1]))
p[i-1] = 0;
else return;
}
}
/**
* Read a range from file.
* @param remain: Rest of line (after RANGE keyword).
@@ -112,7 +99,7 @@ strip_end_white(char* p)
*/
static struct replay_range*
replay_range_read(char* remain, FILE* in, const char* name, int* lineno,
char* line, uint32_t* ttl, ldns_rdf** or, ldns_rdf** prev)
char* line, uint16_t* ttl, ldns_rdf** or, ldns_rdf** prev)
{
struct replay_range* rng = (struct replay_range*)malloc(
sizeof(struct replay_range));
@@ -137,19 +124,6 @@ replay_range_read(char* remain, FILE* in, const char* name, int* lineno,
parse++;
if(!*parse || *parse == ';')
continue;
if(parse_keyword(&parse, "ADDRESS")) {
while(isspace(*parse))
parse++;
strip_end_white(parse);
if(!extstrtoaddr(parse, &rng->addr, &rng->addrlen)) {
log_err("Line %d: could not read ADDRESS: %s",
*lineno, parse);
free(rng);
return NULL;
}
pos = ftello(in);
continue;
}
if(parse_keyword(&parse, "RANGE_END")) {
return rng;
}
@@ -184,7 +158,7 @@ replay_range_read(char* remain, FILE* in, const char* name, int* lineno,
*/
static struct replay_moment*
replay_moment_read(char* remain, FILE* in, const char* name, int* lineno,
uint32_t* ttl, ldns_rdf** or, ldns_rdf** prev)
uint16_t* ttl, ldns_rdf** or, ldns_rdf** prev)
{
struct replay_moment* mom = (struct replay_moment*)malloc(
sizeof(struct replay_moment));
@@ -224,16 +198,6 @@ replay_moment_read(char* remain, FILE* in, const char* name, int* lineno,
free(mom);
return NULL;
}
while(isspace(*remain))
remain++;
if(parse_keyword(&remain, "ADDRESS")) {
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);
@@ -246,7 +210,7 @@ replay_moment_read(char* remain, FILE* in, const char* name, int* lineno,
return mom;
}
/** makes scenario with title on rest of line */
/** makes scenario with title on rest of line. */
static struct replay_scenario*
make_scenario(char* line)
{
@@ -275,7 +239,7 @@ replay_scenario_read(FILE* in, const char* name, int* lineno)
char line[MAX_LINE_LEN];
char *parse;
struct replay_scenario* scen = NULL;
uint32_t ttl = 3600;
uint16_t ttl = 3600;
ldns_rdf* or = NULL;
ldns_rdf* prev = NULL;
line[MAX_LINE_LEN-1]=0;
+1 -16
View File
@@ -44,13 +44,11 @@
* ; comment line.
* SCENARIO_BEGIN name_of_scenario
* RANGE_BEGIN start_time end_time
* ; give ip of the virtual server, it matches any ip if not present.
* ADDRESS ip_address
* match_entries
* RANGE_END
* ; more RANGE items.
* ; go to the next moment
* STEP time_step event_type [ADDRESS ip_address]
* STEP time_step event_type
* ; event_type can be:
* o NOTHING - nothing
* o QUERY - followed by entry
@@ -160,11 +158,6 @@ struct replay_moment {
/** The sent packet must match this. Incoming events, the data. */
struct entry* match;
/** address that must be matched, or packet remote host address. */
struct sockaddr_storage addr;
/** length of addr, if 0, then any address will do */
socklen_t addrlen;
/** what pending query should timeout or is answered. or
* NULL for last sent query.
* Unused at this time.
@@ -180,10 +173,6 @@ struct replay_range {
int start_step;
/** end step of time range. */
int end_step;
/** address of where this range is served. */
struct sockaddr_storage addr;
/** length of addr, if 0, then any address will do */
socklen_t addrlen;
/** Matching list */
struct entry* match;
@@ -256,10 +245,6 @@ struct fake_pending {
ldns_pkt* pkt;
/** by what transport was the query sent out */
enum transport_type transport;
/** if this is a serviced query */
int serviced;
/** the runtime structure this is part of */
struct replay_runtime* runtime;
};
/**
+1 -1
View File
@@ -105,7 +105,7 @@ add_opts(char* optarg, int* pass_argc, char* pass_argv[])
}
}
/** pretty print commandline for unbound in this test */
/** pretty print commandline for unbound in this test. */
static void
echo_cmdline(int argc, char* argv[])
{
-450
View File
@@ -1,450 +0,0 @@
/*
* testcode/unitdname.c - unit test for dname routines.
*
* 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
* Calls dname unit tests. Exits with code 1 on a failure.
*/
#include "config.h"
#include "util/log.h"
#include "testcode/unitmain.h"
#include "util/data/dname.h"
/** put dname into buffer */
static ldns_buffer*
dname_to_buf(ldns_buffer* b, const char* str)
{
ldns_rdf* rdf;
ldns_status status;
ldns_buffer_clear(b);
rdf = ldns_dname_new_frm_str(str);
status = ldns_dname2buffer_wire(b, rdf);
if(status != LDNS_STATUS_OK)
fatal_exit("%s ldns: %s", __func__,
ldns_get_errorstr_by_id(status));
ldns_rdf_deep_free(rdf);
ldns_buffer_flip(b);
return b;
}
/** test query_dname_len function */
static void
dname_test_qdl(ldns_buffer* buff)
{
unit_assert( query_dname_len(buff) == 0);
unit_assert( query_dname_len(dname_to_buf(buff, ".")) == 1 );
unit_assert( query_dname_len(dname_to_buf(buff, "bla.foo.")) == 9 );
unit_assert( query_dname_len(dname_to_buf(buff, "x.y.z.example.com."
)) == 19 );
}
/** test query_dname_tolower */
static void
dname_test_qdtl(ldns_buffer* buff)
{
ldns_buffer_write_at(buff, 0, "\012abCDeaBCde\003cOm\000", 16);
query_dname_tolower(ldns_buffer_begin(buff), 16);
unit_assert( memcmp(ldns_buffer_begin(buff),
"\012abcdeabcde\003com\000", 16) == 0);
ldns_buffer_write_at(buff, 0, "\001+\012abC{e-ZYXe\003NET\000", 18);
query_dname_tolower(ldns_buffer_begin(buff), 18);
unit_assert( memcmp(ldns_buffer_begin(buff),
"\001+\012abc{e-zyxe\003net\000", 18) == 0);
ldns_buffer_write_at(buff, 0, "\000", 1);
query_dname_tolower(ldns_buffer_begin(buff), 1);
unit_assert( memcmp(ldns_buffer_begin(buff), "\000", 1) == 0);
ldns_buffer_write_at(buff, 0, "\002NL\000", 4);
query_dname_tolower(ldns_buffer_begin(buff), 4);
unit_assert( memcmp(ldns_buffer_begin(buff), "\002nl\000", 4) == 0);
}
/** test query_dname_compare */
static void
dname_test_query_dname_compare()
{
unit_assert(query_dname_compare((uint8_t*)"", (uint8_t*)"") == 0);
unit_assert(query_dname_compare((uint8_t*)"\001a",
(uint8_t*)"\001a") == 0);
unit_assert(query_dname_compare((uint8_t*)"\003abc\001a",
(uint8_t*)"\003abc\001a") == 0);
unit_assert(query_dname_compare((uint8_t*)"\003aBc\001a",
(uint8_t*)"\003AbC\001A") == 0);
unit_assert(query_dname_compare((uint8_t*)"\003abc",
(uint8_t*)"\003abc\001a") == -1);
unit_assert(query_dname_compare((uint8_t*)"\003abc\001a",
(uint8_t*)"\003abc") == +1);
unit_assert(query_dname_compare((uint8_t*)"\003abc\001a",
(uint8_t*)"") == +1);
unit_assert(query_dname_compare((uint8_t*)"",
(uint8_t*)"\003abc\001a") == -1);
unit_assert(query_dname_compare((uint8_t*)"\003abc\001a",
(uint8_t*)"\003xxx\001a") == -1);
unit_assert(query_dname_compare((uint8_t*)"\003axx\001a",
(uint8_t*)"\003abc\001a") == 1);
unit_assert(query_dname_compare((uint8_t*)"\003abc\001a",
(uint8_t*)"\003abc\001Z") == -1);
unit_assert(query_dname_compare((uint8_t*)"\003abc\001Z",
(uint8_t*)"\003abc\001a") == 1);
}
/** test dname_count_labels */
static void
dname_test_count_labels()
{
unit_assert(dname_count_labels((uint8_t*)"") == 1);
unit_assert(dname_count_labels((uint8_t*)"\003com") == 2);
unit_assert(dname_count_labels((uint8_t*)"\003org") == 2);
unit_assert(dname_count_labels((uint8_t*)"\007example\003com") == 3);
unit_assert(dname_count_labels((uint8_t*)"\003bla\007example\003com")
== 4);
}
/** test dname_count_size_labels */
static void
dname_test_count_size_labels()
{
size_t sz = 0;
unit_assert(dname_count_size_labels((uint8_t*)"", &sz) == 1);
unit_assert(sz == 1);
unit_assert(dname_count_size_labels((uint8_t*)"\003com", &sz) == 2);
unit_assert(sz == 5);
unit_assert(dname_count_size_labels((uint8_t*)"\003org", &sz) == 2);
unit_assert(sz == 5);
unit_assert(dname_count_size_labels((uint8_t*)"\007example\003com",
&sz) == 3);
unit_assert(sz == 13);
unit_assert(dname_count_size_labels((uint8_t*)"\003bla\007example"
"\003com", &sz) == 4);
unit_assert(sz == 17);
}
/** test pkt_dname_len */
static void
dname_test_pkt_dname_len(ldns_buffer* buff)
{
ldns_buffer_clear(buff);
ldns_buffer_write(buff, "\000", 1);
ldns_buffer_flip(buff);
unit_assert( pkt_dname_len(buff) == 1 );
unit_assert( ldns_buffer_position(buff) == 1);
ldns_buffer_clear(buff);
ldns_buffer_write(buff, "\003org\000", 5);
ldns_buffer_flip(buff);
unit_assert( pkt_dname_len(buff) == 5 );
unit_assert( ldns_buffer_position(buff) == 5);
ldns_buffer_clear(buff);
ldns_buffer_write(buff, "\002os\007example\003org\000", 16);
ldns_buffer_flip(buff);
unit_assert( pkt_dname_len(buff) == 16 );
unit_assert( ldns_buffer_position(buff) == 16);
/* invalid compression pointer: to self */
ldns_buffer_clear(buff);
ldns_buffer_write(buff, "\300\000os\007example\003org\000", 17);
ldns_buffer_flip(buff);
unit_assert( pkt_dname_len(buff) == 0 );
/* valid compression pointer */
ldns_buffer_clear(buff);
ldns_buffer_write(buff, "\003com\000\040\300\000", 8);
ldns_buffer_flip(buff);
ldns_buffer_set_position(buff, 6);
unit_assert( pkt_dname_len(buff) == 5 );
unit_assert( ldns_buffer_position(buff) == 8);
/* unknown label type */
ldns_buffer_clear(buff);
ldns_buffer_write(buff, "\002os\107example\003org\000", 16);
ldns_buffer_flip(buff);
unit_assert( pkt_dname_len(buff) == 0 );
/* label too long */
ldns_buffer_clear(buff);
ldns_buffer_write(buff, "\002os\047example\003org\000", 16);
ldns_buffer_flip(buff);
unit_assert( pkt_dname_len(buff) == 0 );
/* label exceeds packet */
ldns_buffer_clear(buff);
ldns_buffer_write(buff, "\002os\007example\007org\004", 16);
ldns_buffer_flip(buff);
unit_assert( pkt_dname_len(buff) == 0 );
/* name very long */
ldns_buffer_clear(buff);
ldns_buffer_write(buff,
"\020a1cdef5555544444"
"\020a2cdef5555544444"
"\020a3cdef5555544444"
"\020a4cdef5555544444"
"\020a5cdef5555544444"
"\020a6cdef5555544444"
"\020a7cdef5555544444"
"\020a8cdef5555544444"
"\020a9cdef5555544444"
"\020aAcdef5555544444"
"\020aBcdef5555544444"
"\020aCcdef5555544444"
"\020aDcdef5555544444"
"\020aEcdef5555544444" /* 238 up to here */
"\007aabbccd" /* 246 up to here */
"\007example\000" /* 255 to here */
, 255);
ldns_buffer_flip(buff);
unit_assert( pkt_dname_len(buff) == 255 );
unit_assert( ldns_buffer_position(buff) == 255);
/* name too long */
ldns_buffer_clear(buff);
ldns_buffer_write(buff,
"\020a1cdef5555544444"
"\020a2cdef5555544444"
"\020a3cdef5555544444"
"\020a4cdef5555544444"
"\020a5cdef5555544444"
"\020a6cdef5555544444"
"\020a7cdef5555544444"
"\020a8cdef5555544444"
"\020a9cdef5555544444"
"\020aAcdef5555544444"
"\020aBcdef5555544444"
"\020aCcdef5555544444"
"\020aXcdef5555544444"
"\020aXcdef5555544444"
"\020aXcdef5555544444"
"\020aDcdef5555544444"
"\020aEcdef5555544444" /* 238 up to here */
"\007aabbccd" /* 246 up to here */
"\007example\000" /* 255 to here */
, 255);
ldns_buffer_flip(buff);
unit_assert( pkt_dname_len(buff) == 0 );
}
/** test dname_lab_cmp */
static void
dname_test_dname_lab_cmp()
{
int ml = 0; /* number of labels that matched exactly */
/* test for equality succeeds */
unit_assert(dname_lab_cmp((uint8_t*)"", 1, (uint8_t*)"", 1, &ml) == 0);
unit_assert(ml == 1);
unit_assert(dname_lab_cmp(
(uint8_t*)"\003net", 2,
(uint8_t*)"\003net", 2,
&ml) == 0);
unit_assert(ml == 2);
unit_assert(dname_lab_cmp(
(uint8_t*)"\007example\003net", 3,
(uint8_t*)"\007example\003net", 3,
&ml) == 0);
unit_assert(ml == 3);
unit_assert(dname_lab_cmp(
(uint8_t*)"\004test\007example\003net", 4,
(uint8_t*)"\004test\007example\003net", 4,
&ml) == 0);
unit_assert(ml == 4);
/* root is smaller than anything else */
unit_assert(dname_lab_cmp(
(uint8_t*)"", 1,
(uint8_t*)"\003net", 2,
&ml) == -1);
unit_assert(ml == 1);
unit_assert(dname_lab_cmp(
(uint8_t*)"\003net", 2,
(uint8_t*)"", 1,
&ml) == 1);
unit_assert(ml == 1);
unit_assert(dname_lab_cmp(
(uint8_t*)"", 1,
(uint8_t*)"\007example\003net", 3,
&ml) == -1);
unit_assert(ml == 1);
unit_assert(dname_lab_cmp(
(uint8_t*)"\007example\003net", 3,
(uint8_t*)"", 1,
&ml) == 1);
unit_assert(ml == 1);
/* label length makes a difference */
unit_assert(dname_lab_cmp(
(uint8_t*)"\004neta", 2,
(uint8_t*)"\003net", 2,
&ml) != 0);
unit_assert(ml == 1);
unit_assert(dname_lab_cmp(
(uint8_t*)"\002ne", 2,
(uint8_t*)"\004neta", 2,
&ml) != 0);
unit_assert(ml == 1);
/* contents follow the zone apex */
unit_assert(dname_lab_cmp(
(uint8_t*)"\003bla\007example\003net", 4,
(uint8_t*)"\007example\003net", 3,
&ml) == 1);
unit_assert(ml == 3);
unit_assert(dname_lab_cmp(
(uint8_t*)"\007example\003net", 3,
(uint8_t*)"\003bla\007example\003net", 4,
&ml) == -1);
unit_assert(ml == 3);
/* label content makes a difference */
unit_assert(dname_lab_cmp(
(uint8_t*)"\003aag\007example\003net", 4,
(uint8_t*)"\003bla\007example\003net", 4,
&ml) == -1);
unit_assert(ml == 3);
unit_assert(dname_lab_cmp(
(uint8_t*)"\003aag\007example\003net", 4,
(uint8_t*)"\003bla\007example\003net", 4,
&ml) == -1);
unit_assert(ml == 3);
unit_assert(dname_lab_cmp(
(uint8_t*)"\003bla\003aag\007example\003net", 5,
(uint8_t*)"\003aag\003bla\007example\003net", 5,
&ml) == -1);
unit_assert(ml == 3);
unit_assert(dname_lab_cmp(
(uint8_t*)"\02sn\003opt\003aag\007example\003net", 6,
(uint8_t*)"\02sn\003opt\003bla\007example\003net", 6,
&ml) == -1);
unit_assert(ml == 3);
/* but lowercase/uppercase does not make a difference. */
unit_assert(dname_lab_cmp(
(uint8_t*)"\003bLa\007examPLe\003net", 4,
(uint8_t*)"\003bla\007eXAmple\003nET", 4,
&ml) == 0);
unit_assert(ml == 4);
}
/** test dname_subdomain_c */
static void
dname_test_subdomain()
{
unit_assert(dname_subdomain_c(
(uint8_t*)"",
(uint8_t*)""));
unit_assert(dname_subdomain_c(
(uint8_t*)"\003com",
(uint8_t*)""));
unit_assert(!dname_subdomain_c(
(uint8_t*)"",
(uint8_t*)"\003com"));
unit_assert(dname_subdomain_c(
(uint8_t*)"\007example\003com",
(uint8_t*)"\003com"));
unit_assert(!dname_subdomain_c(
(uint8_t*)"\003com",
(uint8_t*)"\007example\003com"));
unit_assert(dname_subdomain_c(
(uint8_t*)"\007example\003com",
(uint8_t*)""));
unit_assert(!dname_subdomain_c(
(uint8_t*)"\003net",
(uint8_t*)"\003com"));
unit_assert(!dname_subdomain_c(
(uint8_t*)"\003net",
(uint8_t*)"\003org"));
unit_assert(!dname_subdomain_c(
(uint8_t*)"\007example\003net",
(uint8_t*)"\003org"));
unit_assert(!dname_subdomain_c(
(uint8_t*)"\003net",
(uint8_t*)"\007example\003org"));
}
/** test dname_strict_subdomain */
static void
dname_test_strict_subdomain()
{
unit_assert(!dname_strict_subdomain(
(uint8_t*)"", 1,
(uint8_t*)"", 1));
unit_assert(dname_strict_subdomain(
(uint8_t*)"\003com", 2,
(uint8_t*)"", 1));
unit_assert(!dname_strict_subdomain(
(uint8_t*)"", 1,
(uint8_t*)"\003com", 2));
unit_assert(dname_strict_subdomain(
(uint8_t*)"\007example\003com", 3,
(uint8_t*)"\003com", 2));
unit_assert(!dname_strict_subdomain(
(uint8_t*)"\003com", 2,
(uint8_t*)"\007example\003com", 3));
unit_assert(dname_strict_subdomain(
(uint8_t*)"\007example\003com", 3,
(uint8_t*)"", 1));
unit_assert(!dname_strict_subdomain(
(uint8_t*)"\003net", 2,
(uint8_t*)"\003com", 2));
unit_assert(!dname_strict_subdomain(
(uint8_t*)"\003net", 2,
(uint8_t*)"\003org", 2));
unit_assert(!dname_strict_subdomain(
(uint8_t*)"\007example\003net", 3,
(uint8_t*)"\003org", 2));
unit_assert(!dname_strict_subdomain(
(uint8_t*)"\003net", 2,
(uint8_t*)"\007example\003org", 3));
}
void dname_test()
{
ldns_buffer* buff = ldns_buffer_new(65800);
ldns_buffer_flip(buff);
dname_test_qdl(buff);
dname_test_qdtl(buff);
dname_test_query_dname_compare();
dname_test_count_labels();
dname_test_count_size_labels();
dname_test_dname_lab_cmp();
dname_test_pkt_dname_len(buff);
dname_test_strict_subdomain();
dname_test_subdomain();
ldns_buffer_free(buff);
}
+10 -11
View File
@@ -62,14 +62,14 @@ static size_t test_sizefunc(void*, void*);
/** comparefunc for lruhash */
static int test_compfunc(void*, void*);
/** delkey for lruhash */
static void test_delkey(void*, void*, int);
static void test_delkey(void*, void*);
/** deldata for lruhash */
static void test_deldata(void*, void*);
/* --- end test representation --- */
/** hash func, very bad to improve collisions */
/** hash func, very bad to improve collisions. */
static hashvalue_t myhash(int id) {return (hashvalue_t)id & 0x0f;}
/** allocate new key, fill in hash */
/** allocate new key, fill in hash. */
static struct testkey* newkey(int id) {
struct testkey* k = (struct testkey*)calloc(1, sizeof(struct testkey));
if(!k) fatal_exit("out of memory");
@@ -233,8 +233,8 @@ test_short_table(struct lruhash* table)
k->entry.data = d;
k2->entry.data = d2;
lruhash_insert(table, myhash(12), &k->entry, d, NULL);
lruhash_insert(table, myhash(14), &k2->entry, d2, NULL);
lruhash_insert(table, myhash(12), &k->entry, d);
lruhash_insert(table, myhash(14), &k2->entry, d2);
unit_assert( lruhash_lookup(table, myhash(12), k, 0) == &k->entry);
lock_rw_unlock( &k->entry.lock );
@@ -245,7 +245,7 @@ test_short_table(struct lruhash* table)
}
/** number of hash test max */
#define HASHTESTMAX 25
#define HASHTESTMAX 32
/** test adding a random element */
static void
@@ -255,7 +255,7 @@ testadd(struct lruhash* table, struct testdata* ref[])
struct testdata* data = newdata(numtoadd);
struct testkey* key = newkey(numtoadd);
key->entry.data = data;
lruhash_insert(table, myhash(numtoadd), &key->entry, data, NULL);
lruhash_insert(table, myhash(numtoadd), &key->entry, data);
ref[numtoadd] = data;
}
@@ -333,7 +333,7 @@ testadd_unlim(struct lruhash* table, struct testdata** ref)
struct testdata* data = newdata(numtoadd);
struct testkey* key = newkey(numtoadd);
key->entry.data = data;
lruhash_insert(table, myhash(numtoadd), &key->entry, data, NULL);
lruhash_insert(table, myhash(numtoadd), &key->entry, data);
if(ref)
ref[numtoadd] = data;
}
@@ -469,7 +469,7 @@ test_thr_main(void* arg)
return NULL;
}
/** test hash table access by multiple threads */
/** test hash table access by multiple threads. */
static void
test_threaded_table(struct lruhash* table)
{
@@ -524,9 +524,8 @@ static int test_compfunc(void* key1, void* key2)
return -1;
}
static void test_delkey(void* key, void* ATTR_UNUSED(arg), int l)
static void test_delkey(void* key, void* ATTR_UNUSED(arg))
{
if(l) { lock_rw_unlock(&((struct testkey*)key)->entry.lock); }
delkey((struct testkey*)key);
}
+43 -74
View File
@@ -54,9 +54,9 @@ alloc_test() {
struct alloc_cache major, minor1, minor2;
int i;
alloc_init(&major, NULL, 0);
alloc_init(&minor1, &major, 0);
alloc_init(&minor2, &major, 1);
alloc_init(&major, NULL);
alloc_init(&minor1, &major);
alloc_init(&minor2, &major);
t1 = alloc_special_obtain(&minor1);
alloc_clear(&minor1);
@@ -119,82 +119,54 @@ net_test()
unit_assert( !is_pow2(259) );
}
#include "util/rtt.h"
/** test RTT code */
static void
rtt_test()
/** put dname into buffer */
static ldns_buffer*
dname_to_buf(ldns_buffer* b, const char* str)
{
int i;
struct rtt_info r;
rtt_init(&r);
/* initial value sensible */
unit_assert( rtt_timeout(&r) == 3000 );
rtt_lost(&r);
unit_assert( rtt_timeout(&r) == 6000 );
rtt_lost(&r);
unit_assert( rtt_timeout(&r) == 12000 );
rtt_update(&r, 4000);
unit_assert( rtt_timeout(&r) >= 5000 );
rtt_lost(&r);
for(i=0; i<100; i++) {
rtt_lost(&r);
unit_assert( rtt_timeout(&r) > RTT_MIN_TIMEOUT-1);
unit_assert( rtt_timeout(&r) < RTT_MAX_TIMEOUT+1);
}
ldns_rdf* rdf;
ldns_status status;
ldns_buffer_clear(b);
rdf = ldns_dname_new_frm_str(str);
status = ldns_dname2buffer_wire(b, rdf);
if(status != LDNS_STATUS_OK)
fatal_exit("%s ldns: %s", __func__,
ldns_get_errorstr_by_id(status));
ldns_rdf_deep_free(rdf);
ldns_buffer_flip(b);
return b;
}
#include "services/cache/infra.h"
#include "util/config_file.h"
/** test host cache */
#include "util/data/msgreply.h"
/** test query parse code */
static void
infra_test()
msgreply_test()
{
int one = 1;
uint8_t* zone = (uint8_t*)"\007example\003com\000";
size_t zonelen = 13;
struct infra_cache* slab;
struct config_file* cfg = config_create();
time_t now = 0;
int vs, to;
struct infra_host_key* k;
struct infra_host_data* d;
ldns_buffer* buff = ldns_buffer_new(65800);
ldns_buffer_flip(buff);
unit_assert( query_dname_len(buff) == 0);
unit_assert( query_dname_len(dname_to_buf(buff, ".")) == 1 );
unit_assert( query_dname_len(dname_to_buf(buff, "bla.foo.")) == 9 );
unit_assert( query_dname_len(dname_to_buf(buff, "x.y.z.example.com.")) == 19 );
slab = infra_create(cfg);
unit_assert( infra_host(slab, (struct sockaddr_storage*)&one,
(socklen_t)sizeof(int), now, &vs, &to) );
unit_assert( vs == 0 && to == 3000 );
ldns_buffer_write_at(buff, 0, "\012abCDeaBCde\003cOm\000", 16);
query_dname_tolower(ldns_buffer_begin(buff), 16);
unit_assert( memcmp(ldns_buffer_begin(buff),
"\012abcdeabcde\003com\000", 16) == 0);
unit_assert( infra_rtt_update(slab, (struct sockaddr_storage*)&one,
(socklen_t)sizeof(int), -1, now) );
unit_assert( infra_host(slab, (struct sockaddr_storage*)&one,
(socklen_t)sizeof(int), now, &vs, &to) );
unit_assert( vs == 0 && to == 6000 );
ldns_buffer_write_at(buff, 0, "\001+\012abC{e-ZYXe\003NET\000", 18);
query_dname_tolower(ldns_buffer_begin(buff), 18);
unit_assert( memcmp(ldns_buffer_begin(buff),
"\001+\012abc{e-zyxe\003net\000", 18) == 0);
unit_assert( infra_edns_update(slab, (struct sockaddr_storage*)&one,
(socklen_t)sizeof(int), -1, now) );
unit_assert( infra_host(slab, (struct sockaddr_storage*)&one,
(socklen_t)sizeof(int), now, &vs, &to) );
unit_assert( vs == -1 && to == 6000 );
ldns_buffer_write_at(buff, 0, "\000", 1);
query_dname_tolower(ldns_buffer_begin(buff), 1);
unit_assert( memcmp(ldns_buffer_begin(buff), "\000", 1) == 0);
now += cfg->host_ttl + 10;
unit_assert( infra_host(slab, (struct sockaddr_storage*)&one,
(socklen_t)sizeof(int), now, &vs, &to) );
unit_assert( vs == 0 && to == 3000 );
unit_assert( infra_set_lame(slab, (struct sockaddr_storage*)&one,
(socklen_t)sizeof(int), zone, zonelen, now) );
unit_assert( (d=infra_lookup_host(slab, (struct sockaddr_storage*)&one,
(socklen_t)sizeof(int), 0, now, &k)) );
unit_assert( d->ttl == now+cfg->host_ttl );
unit_assert( d->edns_version == 0 );
unit_assert( infra_lookup_lame(d, zone, zonelen, now) );
unit_assert( !infra_lookup_lame(d, zone, zonelen,
now+cfg->lame_ttl+10) );
unit_assert( !infra_lookup_lame(d, (uint8_t*)"\000", 1, now) );
lock_rw_unlock(&k->entry.lock);
ldns_buffer_write_at(buff, 0, "\002NL\000", 4);
query_dname_tolower(ldns_buffer_begin(buff), 4);
unit_assert( memcmp(ldns_buffer_begin(buff), "\002nl\000", 4) == 0);
infra_delete(slab);
config_delete(cfg);
ldns_buffer_free(buff);
}
/**
@@ -214,14 +186,11 @@ main(int argc, char* argv[])
printf("Start of %s unit test.\n", PACKAGE_STRING);
checklock_start();
net_test();
dname_test();
rtt_test();
alloc_test();
msgreply_test();
lruhash_test();
slabhash_test();
infra_test();
msgparse_test();
checklock_stop();
printf("%d checks ok.\n", testcount);
printf("%d tests succeeded\n", testcount);
return 0;
}
-4
View File
@@ -51,9 +51,5 @@ extern int testcount;
void lruhash_test();
/** unit test slabhashtable implementation */
void slabhash_test();
/** unit test for msgreply and msgparse */
void msgparse_test();
/** unit test dname handling functions */
void dname_test();
#endif /* TESTCODE_UNITMAIN_H */
-441
View File
@@ -1,441 +0,0 @@
/*
* testcode/unitmsgparse.c - unit test for msg parse routines.
*
* 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
* Calls msg parse unit tests. Exits with code 1 on a failure.
*/
#include "config.h"
#include "util/log.h"
#include "testcode/unitmain.h"
#include "util/data/msgparse.h"
#include "util/data/msgreply.h"
#include "util/data/msgencode.h"
#include "util/alloc.h"
#include "util/region-allocator.h"
#include "util/net_help.h"
#include "testcode/readhex.h"
/** verbose message parse unit test */
static int vbmp = 0;
/** match two rr lists */
static int
match_list(ldns_rr_list* q, ldns_rr_list *p)
{
size_t i;
if(ldns_rr_list_rr_count(q) != ldns_rr_list_rr_count(p)) {
verbose(3, "rrlistcount different %d %d",
(int)ldns_rr_list_rr_count(q),
(int)ldns_rr_list_rr_count(p));
return 0;
}
for(i=0; i<ldns_rr_list_rr_count(q); i++)
{
if(ldns_rr_compare(ldns_rr_list_rr(q, i),
ldns_rr_list_rr(p, i)) != 0) {
verbose(3, "rr %u different", (unsigned)i);
return 0;
}
/* and check the ttl */
if(ldns_rr_ttl(ldns_rr_list_rr(q, i)) !=
ldns_rr_ttl(ldns_rr_list_rr(p, i))) {
verbose(3, "rr %u ttl different", (unsigned)i);
return 0;
}
}
return 1;
}
/** match edns sections */
static int
match_edns(ldns_pkt* q, ldns_pkt* p)
{
if(ldns_pkt_edns_udp_size(q) != ldns_pkt_edns_udp_size(p))
return 0;
if(ldns_pkt_edns_extended_rcode(q) != ldns_pkt_edns_extended_rcode(p))
return 0;
if(ldns_pkt_edns_version(q) != ldns_pkt_edns_version(p))
return 0;
if(ldns_pkt_edns_do(q) != ldns_pkt_edns_do(p))
return 0;
if(ldns_pkt_edns_z(q) != ldns_pkt_edns_z(p))
return 0;
if(ldns_rdf_compare(ldns_pkt_edns_data(q), ldns_pkt_edns_data(p)) != 0)
return 0;
return 1;
}
/** compare two booleans */
static int
cmp_bool(int x, int y)
{
if(!x && !y) return 0;
if(x && y) return 0;
if(!x) return -1;
return 1;
}
/** match all of the packet */
static int
match_all(ldns_pkt* q, ldns_pkt* p)
{
if(ldns_pkt_get_opcode(q) != ldns_pkt_get_opcode(p))
{ verbose(3, "allmatch: opcode different"); return 0;}
if(ldns_pkt_get_rcode(q) != ldns_pkt_get_rcode(p))
{ verbose(3, "allmatch: rcode different"); return 0;}
if(ldns_pkt_id(q) != ldns_pkt_id(p))
{ verbose(3, "allmatch: id different"); return 0;}
if(cmp_bool(ldns_pkt_qr(q), ldns_pkt_qr(p)) != 0)
{ verbose(3, "allmatch: qr different"); return 0;}
if(cmp_bool(ldns_pkt_aa(q), ldns_pkt_aa(p)) != 0)
{ verbose(3, "allmatch: aa different"); return 0;}
if(cmp_bool(ldns_pkt_tc(q), ldns_pkt_tc(p)) != 0)
{ verbose(3, "allmatch: tc different"); return 0;}
if(cmp_bool(ldns_pkt_rd(q), ldns_pkt_rd(p)) != 0)
{ verbose(3, "allmatch: rd different"); return 0;}
if(cmp_bool(ldns_pkt_cd(q), ldns_pkt_cd(p)) != 0)
{ verbose(3, "allmatch: cd different"); return 0;}
if(cmp_bool(ldns_pkt_ra(q), ldns_pkt_ra(p)) != 0)
{ verbose(3, "allmatch: ra different"); return 0;}
if(cmp_bool(ldns_pkt_ad(q), ldns_pkt_ad(p)) != 0)
{ verbose(3, "allmatch: ad different"); return 0;}
if(ldns_pkt_qdcount(q) != ldns_pkt_qdcount(p))
{ verbose(3, "allmatch: qdcount different"); return 0;}
if(ldns_pkt_ancount(q) != ldns_pkt_ancount(p))
{ verbose(3, "allmatch: ancount different"); return 0;}
if(ldns_pkt_nscount(q) != ldns_pkt_nscount(p))
{ verbose(3, "allmatch: nscount different"); return 0;}
if(ldns_pkt_arcount(q) != ldns_pkt_arcount(p))
{ verbose(3, "allmatch: arcount different"); return 0;}
if(!match_list(ldns_pkt_question(q), ldns_pkt_question(p)))
{ verbose(3, "allmatch: qd section different"); return 0;}
if(!match_list(ldns_pkt_answer(q), ldns_pkt_answer(p)))
{ verbose(3, "allmatch: an section different"); return 0;}
if(!match_list(ldns_pkt_authority(q), ldns_pkt_authority(p)))
{ verbose(3, "allmatch: ns section different"); return 0;}
if(!match_list(ldns_pkt_additional(q), ldns_pkt_additional(p)))
{ verbose(3, "allmatch: ar section different"); return 0;}
if(!match_edns(q, p))
{ verbose(3, "edns different."); return 0;}
return 1;
}
/** see if buffers contain the same packet */
static int
test_buffers(ldns_buffer* pkt, ldns_buffer* out)
{
ldns_pkt* p1=0, *p2=0;
ldns_status s1, s2;
/* check binary same */
if(ldns_buffer_limit(pkt) == ldns_buffer_limit(out) &&
memcmp(ldns_buffer_begin(pkt), ldns_buffer_begin(out),
ldns_buffer_limit(pkt)) == 0) {
if(vbmp) printf("binary the same (length=%u)\n",
(unsigned)ldns_buffer_limit(pkt));
return 1;
}
if(vbmp) {
size_t sz = 16;
size_t count;
size_t lim = ldns_buffer_limit(out);
if(ldns_buffer_limit(pkt) < lim)
lim = ldns_buffer_limit(pkt);
for(count=0; count<lim; count+=sz) {
size_t rem = sz;
if(lim-count < sz) rem = lim-count;
if(memcmp(ldns_buffer_at(pkt, count),
ldns_buffer_at(out, count), rem) == 0) {
log_info("same %d %d", (int)count, (int)rem);
log_hex("same: ", ldns_buffer_at(pkt, count),
rem);
} else {
log_info("diff %d %d", (int)count, (int)rem);
log_hex("difp: ", ldns_buffer_at(pkt, count),
rem);
log_hex("difo: ", ldns_buffer_at(out, count),
rem);
}
}
}
/* check if it 'means the same' */
s1 = ldns_buffer2pkt_wire(&p1, pkt);
s2 = ldns_buffer2pkt_wire(&p2, out);
if(vbmp) {
log_hex("orig in hex", ldns_buffer_begin(pkt),
ldns_buffer_limit(pkt));
log_hex("unbound out in hex", ldns_buffer_begin(out),
ldns_buffer_limit(out));
printf("\npacket from unbound (%d):\n",
(int)ldns_buffer_limit(out));
ldns_pkt_print(stdout, p2);
printf("\npacket original (%d):\n",
(int)ldns_buffer_limit(pkt));
ldns_pkt_print(stdout, p1);
printf("\n");
}
if(s1 != s2) {
/* oops! */
printf("input ldns parse: %s, output ldns parse: %s.\n",
ldns_get_errorstr_by_id(s1),
ldns_get_errorstr_by_id(s2));
unit_assert(0);
}
/* compare packets */
unit_assert(match_all(p1, p2));
ldns_pkt_free(p1);
ldns_pkt_free(p2);
return 0;
}
/** check if unbound formerr equals ldns formerr */
static void
checkformerr(ldns_buffer* pkt)
{
ldns_pkt* p;
ldns_status status = ldns_buffer2pkt_wire(&p, pkt);
if(vbmp) printf("formerr, ldns parse is: %s\n",
ldns_get_errorstr_by_id(status));
if(status == LDNS_STATUS_OK) {
printf("Formerr, but ldns gives packet:\n");
ldns_pkt_print(stdout, p);
exit(1);
}
unit_assert(status != LDNS_STATUS_OK);
}
/** test a packet */
static void
testpkt(ldns_buffer* pkt, struct alloc_cache* alloc, ldns_buffer* out,
const char* hex)
{
struct query_info qi;
struct reply_info* rep = 0;
int ret;
uint16_t id;
uint16_t flags;
uint32_t timenow = 0;
region_type *region = region_create(malloc, free);
struct edns_data edns;
hex_to_buf(pkt, hex);
memmove(&id, ldns_buffer_begin(pkt), sizeof(id));
if(ldns_buffer_limit(pkt) < 2)
flags = 0;
else memmove(&flags, ldns_buffer_at(pkt, 2), sizeof(flags));
flags = ntohs(flags);
ret = reply_info_parse(pkt, alloc, &qi, &rep, region, &edns);
if(ret != 0) {
if(vbmp) printf("parse code %d: %s\n", ret,
ldns_lookup_by_id(ldns_rcodes, ret)->name);
if(ret == LDNS_RCODE_FORMERR)
checkformerr(pkt);
unit_assert(ret != LDNS_RCODE_SERVFAIL);
} else {
const size_t lim = 512;
ret = reply_info_encode(&qi, rep, id, flags, out, timenow,
region, 65535, (int)(edns.bits & EDNS_DO) );
unit_assert(ret != 0); /* udp packets should fit */
attach_edns_record(out, &edns);
if(vbmp) printf("inlen %u outlen %u\n",
(unsigned)ldns_buffer_limit(pkt),
(unsigned)ldns_buffer_limit(out));
test_buffers(pkt, out);
if(ldns_buffer_limit(out) > lim) {
ret = reply_info_encode(&qi, rep, id, flags, out,
timenow, region,
lim - calc_edns_field_size(&edns),
(int)(edns.bits & EDNS_DO));
unit_assert(ret != 0); /* should fit, but with TC */
attach_edns_record(out, &edns);
if( LDNS_QDCOUNT(ldns_buffer_begin(out)) !=
LDNS_QDCOUNT(ldns_buffer_begin(pkt)) ||
LDNS_ANCOUNT(ldns_buffer_begin(out)) !=
LDNS_ANCOUNT(ldns_buffer_begin(pkt)) ||
LDNS_NSCOUNT(ldns_buffer_begin(out)) !=
LDNS_NSCOUNT(ldns_buffer_begin(pkt)))
unit_assert(
LDNS_TC_WIRE(ldns_buffer_begin(out)));
/* must set TC bit if shortened */
unit_assert(ldns_buffer_limit(out) <= lim);
}
}
query_info_clear(&qi);
reply_info_parsedelete(rep, alloc);
region_destroy(region);
}
/** simple test of parsing */
static void
simpletest(ldns_buffer* pkt, struct alloc_cache* alloc, ldns_buffer* out)
{
/* a root query drill -q - */
testpkt(pkt, alloc, out,
" c5 40 01 00 00 01 00 00 00 00 00 00 00 00 02 00 01 ");
/* very small packet */
testpkt(pkt, alloc, out,
"; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19\n"
";-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --\n"
"74 0c 85 83 00 01 00 00 00 01 00 00 03 62 6c 61 09 6e 6c 6e ; 1- 20\n"
"65 74 6c 61 62 73 02 6e 6c 00 00 0f 00 01 09 6e 6c 6e 65 74 ; 21- 40\n"
"6c 61 62 73 02 6e 6c 00 00 06 00 01 00 00 46 50 00 40 04 6f ; 41- 60\n"
"70 65 6e 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 0a 68 6f ; 61- 80\n"
"73 74 6d 61 73 74 65 72 09 6e 6c 6e 65 74 6c 61 62 73 02 6e ; 81- 100\n"
"6c 00 77 a1 02 58 00 00 70 80 00 00 1c 20 00 09 3a 80 00 00 ; 101- 120\n"
"46 50\n");
/* a root reply drill -w - */
testpkt(pkt, alloc, out,
" ; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19\n"
" ;-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --\n"
" 97 3f 81 80 00 01 00 0d 00 00 00 02 00 00 02 00 01 00 00 02 ; 1- 20\n"
" 00 01 00 06 6d 38 00 14 01 49 0c 52 4f 4f 54 2d 53 45 52 56 ; 21- 40\n"
" 45 52 53 03 4e 45 54 00 00 00 02 00 01 00 06 6d 38 00 14 01 ; 41- 60\n"
" 4a 0c 52 4f 4f 54 2d 53 45 52 56 45 52 53 03 4e 45 54 00 00 ; 61- 80\n"
" 00 02 00 01 00 06 6d 38 00 14 01 4b 0c 52 4f 4f 54 2d 53 45 ; 81- 100\n"
" 52 56 45 52 53 03 4e 45 54 00 00 00 02 00 01 00 06 6d 38 00 ; 101- 120\n"
" 14 01 4c 0c 52 4f 4f 54 2d 53 45 52 56 45 52 53 03 4e 45 54 ; 121- 140\n"
" 00 00 00 02 00 01 00 06 6d 38 00 14 01 4d 0c 52 4f 4f 54 2d ; 141- 160\n"
" 53 45 52 56 45 52 53 03 4e 45 54 00 00 00 02 00 01 00 06 6d ; 161- 180\n"
" 38 00 14 01 41 0c 52 4f 4f 54 2d 53 45 52 56 45 52 53 03 4e ; 181- 200\n"
" 45 54 00 00 00 02 00 01 00 06 6d 38 00 14 01 42 0c 52 4f 4f ; 201- 220\n"
" 54 2d 53 45 52 56 45 52 53 03 4e 45 54 00 00 00 02 00 01 00 ; 221- 240\n"
" 06 6d 38 00 14 01 43 0c 52 4f 4f 54 2d 53 45 52 56 45 52 53 ; 241- 260\n"
" 03 4e 45 54 00 00 00 02 00 01 00 06 6d 38 00 14 01 44 0c 52 ; 261- 280\n"
" 4f 4f 54 2d 53 45 52 56 45 52 53 03 4e 45 54 00 00 00 02 00 ; 281- 300\n"
" 01 00 06 6d 38 00 14 01 45 0c 52 4f 4f 54 2d 53 45 52 56 45 ; 301- 320\n"
" 52 53 03 4e 45 54 00 00 00 02 00 01 00 06 6d 38 00 14 01 46 ; 321- 340\n"
" 0c 52 4f 4f 54 2d 53 45 52 56 45 52 53 03 4e 45 54 00 00 00 ; 341- 360\n"
" 02 00 01 00 06 6d 38 00 14 01 47 0c 52 4f 4f 54 2d 53 45 52 ; 361- 380\n"
" 56 45 52 53 03 4e 45 54 00 00 00 02 00 01 00 06 6d 38 00 14 ; 381- 400\n"
" 01 48 0c 52 4f 4f 54 2d 53 45 52 56 45 52 53 03 4e 45 54 00 ; 401- 420\n"
" 01 41 0c 52 4f 4f 54 2d 53 45 52 56 45 52 53 03 4e 45 54 00 ; 421- 440\n"
" 00 01 00 01 00 02 64 b9 00 04 c6 29 00 04 01 4a 0c 52 4f 4f ; 441- 460\n"
" 54 2d 53 45 52 56 45 52 53 03 4e 45 54 00 00 01 00 01 00 02 ; 461- 480\n"
" 64 b9 00 04 c0 3a 80 1e ");
}
/** simple test of parsing, pcat file */
static void
testfromfile(ldns_buffer* pkt, struct alloc_cache* alloc, ldns_buffer* out,
const char* fname)
{
FILE* in = fopen(fname, "r");
char buf[102400];
int no=0;
if(!in) {
perror("fname");
return;
}
while(fgets(buf, (int)sizeof(buf), in)) {
if(buf[0] == ';') /* comment */
continue;
if(strlen(buf) < 10) /* skip pcat line numbers. */
continue;
if(vbmp) {
printf("test no %d: %s", no, buf);
fflush(stdout);
}
testpkt(pkt, alloc, out, buf);
no++;
}
fclose(in);
}
/** simple test of parsing, drill file */
static void
testfromdrillfile(ldns_buffer* pkt, struct alloc_cache* alloc,
ldns_buffer* out, const char* fname)
{
/* ;-- is used to indicate a new message */
FILE* in = fopen(fname, "r");
char buf[102400];
char* np = buf;
buf[0]=0;
if(!in) {
perror("fname");
return;
}
while(fgets(np, (int)sizeof(buf) - (np-buf), in)) {
if(strncmp(np, ";--", 3) == 0) {
/* new entry */
/* test previous */
if(np != buf)
testpkt(pkt, alloc, out, buf);
/* set for new entry */
np = buf;
buf[0]=0;
continue;
}
if(np[0] == ';') /* comment */
continue;
np = &np[strlen(np)];
}
testpkt(pkt, alloc, out, buf);
fclose(in);
}
void msgparse_test()
{
ldns_buffer* pkt = ldns_buffer_new(65553);
ldns_buffer* out = ldns_buffer_new(65553);
struct alloc_cache super_a, alloc;
/* init */
alloc_init(&super_a, NULL, 0);
alloc_init(&alloc, &super_a, 2);
printf("testmsgparse\n");
simpletest(pkt, &alloc, out);
/* plain hex dumps, like pcat */
testfromfile(pkt, &alloc, out, "testdata/test_packets.1");
testfromfile(pkt, &alloc, out, "testdata/test_packets.2");
testfromfile(pkt, &alloc, out, "testdata/test_packets.3");
/* like from drill -w - */
testfromdrillfile(pkt, &alloc, out, "testdata/test_packets.4");
testfromdrillfile(pkt, &alloc, out, "testdata/test_packets.5");
/* cleanup */
alloc_clear(&alloc);
alloc_clear(&super_a);
ldns_buffer_free(pkt);
ldns_buffer_free(out);
}
+11 -12
View File
@@ -62,19 +62,19 @@ static size_t test_sizefunc(void*, void*);
/** comparefunc for lruhash */
static int test_compfunc(void*, void*);
/** delkey for lruhash */
static void test_delkey(void*, void*, int);
static void test_delkey(void*, void*);
/** deldata for lruhash */
static void test_deldata(void*, void*);
/* --- end test representation --- */
/** hash func, very bad to improve collisions, both high and low bits */
/** hash func, very bad to improve collisions, both high and low bits. */
static hashvalue_t myhash(int id) {
hashvalue_t h = (hashvalue_t)id & 0x0f;
h |= (h << 28);
return h;
}
/** allocate new key, fill in hash */
/** allocate new key, fill in hash. */
static struct slabtestkey* newkey(int id) {
struct slabtestkey* k = (struct slabtestkey*)calloc(1, sizeof(struct slabtestkey));
if(!k) fatal_exit("out of memory");
@@ -110,8 +110,8 @@ test_short_table(struct slabhash* table)
k->entry.data = d;
k2->entry.data = d2;
slabhash_insert(table, myhash(12), &k->entry, d, NULL);
slabhash_insert(table, myhash(14), &k2->entry, d2, NULL);
slabhash_insert(table, myhash(12), &k->entry, d);
slabhash_insert(table, myhash(14), &k2->entry, d2);
unit_assert( slabhash_lookup(table, myhash(12), k, 0) == &k->entry);
lock_rw_unlock( &k->entry.lock );
@@ -132,7 +132,7 @@ testadd(struct slabhash* table, struct slabtestdata* ref[])
struct slabtestdata* data = newdata(numtoadd);
struct slabtestkey* key = newkey(numtoadd);
key->entry.data = data;
slabhash_insert(table, myhash(numtoadd), &key->entry, data, NULL);
slabhash_insert(table, myhash(numtoadd), &key->entry, data);
ref[numtoadd] = data;
}
@@ -219,7 +219,7 @@ testadd_unlim(struct slabhash* table, struct slabtestdata** ref)
struct slabtestdata* data = newdata(numtoadd);
struct slabtestkey* key = newkey(numtoadd);
key->entry.data = data;
slabhash_insert(table, myhash(numtoadd), &key->entry, data, NULL);
slabhash_insert(table, myhash(numtoadd), &key->entry, data);
if(ref)
ref[numtoadd] = data;
}
@@ -351,7 +351,7 @@ test_thr_main(void* arg)
return NULL;
}
/** test hash table access by multiple threads */
/** test hash table access by multiple threads. */
static void
test_threaded_table(struct slabhash* table)
{
@@ -377,12 +377,12 @@ void slabhash_test()
/* also small in size so that reclaim has to be done quickly. */
struct slabhash* table;
printf("slabhash test\n");
table = slabhash_create(4, 2, 5200,
table = slabhash_create(4, 2, 4096,
test_sizefunc, test_compfunc, test_delkey, test_deldata, NULL);
test_short_table(table);
test_long_table(table);
slabhash_delete(table);
table = slabhash_create(4, 2, 5200,
table = slabhash_create(4, 2, 4096,
test_sizefunc, test_compfunc, test_delkey, test_deldata, NULL);
test_threaded_table(table);
slabhash_delete(table);
@@ -404,9 +404,8 @@ static int test_compfunc(void* key1, void* key2)
return -1;
}
static void test_delkey(void* key, void* ATTR_UNUSED(arg), int l)
static void test_delkey(void* key, void* ATTR_UNUSED(arg))
{
if(l) { lock_rw_unlock(&((struct slabtestkey*)key)->entry.lock); }
delkey((struct slabtestkey*)key);
}
-149
View File
@@ -1,149 +0,0 @@
; config options
stub-zone:
name: "."
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
CONFIG_END
SCENARIO_BEGIN Fetch glue when missing or timed out.
; 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
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.
; is missing the glue!
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
ns.example.com. IN A
SECTION ANSWER
ns.example.com. IN A 1.2.3.4
SECTION AUTHORITY
example.com. IN NS ns.example.com.
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
ns.example.com. IN AAAA
SECTION AUTHORITY
example.com. IN NS ns.example.com.
ENTRY_END
RANGE_END
; ns.example.com.
RANGE_BEGIN 0 100
ADDRESS 1.2.3.4
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. IN A 10.20.30.40
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
ns.example.com. IN A
SECTION ANSWER
ns.example.com. IN A 1.2.3.4
SECTION AUTHORITY
example.com. IN NS ns.example.com.
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
ns.example.com. IN AAAA
SECTION AUTHORITY
example.com. IN NS ns.example.com.
SECTION ADDITIONAL
ns.example.com. IN A 1.2.3.4
ENTRY_END
RANGE_END
STEP 1 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
; recursion happens here.
STEP 10 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. IN A 10.20.30.40
SECTION AUTHORITY
example.com. IN NS ns.example.com.
SECTION ADDITIONAL
ns.example.com. IN A 1.2.3.4
ENTRY_END
; due to ordering of answer packets, this is still outstanding, remove it
STEP 21 CHECK_OUT_QUERY
ENTRY_BEGIN
ADJUST copy_id
MATCH qname qtype
REPLY QR
SECTION QUESTION
ns.example.com IN AAAA
ENTRY_END
SCENARIO_END
-1
View File
@@ -1,6 +1,5 @@
; This is a comment.
; config options go here.
forward-zone: name: "." forward-addr: 216.0.0.1
CONFIG_END
SCENARIO_BEGIN Sample of a valid query
+2 -2
View File
@@ -1,6 +1,5 @@
; This is a comment.
; config options go here.
forward-zone: name: "." forward-addr: 216.0.0.1
CONFIG_END
SCENARIO_BEGIN Query receives answer from the cache
@@ -36,7 +35,8 @@ ENTRY_END
STEP 4 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA
; first reply, have AA set.
REPLY QR AA RD RA
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
+1 -2
View File
@@ -1,5 +1,4 @@
; config options go here.
forward-zone: name: "." forward-addr: 216.0.0.1
CONFIG_END
SCENARIO_BEGIN Forwarder and an error happens on server query.
STEP 1 QUERY
@@ -14,7 +13,7 @@ STEP 4 CHECK_ANSWER
ENTRY_BEGIN
MATCH opcode qname qtype
SECTION QUESTION
REPLY SERVFAIL QR RA
REPLY SERVFAIL QR
MATCH all
www.example.com. IN A
ENTRY_END
-1
View File
@@ -4,7 +4,6 @@
server:
msg-cache-size: 1 # one whole byte!
msg-cache-slabs: 1
forward-zone: name: "." forward-addr: 216.0.0.1
CONFIG_END
SCENARIO_BEGIN Old answer is dropped from the cache
BIN
View File
Binary file not shown.
-3
View File
@@ -5,9 +5,6 @@
; here config file options:
server:
msg-cache-size: 1024
forward-zone:
name: "."
forward-addr: 216.0.0.1
CONFIG_END
SCENARIO_BEGIN Query receives answer not from the cache
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+1 -2
View File
@@ -1,5 +1,4 @@
; config options go here.
forward-zone: name: "." forward-addr: 216.0.0.1
CONFIG_END
SCENARIO_BEGIN Forwarder and a timeout happens on server query.
STEP 1 QUERY
@@ -14,7 +13,7 @@ STEP 4 CHECK_ANSWER
ENTRY_BEGIN
MATCH opcode qname qtype
SECTION QUESTION
REPLY SERVFAIL QR RA
REPLY SERVFAIL QR
MATCH all
www.example.com. IN A
ENTRY_END
BIN
View File
Binary file not shown.
-12
View File
@@ -1,9 +1,6 @@
; config options go here.
server:
num-queries-per-thread: 1
forward-zone:
name: "."
forward-addr: 216.0.0.1
CONFIG_END
SCENARIO_BEGIN Sample of a valid query
@@ -71,15 +68,6 @@ www.example.com. IN A
SECTION ANSWER
www.example.com. IN A 10.20.30.40
ENTRY_END
STEP 11 CHECK_ANSWER
ENTRY_BEGIN
MATCH opcode qname qtype
SECTION QUESTION
www.example.net. IN A
SECTION ANSWER
www.example.net. IN A 10.20.30.40
ENTRY_END
SCENARIO_END
; testbound checks before exit:
BIN
View File
Binary file not shown.
-151
View File
@@ -1,151 +0,0 @@
; config options
stub-zone:
name: "."
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
CONFIG_END
SCENARIO_BEGIN Test resolution with dependency cycle
; query for ns.example.com, needs ns.example.net, needs ns.example.com.
; 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
ns.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
ns.example.com. IN AAAA
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
ns.example.net. IN A
SECTION AUTHORITY
net. IN NS e.gtld-servers.net.
SECTION ADDITIONAL
e.gtld-servers.net. IN A 192.12.94.30
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
ns.example.net. IN AAAA
SECTION AUTHORITY
net. IN NS e.gtld-servers.net.
SECTION ADDITIONAL
e.gtld-servers.net. IN A 192.12.94.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
ns.example.com. IN A
SECTION AUTHORITY
example.com. IN NS ns.example.net.
SECTION ADDITIONAL
; note this will be scrubbed off
ns.example.net. IN A 1.2.3.1
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
ns.example.com. IN AAAA
SECTION AUTHORITY
example.com. IN NS ns.example.net.
SECTION ADDITIONAL
; note this will be scrubbed off
ns.example.net. IN A 1.2.3.1
ENTRY_END
RANGE_END
; e.gtld-servers.net.
RANGE_BEGIN 0 100
ADDRESS 192.12.94.30
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
ns.example.net. IN A
SECTION AUTHORITY
example.net. IN NS ns.example.com.
SECTION ADDITIONAL
; note this will be scrubbed off
ns.example.com. IN A 1.2.3.2
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
ns.example.net. IN AAAA
SECTION AUTHORITY
example.net. IN NS ns.example.com.
SECTION ADDITIONAL
; note this will be scrubbed off
ns.example.com. IN A 1.2.3.2
ENTRY_END
RANGE_END
STEP 1 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
ns.example.com. IN A
ENTRY_END
; recursion happens here.
; cycle detected and it fails.
STEP 20 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA SERVFAIL
SECTION QUESTION
ns.example.com. IN A
ENTRY_END
SCENARIO_END
-175
View File
@@ -1,175 +0,0 @@
; config options
server:
harden-glue: "no"
stub-zone:
name: "."
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
CONFIG_END
SCENARIO_BEGIN Test resolution where disabled scrubber avoids cycle
; query for ns.example.com, needs ns.example.net, needs ns.example.com.
; scrubber disabled, so extra glue is trusted.
; 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
ns.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
ns.example.com. IN AAAA
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
ns.example.net. IN A
SECTION AUTHORITY
net. IN NS e.gtld-servers.net.
SECTION ADDITIONAL
e.gtld-servers.net. IN A 192.12.94.30
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
ns.example.net. IN AAAA
SECTION AUTHORITY
net. IN NS e.gtld-servers.net.
SECTION ADDITIONAL
e.gtld-servers.net. IN A 192.12.94.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
ns.example.com. IN A
SECTION AUTHORITY
example.com. IN NS ns.example.net.
SECTION ADDITIONAL
ns.example.net. IN A 1.2.3.1
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
ns.example.com. IN AAAA
SECTION AUTHORITY
example.com. IN NS ns.example.net.
SECTION ADDITIONAL
ns.example.net. IN A 1.2.3.1
ENTRY_END
RANGE_END
; e.gtld-servers.net.
RANGE_BEGIN 0 100
ADDRESS 192.12.94.30
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
ns.example.net. IN A
SECTION AUTHORITY
example.net. IN NS ns.example.com.
SECTION ADDITIONAL
ns.example.com. IN A 1.2.3.2
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
ns.example.net. IN AAAA
SECTION AUTHORITY
example.net. IN NS ns.example.com.
SECTION ADDITIONAL
ns.example.com. IN A 1.2.3.2
ENTRY_END
RANGE_END
; ns.example.net.
RANGE_BEGIN 0 100
ADDRESS 1.2.3.1
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
ns.example.com. IN A
SECTION ANSWER
ns.example.com. IN A 1.2.3.2
SECTION AUTHORITY
example.com. IN NS ns.example.net.
SECTION ADDITIONAL
ns.example.net. IN A 1.2.3.1
ENTRY_END
RANGE_END
STEP 1 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
ns.example.com. IN A
ENTRY_END
; recursion happens here.
; cycle detected and it fails.
STEP 20 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA
SECTION QUESTION
ns.example.com. IN A
SECTION ANSWER
ns.example.com. IN A 1.2.3.2
SECTION AUTHORITY
example.com. IN NS ns.example.net.
; scrubbed off
; SECTION ADDITIONAL
; ns.example.net. IN A 1.2.3.1
ENTRY_END
SCENARIO_END
-178
View File
@@ -1,178 +0,0 @@
; config options
stub-zone:
name: "."
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
CONFIG_END
SCENARIO_BEGIN Test resolution with recursion for NS target.
; 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
ns.example.net. IN A
SECTION AUTHORITY
net. IN NS e.gtld-servers.net.
SECTION ADDITIONAL
e.gtld-servers.net. IN A 192.12.94.30
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
ns.example.net. IN AAAA
SECTION AUTHORITY
net. IN NS e.gtld-servers.net.
SECTION ADDITIONAL
e.gtld-servers.net. IN A 192.12.94.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.net.
ENTRY_END
RANGE_END
; e.gtld-servers.net.
RANGE_BEGIN 0 100
ADDRESS 192.12.94.30
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
ns.example.net. IN A
SECTION AUTHORITY
example.net. IN NS ns.example.net.
SECTION ADDITIONAL
ns.example.net. IN A 1.2.3.44
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
ns.example.net. IN AAAA
SECTION AUTHORITY
example.net. IN NS ns.example.net.
SECTION ADDITIONAL
ns.example.net. IN A 1.2.3.44
ENTRY_END
RANGE_END
; ns.example.net.
RANGE_BEGIN 0 100
ADDRESS 1.2.3.44
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
ns.example.net. IN A
SECTION ANSWER
ns.example.net. IN A 1.2.3.44
SECTION AUTHORITY
example.net. IN NS ns.example.net.
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
ns.example.net. IN AAAA
SECTION AUTHORITY
example.net. IN NS ns.example.net.
SECTION ADDITIONAL
www.example.net. IN A 1.2.3.44
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. IN A 10.20.30.40
SECTION AUTHORITY
example.com. IN NS ns.example.net.
SECTION ADDITIONAL
ns.example.net IN A 1.2.3.44
ENTRY_END
RANGE_END
STEP 1 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
; recursion happens here.
STEP 20 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. IN A 10.20.30.40
SECTION AUTHORITY
example.com. IN NS ns.example.net.
; scrubbed off
;SECTION ADDITIONAL
;ns.example.net IN A 1.2.3.44
ENTRY_END
; due to ordering of answer packets, this is still outstanding, remove it
STEP 21 CHECK_OUT_QUERY
ENTRY_BEGIN
ADJUST copy_id
MATCH qname qtype
REPLY QR
SECTION QUESTION
ns.example.net IN AAAA
ENTRY_END
SCENARIO_END
-93
View File
@@ -1,93 +0,0 @@
; config options
stub-zone:
name: "."
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
CONFIG_END
SCENARIO_BEGIN Test basic iterative resolve of www.example.com.
; 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
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
RANGE_END
; ns.example.com.
RANGE_BEGIN 0 100
ADDRESS 1.2.3.4
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. IN A 10.20.30.40
SECTION AUTHORITY
example.com. IN NS ns.example.com.
SECTION ADDITIONAL
ns.example.com. IN A 1.2.3.4
ENTRY_END
RANGE_END
STEP 1 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
; recursion happens here.
STEP 10 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. IN A 10.20.30.40
SECTION AUTHORITY
example.com. IN NS ns.example.com.
SECTION ADDITIONAL
ns.example.com. IN A 1.2.3.4
ENTRY_END
SCENARIO_END
-37
View File
@@ -1,37 +0,0 @@
; config options
CONFIG_END
SCENARIO_BEGIN Test AXFR and IXFR queries.
; AXFR
STEP 1 QUERY
ENTRY_BEGIN
SECTION QUESTION
nlnetlabs.nl. IN AXFR
ENTRY_END
STEP 2 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR REFUSED
SECTION QUESTION
nlnetlabs.nl. IN AXFR
ENTRY_END
; IXFR
STEP 3 QUERY
ENTRY_BEGIN
SECTION QUESTION
nlnetlabs.nl. IN IXFR
SECTION AUTHORITY
nlnetlabs.nl. IN SOA mr. op. 12 0 0 0 0
ENTRY_END
STEP 4 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR FORMERR
SECTION QUESTION
nlnetlabs.nl. IN IXFR
SECTION AUTHORITY
nlnetlabs.nl. IN SOA mr. op. 12 0 0 0 0
ENTRY_END
SCENARIO_END
-118
View File
@@ -1,118 +0,0 @@
; This is a comment.
; config options go here.
forward-zone: name: "." forward-addr: 216.0.0.1
CONFIG_END
SCENARIO_BEGIN RRset TTL is updated from message.
STEP 1 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
; the query is sent to the forwarder - no cache yet.
STEP 2 CHECK_OUT_QUERY
ENTRY_BEGIN
MATCH qname qtype opcode
SECTION QUESTION
www.example.com. IN A
ENTRY_END
STEP 3 REPLY
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
; authoritative answer
REPLY QR AA RD RA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. IN A 10.20.30.40
SECTION AUTHORITY
example.com. 100 IN NS ns.example.com.
SECTION ADDITIONAL
ns.example.com. IN A 10.20.30.50
ENTRY_END
STEP 4 CHECK_ANSWER
ENTRY_BEGIN
MATCH all ttl
REPLY QR RD RA
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. IN A 10.20.30.40
SECTION AUTHORITY
example.com. 100 IN NS ns.example.com.
SECTION ADDITIONAL
ns.example.com. IN A 10.20.30.50
ENTRY_END
; another query passes along
STEP 6 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
bla.example.com. IN A
ENTRY_END
STEP 7 CHECK_OUT_QUERY
ENTRY_BEGIN
MATCH qname qtype opcode
SECTION QUESTION
bla.example.com. IN A
ENTRY_END
STEP 8 REPLY
; This answer has a fresh TTL
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
; authoritative answer
REPLY QR AA RD RA NOERROR
SECTION QUESTION
bla.example.com. IN A
SECTION ANSWER
bla.example.com. IN A 10.20.30.140
SECTION AUTHORITY
example.com. 200 IN NS ns.example.com.
SECTION ADDITIONAL
ns.example.com. IN A 10.20.30.50
ENTRY_END
STEP 9 CHECK_ANSWER
ENTRY_BEGIN
MATCH all ttl
REPLY QR RD RA
SECTION QUESTION
bla.example.com. IN A
SECTION ANSWER
bla.example.com. IN A 10.20.30.140
SECTION AUTHORITY
example.com. 200 IN NS ns.example.com.
SECTION ADDITIONAL
ns.example.com. IN A 10.20.30.50
ENTRY_END
; original www.example.com query
STEP 10 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
; immediate answer without an OUT_QUERY happening (checked on exit)
; also, the answer does not have AA set
; NS rrset has been updated.
STEP 11 CHECK_ANSWER
ENTRY_BEGIN
MATCH all ttl
REPLY QR RD RA
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. IN A 10.20.30.40
SECTION AUTHORITY
example.com. 200 IN NS ns.example.com.
SECTION ADDITIONAL
ns.example.com. IN A 10.20.30.50
ENTRY_END
SCENARIO_END
-121
View File
@@ -1,121 +0,0 @@
; This is a comment.
; config options go here.
forward-zone: name: "." forward-addr: 216.0.0.1
CONFIG_END
SCENARIO_BEGIN Untrusted rrset not used for update
STEP 1 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
; the query is sent to the forwarder - no cache yet.
STEP 2 CHECK_OUT_QUERY
ENTRY_BEGIN
MATCH qname qtype opcode
SECTION QUESTION
www.example.com. IN A
ENTRY_END
STEP 3 REPLY
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
; authoritative answer
REPLY QR AA RD RA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. IN A 10.20.30.40
SECTION AUTHORITY
example.com. IN NS ns.example.com.
SECTION ADDITIONAL
ns.example.com. IN A 10.20.30.50
ENTRY_END
STEP 4 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. IN A 10.20.30.40
SECTION AUTHORITY
example.com. IN NS ns.example.com.
SECTION ADDITIONAL
ns.example.com. IN A 10.20.30.50
ENTRY_END
; another query passes along
STEP 6 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
bla.example.com. IN A
ENTRY_END
STEP 7 CHECK_OUT_QUERY
ENTRY_BEGIN
MATCH qname qtype opcode
SECTION QUESTION
bla.example.com. IN A
ENTRY_END
STEP 8 REPLY
; This answer has updated information on ns2.example.com.
; But it is nerfed into the additional. Must be ignored per rfc2181.
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
; authoritative answer
REPLY QR AA RD RA NOERROR
SECTION QUESTION
bla.example.com. IN A
SECTION ANSWER
bla.example.com. IN A 10.20.30.140
SECTION AUTHORITY
SECTION ADDITIONAL
example.com. IN NS ns.eeeek.com.
example.com. IN NS ns2.eeeek.com.
ns.eeeek.com. IN A 55.44.33.22
ns2.eeeek.com. IN A 55.44.33.24
ENTRY_END
STEP 9 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA
SECTION QUESTION
bla.example.com. IN A
SECTION ANSWER
bla.example.com. IN A 10.20.30.140
SECTION AUTHORITY
SECTION ADDITIONAL
example.com. IN NS ns.eeeek.com.
example.com. IN NS ns2.eeeek.com.
ENTRY_END
; original www.example.com query
STEP 10 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
; immediate answer without an OUT_QUERY happening (checked on exit)
; also, the answer does not have AA set
; NS rrset has not been updated from the additional seen before.
STEP 11 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. IN A 10.20.30.40
SECTION AUTHORITY
example.com. IN NS ns.example.com.
SECTION ADDITIONAL
ns.example.com. IN A 10.20.30.50
ENTRY_END
SCENARIO_END
-123
View File
@@ -1,123 +0,0 @@
; This is a comment.
; config options go here.
forward-zone: name: "." forward-addr: 216.0.0.1
CONFIG_END
SCENARIO_BEGIN RRset is updated from other message that passes by.
STEP 1 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
; the query is sent to the forwarder - no cache yet.
STEP 2 CHECK_OUT_QUERY
ENTRY_BEGIN
MATCH qname qtype opcode
SECTION QUESTION
www.example.com. IN A
ENTRY_END
STEP 3 REPLY
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
; authoritative answer
REPLY QR AA RD RA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. IN A 10.20.30.40
SECTION AUTHORITY
example.com. IN NS ns.example.com.
SECTION ADDITIONAL
ns.example.com. IN A 10.20.30.50
ENTRY_END
STEP 4 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. IN A 10.20.30.40
SECTION AUTHORITY
example.com. IN NS ns.example.com.
SECTION ADDITIONAL
ns.example.com. IN A 10.20.30.50
ENTRY_END
; another query passes along
STEP 6 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
bla.example.com. IN A
ENTRY_END
STEP 7 CHECK_OUT_QUERY
ENTRY_BEGIN
MATCH qname qtype opcode
SECTION QUESTION
bla.example.com. IN A
ENTRY_END
STEP 8 REPLY
; This answer has updated information on ns2.example.com.
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
; authoritative answer
REPLY QR AA RD RA NOERROR
SECTION QUESTION
bla.example.com. IN A
SECTION ANSWER
bla.example.com. IN A 10.20.30.140
SECTION AUTHORITY
example.com. IN NS ns.example.com.
example.com. IN NS ns2.example.com.
SECTION ADDITIONAL
ns.example.com. IN A 10.20.30.50
ns2.example.com. IN A 10.20.30.53
ENTRY_END
STEP 9 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA
SECTION QUESTION
bla.example.com. IN A
SECTION ANSWER
bla.example.com. IN A 10.20.30.140
SECTION AUTHORITY
example.com. IN NS ns.example.com.
example.com. IN NS ns2.example.com.
SECTION ADDITIONAL
ns.example.com. IN A 10.20.30.50
ns2.example.com. IN A 10.20.30.53
ENTRY_END
; original www.example.com query
STEP 10 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
; immediate answer without an OUT_QUERY happening (checked on exit)
; also, the answer does not have AA set
; NS rrset has been updated.
STEP 11 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. IN A 10.20.30.40
SECTION AUTHORITY
example.com. IN NS ns.example.com.
example.com. IN NS ns2.example.com.
SECTION ADDITIONAL
ns.example.com. IN A 10.20.30.50
ENTRY_END
SCENARIO_END
-80000
View File
File diff suppressed because it is too large Load Diff
-50
View File
@@ -1,50 +0,0 @@
b29092340000000000000000
289
98d50000000100000000000003626c3402626c06787334616c6c026e6c0000010001
98d58000000100000003000203626c3402626c06787334616c6c026e6c0000010001c01300020001000151800005026e73c013c01300020001000151800006036e7332c013c0130002000100015180000d026e730472697065036e657400c02e00010001000151800004c26d0642c03f00010001000151800004c26d0963
290
b28f6a4e5011431228310000000000000000
b28fea440000000000000000
291
de6028000001000000010000026e6c0000060001055f6c646170045f746370026463065f6d736463730b6f7372646f6d65696e2d31026e6c00002100010000025800230000006401850c504f574552454447452d53420b6f7372646f6d65696e2d31026e6c00
de60a8040000000000000000
292
b353000000010000000000000450434b4e087963646f6d65696e026e6c0000010001
b353840300010000000100000450434b4e087963646f6d65696e026e6c0000010001c01a00060001000038400036026e730f646f6d61696e2d7265676973747279c01a0a686f73746d6173746572c0310bf1e540000070800000384000278d0000003840
293
b2901243501140a2340b0000000000000000
b29092440000000000000000
294
b28f6a4f5010431228300000000000000000
b28fea440000000000000000
295
e0f600000001000000000000066b6d742d6570026e6c0000020001
e0f680000001000000020002066b6d742d6570026e6c0000020001c00c0002000100015180000c036e73310564656d6f6ec013c00c00020001000151800006036e7332c02bc02700010001000151800004c29f4906c03f00010001000151800004c29fb004
296
0000000070024000a52500000204056401010402
000080010000000000000000
297
000000007002400088e600000204059801010402
000080010000000000000000
298
00000000700240001f5900000204059801010402
000080010000000000000000
299
b2901244501040a2340a0000000000000000
b29092440000000000000000
300
b293149b50104320eb2f0000000000000000
b29394940000000000000000
-496
View File
@@ -1,496 +0,0 @@
1576
1ca000000001000000000000036e73310762617365776562026e6c0000010001
1ca080000001000000020002036e73310762617365776562026e6c0000010001c01000020001000151800002c00cc01000020001000151800006036e7332c010c00c00010001000151800004d535d035c03a00010001000151800004d535d034
1577
221c0000000100000000000009652d6c756e61746963026e6c0000010001
221c8000000100000002000009652d6c756e61746963026e6c0000010001c00c0002000100015180000e036e73330767617574656e67c016c00c00020001000151800006036e7334c02e
1578
b9ab000000010000000000000962626469676974616c026e6c0000010001
b9ab800000010000000200000962626469676974616c026e6c0000010001c00c0002000100015180001105646e732d33056c61646f7403636f6d00c00c0002000100015180000805646e732d34c030
1579
b2c21baf5011fae2e9c00000000000000000
b2c29ba40000000000000000
1580
e1be0000000100000000000008686f75736561647303696467026e6c0000010001
e1be8000000100000003000308686f75736561647303696467026e6c0000010001c01500020001000151800006036e7331c015c01500020001000151800006036e7332c015c01500020001000151800006036e7333c015c02d0001000100015180000451af4646c03f0001000100015180000451af4647c05100010001000151800004d5a0fde6
1581
000000007002faf00a970000020405b401010402
000080010000000000000000
1582
02ac00000001000000000000036e73310563736e6574026e6c0000010001
02ac80000001000000020002036e73310563736e6574026e6c0000010001c01000020001000151800002c00cc01000020001000151800006036e7332c010c00c00010001000151800004c2451012c03800010001000151800004c2451212
1583
153e00000001000000000000095f6b65726265726f73045f746370026463065f6d736463730644494b534954024e4c0000210001
153e84030001000000010000095f6b65726265726f73045f746370026463065f6d736463730644494b534954024e4c0000210001c02c00060001000038400036026e730f646f6d61696e2d7265676973747279c02c0a686f73746d6173746572c0430bf1e540000070800000384000278d0000003840
1584
b2c21bb05010fae2e9bf0000000000000000
b2c29bb40000000000000000
1585
b2c2d04f5010faf0b4380000000000000000
1586
b2c2d04f5018faf0747c0000008f552d000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005303677373096d6963726f736f667403636f6d00403afc84403c4e040003000000304e544c4d535350000100000097b208e00b000b002500000005000500200000004e54465331544543484e4f50414e454c0000
1587
bf28000000010000000000000962696a656e6b6f7266026e6c0000010001
bf28800000010000000300030962696a656e6b6f7266026e6c0000010001c00c00020001000151800010036e7331096d61726b6772616166c016c00c00020001000151800006036e7332c02ec00c00020001000151800006036e7333c02ec02a00010001000151800004c3f13ceec04600010001000151800004c372eb43c058000100010001518000043e320e8f
1588
f95900000001000000000000037777770766636f72696f6e026e6c0000010001
f95984030001000000010000037777770766636f72696f6e026e6c0000010001c01800060001000038400036026e730f646f6d61696e2d7265676973747279c0180a686f73746d6173746572c02f0bf1e540000070800000384000278d0000003840
1589
b2c2d05d5011fae2b3a60000000000000000
1590
000000007002faf0d9770000020405b401010402
000080010000000000000000
1591
b2c2d05e5010fae2b3a50000000000000000
1592
a18b00000001000000000000036e733107626265796f6e64026e6c0000010001
a18b80000001000000020002036e733107626265796f6e64026e6c0000010001c01000020001000151800002c00cc01000020001000151800006036e7332c010c00c000100010001518000043eb1900bc03a000100010001518000043eb19002
1593
b2c379ae5010faf0d9b90000000000000000
b2c3f9a40000000000000000
1594
410400000001000000000000036e733107626265796f6e64026e6c0000260001
410480000001000000020002036e733107626265796f6e64026e6c0000260001c01000020001000151800002c00cc01000020001000151800006036e7332c010c00c000100010001518000043eb1900bc03a000100010001518000043eb19002
1595
852300000001000000000000037777770f64616d696174652d636f6c6c656765026e6c0000010001
852380000001000000020002037777770f64616d696174652d636f6c6c656765026e6c0000010001c0100002000100015180000d036e7331066e6c74726565c020c01000020001000151800006036e7332c038c03400010001000151800004d4b20403c04d00010001000151800004d5881e45
1596
208200000001000000000000036e733207626265796f6e64026e6c0000010001
208280000001000000020002036e733207626265796f6e64026e6c0000010001c01000020001000151800006036e7331c010c01000020001000151800002c00cc02c000100010001518000043eb1900bc00c000100010001518000043eb19002
1597
883a00000001000000000000036e733207626265796f6e64026e6c0000260001
883a80000001000000020002036e733207626265796f6e64026e6c0000260001c01000020001000151800006036e7331c010c01000020001000151800002c00cc02c000100010001518000043eb1900bc00c000100010001518000043eb19002
1598
b2c379ae5018faf0d58e0000008f199c000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005303677373096d6963726f736f667403636f6d00403afc84403c4e040003000000304e544c4d535350000100000097b208e00b000b002500000005000500200000004e54465331544543484e4f50414e454c0000
b2c3f9a40000000000000000
1599
2a640000000100000000000009652d6c756e61746963026e6c0000010001
2a648000000100000002000009652d6c756e61746963026e6c0000010001c00c0002000100015180000e036e73330767617574656e67c016c00c00020001000151800006036e7334c02e
1600
99a400000001000000000000037777770e7765736c6579736e65696a646572026e6c0000010001
99a480000001000000020000037777770e7765736c6579736e65696a646572026e6c0000010001c01000020001000151800014046e733031096772616669782d697303636f6d00c01000020001000151800007046e733033c038
1601
7ab500000001000000000000096d61696c686f7374320b66726565686f7374696e67026e6c0000010001
7ab580000001000000020000096d61696c686f7374320b66726565686f7374696e67026e6c0000010001c0160002000100015180001105646e732d33056c61646f7403636f6d00c0160002000100015180000805646e732d34c03c
1602
c3e800000001000000000000037777770f64616d696174652d636f6c6c656765026e6c0000010001
c3e880000001000000020002037777770f64616d696174652d636f6c6c656765026e6c0000010001c0100002000100015180000d036e7331066e6c74726565c020c01000020001000151800006036e7332c038c03400010001000151800004d4b20403c04d00010001000151800004d5881e45
1603
95af00100001000000000001046d61696c03777873026e6c00000100010000290800000080000000
95af80000001000000030004046d61696c03777873026e6c0000010001c01100020001000151800007046e733038c011c01100020001000151800007046e733039c011c01100020001000151800006036e7334c011c02900010001000151800004c3790128c03c00010001000151800004c3790143c04f00010001000151800004d5ef9a650000291000000000000000
1604
b2c379bc5011fae2d9270000000000000000
b2c3f9b40000000000000000
1605
61be00000001000000000000037777771a676f6c666261616e68657472696a6b76616e6e696a6d6567656e026e6c0000010001
61be80000001000000020000037777771a676f6c666261616e68657472696a6b76616e6e696a6d6567656e026e6c0000010001c0100002000100015180000b026e73026e6c036e657400c0100002000100015180001206617574683630026e73026e6c027575c045
1606
f99c00000001000000000000095f6b65726265726f73045f746370026463065f6d736463730b746563686e6f70616e656c026e6c0000060001
f99c84030001000000010000095f6b65726265726f73045f746370026463065f6d736463730b746563686e6f70616e656c026e6c0000060001c03100060001000038400036026e730f646f6d61696e2d7265676973747279c0310a686f73746d6173746572c0480bf1e540000070800000384000278d0000003840
1607
d8bd00000001000000000000037777770c636170636974796368657679026e6c0000010001
d8bd84030001000000010000037777770c636170636974796368657679026e6c0000010001c01d00060001000038400036026e730f646f6d61696e2d7265676973747279c01d0a686f73746d6173746572c0340bf1e540000070800000384000278d0000003840
1608
f05f00000001000000000000087261626f62616e6b026e6c0000010001
f05f80000001000000020001087261626f62616e6b026e6c0000010001c00c00020001000151800005026e73c00cc00c0002000100015180000b026e73026e6c036e657400c0290001000100015180000491484fde
1609
b2c379bd5010fae2d9260000000000000000
b2c3f9b40000000000000000
1610
175928000001000000010000026e6c0000060001095f6b65726265726f73045f746370026463065f6d736463730b746563686e6f70616e656c026e6c000021000100000258001c000000640058056e746673310b746563686e6f70616e656c026e6c00
1759a8040000000000000000
1611
4d9a0000000100000000000005646e732d31056c61646f74026e6c0000010001
4d9a8000000100000002000005646e732d31056c61646f74026e6c0000010001c0120002000100015180001105646e732d33056c61646f7403636f6d00c0120002000100015180000805646e732d34c032
1612
adb60000000100000000000005646e732d32056c61646f74026e6c0000010001
adb68000000100000002000005646e732d32056c61646f74026e6c0000010001c0120002000100015180001105646e732d33056c61646f7403636f6d00c0120002000100015180000805646e732d34c032
1613
b22d00000001000000000000037777771777696a6b766572656e6967696e672d68616e65766f6574026e6c0000010001
b22d84030001000000010000037777771777696a6b766572656e6967696e672d68616e65766f6574026e6c0000010001c02800060001000038400036026e730f646f6d61696e2d7265676973747279c0280a686f73746d6173746572c03f0bf1e540000070800000384000278d0000003840
1614
ba9a00000001000000000000037777771076616b616e746965776f6e696e67656e0f76616b616e7469652d61616e626f64026e6c0000010001
ba9a80000001000000020000037777771076616b616e746965776f6e696e67656e0f76616b616e7469652d61616e626f64026e6c0000010001c02100020001000151800011036e733005736572766502636f02756b00c02100020001000151800010036e7330057365727665036e6574c052
1615
000000007002faf0ec1e0000020405b401010402
000080010000000000000000
1616
8f9e00000001000000000000097463676e777331313608686e65746f6e7477026e6c0000010001
8f9e84030001000000010000097463676e777331313608686e65746f6e7477026e6c0000010001c01f00060001000038400036026e730f646f6d61696e2d7265676973747279c01f0a686f73746d6173746572c0360bf1e540000070800000384000278d0000003840
1617
230b0000000100000000000004646e73310471776562026e6c0000260001
230b8000000100000002000204646e73310471776562026e6c0000260001c01100020001000151800002c00cc0110002000100015180000704646e7332c011c00c00010001000151800004d994ac0cc03800010001000151800004d5c42f6c
1618
f8200000000100000000000004646e73320471776562026e6c0000260001
f8208000000100000002000204646e73320471776562026e6c0000260001c0110002000100015180000704646e7331c011c01100020001000151800002c00cc02a00010001000151800004d994ac0cc00c00010001000151800004d5c42f6c
1619
825800000001000000000000046d61696c0761627374726163026e6c0000010001
825880000001000000020002046d61696c0761627374726163026e6c0000010001c01100020001000151800013036e73310c706f77657273657276657233c019c01100020001000151800006036e7332c031c02d000100010001518000045104741ec04c000100010001518000045104741f
1620
f8f000000001000000000000037777770d6165726f736f6c64657369676e026e6c0000010001
f8f080000001000000020002037777770d6165726f736f6c64657369676e026e6c0000010001c01000020001000151800006036e7331c010c01000020001000151800006036e7332c010c0320001000100015180000451044432c0440001000100015180000451044433
1621
cd46000000010000000000000c626c65696a656e6265726768026e6c0000ff0001
cd46800000010000000200020c626c65696a656e6265726768026e6c0000ff0001c00c00020001000151800010036e7331096e657467726f756e64c019c00c00020001000151800006036e7332c031c02d000100010001518000045054e415c0490001000100015180000451046014
1622
b2c4383f5010faf02dcf0000000000000000
b2c4b8340000000000000000
1623
5e1200000001000000000000037777770864616e69656c6c61026e6c0000010001
5e1280000001000000020002037777770864616e69656c6c61026e6c0000010001c01000020001000151800012026e730c6d65676170726f7669646572c019c01000020001000151800006036e7332c030c02d0001000100015180000450474002c04b0001000100015180000450474102
1624
b2c4383f5018faf0d3750000008f6ec9000000010001000000000f313133333837313336363136322d330000f900010f313133333837313336363136322d330000f900ff00000000005303677373096d6963726f736f667403636f6d00403afc84403c4e040003000000304e544c4d535350000100000097b208e00b000b002500000005000500200000004e54465331544543484e4f50414e454c0000
b2c4b8340000000000000000
1625
e81f000000010000000000000d7469636b6574736576656e7473026e6c00000f0001
e81f800000010000000200020d7469636b6574736576656e7473026e6c00000f0001c00c0002000100015180000c026e7306787334616c6cc01ac00c00020001000151800006036e7332c031c02e00010001000151800004c26d0642c04600010001000151800004c26d0963
1626
6bf800100001000000000001034e53320743495354524f4e024e4c00000100010000290800000080000000
6bf880000001000000020003034e53320743495354524f4e024e4c0000010001c01000020001000151800005026e73c010c01000020001000151800002c00cc02c000100010001518000043ed81f37c00c000100010001518000043ed81f380000291000000000000000
1627
b2c4384d5011fae22d3d0000000000000000
b2c4b8440000000000000000
1628
000000007002faf042610000020405b401010402
000080010000000000000000
1629
39f400000001000000000000036e73320a6461632d706c616e6574026e6c0000010001
39f480000001000000030003036e73320a6461632d706c616e6574026e6c0000010001c0100002000100015180000c036e7331056264726567c01bc01000020001000151800006036e7332c033c01000020001000151800006036e7333c033c02f00010001000151800004d44ff4dac04700010001000151800004d44ff642c05900010001000151800004c3f5c70a
1630
b2c4384e5010fae22d3c0000000000000000
b2c4b8440000000000000000
1631
6adb00000001000000000000037777770773657870657274026e6c0000010001
6adb80000001000000030003037777770773657870657274026e6c0000010001c0100002000100015180000e04646e733106626c6978656dc018c0100002000100015180000704646e7332c031c0100002000100015180000704646e7333c031c02c00010001000151800004d44fe803c04600010001000151800004c3f5c782c05900010001000151800004d44ff303
1632
b2c4e8a95010faf0d3a60000000000000000
1633
3a440000000100000000000006504152495445024e4c00000f0001
3a448000000100000002000206504152495445024e4c00000f0001c00c0002000100015180000c036e7331056f72696f6ec013c00c00020001000151800006036e7332c02bc02700010001000151800004c2862282c03f00010001000151800004c2862b02
1634
e9e400000001000000000000037777770b617564696f636f76657273026e6c0000010001
e9e480000001000000020000037777770b617564696f636f76657273026e6c0000010001c0100002000100015180001105646e732d33056c61646f7403636f6d00c0100002000100015180000805646e732d34c036
1635
b2c4e8a95018faf0b5df0000008f3338000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005303677373096d6963726f736f667403636f6d00403afc84403c4e040003000000304e544c4d535350000100000097b208e00b000b002500000005000500200000004e54465331544543484e4f50414e454c0000
1636
02eb00000001000000000000046d61696c03777873026e6c0000010001
02eb80000001000000030003046d61696c03777873026e6c0000010001c01100020001000151800007046e733038c011c01100020001000151800007046e733039c011c01100020001000151800006036e7334c011c02900010001000151800004c3790128c03c00010001000151800004c3790143c04f00010001000151800004d5ef9a65
1637
e16d00000001000000000000086a756c69657474650762657374776562026e6c0000010001
e16d80000001000000020002086a756c69657474650762657374776562026e6c0000010001c0150002000100015180000e08706f7765722d6133026133c01dc0150002000100015180000c09706f7765722d697078c03ac0310001000100015180000451113b42c04b00010001000151800004d5ab40e6
1638
04920000000100000000000003323034033139320236310232340770726f786965730a626c61636b686f6c657307656173796e6574026e6c00001c0001
04928000000100000002000203323034033139320236310232340770726f786965730a626c61636b686f6c657307656173796e6574026e6c00001c0001c02d00020001000151800006036e7330c02dc02d00020001000151800006036e7331c02dc04900010001000151800004c2a55e01c05b00010001000151800004c2a55e05
1639
b2c4e8b75011fae2d3140000000000000000
1640
000000007002faf00f9e0000020405b401010402
000080010000000000000000
1641
613000000001000000000000046d61696c086e65646c696e7578026e6c0000010001
613080000001000000030003046d61696c086e65646c696e7578026e6c0000010001c01100020001000151800006036e7331c011c01100020001000151800006036e7332c011c01100020001000151800006036e7333c011c02e00010001000151800004d5ef87d2c04000010001000151800004d5ef87d3c05200010001000151800004d5ef8005
1642
b2c4e8b85010fae2d3130000000000000000
1643
e6930000000100000000000006636861726973026e6c00000f0001
e6938000000100000002000006636861726973026e6c00000f0001c00c0002000100015180000c026e7306766576696461c013c00c00020001000151800006036e7332c02a
1644
b2c581cb5010faf007c10000000000000000
1645
b2c581cb5018faf0258a0000008ff7a7000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005303677373096d6963726f736f667403636f6d00403afc84403c4e040003000000304e544c4d535350000100000097b208e00b000b002500000005000500200000004e54465331544543484e4f50414e454c0000
1646
e97b00000001000000000000036e73310b7669727475616c686f7374026e6c0000010001
e97b80000001000000020000036e73310b7669727475616c686f7374026e6c0000010001c01000020001000151800013036e733109676c6f62616c6e656403636f6d00c01000020001000151800006036e7332c034
1647
e97c00000001000000000000036e73320b7669727475616c686f7374026e6c0000010001
e97c80000001000000020000036e73320b7669727475616c686f7374026e6c0000010001c01000020001000151800013036e733109676c6f62616c6e656403636f6d00c01000020001000151800006036e7332c034
1648
bffb0000000100000000000003626c3102626c06787334616c6c026e6c0000010001
bffb8000000100000003000203626c3102626c06787334616c6c026e6c0000010001c01300020001000151800005026e73c013c01300020001000151800006036e7332c013c0130002000100015180000d026e730472697065036e657400c02e00010001000151800004c26d0642c03f00010001000151800004c26d0963
1649
37fd00000001000000000000036e73340767617574656e67026e6c0000010001
37fd80000001000000020000036e73340767617574656e67026e6c0000010001c0100002000100015180000d036e7331066c696e6b7570c018c01000020001000151800006036e7332c030
1650
73360000000100000000000004646e7331057368656c6c026e6c0000010001
73368000000100000003000004646e7331057368656c6c026e6c0000010001c0110002000100015180001004646e7331057368656c6c03636f6d00c0110002000100015180000704646e7332c030c0110002000100015180000704646e7333c030
1651
8bea00000001000000000000037777770764736c6465736b026e6c0000010001
8bea80000001000000020000037777770764736c6465736b026e6c0000010001c01000020001000151800014036e73310a676f6c64766973696f6e03636f6d00c01000020001000151800006036e7332c030
1652
35fc00000001000000000000034e53320743495354524f4e024e4c0000010001
35fc80000001000000020002034e53320743495354524f4e024e4c0000010001c01000020001000151800005026e73c010c01000020001000151800002c00cc02c000100010001518000043ed81f37c00c000100010001518000043ed81f38
1653
b2c581d95011fae2072f0000000000000000
1654
e94000000001000000000000037777770a6c696e6b746970706572026e6c0000010001
e94080000001000000030003037777770a6c696e6b746970706572026e6c0000010001c0100002000100015180000c036e7331056d61786573c01bc01000020001000151800006036e7332c033c01000020001000151800006036e7333c033c02f000100010001518000045045402ec047000100010001518000045045402fc059000100010001518000045045440a
1655
77be0000000100000000000003777777086879706f686f6d65026e6c0000010001
77be8000000100000002000003777777086879706f686f6d65026e6c0000010001c01000020001000151800013036e733109696d6167653264617903636f6d00c01000020001000151800006036e7332c031
1656
4fb500000001000000000000036e733208696e74726f776562026e6c0000010001
4fb580000001000000020002036e733208696e74726f776562026e6c0000010001c01000020001000151800006036e7331c010c01000020001000151800002c00cc02d0001000100015180000450416028c00c00010001000151800004c356780c
1657
b2c581da5010fae2072e0000000000000000
1658
5c6a0010000100000000000007636172746d616e076e6574666c6f77026e6c0000010001
5c6a8000000100000002000207636172746d616e076e6574666c6f77026e6c0000010001c01400020001000151800006036e7331c014c01400020001000151800006036e7332c014c030000100010001518000043eb1ef24c042000100010001518000043eb1ef25
1659
92d100000001000000000000036e7332076e656473746174026e6c0000010001
92d180000001000000020002036e7332076e656473746174026e6c0000010001c01000020001000151800005026e73c010c01000020001000151800006036e7333c010c02c00010001000151800004d4482615c03d00010001000151800004d5c4021d
1660
921500000001000000000000036e7334076e656473746174026e6c0000010001
921580000001000000020002036e7334076e656473746174026e6c0000010001c01000020001000151800005026e73c010c01000020001000151800006036e7333c010c02c00010001000151800004d4482615c03d00010001000151800004d5c4021d
1661
ba9500000001000000000000036e7332076e656473746174026e6c0000260001
ba9580000001000000020002036e7332076e656473746174026e6c0000260001c01000020001000151800005026e73c010c01000020001000151800006036e7333c010c02c00010001000151800004d4482615c03d00010001000151800004d5c4021d
1662
3a9f00000001000000000000036e7334076e656473746174026e6c0000260001
3a9f80000001000000020002036e7334076e656473746174026e6c0000260001c01000020001000151800005026e73c010c01000020001000151800006036e7333c010c02c00010001000151800004d4482615c03d00010001000151800004d5c4021d
1663
175c28000001000000010000026e6c0000060001095f6b65726265726f73045f746370155374616e64616172642d6565727374652d73697465065f7369746573026463065f6d736463730b746563686e6f70616e656c026e6c000021000100000258001c000000640058056e746673310b746563686e6f70616e656c026e6c00
175ca8040000000000000000
1664
3cfa00000001000000000000036e733108696e74726f776562026e6c0000010001
3cfa80000001000000020002036e733108696e74726f776562026e6c0000010001c01000020001000151800002c00cc01000020001000151800006036e7332c010c00c0001000100015180000450416028c03b00010001000151800004c356780c
1665
e0ea0000000100000000000006636f6f6b696504696c7365026e6c0000010001
e0ea8000000100000003000306636f6f6b696504696c7365026e6c0000010001c01300020001000151800006036e7331c013c01300020001000151800006036e7332c013c01300020001000151800006036e7333c013c02c000100010001518000043e45a282c03e000100010001518000043e45a283c050000100010001518000043e45a284
1666
000000007002faf01bd90000020405b401010402
000080010000000000000000
1667
ddaf000000010000000000000377777709766572626f7577656e026e6c0000010001
ddaf800000010000000200020377777709766572626f7577656e026e6c0000010001c0100002000100015180000f036e7331086765656e70756e74c01ac01000020001000151800006036e7332c032c02e00010001000151800004d4ccd865c049000100010001518000045054ec34
1668
b2c62b8d5010faf06a390000000000000000
b2c6ab840000000000000000
1669
b2c62b8d5018faf031d50000008f4cd4000000010001000000000f313133333837313336363136322d330000f900010f313133333837313336363136322d330000f900ff00000000005303677373096d6963726f736f667403636f6d00403afc84403c4e040003000000304e544c4d535350000100000097b208e00b000b002500000005000500200000004e54465331544543484e4f50414e454c0000
b2c6ab840000000000000000
1670
897c0000000100000000000004686f6d650774697363616c69026e6c0000010001
897c8000000100000003000204686f6d650774697363616c69026e6c0000010001c0110002000100015180000704616e7331c011c0110002000100015180000704616e7332c011c0110002000100015180001404616e73330a74697363616c696e657402626500c02d00010001000151800004c3f14d38c04000010001000151800004c3f13325
1671
4caa00000001000000000000086f76657268656964047a6f656b026e6c0000010001
4caa80000001000000020002086f76657268656964047a6f656b026e6c0000010001c0150002000100015180000d026e73076e65746c616e64c01ac01500020001000151800006036e7332c031c02e00010001000151800004d9aa2042c04700010001000151800004d9aa2c06
1672
5eb200000001000000000000086f76657268656964047a6f656b026e6c0000010001
5eb280000001000000020002086f76657268656964047a6f656b026e6c0000010001c0150002000100015180000d026e73076e65746c616e64c01ac01500020001000151800006036e7332c031c02e00010001000151800004d9aa2042c04700010001000151800004d9aa2c06
1673
b2c62b9b5011fae269a70000000000000000
b2c6ab940000000000000000
1674
000000007002faf04d060000020405b401010402
000080010000000000000000
1675
e97f00000001000000000000036e73320b7669727475616c686f7374026e6c0000010001
e97f80000001000000020000036e73320b7669727475616c686f7374026e6c0000010001c01000020001000151800013036e733109676c6f62616c6e656403636f6d00c01000020001000151800006036e7332c034
1676
e97e00000001000000000000036e73310b7669727475616c686f7374026e6c0000010001
e97e80000001000000020000036e73310b7669727475616c686f7374026e6c0000010001c01000020001000151800013036e733109676c6f62616c6e656403636f6d00c01000020001000151800006036e7332c034
1677
c36200000001000000000000046d61696c06737469626265026e6c0000010001
c36280000001000000020002046d61696c06737469626265026e6c0000010001c01100020001000151800011026e730b666163696e676661637473c018c01100020001000151800006036e7332c02fc02c00010001000151800004d513b013c04900010001000151800004d513b012
1678
7637000000010000000000000777656276696577026e6c00000f0001
7637800000010000000200000777656276696577026e6c00000f0001c00c00020001000151800012036e73310b6d6565737465726c696a6bc014c00c00020001000151800006036e7332c02c
1679
e7000000000100000000000005627261616d026e6c00000f0001
e7008000000100000002000205627261616d026e6c00000f0001c00c0002000100015180000b036e73310461786974c012c00c00020001000151800006036e7332c02ac026000100010001518000043e3a440bc03d000100010001518000043e3a440c
1680
b2c62b9c5010fae269a60000000000000000
b2c6ab940000000000000000
1681
e5cc000000010000000000000f6d656c6b7765672d686f6c6c616e64026e6c00000f0001
e5cc800000010000000300030f6d656c6b7765672d686f6c6c616e64026e6c00000f0001c00c0002000100015180000e076e73617574683103626974c01cc00c0002000100015180000a076e736175746832c038c00c0002000100015180000a076e736175746833c038c03000010001000151800004d5880c33c04a00010001000151800004d5880c3bc06000010001000151800004d4ccc00b
1682
3a0f000000010000000000000964656e68656c646572026e6c00000f0001
3a0f800000010000000200020964656e68656c646572026e6c00000f0001c00c00020001000151800011036e73310a7765626275726f646e73c016c00c00020001000151800006036e7332c02ec02a00010001000151800004d51380cec04700010001000151800004d513806a
1683
b2c6b1045010faf015ef0000000000000000
1684
b2c6b1045018faf01a1d0000008f1143000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005303677373096d6963726f736f667403636f6d00403afc84403c4e040003000000304e544c4d535350000100000097b208e00b000b002500000005000500200000004e54465331544543484e4f50414e454c0000
1685
c22900000001000000000000036e733103727567026e6c0000010001
c22980000001000000030003036e733103727567026e6c0000010001c01000020001000151800002c00cc01000020001000151800006036e7332c010c0100002000100015180000e036e733107737572666e6574c014c00c00010001000151800004817d0406c03600010001000151800004817d040dc04800010001000151800004c0576a65
1686
ab8400000001000000000000036e733203727567026e6c0000010001
ab8480000001000000030003036e733203727567026e6c0000010001c01000020001000151800006036e7331c010c01000020001000151800002c00cc0100002000100015180000e036e733107737572666e6574c014c02800010001000151800004817d0406c00c00010001000151800004817d040dc04800010001000151800004c0576a65
1687
0359000000010000000000000f50432d30392054454120262052494108627275696e686f66026e6c0000010001
0359800000010000000300020f50432d30392054454120262052494108627275696e686f66026e6c0000010001c01c0002000100015180000d036e733106776964657873c025c01c00020001000151800010036e733206776964657873036e657400c01c00020001000151800006036e7333c03dc03900010001000151800004d4ccc0fcc06e000100010001518000043efa0703
1688
38fd0000000100000000000006636861726973026e6c0000ff0001
38fd8000000100000002000006636861726973026e6c0000ff0001c00c0002000100015180000c026e7306766576696461c013c00c00020001000151800006036e7332c02a
1689
4e9100000001000000000000076e6372766e6574026e6c00000f0001
4e9180000001000000030003076e6372766e6574026e6c00000f0001c00c0002000100015180001208736f6c7574696f6e06736f6c636f6ec014c00c00020001000151800006036e7331c031c00c00020001000151800006036e7332c031c02800010001000151800004d42d2005c04600010001000151800004d42d2003c05800010001000151800004d42d2103
1690
964b00000001000000000000066b7669616e61036b7669026e6c0000010001
964b80000001000000030003066b7669616e61036b7669026e6c0000010001c01300020001000151800009066b7669657870c013c01300020001000151800002c00cc0130002000100015180000e04616a6178066e696b686566c017c02b00010001000151800004817d0f01c00c00010001000151800004817d0f02c04e00010001000151800004c010c701
1691
0ba600000001000000000000066b7669617376036b7669026e6c0000010001
0ba680000001000000030003066b7669617376036b7669026e6c0000010001c01300020001000151800009066b7669657870c013c01300020001000151800009066b7669616e61c013c0130002000100015180000e04616a6178066e696b686566c017c02b00010001000151800004817d0f01c04000010001000151800004817d0f02c05500010001000151800004c010c701
1692
85d300000001000000000000066b7669657870036b7669026e6c0000010001
85d380000001000000030003066b7669657870036b7669026e6c0000010001c01300020001000151800002c00cc01300020001000151800009066b7669616e61c013c0130002000100015180000e04616a6178066e696b686566c017c00c00010001000151800004817d0f01c03900010001000151800004817d0f02c04e00010001000151800004c010c701
1693
11fc000000010000000000000234330332313503313733033134320770726f786965730a626c61636b686f6c657307656173796e6574026e6c00001c0001
11fc800000010000000200020234330332313503313733033134320770726f786965730a626c61636b686f6c657307656173796e6574026e6c00001c0001c02e00020001000151800006036e7330c02ec02e00020001000151800006036e7331c02ec04a00010001000151800004c2a55e01c05c00010001000151800004c2a55e05
1694
769c000000010000000000000a6d61726b656e6865656d026e6c00000f0001
769c800000010000000200020a6d61726b656e6865656d026e6c00000f0001c00c0002000100015180000c026e7306787334616c6cc017c00c00020001000151800006036e7332c02ec02b00010001000151800004c26d0642c04300010001000151800004c26d0963
1695
9355000000010000000000000d3231312d3233322d34372d343708696e746572746e7303636f6d06787369746573026e6c0000010001
9355800000010000000200020d3231312d3233322d34372d343708696e746572746e7303636f6d06787369746573026e6c0000010001c02700020001000151800006036e7331c027c02700020001000151800006036e7332c027c042000100010001518000045054f526c054000100010001518000045054f527
1696
51c600000001000000000000056761726f74026e6c00000f0001
51c680000001000000020002056761726f74026e6c00000f0001c00c0002000100015180000f026e7309656174736572766572c012c00c00020001000151800006036e7332c029c02600010001000151800004d4cb0e42c04100010001000151800004d4cb1221
1697
b2c6b1125011fae2155d0000000000000000
1698
000000007002faf041280000020405b401010402
000080010000000000000000
1699
c1f700000001000000000000096e696a656e6b616d70026e6c00000f0001
c1f780000001000000020002096e696a656e6b616d70026e6c00000f0001c00c0002000100015180000f036e733108696e74726f776562c016c00c00020001000151800006036e7332c02ec02a0001000100015180000450416028c04500010001000151800004c356780c
-929
View File
@@ -1,929 +0,0 @@
; DNSSEC test packets.
; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
;-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2e 15 85 00 00 01 00 01 00 03 00 05 09 6e 6c 6e 65 74 6c 61 ; 1- 20
62 73 02 6e 6c 00 00 01 00 01 09 6e 6c 6e 65 74 6c 61 62 73 ; 21- 40
02 6e 6c 00 00 01 00 01 00 01 51 80 00 04 d5 9a e0 01 09 6e ; 41- 60
6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 02 00 01 00 01 51 80 ; 61- 80
00 18 03 6e 73 37 0f 64 6f 6d 61 69 6e 2d 72 65 67 69 73 74 ; 81- 100
72 79 02 6e 6c 00 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 ; 101- 120
00 02 00 01 00 01 51 80 00 13 04 6f 70 65 6e 09 6e 6c 6e 65 ; 121- 140
74 6c 61 62 73 02 6e 6c 00 09 6e 6c 6e 65 74 6c 61 62 73 02 ; 141- 160
6e 6c 00 00 02 00 01 00 01 51 80 00 11 05 6f 6d 76 61 6c 06 ; 161- 180
74 65 64 6e 65 74 02 6e 6c 00 04 6f 70 65 6e 09 6e 6c 6e 65 ; 181- 200
74 6c 61 62 73 02 6e 6c 00 00 01 00 01 00 01 51 80 00 04 d5 ; 201- 220
9a e0 01 04 6f 70 65 6e 09 6e 6c 6e 65 74 6c 61 62 73 02 6e ; 221- 240
6c 00 00 1c 00 01 00 01 51 80 00 10 20 01 07 b8 02 06 00 01 ; 241- 260
00 00 00 00 00 00 00 53 04 6f 70 65 6e 09 6e 6c 6e 65 74 6c ; 261- 280
61 62 73 02 6e 6c 00 00 1c 00 01 00 01 51 80 00 10 20 01 07 ; 281- 300
b8 02 06 00 01 00 00 00 00 00 00 00 01 05 6f 6d 76 61 6c 06 ; 301- 320
74 65 64 6e 65 74 02 6e 6c 00 00 01 00 01 00 00 70 80 00 04 ; 321- 340
d5 9a e0 11 05 6f 6d 76 61 6c 06 74 65 64 6e 65 74 02 6e 6c ; 341- 360
00 00 1c 00 01 00 00 70 80 00 10 20 01 07 b8 02 06 00 01 02 ; 361- 380
00 39 ff fe 59 b1 87
; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
;-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
4d 79 85 00 00 01 00 02 00 04 00 08 09 6e 6c 6e 65 74 6c 61 ; 1- 20
62 73 02 6e 6c 00 00 01 00 01 09 6e 6c 6e 65 74 6c 61 62 73 ; 21- 40
02 6e 6c 00 00 01 00 01 00 01 51 80 00 04 d5 9a e0 01 09 6e ; 41- 60
6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 2e 00 01 00 01 51 80 ; 61- 80
00 a0 00 01 05 02 00 01 51 80 46 3d 18 29 46 15 8b 29 ab 0f ; 81- 100
09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 46 0f 5f 69 aa fe ; 101- 120
22 ae bf 65 52 2f 18 39 d7 3c 76 6b b0 4d a8 e4 32 46 60 e2 ; 121- 140
3b 68 5f 3f b1 3a 7b 4f 3f 47 62 45 89 19 60 a8 04 53 19 9b ; 141- 160
6c 7d 5a eb fe ce b3 2e 5b 2d 7d e5 87 3f 53 f7 3a ab c3 39 ; 161- 180
83 bb 1a 77 a1 1a 36 4d bc 46 4d 28 3c ba 93 70 d7 dd dc 2e ; 181- 200
f9 9b ea eb a8 75 8e 6b a2 03 41 4f f6 36 77 8a 61 87 72 b3 ; 201- 220
4f db 96 20 19 04 93 f8 63 cb 0a 55 cf 25 95 9c fd 94 e6 90 ; 221- 240
7f 5f 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 02 00 01 ; 241- 260
00 01 51 80 00 18 03 6e 73 37 0f 64 6f 6d 61 69 6e 2d 72 65 ; 261- 280
67 69 73 74 72 79 02 6e 6c 00 09 6e 6c 6e 65 74 6c 61 62 73 ; 281- 300
02 6e 6c 00 00 02 00 01 00 01 51 80 00 13 04 6f 70 65 6e 09 ; 301- 320
6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 09 6e 6c 6e 65 74 6c ; 321- 340
61 62 73 02 6e 6c 00 00 02 00 01 00 01 51 80 00 11 05 6f 6d ; 341- 360
76 61 6c 06 74 65 64 6e 65 74 02 6e 6c 00 09 6e 6c 6e 65 74 ; 361- 380
6c 61 62 73 02 6e 6c 00 00 2e 00 01 00 01 51 80 00 a0 00 02 ; 381- 400
05 02 00 01 51 80 46 3d 18 29 46 15 8b 29 ab 0f 09 6e 6c 6e ; 401- 420
65 74 6c 61 62 73 02 6e 6c 00 ad 07 18 03 3f 18 f6 5c 35 8d ; 421- 440
5b 89 d8 cf 6a 11 fc 3c 32 6b bc 06 e3 c4 c8 ec 47 83 1d ab ; 441- 460
a0 ea e3 af 43 b0 f5 ec aa 5d 4e aa fa 79 6f 1a 2d fc 1f 44 ; 461- 480
81 7a 61 a2 49 76 0b 8e 9d 9f 34 95 66 56 89 99 dc f6 31 6e ; 481- 500
42 bb 16 45 93 60 44 7b 19 3a c4 e6 9a ab 69 9a b5 84 8f 86 ; 501- 520
b5 17 af c1 e0 4c b1 33 eb 67 cc cf 5b f6 e9 27 ff f3 d9 d0 ; 521- 540
c5 8e f0 91 b0 ab 77 93 18 e7 7e dc 44 1e f1 73 72 7e 04 6f ; 541- 560
70 65 6e 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 01 00 ; 561- 580
01 00 01 51 80 00 04 d5 9a e0 01 04 6f 70 65 6e 09 6e 6c 6e ; 581- 600
65 74 6c 61 62 73 02 6e 6c 00 00 1c 00 01 00 01 51 80 00 10 ; 601- 620
20 01 07 b8 02 06 00 01 00 00 00 00 00 00 00 53 04 6f 70 65 ; 621- 640
6e 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 1c 00 01 00 ; 641- 660
01 51 80 00 10 20 01 07 b8 02 06 00 01 00 00 00 00 00 00 00 ; 661- 680
01 05 6f 6d 76 61 6c 06 74 65 64 6e 65 74 02 6e 6c 00 00 01 ; 681- 700
00 01 00 00 70 80 00 04 d5 9a e0 11 05 6f 6d 76 61 6c 06 74 ; 701- 720
65 64 6e 65 74 02 6e 6c 00 00 1c 00 01 00 00 70 80 00 10 20 ; 721- 740
01 07 b8 02 06 00 01 02 00 39 ff fe 59 b1 87 04 6f 70 65 6e ; 741- 760
09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 2e 00 01 00 01 ; 761- 780
51 80 00 a0 00 01 05 03 00 01 51 80 46 3d 18 29 46 15 8b 29 ; 781- 800
ab 0f 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 33 42 f9 d1 ; 801- 820
94 cb d3 27 dc e3 6b fd 80 34 a8 c0 ab 2a 76 f8 ef 9d c2 f7 ; 821- 840
b4 08 2f ff 3c 35 c1 b4 13 46 5b 05 38 e7 97 96 41 b9 01 ff ; 841- 860
8c 0b de 62 78 29 68 2f fe fb 53 7a 61 92 3f 89 79 3e df 49 ; 861- 880
cc ad a3 f7 45 13 7b 99 4c 0b 74 06 ee 1e 97 5a fc 6b 74 60 ; 881- 900
6d a7 68 24 5f 01 f8 5a e2 84 ad 18 cf 52 ff f7 a5 66 84 76 ; 901- 920
b0 34 5c 42 8f c6 58 c2 38 c4 8c 6b 7a 72 90 4c 9c 77 90 d4 ; 921- 940
dc cf cf 2a 04 6f 70 65 6e 09 6e 6c 6e 65 74 6c 61 62 73 02 ; 941- 960
6e 6c 00 00 2e 00 01 00 01 51 80 00 a0 00 1c 05 03 00 01 51 ; 961- 980
80 46 3d 18 29 46 15 8b 29 ab 0f 09 6e 6c 6e 65 74 6c 61 62 ; 981-1000
73 02 6e 6c 00 53 09 41 45 b5 88 59 88 6e 2a 21 8e 42 ac 80 ; 1001-1020
7c e2 9f 2e d4 f6 48 3f 70 40 d8 61 1d 3f ea e2 ba ad 20 83 ; 1021-1040
80 bc 7e 3f 40 e7 41 74 9c c3 7c 51 30 e6 f2 99 50 0a 3f d9 ; 1041-1060
26 5a fd d2 38 09 79 e5 27 f1 25 80 e5 13 58 a5 2b 95 70 c3 ; 1061-1080
53 cd ee 0e c3 07 32 f6 73 17 60 b2 1d 3a b0 a4 0c 8f ef c3 ; 1081-1100
65 5e 87 01 98 51 51 a9 fe c0 f7 b2 0d 02 d8 29 40 b2 a8 c4 ; 1101-1120
8d 52 da 36 f9 98 f9 c4 6d 6e 1b ed 42 00 00 29 10 00 00 00 ; 1121-1140
80 00 00 00
; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
;-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
b2 88 85 03 00 01 00 00 00 01 00 00 04 7a 61 72 66 09 6e 6c ; 1- 20
6e 65 74 6c 61 62 73 02 6e 6c 00 00 01 00 01 09 6e 6c 6e 65 ; 21- 40
74 6c 61 62 73 02 6e 6c 00 00 06 00 01 00 00 46 50 00 40 04 ; 41- 60
6f 70 65 6e 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 0a 68 ; 61- 80
6f 73 74 6d 61 73 74 65 72 09 6e 6c 6e 65 74 6c 61 62 73 02 ; 81- 100
6e 6c 00 77 a1 02 58 00 00 70 80 00 00 1c 20 00 09 3a 80 00 ; 101- 120
00 46 50
; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
;-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
1c be 85 03 00 01 00 00 00 06 00 01 04 7a 61 72 66 09 6e 6c ; 1- 20
6e 65 74 6c 61 62 73 02 6e 6c 00 00 01 00 01 09 6e 6c 6e 65 ; 21- 40
74 6c 61 62 73 02 6e 6c 00 00 06 00 01 00 00 46 50 00 40 04 ; 41- 60
6f 70 65 6e 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 0a 68 ; 61- 80
6f 73 74 6d 61 73 74 65 72 09 6e 6c 6e 65 74 6c 61 62 73 02 ; 81- 100
6e 6c 00 77 a1 02 58 00 00 70 80 00 00 1c 20 00 09 3a 80 00 ; 101- 120
00 46 50 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 2e 00 ; 121- 140
01 00 00 46 50 00 a0 00 06 05 02 00 01 51 80 46 3d 18 29 46 ; 141- 160
15 8b 29 ab 0f 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 81 ; 161- 180
de 4b b8 1d 81 1f 95 cb ca 8e fa 04 bc b6 a4 05 7f b1 7f de ; 181- 200
e7 bd cc 8f 39 63 1d 0a 9a ac 7c b7 eb b5 e5 e8 38 a0 d6 9d ; 201- 220
ec 34 06 43 9b 5a 4f 61 f3 18 21 32 c7 79 43 6f 99 32 b8 25 ; 221- 240
54 3b 19 6c 25 d3 3e ef ec 2a d1 1e 4a 86 f6 17 ca 84 07 44 ; 241- 260
73 a2 39 df d1 66 09 c1 e2 21 83 bf 79 73 2b 8d 2d bb bf 37 ; 261- 280
c5 e0 95 a9 2a f3 79 75 67 1d 90 29 5c 57 06 07 4b 69 25 05 ; 281- 300
dd 63 05 91 c5 81 0d 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c ; 301- 320
00 00 2f 00 01 00 00 46 50 00 21 04 5f 73 69 70 04 5f 75 64 ; 321- 340
70 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 07 62 01 80 ; 341- 360
08 10 03 80 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 2e ; 361- 380
00 01 00 00 46 50 00 a0 00 2f 05 02 00 00 46 50 46 3d 18 29 ; 381- 400
46 15 8b 29 ab 0f 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 ; 401- 420
53 04 6e cf ce b4 19 e1 40 c5 47 36 02 c5 1b fa ab 43 57 ec ; 421- 440
d1 57 da 02 d6 13 16 b1 4d 15 58 d1 a6 cb 5d 27 67 71 33 c2 ; 441- 460
87 16 12 af 45 99 7f 95 74 19 71 e3 ea 33 b5 60 39 21 15 11 ; 461- 480
af 5d df 33 f3 c4 9d 9c 62 9f ba f8 10 f6 18 4c eb 92 84 8a ; 481- 500
85 5c a3 83 aa 00 01 c8 48 b7 5b de 80 9a 38 00 3d d9 cd f5 ; 501- 520
09 68 06 7f 5c 83 4e 2c a1 99 76 53 dc 01 ac 06 f1 ed 9a a4 ; 521- 540
d3 03 17 33 4b 71 bd 94 03 77 77 77 09 6e 6c 6e 65 74 6c 61 ; 541- 560
62 73 02 6e 6c 00 00 2f 00 01 00 00 46 50 00 16 09 6e 6c 6e ; 561- 580
65 74 6c 61 62 73 02 6e 6c 00 00 06 40 00 00 08 00 03 03 77 ; 581- 600
77 77 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 2e 00 01 ; 601- 620
00 00 46 50 00 a0 00 2f 05 03 00 00 46 50 46 3d 18 29 46 15 ; 621- 640
8b 29 ab 0f 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 3f f2 ; 641- 660
fd 50 50 3a ea 29 bf 75 26 28 0c 22 72 29 77 5a 8f ef 2f 34 ; 661- 680
96 18 27 32 79 57 1e 08 ce 04 0f 22 c8 4e 32 db 1d 90 c6 68 ; 681- 700
0c 23 c8 43 44 2a ab fe e6 bb 90 3a 73 7d 79 44 63 93 e8 97 ; 701- 720
4f aa 51 f5 91 c2 ee d3 13 ea 94 68 4b 1d fc 9c 8e f5 1a 7b ; 721- 740
5f f6 09 e8 94 58 7e 26 4e 00 9e 98 a5 b9 c7 4d 34 8c f0 1e ; 741- 760
8e 74 f1 6d 54 ef d0 45 70 57 5a d0 fe 3d 54 78 e0 96 70 0e ; 761- 780
a7 b8 e2 be 13 00 00 00 29 10 00 00 00 80 00 00 00
; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
;-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
95 7c 85 00 00 01 00 00 00 01 00 00 09 6e 6c 6e 65 74 6c 61 ; 1- 20
62 73 02 6e 6c 00 00 07 00 01 09 6e 6c 6e 65 74 6c 61 62 73 ; 21- 40
02 6e 6c 00 00 06 00 01 00 00 46 50 00 40 04 6f 70 65 6e 09 ; 41- 60
6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 0a 68 6f 73 74 6d 61 ; 61- 80
73 74 65 72 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 77 a1 ; 81- 100
02 58 00 00 70 80 00 00 1c 20 00 09 3a 80 00 00 46 50
; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
;-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
78 1a 85 00 00 01 00 00 00 04 00 01 09 6e 6c 6e 65 74 6c 61 ; 1- 20
62 73 02 6e 6c 00 00 07 00 01 09 6e 6c 6e 65 74 6c 61 62 73 ; 21- 40
02 6e 6c 00 00 06 00 01 00 00 46 50 00 40 04 6f 70 65 6e 09 ; 41- 60
6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 0a 68 6f 73 74 6d 61 ; 61- 80
73 74 65 72 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 77 a1 ; 81- 100
02 58 00 00 70 80 00 00 1c 20 00 09 3a 80 00 00 46 50 09 6e ; 101- 120
6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 2e 00 01 00 00 46 50 ; 121- 140
00 a0 00 06 05 02 00 01 51 80 46 3d 18 29 46 15 8b 29 ab 0f ; 141- 160
09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 81 de 4b b8 1d 81 ; 161- 180
1f 95 cb ca 8e fa 04 bc b6 a4 05 7f b1 7f de e7 bd cc 8f 39 ; 181- 200
63 1d 0a 9a ac 7c b7 eb b5 e5 e8 38 a0 d6 9d ec 34 06 43 9b ; 201- 220
5a 4f 61 f3 18 21 32 c7 79 43 6f 99 32 b8 25 54 3b 19 6c 25 ; 221- 240
d3 3e ef ec 2a d1 1e 4a 86 f6 17 ca 84 07 44 73 a2 39 df d1 ; 241- 260
66 09 c1 e2 21 83 bf 79 73 2b 8d 2d bb bf 37 c5 e0 95 a9 2a ; 261- 280
f3 79 75 67 1d 90 29 5c 57 06 07 4b 69 25 05 dd 63 05 91 c5 ; 281- 300
81 0d 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 2f 00 01 ; 301- 320
00 00 46 50 00 21 04 5f 73 69 70 04 5f 75 64 70 09 6e 6c 6e ; 321- 340
65 74 6c 61 62 73 02 6e 6c 00 00 07 62 01 80 08 10 03 80 09 ; 341- 360
6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 2e 00 01 00 00 46 ; 361- 380
50 00 a0 00 2f 05 02 00 00 46 50 46 3d 18 29 46 15 8b 29 ab ; 381- 400
0f 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 53 04 6e cf ce ; 401- 420
b4 19 e1 40 c5 47 36 02 c5 1b fa ab 43 57 ec d1 57 da 02 d6 ; 421- 440
13 16 b1 4d 15 58 d1 a6 cb 5d 27 67 71 33 c2 87 16 12 af 45 ; 441- 460
99 7f 95 74 19 71 e3 ea 33 b5 60 39 21 15 11 af 5d df 33 f3 ; 461- 480
c4 9d 9c 62 9f ba f8 10 f6 18 4c eb 92 84 8a 85 5c a3 83 aa ; 481- 500
00 01 c8 48 b7 5b de 80 9a 38 00 3d d9 cd f5 09 68 06 7f 5c ; 501- 520
83 4e 2c a1 99 76 53 dc 01 ac 06 f1 ed 9a a4 d3 03 17 33 4b ; 521- 540
71 bd 94 00 00 29 10 00 00 00 80 00 00 00
; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
;-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
0d 5b 85 00 00 01 00 01 00 03 00 05 04 64 69 76 61 09 6e 6c ; 1- 20
6e 65 74 6c 61 62 73 02 6e 6c 00 00 01 00 01 04 64 69 76 61 ; 21- 40
09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 01 00 01 00 01 ; 41- 60
51 80 00 04 d5 9a e0 26 09 6e 6c 6e 65 74 6c 61 62 73 02 6e ; 61- 80
6c 00 00 02 00 01 00 01 51 80 00 18 03 6e 73 37 0f 64 6f 6d ; 81- 100
61 69 6e 2d 72 65 67 69 73 74 72 79 02 6e 6c 00 09 6e 6c 6e ; 101- 120
65 74 6c 61 62 73 02 6e 6c 00 00 02 00 01 00 01 51 80 00 13 ; 121- 140
04 6f 70 65 6e 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 09 ; 141- 160
6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 02 00 01 00 01 51 ; 161- 180
80 00 11 05 6f 6d 76 61 6c 06 74 65 64 6e 65 74 02 6e 6c 00 ; 181- 200
04 6f 70 65 6e 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 ; 201- 220
01 00 01 00 01 51 80 00 04 d5 9a e0 01 04 6f 70 65 6e 09 6e ; 221- 240
6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 1c 00 01 00 01 51 80 ; 241- 260
00 10 20 01 07 b8 02 06 00 01 00 00 00 00 00 00 00 01 04 6f ; 261- 280
70 65 6e 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 1c 00 ; 281- 300
01 00 01 51 80 00 10 20 01 07 b8 02 06 00 01 00 00 00 00 00 ; 301- 320
00 00 53 05 6f 6d 76 61 6c 06 74 65 64 6e 65 74 02 6e 6c 00 ; 321- 340
00 01 00 01 00 00 70 80 00 04 d5 9a e0 11 05 6f 6d 76 61 6c ; 341- 360
06 74 65 64 6e 65 74 02 6e 6c 00 00 1c 00 01 00 00 70 80 00 ; 361- 380
10 20 01 07 b8 02 06 00 01 02 00 39 ff fe 59 b1 87
; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
;-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
0e 87 85 00 00 01 00 02 00 04 00 08 04 64 69 76 61 09 6e 6c ; 1- 20
6e 65 74 6c 61 62 73 02 6e 6c 00 00 01 00 01 04 64 69 76 61 ; 21- 40
09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 01 00 01 00 01 ; 41- 60
51 80 00 04 d5 9a e0 26 04 64 69 76 61 09 6e 6c 6e 65 74 6c ; 61- 80
61 62 73 02 6e 6c 00 00 2e 00 01 00 01 51 80 00 a0 00 01 05 ; 81- 100
03 00 01 51 80 46 3d 18 29 46 15 8b 29 ab 0f 09 6e 6c 6e 65 ; 101- 120
74 6c 61 62 73 02 6e 6c 00 7d 90 9b 21 31 d6 0d b5 91 2b b1 ; 121- 140
e8 ff 90 4a 39 6f 61 bd 50 61 ee 64 8c 50 99 4a 95 04 cd 9e ; 141- 160
48 d8 d4 13 2a 7f 3a f2 ff 5f e5 2b ec 58 56 b7 e7 95 b0 89 ; 161- 180
23 84 be 57 bd fd 85 59 2e b2 a1 dd 0c 59 23 63 9d 77 68 b0 ; 181- 200
1d 37 84 2b 47 1b 70 00 04 2e 27 56 3c 39 37 e9 9e 93 74 34 ; 201- 220
1b d9 46 7a 8f cf b5 c2 03 b8 fe 65 97 f9 0f 09 04 f4 6e fd ; 221- 240
38 fc 47 c6 e0 b6 2f 21 77 d1 f1 05 65 6a 87 7f 26 09 6e 6c ; 241- 260
6e 65 74 6c 61 62 73 02 6e 6c 00 00 02 00 01 00 01 51 80 00 ; 261- 280
11 05 6f 6d 76 61 6c 06 74 65 64 6e 65 74 02 6e 6c 00 09 6e ; 281- 300
6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 02 00 01 00 01 51 80 ; 301- 320
00 18 03 6e 73 37 0f 64 6f 6d 61 69 6e 2d 72 65 67 69 73 74 ; 321- 340
72 79 02 6e 6c 00 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 ; 341- 360
00 02 00 01 00 01 51 80 00 13 04 6f 70 65 6e 09 6e 6c 6e 65 ; 361- 380
74 6c 61 62 73 02 6e 6c 00 09 6e 6c 6e 65 74 6c 61 62 73 02 ; 381- 400
6e 6c 00 00 2e 00 01 00 01 51 80 00 a0 00 02 05 02 00 01 51 ; 401- 420
80 46 3d 18 29 46 15 8b 29 ab 0f 09 6e 6c 6e 65 74 6c 61 62 ; 421- 440
73 02 6e 6c 00 ad 07 18 03 3f 18 f6 5c 35 8d 5b 89 d8 cf 6a ; 441- 460
11 fc 3c 32 6b bc 06 e3 c4 c8 ec 47 83 1d ab a0 ea e3 af 43 ; 461- 480
b0 f5 ec aa 5d 4e aa fa 79 6f 1a 2d fc 1f 44 81 7a 61 a2 49 ; 481- 500
76 0b 8e 9d 9f 34 95 66 56 89 99 dc f6 31 6e 42 bb 16 45 93 ; 501- 520
60 44 7b 19 3a c4 e6 9a ab 69 9a b5 84 8f 86 b5 17 af c1 e0 ; 521- 540
4c b1 33 eb 67 cc cf 5b f6 e9 27 ff f3 d9 d0 c5 8e f0 91 b0 ; 541- 560
ab 77 93 18 e7 7e dc 44 1e f1 73 72 7e 04 6f 70 65 6e 09 6e ; 561- 580
6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 01 00 01 00 01 51 80 ; 581- 600
00 04 d5 9a e0 01 04 6f 70 65 6e 09 6e 6c 6e 65 74 6c 61 62 ; 601- 620
73 02 6e 6c 00 00 1c 00 01 00 01 51 80 00 10 20 01 07 b8 02 ; 621- 640
06 00 01 00 00 00 00 00 00 00 01 04 6f 70 65 6e 09 6e 6c 6e ; 641- 660
65 74 6c 61 62 73 02 6e 6c 00 00 1c 00 01 00 01 51 80 00 10 ; 661- 680
20 01 07 b8 02 06 00 01 00 00 00 00 00 00 00 53 05 6f 6d 76 ; 681- 700
61 6c 06 74 65 64 6e 65 74 02 6e 6c 00 00 01 00 01 00 00 70 ; 701- 720
80 00 04 d5 9a e0 11 05 6f 6d 76 61 6c 06 74 65 64 6e 65 74 ; 721- 740
02 6e 6c 00 00 1c 00 01 00 00 70 80 00 10 20 01 07 b8 02 06 ; 741- 760
00 01 02 00 39 ff fe 59 b1 87 04 6f 70 65 6e 09 6e 6c 6e 65 ; 761- 780
74 6c 61 62 73 02 6e 6c 00 00 2e 00 01 00 01 51 80 00 a0 00 ; 781- 800
01 05 03 00 01 51 80 46 3d 18 29 46 15 8b 29 ab 0f 09 6e 6c ; 801- 820
6e 65 74 6c 61 62 73 02 6e 6c 00 33 42 f9 d1 94 cb d3 27 dc ; 821- 840
e3 6b fd 80 34 a8 c0 ab 2a 76 f8 ef 9d c2 f7 b4 08 2f ff 3c ; 841- 860
35 c1 b4 13 46 5b 05 38 e7 97 96 41 b9 01 ff 8c 0b de 62 78 ; 861- 880
29 68 2f fe fb 53 7a 61 92 3f 89 79 3e df 49 cc ad a3 f7 45 ; 881- 900
13 7b 99 4c 0b 74 06 ee 1e 97 5a fc 6b 74 60 6d a7 68 24 5f ; 901- 920
01 f8 5a e2 84 ad 18 cf 52 ff f7 a5 66 84 76 b0 34 5c 42 8f ; 921- 940
c6 58 c2 38 c4 8c 6b 7a 72 90 4c 9c 77 90 d4 dc cf cf 2a 04 ; 941- 960
6f 70 65 6e 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 2e ; 961- 980
00 01 00 01 51 80 00 a0 00 1c 05 03 00 01 51 80 46 3d 18 29 ; 981-1000
46 15 8b 29 ab 0f 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 ; 1001-1020
53 09 41 45 b5 88 59 88 6e 2a 21 8e 42 ac 80 7c e2 9f 2e d4 ; 1021-1040
f6 48 3f 70 40 d8 61 1d 3f ea e2 ba ad 20 83 80 bc 7e 3f 40 ; 1041-1060
e7 41 74 9c c3 7c 51 30 e6 f2 99 50 0a 3f d9 26 5a fd d2 38 ; 1061-1080
09 79 e5 27 f1 25 80 e5 13 58 a5 2b 95 70 c3 53 cd ee 0e c3 ; 1081-1100
07 32 f6 73 17 60 b2 1d 3a b0 a4 0c 8f ef c3 65 5e 87 01 98 ; 1101-1120
51 51 a9 fe c0 f7 b2 0d 02 d8 29 40 b2 a8 c4 8d 52 da 36 f9 ; 1121-1140
98 f9 c4 6d 6e 1b ed 42 00 00 29 10 00 00 00 80 00 00 00
; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
;-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
5c 21 87 00 00 01 00 02 00 00 00 00 04 64 69 76 61 09 6e 6c ; 1- 20
6e 65 74 6c 61 62 73 02 6e 6c 00 00 2e 00 01 04 64 69 76 61 ; 21- 40
09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 2e 00 01 00 01 ; 41- 60
51 80 00 a0 00 01 05 03 00 01 51 80 46 3d 18 29 46 15 8b 29 ; 61- 80
ab 0f 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 7d 90 9b 21 ; 81- 100
31 d6 0d b5 91 2b b1 e8 ff 90 4a 39 6f 61 bd 50 61 ee 64 8c ; 101- 120
50 99 4a 95 04 cd 9e 48 d8 d4 13 2a 7f 3a f2 ff 5f e5 2b ec ; 121- 140
58 56 b7 e7 95 b0 89 23 84 be 57 bd fd 85 59 2e b2 a1 dd 0c ; 141- 160
59 23 63 9d 77 68 b0 1d 37 84 2b 47 1b 70 00 04 2e 27 56 3c ; 161- 180
39 37 e9 9e 93 74 34 1b d9 46 7a 8f cf b5 c2 03 b8 fe 65 97 ; 181- 200
f9 0f 09 04 f4 6e fd 38 fc 47 c6 e0 b6 2f 21 77 d1 f1 05 65 ; 201- 220
6a 87 7f 26 04 64 69 76 61 09 6e 6c 6e 65 74 6c 61 62 73 02 ; 221- 240
6e 6c 00 00 2e 00 01 00 01 51 80 00 a0 00 1c 05 03 00 01 51 ; 241- 260
80 46 3d 18 29 46 15 8b 29 ab 0f 09 6e 6c 6e 65 74 6c 61 62 ; 261- 280
73 02 6e 6c 00 de 55 75 bf 56 52 fb 36 13 2a c6 1b cd 95 d1 ; 281- 300
3f 28 f8 60 f8 b9 d5 e1 4b ae 51 e5 b2 3c c3 87 43 53 04 19 ; 301- 320
13 64 42 86 62 9c f3 b7 af b7 52 29 c5 cd 53 d2 5e 70 cb 59 ; 321- 340
4e 66 7b 02 d5 d6 29 46 1a 2a 6c 4b 22 81 b8 93 65 0d 9d 12 ; 341- 360
de e8 9d 59 41 17 d2 c4 fd d2 76 92 fc fb 83 3d 97 85 06 f9 ; 361- 380
f5 08 c8 dc 2b d4 7c e0 da eb 96 ff 5a be 15 c3 17 4c b3 a7 ; 381- 400
c3 54 84 55 b6 be f2 cd 05 ca 99 5d c8
; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
;-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
f6 7d 85 00 00 01 00 03 00 04 00 08 04 64 69 76 61 09 6e 6c ; 1- 20
6e 65 74 6c 61 62 73 02 6e 6c 00 00 2e 00 01 04 64 69 76 61 ; 21- 40
09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 2e 00 01 00 01 ; 41- 60
51 80 00 a0 00 01 05 03 00 01 51 80 46 3d 18 29 46 15 8b 29 ; 61- 80
ab 0f 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 7d 90 9b 21 ; 81- 100
31 d6 0d b5 91 2b b1 e8 ff 90 4a 39 6f 61 bd 50 61 ee 64 8c ; 101- 120
50 99 4a 95 04 cd 9e 48 d8 d4 13 2a 7f 3a f2 ff 5f e5 2b ec ; 121- 140
58 56 b7 e7 95 b0 89 23 84 be 57 bd fd 85 59 2e b2 a1 dd 0c ; 141- 160
59 23 63 9d 77 68 b0 1d 37 84 2b 47 1b 70 00 04 2e 27 56 3c ; 161- 180
39 37 e9 9e 93 74 34 1b d9 46 7a 8f cf b5 c2 03 b8 fe 65 97 ; 181- 200
f9 0f 09 04 f4 6e fd 38 fc 47 c6 e0 b6 2f 21 77 d1 f1 05 65 ; 201- 220
6a 87 7f 26 04 64 69 76 61 09 6e 6c 6e 65 74 6c 61 62 73 02 ; 221- 240
6e 6c 00 00 2e 00 01 00 01 51 80 00 a0 00 1c 05 03 00 01 51 ; 241- 260
80 46 3d 18 29 46 15 8b 29 ab 0f 09 6e 6c 6e 65 74 6c 61 62 ; 261- 280
73 02 6e 6c 00 de 55 75 bf 56 52 fb 36 13 2a c6 1b cd 95 d1 ; 281- 300
3f 28 f8 60 f8 b9 d5 e1 4b ae 51 e5 b2 3c c3 87 43 53 04 19 ; 301- 320
13 64 42 86 62 9c f3 b7 af b7 52 29 c5 cd 53 d2 5e 70 cb 59 ; 321- 340
4e 66 7b 02 d5 d6 29 46 1a 2a 6c 4b 22 81 b8 93 65 0d 9d 12 ; 341- 360
de e8 9d 59 41 17 d2 c4 fd d2 76 92 fc fb 83 3d 97 85 06 f9 ; 361- 380
f5 08 c8 dc 2b d4 7c e0 da eb 96 ff 5a be 15 c3 17 4c b3 a7 ; 381- 400
c3 54 84 55 b6 be f2 cd 05 ca 99 5d c8 04 64 69 76 61 09 6e ; 401- 420
6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 2e 00 01 00 00 46 50 ; 421- 440
00 a0 00 2f 05 03 00 00 46 50 46 3d 18 29 46 15 8b 29 ab 0f ; 441- 460
09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 5a 75 f4 5c 4f fc ; 461- 480
4e 1b 16 09 6f a9 12 d2 ac c3 ef 00 4f 45 f8 f9 e7 d5 77 58 ; 481- 500
2a 2a da cd cd 7a a3 0b 4c 18 30 d1 c2 89 f6 e3 49 64 9c 81 ; 501- 520
f1 a8 e9 f5 29 35 e0 f0 c9 e7 33 42 3d d5 c5 0c b8 da e6 27 ; 521- 540
29 45 96 df 89 5d 32 30 d6 8b b0 ee 07 d7 63 17 17 3a 44 c5 ; 541- 560
1a 13 bf 72 a8 ec fe 2d 88 82 8a 3b 43 4a 30 a0 af 87 64 33 ; 561- 580
23 42 ec 46 0d 19 f2 d9 34 31 ee 6b 11 f3 10 22 49 8a d7 5f ; 581- 600
15 65 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 02 00 01 ; 601- 620
00 01 51 80 00 11 05 6f 6d 76 61 6c 06 74 65 64 6e 65 74 02 ; 621- 640
6e 6c 00 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 02 00 ; 641- 660
01 00 01 51 80 00 18 03 6e 73 37 0f 64 6f 6d 61 69 6e 2d 72 ; 661- 680
65 67 69 73 74 72 79 02 6e 6c 00 09 6e 6c 6e 65 74 6c 61 62 ; 681- 700
73 02 6e 6c 00 00 02 00 01 00 01 51 80 00 13 04 6f 70 65 6e ; 701- 720
09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 09 6e 6c 6e 65 74 ; 721- 740
6c 61 62 73 02 6e 6c 00 00 2e 00 01 00 01 51 80 00 a0 00 02 ; 741- 760
05 02 00 01 51 80 46 3d 18 29 46 15 8b 29 ab 0f 09 6e 6c 6e ; 761- 780
65 74 6c 61 62 73 02 6e 6c 00 ad 07 18 03 3f 18 f6 5c 35 8d ; 781- 800
5b 89 d8 cf 6a 11 fc 3c 32 6b bc 06 e3 c4 c8 ec 47 83 1d ab ; 801- 820
a0 ea e3 af 43 b0 f5 ec aa 5d 4e aa fa 79 6f 1a 2d fc 1f 44 ; 821- 840
81 7a 61 a2 49 76 0b 8e 9d 9f 34 95 66 56 89 99 dc f6 31 6e ; 841- 860
42 bb 16 45 93 60 44 7b 19 3a c4 e6 9a ab 69 9a b5 84 8f 86 ; 861- 880
b5 17 af c1 e0 4c b1 33 eb 67 cc cf 5b f6 e9 27 ff f3 d9 d0 ; 881- 900
c5 8e f0 91 b0 ab 77 93 18 e7 7e dc 44 1e f1 73 72 7e 04 6f ; 901- 920
70 65 6e 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 01 00 ; 921- 940
01 00 01 51 80 00 04 d5 9a e0 01 04 6f 70 65 6e 09 6e 6c 6e ; 941- 960
65 74 6c 61 62 73 02 6e 6c 00 00 1c 00 01 00 01 51 80 00 10 ; 961- 980
20 01 07 b8 02 06 00 01 00 00 00 00 00 00 00 01 04 6f 70 65 ; 981-1000
6e 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 1c 00 01 00 ; 1001-1020
01 51 80 00 10 20 01 07 b8 02 06 00 01 00 00 00 00 00 00 00 ; 1021-1040
53 05 6f 6d 76 61 6c 06 74 65 64 6e 65 74 02 6e 6c 00 00 01 ; 1041-1060
00 01 00 00 70 80 00 04 d5 9a e0 11 05 6f 6d 76 61 6c 06 74 ; 1061-1080
65 64 6e 65 74 02 6e 6c 00 00 1c 00 01 00 00 70 80 00 10 20 ; 1081-1100
01 07 b8 02 06 00 01 02 00 39 ff fe 59 b1 87 04 6f 70 65 6e ; 1101-1120
09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 2e 00 01 00 01 ; 1121-1140
51 80 00 a0 00 01 05 03 00 01 51 80 46 3d 18 29 46 15 8b 29 ; 1141-1160
ab 0f 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 33 42 f9 d1 ; 1161-1180
94 cb d3 27 dc e3 6b fd 80 34 a8 c0 ab 2a 76 f8 ef 9d c2 f7 ; 1181-1200
b4 08 2f ff 3c 35 c1 b4 13 46 5b 05 38 e7 97 96 41 b9 01 ff ; 1201-1220
8c 0b de 62 78 29 68 2f fe fb 53 7a 61 92 3f 89 79 3e df 49 ; 1221-1240
cc ad a3 f7 45 13 7b 99 4c 0b 74 06 ee 1e 97 5a fc 6b 74 60 ; 1241-1260
6d a7 68 24 5f 01 f8 5a e2 84 ad 18 cf 52 ff f7 a5 66 84 76 ; 1261-1280
b0 34 5c 42 8f c6 58 c2 38 c4 8c 6b 7a 72 90 4c 9c 77 90 d4 ; 1281-1300
dc cf cf 2a 04 6f 70 65 6e 09 6e 6c 6e 65 74 6c 61 62 73 02 ; 1301-1320
6e 6c 00 00 2e 00 01 00 01 51 80 00 a0 00 1c 05 03 00 01 51 ; 1321-1340
80 46 3d 18 29 46 15 8b 29 ab 0f 09 6e 6c 6e 65 74 6c 61 62 ; 1341-1360
73 02 6e 6c 00 53 09 41 45 b5 88 59 88 6e 2a 21 8e 42 ac 80 ; 1361-1380
7c e2 9f 2e d4 f6 48 3f 70 40 d8 61 1d 3f ea e2 ba ad 20 83 ; 1381-1400
80 bc 7e 3f 40 e7 41 74 9c c3 7c 51 30 e6 f2 99 50 0a 3f d9 ; 1401-1420
26 5a fd d2 38 09 79 e5 27 f1 25 80 e5 13 58 a5 2b 95 70 c3 ; 1421-1440
53 cd ee 0e c3 07 32 f6 73 17 60 b2 1d 3a b0 a4 0c 8f ef c3 ; 1441-1460
65 5e 87 01 98 51 51 a9 fe c0 f7 b2 0d 02 d8 29 40 b2 a8 c4 ; 1461-1480
8d 52 da 36 f9 98 f9 c4 6d 6e 1b ed 42 00 00 29 10 00 00 00 ; 1481-1500
80 00 00 00
; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
;-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
f6 7d 85 00 00 01 00 01 00 03 00 05 09 6e 6c 6e 65 74 6c 61 ; 1- 20
62 73 02 6e 6c 00 00 30 00 01 09 6e 6c 6e 65 74 6c 61 62 73 ; 21- 40
02 6e 6c 00 00 30 00 01 00 01 51 80 00 86 01 01 03 05 01 03 ; 41- 60
f3 cd 35 8c cf ca 92 58 84 25 7d 19 cf 72 4c 76 06 25 66 91 ; 61- 80
53 7a 2c fb a9 3b 79 9b cf b1 61 2d 29 e6 db a9 fa 88 6f 4d ; 81- 100
2d bc bd ec 98 b8 e7 76 96 65 8d cc e7 fc 49 05 23 92 da f5 ; 101- 120
ad 72 8d ad f0 2d 3e c5 e3 b5 6d cf dd e9 94 f2 df 60 c7 72 ; 121- 140
1a 56 ea b0 c7 d6 fa 7c e8 b9 7e 85 ad 2d 9b 0c b2 f5 03 fb ; 141- 160
cb 66 d5 c3 9c d2 6c 50 ab 79 f9 3c a8 25 01 81 f1 e6 f5 b1 ; 161- 180
f3 30 6d 54 05 8b 44 21 09 6e 6c 6e 65 74 6c 61 62 73 02 6e ; 181- 200
6c 00 00 02 00 01 00 01 51 80 00 18 03 6e 73 37 0f 64 6f 6d ; 201- 220
61 69 6e 2d 72 65 67 69 73 74 72 79 02 6e 6c 00 09 6e 6c 6e ; 221- 240
65 74 6c 61 62 73 02 6e 6c 00 00 02 00 01 00 01 51 80 00 13 ; 241- 260
04 6f 70 65 6e 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 09 ; 261- 280
6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 02 00 01 00 01 51 ; 281- 300
80 00 11 05 6f 6d 76 61 6c 06 74 65 64 6e 65 74 02 6e 6c 00 ; 301- 320
04 6f 70 65 6e 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 ; 321- 340
01 00 01 00 01 51 80 00 04 d5 9a e0 01 04 6f 70 65 6e 09 6e ; 341- 360
6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 1c 00 01 00 01 51 80 ; 361- 380
00 10 20 01 07 b8 02 06 00 01 00 00 00 00 00 00 00 53 04 6f ; 381- 400
70 65 6e 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 1c 00 ; 401- 420
01 00 01 51 80 00 10 20 01 07 b8 02 06 00 01 00 00 00 00 00 ; 421- 440
00 00 01 05 6f 6d 76 61 6c 06 74 65 64 6e 65 74 02 6e 6c 00 ; 441- 460
00 01 00 01 00 00 70 80 00 04 d5 9a e0 11 05 6f 6d 76 61 6c ; 461- 480
06 74 65 64 6e 65 74 02 6e 6c 00 00 1c 00 01 00 00 70 80 00 ; 481- 500
10 20 01 07 b8 02 06 00 01 02 00 39 ff fe 59 b1 87
; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
;-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
7d b9 85 00 00 01 00 02 00 04 00 08 09 6e 6c 6e 65 74 6c 61 ; 1- 20
62 73 02 6e 6c 00 00 30 00 01 09 6e 6c 6e 65 74 6c 61 62 73 ; 21- 40
02 6e 6c 00 00 30 00 01 00 01 51 80 00 86 01 01 03 05 01 03 ; 41- 60
f3 cd 35 8c cf ca 92 58 84 25 7d 19 cf 72 4c 76 06 25 66 91 ; 61- 80
53 7a 2c fb a9 3b 79 9b cf b1 61 2d 29 e6 db a9 fa 88 6f 4d ; 81- 100
2d bc bd ec 98 b8 e7 76 96 65 8d cc e7 fc 49 05 23 92 da f5 ; 101- 120
ad 72 8d ad f0 2d 3e c5 e3 b5 6d cf dd e9 94 f2 df 60 c7 72 ; 121- 140
1a 56 ea b0 c7 d6 fa 7c e8 b9 7e 85 ad 2d 9b 0c b2 f5 03 fb ; 141- 160
cb 66 d5 c3 9c d2 6c 50 ab 79 f9 3c a8 25 01 81 f1 e6 f5 b1 ; 161- 180
f3 30 6d 54 05 8b 44 21 09 6e 6c 6e 65 74 6c 61 62 73 02 6e ; 181- 200
6c 00 00 2e 00 01 00 01 51 80 00 a0 00 30 05 02 00 01 51 80 ; 201- 220
46 3d 18 29 46 15 8b 29 ab 0f 09 6e 6c 6e 65 74 6c 61 62 73 ; 221- 240
02 6e 6c 00 e6 20 9a 3f 0b d4 7f fe e3 aa ac 29 eb d1 4e 9c ; 241- 260
eb dd 76 21 9c cc 7a 4d 42 f2 47 16 f7 06 fb 48 e5 fd f6 73 ; 261- 280
91 23 e1 dc 7b 43 8b 64 72 f7 06 5e a3 08 8f bd 38 7e 16 22 ; 281- 300
ea a2 a2 a3 10 3c 0c d0 ec 67 26 b7 06 7e e6 71 b8 8a 3a a9 ; 301- 320
7f 00 d5 14 db 2c 32 02 b0 5e 65 25 07 a3 89 71 00 f2 3c db ; 321- 340
20 86 01 1e 53 80 d9 46 46 04 ec 26 8d 35 97 cc 81 a9 fe d8 ; 341- 360
5b 25 6b 2e e9 f7 0c eb e7 6e b0 37 09 6e 6c 6e 65 74 6c 61 ; 361- 380
62 73 02 6e 6c 00 00 02 00 01 00 01 51 80 00 11 05 6f 6d 76 ; 381- 400
61 6c 06 74 65 64 6e 65 74 02 6e 6c 00 09 6e 6c 6e 65 74 6c ; 401- 420
61 62 73 02 6e 6c 00 00 02 00 01 00 01 51 80 00 18 03 6e 73 ; 421- 440
37 0f 64 6f 6d 61 69 6e 2d 72 65 67 69 73 74 72 79 02 6e 6c ; 441- 460
00 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 02 00 01 00 ; 461- 480
01 51 80 00 13 04 6f 70 65 6e 09 6e 6c 6e 65 74 6c 61 62 73 ; 481- 500
02 6e 6c 00 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 2e ; 501- 520
00 01 00 01 51 80 00 a0 00 02 05 02 00 01 51 80 46 3d 18 29 ; 521- 540
46 15 8b 29 ab 0f 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 ; 541- 560
ad 07 18 03 3f 18 f6 5c 35 8d 5b 89 d8 cf 6a 11 fc 3c 32 6b ; 561- 580
bc 06 e3 c4 c8 ec 47 83 1d ab a0 ea e3 af 43 b0 f5 ec aa 5d ; 581- 600
4e aa fa 79 6f 1a 2d fc 1f 44 81 7a 61 a2 49 76 0b 8e 9d 9f ; 601- 620
34 95 66 56 89 99 dc f6 31 6e 42 bb 16 45 93 60 44 7b 19 3a ; 621- 640
c4 e6 9a ab 69 9a b5 84 8f 86 b5 17 af c1 e0 4c b1 33 eb 67 ; 641- 660
cc cf 5b f6 e9 27 ff f3 d9 d0 c5 8e f0 91 b0 ab 77 93 18 e7 ; 661- 680
7e dc 44 1e f1 73 72 7e 04 6f 70 65 6e 09 6e 6c 6e 65 74 6c ; 681- 700
61 62 73 02 6e 6c 00 00 01 00 01 00 01 51 80 00 04 d5 9a e0 ; 701- 720
01 04 6f 70 65 6e 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 ; 721- 740
00 1c 00 01 00 01 51 80 00 10 20 01 07 b8 02 06 00 01 00 00 ; 741- 760
00 00 00 00 00 53 04 6f 70 65 6e 09 6e 6c 6e 65 74 6c 61 62 ; 761- 780
73 02 6e 6c 00 00 1c 00 01 00 01 51 80 00 10 20 01 07 b8 02 ; 781- 800
06 00 01 00 00 00 00 00 00 00 01 05 6f 6d 76 61 6c 06 74 65 ; 801- 820
64 6e 65 74 02 6e 6c 00 00 01 00 01 00 00 70 80 00 04 d5 9a ; 821- 840
e0 11 05 6f 6d 76 61 6c 06 74 65 64 6e 65 74 02 6e 6c 00 00 ; 841- 860
1c 00 01 00 00 70 80 00 10 20 01 07 b8 02 06 00 01 02 00 39 ; 861- 880
ff fe 59 b1 87 04 6f 70 65 6e 09 6e 6c 6e 65 74 6c 61 62 73 ; 881- 900
02 6e 6c 00 00 2e 00 01 00 01 51 80 00 a0 00 01 05 03 00 01 ; 901- 920
51 80 46 3d 18 29 46 15 8b 29 ab 0f 09 6e 6c 6e 65 74 6c 61 ; 921- 940
62 73 02 6e 6c 00 33 42 f9 d1 94 cb d3 27 dc e3 6b fd 80 34 ; 941- 960
a8 c0 ab 2a 76 f8 ef 9d c2 f7 b4 08 2f ff 3c 35 c1 b4 13 46 ; 961- 980
5b 05 38 e7 97 96 41 b9 01 ff 8c 0b de 62 78 29 68 2f fe fb ; 981-1000
53 7a 61 92 3f 89 79 3e df 49 cc ad a3 f7 45 13 7b 99 4c 0b ; 1001-1020
74 06 ee 1e 97 5a fc 6b 74 60 6d a7 68 24 5f 01 f8 5a e2 84 ; 1021-1040
ad 18 cf 52 ff f7 a5 66 84 76 b0 34 5c 42 8f c6 58 c2 38 c4 ; 1041-1060
8c 6b 7a 72 90 4c 9c 77 90 d4 dc cf cf 2a 04 6f 70 65 6e 09 ; 1061-1080
6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 2e 00 01 00 01 51 ; 1081-1100
80 00 a0 00 1c 05 03 00 01 51 80 46 3d 18 29 46 15 8b 29 ab ; 1101-1120
0f 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 53 09 41 45 b5 ; 1121-1140
88 59 88 6e 2a 21 8e 42 ac 80 7c e2 9f 2e d4 f6 48 3f 70 40 ; 1141-1160
d8 61 1d 3f ea e2 ba ad 20 83 80 bc 7e 3f 40 e7 41 74 9c c3 ; 1161-1180
7c 51 30 e6 f2 99 50 0a 3f d9 26 5a fd d2 38 09 79 e5 27 f1 ; 1181-1200
25 80 e5 13 58 a5 2b 95 70 c3 53 cd ee 0e c3 07 32 f6 73 17 ; 1201-1220
60 b2 1d 3a b0 a4 0c 8f ef c3 65 5e 87 01 98 51 51 a9 fe c0 ; 1221-1240
f7 b2 0d 02 d8 29 40 b2 a8 c4 8d 52 da 36 f9 98 f9 c4 6d 6e ; 1241-1260
1b ed 42 00 00 29 10 00 00 00 80 00 00 00
; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
;-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50 e5 81 80 00 01 00 08 00 0a 00 18 02 73 65 00 00 30 00 01 ; 1- 20
02 73 65 00 00 30 00 01 00 00 0e 10 00 86 01 00 03 05 01 03 ; 21- 40
db 42 4d 16 35 1a f6 8e 87 cb dc 52 4a 49 1f 15 27 68 bc 86 ; 41- 60
c5 d4 0b 6b e9 e0 bf 69 ab ce 9c 6b ad fe 4b 00 fb 9a 59 74 ; 61- 80
f2 36 1f 61 8d 9f b2 7e 63 84 fc 72 45 8d 57 bd ae ca c2 1a ; 81- 100
77 e6 8d 4d 5f 21 c1 05 c0 66 06 45 77 af 60 46 4b d7 3a d9 ; 101- 120
8c d2 8f 2b ff 44 8e 32 1e 0b 3e d3 73 55 b2 a9 4d 68 cc fd ; 121- 140
0b 0d f8 a2 fd 38 2b ae 6c e3 96 52 27 47 c5 83 4e 55 55 50 ; 141- 160
a0 09 49 62 de 1e a1 25 02 73 65 00 00 30 00 01 00 00 0e 10 ; 161- 180
00 88 01 00 03 05 03 01 00 01 b9 a9 68 15 f6 09 f9 32 a4 7b ; 181- 200
0e c9 8f 95 f6 df d3 87 18 f3 75 9c 8b de 4f 3d f9 5b b7 6f ; 201- 220
51 a5 60 46 fb 10 c2 f0 84 5e 67 e4 49 89 11 c4 5e 55 de 26 ; 221- 240
67 9e 5b 54 0a d4 43 c1 af 86 2a 17 b6 8a 19 ad d2 ba db 4c ; 241- 260
15 38 78 28 ca 1c ed 2c 98 5c 8c f4 96 19 fc c1 46 59 8d 66 ; 261- 280
11 72 48 34 b7 49 e8 58 31 5e 82 17 1b 00 88 55 e2 e1 bb ae ; 281- 300
13 5d de 1a dd 92 df 3d 64 a1 b5 8c 34 74 b3 55 6e 29 02 73 ; 301- 320
65 00 00 30 00 01 00 00 0e 10 00 88 01 00 03 05 03 01 00 01 ; 321- 340
cd e7 e2 f5 7b 7f a4 db 46 34 a9 7c 00 dc 20 19 fe 30 3a b3 ; 341- 360
b8 55 28 fa cd db f3 9c 02 f1 3a 7e 77 51 03 94 b3 c5 ff 91 ; 361- 380
88 47 86 37 3f ef 2e d4 ea 4f 2a e0 82 ce ea ef 7e 27 2c fc ; 381- 400
78 86 41 4d c9 92 fd f0 94 53 f9 71 92 c1 4a 90 a2 c1 ac d8 ; 401- 420
db 9d ee 27 05 e9 22 d4 be 96 23 fa 00 af a4 38 ec 2c 11 64 ; 421- 440
d8 c4 6e af bc 1a 1d 9b f0 12 4d ba ac d8 5a a8 90 54 cf 2d ; 441- 460
6e f8 95 33 a9 e7 56 b9 02 73 65 00 00 30 00 01 00 00 0e 10 ; 461- 480
01 08 01 01 03 05 03 01 00 01 ac 4f 31 c4 76 c7 41 db 41 5e ; 481- 500
16 79 90 7a a0 40 d7 fa bd 10 33 ae 4a 6e 14 e3 ad 6d 59 68 ; 501- 520
04 66 3e 11 19 65 ed d8 f6 27 e0 12 ea bb bd 9f f3 19 95 1d ; 521- 540
10 63 56 cb e2 59 ce eb 34 95 4a 6d c2 08 c6 c2 15 12 d7 9e ; 541- 560
7c 1d be 09 29 46 db 39 37 0c f2 9c 17 96 3d 04 89 7d e8 0c ; 561- 580
55 66 8c 73 b8 e3 88 0b 90 13 94 29 47 ff 98 2e c7 bd fc 18 ; 581- 600
1f f0 5e db 61 a7 0a 5a e2 9c a2 69 d4 e8 38 cb 0c ce f5 68 ; 601- 620
25 32 4e e3 6d f5 b7 de 05 0a be 2a d3 1e bd b9 18 be d2 4d ; 621- 640
05 33 05 be 54 b3 1b 7c 96 09 f2 4d 41 ec d6 dd c9 c0 26 39 ; 641- 660
84 a6 7a 0a a1 71 98 05 59 3f 6d 22 81 38 b1 8a 7f f5 2d ca ; 661- 680
e0 5f f2 8c 10 67 7f 6e eb c5 e2 a2 42 c9 db a2 78 7b a4 b9 ; 681- 700
8d c7 e1 73 00 71 1f b1 89 ad a7 21 43 ef 9b fa 32 59 1f 01 ; 701- 720
5b f8 56 77 33 af 9d 20 93 86 51 df df 18 98 95 e0 db b7 fa ; 721- 740
35 39 34 34 f4 0d 02 73 65 00 00 30 00 01 00 00 0e 10 01 08 ; 741- 760
01 01 03 05 03 01 00 01 be b1 45 91 c4 7f e3 f2 17 97 71 12 ; 761- 780
fc f4 04 71 07 6f 38 ae ea 26 5a 88 d5 bf ca 34 9a 65 c9 ab ; 781- 800
99 98 91 30 5f 05 3e 9a 43 f9 7b 8a 49 ab b4 ae 0b b8 78 1c ; 801- 820
18 76 99 04 a0 c5 51 e0 58 48 f1 fa e4 b8 f1 c8 b9 ed 8b 3f ; 821- 840
51 13 a3 ed a1 0a b7 6b eb 42 b5 e7 7f 32 2e fc db 3a 13 31 ; 841- 860
5e de a4 9e 33 cd f8 e9 5a 94 c9 82 92 76 9d 6a 87 ca 81 ae ; 861- 880
45 2c a3 8f 42 cd 82 de 7c 3a 00 7e 16 50 d1 ab 72 19 83 31 ; 881- 900
50 70 47 07 d9 75 05 d8 65 35 de b2 a5 0b 98 63 0a ee 6c 23 ; 901- 920
40 63 b1 7a b4 43 41 6a c5 bf c3 61 36 75 55 df 53 e2 85 a6 ; 921- 940
01 75 0d 53 26 3b df 19 2f c5 61 92 70 bf f0 5d 76 21 0b 88 ; 941- 960
b7 94 9c d5 ae dc 03 ac 44 0b 21 80 e7 03 04 e0 0f 52 f2 89 ; 961- 980
34 4a ba 44 71 0b 16 6b d7 38 e7 b6 77 c1 f6 cb 3b f4 d8 43 ; 981-1000
10 8a 4e 86 c1 49 b5 e8 3a d2 76 65 fe 49 67 de 95 0b 3e f4 ; 1001-1020
42 c5 37 a9 02 73 65 00 00 2e 00 01 00 00 0e 10 00 96 00 30 ; 1021-1040
05 01 00 00 0e 10 46 2e a3 b7 46 26 25 d5 95 7b 02 73 65 00 ; 1041-1060
a5 f8 54 11 87 a1 c5 0a 62 cf 21 27 61 8f 82 4e 32 8f ca 1e ; 1061-1080
25 10 34 48 4c 23 46 52 fc 7c 79 c5 91 77 8a 81 b3 08 29 d2 ; 1081-1100
89 64 d3 4c ad 20 b9 b3 4e e3 e2 6b bb d6 e1 56 59 c0 aa b8 ; 1101-1120
12 c5 b3 39 2e 8f 4a ae c1 b3 78 07 8f ac 40 4f 28 a0 ea 98 ; 1121-1140
6f 1f 80 f3 d3 70 11 1b 4b c0 fc 5d f3 f2 a6 32 22 10 1f e7 ; 1141-1160
c8 40 82 9a 4c 21 d1 93 ce 17 87 b6 2a 42 67 89 f9 5c 71 a1 ; 1161-1180
89 a3 5f b0 e0 15 3d d0 02 73 65 00 00 2e 00 01 00 00 0e 10 ; 1181-1200
01 16 00 30 05 01 00 00 0e 10 46 47 a6 80 46 12 1c 59 18 16 ; 1201-1220
02 73 65 00 4c bd 74 15 bd 17 0b e1 34 d1 b5 57 4f 18 c8 7d ; 1221-1240
7c 80 75 22 d7 f4 43 aa 7b 83 61 e8 c1 70 cd d5 8c 93 2a c7 ; 1241-1260
b6 7f 9c 73 79 52 1a 58 68 54 ef 12 83 4a 5f f3 45 e6 25 65 ; 1261-1280
fe 4f 18 72 b3 84 ea 9c 4b 54 39 ad 1b 18 29 ed 0b ca e2 80 ; 1281-1300
3c 07 98 44 09 55 95 d3 57 0f 0a 81 af 61 d0 9c 93 7c aa b3 ; 1301-1320
7c 36 52 f3 f2 e6 93 0c 20 06 5c 45 c6 45 fe 5c 8c 84 24 d0 ; 1321-1340
e9 c5 87 1e 1b 83 e2 30 b8 2a 41 59 b7 5b a5 a6 b0 22 0e bf ; 1341-1360
55 c9 99 5a ff 7b 43 74 a4 d1 8f d0 ed f5 20 d1 8d a3 e3 f9 ; 1361-1380
f8 c6 db 4d e3 3d 6e 33 9c 49 c4 14 3a b8 59 db bc 02 ef 94 ; 1381-1400
d6 d1 f3 74 f9 2c 0d 5e 98 61 8f f7 3a 22 85 18 8f 4c 36 df ; 1401-1420
3e 2f 1b 5f 4a 5c a1 39 ff fd 33 52 ab 43 b9 7e 89 5e d1 ac ; 1421-1440
e0 bd d4 88 56 39 c1 e3 4a ef f0 41 0a ee d2 96 5b c1 d8 d3 ; 1441-1460
4a 55 48 d3 e9 cf dc 96 b8 22 ca f7 75 fd 6d df cf d8 b2 2e ; 1461-1480
02 73 65 00 00 2e 00 01 00 00 0e 10 01 16 00 30 05 01 00 00 ; 1481-1500
0e 10 46 47 a6 80 46 12 1c 59 45 16 02 73 65 00 20 f7 f4 13 ; 1501-1520
08 99 61 ca f1 75 9f 71 9a c8 c4 06 77 1a 48 a8 d8 4f 45 e8 ; 1521-1540
25 92 b2 5c 16 b1 14 b4 79 44 23 23 37 20 0e 36 2f 57 8f 17 ; 1541-1560
c3 69 65 49 11 a9 40 86 06 13 ff f6 d6 ac 5e 58 ea de aa de ; 1561-1580
06 d4 19 1b 0d 58 84 83 c2 1a 01 2b 6e 7b 18 e6 38 5f 2d eb ; 1581-1600
c5 76 01 60 a4 52 5a 23 ec 7c d0 e6 21 ca 6f 29 9e 83 5f db ; 1601-1620
fb 49 0b 03 ad 09 5b 3b 28 23 1c cb 99 82 5b 1c 81 a7 7d ca ; 1621-1640
00 fd 52 22 66 19 51 1d c6 ac da 2d 65 6d 53 40 e7 b7 c0 6c ; 1641-1660
97 73 7d e2 df e7 75 df 7b 6b 7d a9 9e cb e2 6a d3 35 0c 31 ; 1661-1680
ee 6b 98 44 c7 17 47 4a 3c 69 d4 1b eb 90 40 79 6f 86 bb 53 ; 1681-1700
a6 8c e7 04 4d e4 c3 6b a6 13 5f f8 21 76 f3 ff cd de c9 88 ; 1701-1720
9f 2a 0b a5 4a aa 43 13 f1 cd 2c 28 98 9c eb 91 cc 0a da ca ; 1721-1740
d8 b5 47 78 ed c2 f4 19 78 27 f7 05 d6 4a 4f 93 7a 22 43 3d ; 1741-1760
59 15 da 1c 60 7a 46 ca 86 95 c3 77 02 73 65 00 00 02 00 01 ; 1761-1780
00 02 7b f1 00 09 01 63 02 4e 53 02 73 65 00 02 73 65 00 00 ; 1781-1800
02 00 01 00 02 7b f1 00 09 01 64 02 4e 53 02 73 65 00 02 73 ; 1801-1820
65 00 00 02 00 01 00 02 7b f1 00 09 01 65 02 4e 53 02 73 65 ; 1821-1840
00 02 73 65 00 00 02 00 01 00 02 7b f1 00 09 01 66 02 4e 53 ; 1841-1860
02 73 65 00 02 73 65 00 00 02 00 01 00 02 7b f1 00 09 01 67 ; 1861-1880
02 4e 53 02 73 65 00 02 73 65 00 00 02 00 01 00 02 7b f1 00 ; 1881-1900
09 01 68 02 4e 53 02 73 65 00 02 73 65 00 00 02 00 01 00 02 ; 1901-1920
7b f1 00 09 01 69 02 4e 53 02 73 65 00 02 73 65 00 00 02 00 ; 1921-1940
01 00 02 7b f1 00 09 01 41 02 4e 53 02 73 65 00 02 73 65 00 ; 1941-1960
00 02 00 01 00 02 7b f1 00 09 01 62 02 4e 53 02 73 65 00 02 ; 1961-1980
73 65 00 00 2e 00 01 00 02 a3 00 00 96 00 02 05 01 00 02 a3 ; 1981-2000
00 46 2e ad 6a 46 27 22 f5 95 7b 02 73 65 00 d0 db 15 15 e6 ; 2001-2020
6f 13 58 01 d7 c2 07 d1 54 e4 bf 64 00 6d ca a6 b7 61 5e 69 ; 2021-2040
2f e8 b4 b1 3e 91 d6 65 21 9e 92 82 c7 e8 6b ec 2a 1c 86 60 ; 2041-2060
6d 52 03 9c d3 7c 29 3b 60 46 0f 41 83 86 59 66 95 76 9c 83 ; 2061-2080
22 fd 27 aa c6 68 ce 41 44 c0 bb bb 8e 56 79 c1 66 3c 9b 07 ; 2081-2100
ed 50 05 88 22 24 88 0e 83 09 7f 6d 81 4c 12 ab 79 df f2 d9 ; 2101-2120
0b 6d 41 38 55 7b 7c ac 5d cd 28 04 a6 b0 54 9b 89 82 9e 39 ; 2121-2140
7e c9 5b 01 41 02 4e 53 02 73 65 00 00 01 00 01 00 02 7b f1 ; 2141-2160
00 04 c0 24 90 6b 01 41 02 4e 53 02 73 65 00 00 1c 00 01 00 ; 2161-2180
02 7b f1 00 10 20 01 06 98 00 09 03 01 00 00 00 00 00 00 00 ; 2181-2200
53 01 62 02 4e 53 02 73 65 00 00 01 00 01 00 02 7b f1 00 04 ; 2201-2220
c0 24 85 6b 01 63 02 4e 53 02 73 65 00 00 01 00 01 00 02 7b ; 2221-2240
f1 00 04 c0 24 87 6b 01 64 02 4e 53 02 73 65 00 00 01 00 01 ; 2241-2260
00 02 7b f3 00 04 51 e4 08 10 01 65 02 4e 53 02 73 65 00 00 ; 2261-2280
01 00 01 00 02 7b f1 00 04 51 e4 0a 39 01 66 02 4e 53 02 73 ; 2281-2300
65 00 00 01 00 01 00 02 7b f1 00 04 c0 24 7d 35 01 66 02 4e ; 2301-2320
53 02 73 65 00 00 1c 00 01 00 02 7b f1 00 10 20 01 06 b0 00 ; 2321-2340
07 00 00 00 00 00 00 00 00 00 53 01 67 02 4e 53 02 73 65 00 ; 2341-2360
00 01 00 01 00 02 7b f3 00 04 82 ef 05 72 01 67 02 4e 53 02 ; 2361-2380
73 65 00 00 1c 00 01 00 02 7b f3 00 10 20 01 06 b0 00 0e 00 ; 2381-2400
03 00 00 00 00 00 00 00 01 01 68 02 4e 53 02 73 65 00 00 01 ; 2401-2420
00 01 00 02 7b f1 00 04 c7 07 31 1e 01 69 02 4e 53 02 73 65 ; 2421-2440
00 00 01 00 01 00 02 7b f1 00 04 c2 92 6a 16 01 41 02 4e 53 ; 2441-2460
02 73 65 00 00 2e 00 01 00 02 7b f1 00 96 00 01 05 03 00 02 ; 2461-2480
a3 00 46 2e bd b4 46 27 06 d4 95 7b 02 73 65 00 36 41 6c 4e ; 2481-2500
6b 37 41 ba 9c 84 4c ca 8a 25 b0 f4 5e b5 38 da 51 78 f6 57 ; 2501-2520
b3 2a b8 06 24 66 06 8f fc e6 48 f6 bd 2e eb 5c 25 f8 ca 6e ; 2521-2540
a2 71 52 c3 b2 1a 21 b4 d3 69 35 b8 65 96 b7 15 9e e2 fa 25 ; 2541-2560
23 6e da e3 20 c1 bd 15 b6 40 86 2d 50 52 33 33 75 c3 97 2c ; 2561-2580
50 e5 3a ec 92 ca 32 b6 e7 7c 72 f0 8c bc dc cb 33 65 b5 0d ; 2581-2600
2b 99 21 81 0a 78 74 41 0a 89 6b 87 dc 4c 31 70 2a 8c f8 68 ; 2601-2620
10 26 e5 2a 01 41 02 4e 53 02 73 65 00 00 2e 00 01 00 02 7b ; 2621-2640
f1 00 96 00 1c 05 03 00 02 a3 00 46 2f f8 c0 46 27 06 d4 95 ; 2641-2660
7b 02 73 65 00 8b 6e 8e 8e 07 47 bc 80 ad dc 07 a4 b3 2f 3c ; 2661-2680
0e 75 a6 50 5e 8b 07 80 19 aa 11 77 74 be 9c fc a5 21 26 2f ; 2681-2700
56 3f cc 0a 46 91 06 78 39 86 5d c1 df 9b b2 1f 2f f5 97 7a ; 2701-2720
a7 91 36 6e 12 56 8c d1 d7 e0 0a b5 1b 8f 0b ac 7d df 4b 32 ; 2721-2740
4d 4a e1 a4 9f 4f 3e 6a dc fe ee d4 f8 00 40 e6 34 48 98 2f ; 2741-2760
c7 b9 df 49 63 80 8d 91 87 8d 24 2d 6d 7f ce e6 eb 93 5d 8b ; 2761-2780
d5 a3 e0 00 64 df 94 51 88 f8 b2 14 c1 01 62 02 4e 53 02 73 ; 2781-2800
65 00 00 2e 00 01 00 02 7b f1 00 96 00 01 05 03 00 02 a3 00 ; 2801-2820
46 30 17 a6 46 27 06 d4 95 7b 02 73 65 00 49 a8 36 07 fd bb ; 2821-2840
2e a3 d3 f0 f7 3d 66 f3 b1 78 74 3b 74 92 b0 97 3e 7a 3c 01 ; 2841-2860
d5 35 97 67 d2 bc d0 47 70 dc cd b6 98 ba 95 b9 db 35 ed b4 ; 2861-2880
c1 68 94 ce 52 df 9d 44 a7 22 27 66 d2 19 4a 70 80 6e 3d cc ; 2881-2900
60 e2 b5 7f 37 3a c1 18 b5 01 41 4a 76 ae 21 33 03 f1 e4 23 ; 2901-2920
0c d7 17 d1 3f 9e 01 d2 0e f3 11 d8 f1 ef 49 ec 75 5c eb fc ; 2921-2940
e3 74 4e 40 a9 eb 80 25 b5 a1 39 c8 e2 b6 cb 7c e3 43 fb 18 ; 2941-2960
f0 2d 01 63 02 4e 53 02 73 65 00 00 2e 00 01 00 02 7b f1 00 ; 2961-2980
96 00 01 05 03 00 02 a3 00 46 2f e5 19 46 27 06 d4 95 7b 02 ; 2981-3000
73 65 00 0d b2 38 33 08 15 51 95 35 8a 52 ef 0f 09 74 51 a2 ; 3001-3020
c8 41 ee a4 d2 01 54 0b 01 1f fb 73 d3 e8 3b 36 2c c5 29 75 ; 3021-3040
78 49 5f 25 03 fa c2 a2 da 7c 59 6c 68 90 dc 9c 7c 6e 88 83 ; 3041-3060
75 a8 de a9 6c 33 13 f6 61 f5 97 89 cf b6 ff 5f 08 e7 77 04 ; 3061-3080
13 67 da 56 1f 88 26 6b 3e db 91 bb 9c 7a 33 ec 7c a9 18 f0 ; 3081-3100
55 28 a3 04 52 fb e0 3d ec 82 b1 8a fa 70 0e 76 4c 40 53 f6 ; 3101-3120
3c 4f e6 86 ed 7f 25 cc cf 84 a1 01 64 02 4e 53 02 73 65 00 ; 3121-3140
00 2e 00 01 00 02 7b f3 00 96 00 01 05 03 00 02 a3 00 46 2f ; 3141-3160
66 45 46 27 06 d4 95 7b 02 73 65 00 d8 0b 9f 5a 79 a2 b5 a3 ; 3161-3180
03 af a6 c6 6d 46 0a c4 45 c8 2c 58 3f a8 eb a6 19 da 01 f2 ; 3181-3200
d4 24 e4 83 99 93 6f 79 d0 c1 a1 29 9e 1f b3 e9 92 ab bd c5 ; 3201-3220
5f 2b 27 e1 4c 8a ec 4c 48 fb ac f7 05 34 6d d3 76 78 77 41 ; 3221-3240
8f 32 92 d3 38 35 4c 18 1b f9 67 7d e0 82 c8 91 69 9b f7 ec ; 3241-3260
7f c1 93 21 c8 2e e7 a8 95 0f 6f 2f 1c d0 f4 93 f8 09 18 07 ; 3261-3280
cc d5 3e e7 88 26 f8 7c c8 6e 4c 3d 29 e8 22 82 af c3 f6 3c ; 3281-3300
01 65 02 4e 53 02 73 65 00 00 2e 00 01 00 02 7b f1 00 96 00 ; 3301-3320
01 05 03 00 02 a3 00 46 2f d6 16 46 27 06 d4 95 7b 02 73 65 ; 3321-3340
00 93 c6 b0 7d be 20 b2 2a da b5 20 c8 52 c7 06 3d 3f 0b 2b ; 3341-3360
a2 2a d8 74 85 47 7c 8c 8d 6e f1 c1 4d ea ea e9 88 ad af d2 ; 3361-3380
5d 31 85 36 c6 9f e5 88 f2 4b 7e 94 cc 4a b7 29 68 ef 19 55 ; 3381-3400
eb 0a f0 f3 12 07 3f a4 72 d9 dc 86 ab f3 9c 36 e1 ec 70 cd ; 3401-3420
d3 cd 29 4d f4 c6 f3 b4 a6 b9 98 b7 63 66 8a 68 1a be 0c d7 ; 3421-3440
32 af 89 14 87 6d d0 32 62 02 69 4b 71 1c bb f9 d6 f1 72 7d ; 3441-3460
a8 8b c3 1e af 97 75 36 9c 01 66 02 4e 53 02 73 65 00 00 2e ; 3461-3480
00 01 00 02 7b f1 00 96 00 01 05 03 00 02 a3 00 46 2f ca 31 ; 3481-3500
46 27 06 d4 95 7b 02 73 65 00 6f dd d9 ae 84 61 ea e3 a3 40 ; 3501-3520
f0 dc 78 f3 db ad f8 a2 08 92 c1 f7 0a 66 65 2d 4b be d6 8d ; 3521-3540
e2 a5 86 24 ff ed f8 f2 a2 87 b4 5a c2 c3 ee 3c 51 36 90 16 ; 3541-3560
e0 de c3 30 43 eb c5 c2 d8 30 fe 93 3c c5 cd 32 74 46 ff 0c ; 3561-3580
32 c3 d8 1d cb 76 e0 0b 39 03 7f c8 07 58 50 2f 4d 69 20 1e ; 3581-3600
e1 c3 4b 78 89 d1 f7 3f 80 42 9d 32 d2 cc f9 de de f7 47 b3 ; 3601-3620
3f 62 98 89 f7 94 14 cf 1b 42 e7 4f 3c 50 d9 f2 05 9a 01 66 ; 3621-3640
02 4e 53 02 73 65 00 00 2e 00 01 00 02 7b f1 00 96 00 1c 05 ; 3641-3660
03 00 02 a3 00 46 2f cc f8 46 27 06 d4 95 7b 02 73 65 00 56 ; 3661-3680
64 a5 e6 69 52 b9 6b 57 b1 0f 2a 8a 5b c5 2f 74 39 1d 6b 63 ; 3681-3700
dd 06 01 5d a9 84 13 0f 1b b1 73 bb 3a 6e 2d 46 f3 83 b8 d3 ; 3701-3720
f5 a8 40 41 05 2a a4 8e 0a c6 6c 6a 26 19 fd f8 ab e7 73 ce ; 3721-3740
52 a4 77 66 56 5b d4 26 42 00 30 9b 3d b0 93 4a 3d e4 70 ca ; 3741-3760
6f a0 2a 20 b6 cb d1 20 b8 05 2f 7c 44 4f 50 f6 8d 70 06 1a ; 3761-3780
7d 8e f5 88 f3 42 63 18 23 0c bc 5d 0a a5 ce 64 2b 4c 9f 3d ; 3781-3800
17 56 c2 64 aa 9c ef 01 67 02 4e 53 02 73 65 00 00 2e 00 01 ; 3801-3820
00 02 7b f3 00 96 00 01 05 03 00 02 a3 00 46 30 07 7e 46 27 ; 3821-3840
06 d4 95 7b 02 73 65 00 39 90 c1 fe 3d b9 69 33 6b 82 7d 36 ; 3841-3860
13 10 1d 14 b2 ca e8 4a e9 dd 32 38 aa a2 6e bf c9 96 32 a9 ; 3861-3880
b5 8d e6 51 be bb 43 4a b6 24 a6 68 39 38 93 0d 20 4c 38 52 ; 3881-3900
cb 6c b1 c8 9d ba f3 cd 36 32 43 65 5f 13 44 8e 0c 01 4e fd ; 3901-3920
d0 ec f7 12 bd 97 8e 4a ac d9 0b 6c 4b 61 f2 17 26 ac a8 cd ; 3921-3940
6b a2 fb f6 54 56 53 03 a0 79 56 e4 b1 69 1f 6a 66 c7 f0 fc ; 3941-3960
db c1 e2 6d 83 5f 2c 7b 9b 99 35 f5 a7 3d 4d 0a 01 67 02 4e ; 3961-3980
53 02 73 65 00 00 2e 00 01 00 02 7b f3 00 96 00 1c 05 03 00 ; 3981-4000
02 a3 00 46 2d cf 81 46 27 06 d4 95 7b 02 73 65 00 73 cf 2a ; 4001-4020
01 60 76 4a 11 2d 2d 98 62 b3 63 dc 42 4c be e9 e9 81 f3 fb ; 4021-4040
c1 83 8b 1e d1 ab d3 73 1d a9 bc bc 25 35 5f ea dc 07 25 99 ; 4041-4060
09 6d b5 ac 9a 04 b2 17 5a c4 61 22 fe 96 a9 d0 16 90 44 18 ; 4061-4080
1d c1 6a 06 8d 2e 48 91 cf 36 75 75 26 5c ef 82 5e 73 4f 10 ; 4081-4100
51 1d ea fd 7d a9 db af 23 44 c1 73 62 98 a6 1e c6 61 5e 3e ; 4101-4120
20 b9 f8 ce 6a 39 3e fc 41 34 5e c7 9d fc 5e cb cb 0d e3 84 ; 4121-4140
bb b2 a1 53 8f 01 68 02 4e 53 02 73 65 00 00 2e 00 01 00 02 ; 4141-4160
7b f1 00 96 00 01 05 03 00 02 a3 00 46 30 0c fe 46 27 06 d4 ; 4161-4180
95 7b 02 73 65 00 3f c3 f3 ff 24 18 26 47 e0 3c 6a bf 3a 96 ; 4181-4200
79 bc 62 52 b1 25 78 d3 71 4b b3 7d d9 60 c5 ca 89 34 75 1e ; 4201-4220
20 18 ef cf 8b bd 77 2a 7c 21 83 1f d1 0e f5 2a c9 5d 77 0b ; 4221-4240
b2 b1 8d df d5 52 a7 b8 94 18 d4 42 70 cb 42 fc 4f ab 50 2f ; 4241-4260
ce ac 3e dc c4 94 d3 d1 ae ac 12 70 4a e1 f8 a5 c4 06 dd 1b ; 4261-4280
da f9 06 28 b3 3d 07 06 71 22 fc 3e f0 4d f0 94 b8 2d e9 40 ; 4281-4300
03 16 d7 96 ac 38 44 58 93 7f 8b 73 6e a3 00 00 29 10 00 00 ; 4301-4320
00 80 00 00 00
; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
;-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
b4 e2 87 00 00 01 00 02 00 00 00 00 09 6e 6c 6e 65 74 6c 61 ; 1- 20
62 73 02 6e 6c 00 00 2e 00 01 09 6e 6c 6e 65 74 6c 61 62 73 ; 21- 40
02 6e 6c 00 00 2e 00 01 00 01 51 80 00 a0 00 06 05 02 00 01 ; 41- 60
51 80 46 4e f9 ff 46 27 6c ff ab 0f 09 6e 6c 6e 65 74 6c 61 ; 61- 80
62 73 02 6e 6c 00 5c 33 2b 93 5d f9 18 8f c6 7d f8 26 d2 d3 ; 81- 100
da 50 a3 60 42 df 19 1b cb e7 40 4a 7b 88 bb 41 08 68 8f 27 ; 101- 120
7d 4f 05 17 86 89 08 a1 a3 7f 56 1f f4 91 db cc 8b 9b 8e a0 ; 121- 140
03 dc 03 d8 2a 35 f7 ed 2e 01 41 9d b2 42 de 3e 50 4a ab 45 ; 141- 160
9d ac cd 1c a0 90 51 12 be 6c ae 51 20 a5 34 b0 38 e9 83 1d ; 161- 180
99 57 d2 a6 2f 53 a2 4c 4e 97 47 c7 d9 43 72 a6 4a d2 83 be ; 181- 200
ed f6 e4 34 6e 48 1b ae ed 2c c5 65 d0 ec 09 6e 6c 6e 65 74 ; 201- 220
6c 61 62 73 02 6e 6c 00 00 2e 00 01 00 01 51 80 00 a0 00 02 ; 221- 240
05 02 00 01 51 80 46 4e f9 ff 46 27 6c ff ab 0f 09 6e 6c 6e ; 241- 260
65 74 6c 61 62 73 02 6e 6c 00 81 18 16 b9 0b 65 db e0 00 19 ; 261- 280
68 06 01 11 46 67 4e 8c 51 c6 66 46 78 d7 7a ec b4 1f 8a 1e ; 281- 300
d7 3c 44 4a 55 b0 16 b5 25 b6 ad 25 2f 7d 24 16 d2 4e 08 67 ; 301- 320
ac 95 fa b3 61 cc 13 9d 72 c2 22 76 9b d4 dc 17 6b 3e 58 d5 ; 321- 340
c3 4b 6f b4 fa 60 17 68 46 57 b8 b5 f3 3d b7 f5 a5 df e3 e4 ; 341- 360
bb 8c 6f 33 07 f2 c8 8f c7 ff 6c 13 72 8d 4c 54 a4 ae 70 29 ; 361- 380
24 72 ba 7d fe e7 c7 4d 18 e4 5d f1 24 17 9a 8e 79 e4
; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
;-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
fe c1 85 00 00 01 00 09 00 03 00 06 09 6e 6c 6e 65 74 6c 61 ; 1- 20
62 73 02 6e 6c 00 00 2e 00 01 09 6e 6c 6e 65 74 6c 61 62 73 ; 21- 40
02 6e 6c 00 00 2e 00 01 00 01 51 80 00 a0 00 06 05 02 00 01 ; 41- 60
51 80 46 4e f9 ff 46 27 6c ff ab 0f 09 6e 6c 6e 65 74 6c 61 ; 61- 80
62 73 02 6e 6c 00 5c 33 2b 93 5d f9 18 8f c6 7d f8 26 d2 d3 ; 81- 100
da 50 a3 60 42 df 19 1b cb e7 40 4a 7b 88 bb 41 08 68 8f 27 ; 101- 120
7d 4f 05 17 86 89 08 a1 a3 7f 56 1f f4 91 db cc 8b 9b 8e a0 ; 121- 140
03 dc 03 d8 2a 35 f7 ed 2e 01 41 9d b2 42 de 3e 50 4a ab 45 ; 141- 160
9d ac cd 1c a0 90 51 12 be 6c ae 51 20 a5 34 b0 38 e9 83 1d ; 161- 180
99 57 d2 a6 2f 53 a2 4c 4e 97 47 c7 d9 43 72 a6 4a d2 83 be ; 181- 200
ed f6 e4 34 6e 48 1b ae ed 2c c5 65 d0 ec 09 6e 6c 6e 65 74 ; 201- 220
6c 61 62 73 02 6e 6c 00 00 2e 00 01 00 01 51 80 00 a0 00 02 ; 221- 240
05 02 00 01 51 80 46 4e f9 ff 46 27 6c ff ab 0f 09 6e 6c 6e ; 241- 260
65 74 6c 61 62 73 02 6e 6c 00 81 18 16 b9 0b 65 db e0 00 19 ; 261- 280
68 06 01 11 46 67 4e 8c 51 c6 66 46 78 d7 7a ec b4 1f 8a 1e ; 281- 300
d7 3c 44 4a 55 b0 16 b5 25 b6 ad 25 2f 7d 24 16 d2 4e 08 67 ; 301- 320
ac 95 fa b3 61 cc 13 9d 72 c2 22 76 9b d4 dc 17 6b 3e 58 d5 ; 321- 340
c3 4b 6f b4 fa 60 17 68 46 57 b8 b5 f3 3d b7 f5 a5 df e3 e4 ; 341- 360
bb 8c 6f 33 07 f2 c8 8f c7 ff 6c 13 72 8d 4c 54 a4 ae 70 29 ; 361- 380
24 72 ba 7d fe e7 c7 4d 18 e4 5d f1 24 17 9a 8e 79 e4 09 6e ; 381- 400
6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 2e 00 01 00 01 51 80 ; 401- 420
00 a0 00 01 05 02 00 01 51 80 46 4e f9 ff 46 27 6c ff ab 0f ; 421- 440
09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 ca ee ca 28 cd cf ; 441- 460
f4 fd a5 6e 5c ad 3f d5 89 7c 06 69 93 30 93 f7 0f b2 43 07 ; 461- 480
eb ad ce 8e f0 da 75 b9 5e 46 d5 28 40 9d 51 17 9e 2d 3d f3 ; 481- 500
85 1b dd 85 4a 82 9d 32 5c ff 27 c9 83 8f 36 04 89 94 52 3b ; 501- 520
01 29 01 62 36 1a 66 67 f7 43 16 5b 2a 19 77 d1 cc 73 7c 86 ; 521- 540
44 4c f5 d0 db a4 f5 ea 62 98 0f 18 9f 72 2c 73 5f cb 62 c2 ; 541- 560
7f 45 91 99 53 bb 70 44 93 3a f5 ea 3c 23 80 3f a6 19 06 33 ; 561- 580
3f 69 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 2e 00 01 ; 581- 600
00 01 51 80 00 a0 00 0f 05 02 00 01 51 80 46 4e f9 ff 46 27 ; 601- 620
6c ff ab 0f 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 8f 79 ; 621- 640
3e 49 68 56 05 e7 6c 01 6d f6 cf 6f f3 5d 5b cb e8 c1 ff fd ; 641- 660
a2 45 de 61 25 44 0d 4f 47 ea 54 8a 46 0f 58 1a 43 dc b4 3b ; 661- 680
02 b4 a3 11 a2 c5 45 0a 4b b2 f1 7a 3b 39 8d b0 ad 02 2e 60 ; 681- 700
15 dd fb b5 66 3a e1 b7 6f 5c 2d ea 99 21 a1 7e d9 8c da d8 ; 701- 720
94 6f e5 fc 1c 1f 0a b2 f6 18 7f 11 66 54 37 ad 1d f1 72 32 ; 721- 740
dd db 48 6b 53 4a 39 54 77 9b dc 54 f0 da 0c ae 94 7d 82 22 ; 741- 760
05 7f ab bb 3b 79 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 ; 761- 780
00 2e 00 01 00 01 51 80 00 a0 00 10 05 02 00 01 51 80 46 4e ; 781- 800
f9 ff 46 27 6c ff ab 0f 09 6e 6c 6e 65 74 6c 61 62 73 02 6e ; 801- 820
6c 00 ce 39 43 cf 06 19 80 eb 18 77 90 6a 43 52 d6 de 3a d0 ; 821- 840
b3 5f 00 49 34 6e bd 2a 38 2b a1 4e 24 7a 59 03 c8 72 90 15 ; 841- 860
c0 59 e0 8b aa da a9 06 f5 a8 25 5d 46 fc 46 d8 63 46 56 d0 ; 861- 880
34 b4 dd ae 6f f6 e6 41 bc ca cf f7 f0 66 be ba a1 cd 2e 9f ; 881- 900
06 91 fe 3c 08 b4 5d de ce 11 ee 22 6d e9 ec 2e 3b 97 60 d4 ; 901- 920
0e f8 de 63 ff a8 42 7f ab a9 26 90 b8 72 21 5d fd 80 f3 64 ; 921- 940
09 1f 0e 9c 89 6a 91 08 46 8b 09 6e 6c 6e 65 74 6c 61 62 73 ; 941- 960
02 6e 6c 00 00 2e 00 01 00 01 51 80 00 a0 00 1c 05 02 00 01 ; 961- 980
51 80 46 4e f9 ff 46 27 6c ff ab 0f 09 6e 6c 6e 65 74 6c 61 ; 981-1000
62 73 02 6e 6c 00 9b a2 35 6e 53 03 58 22 75 43 ae 1a e2 51 ; 1001-1020
09 4e fb 37 0f 60 eb 77 0f bc 4d c0 27 e7 34 a4 3a 27 30 c0 ; 1021-1040
4d 45 ad 4b 4d a1 82 54 92 ad 47 95 2b 78 70 6b c4 c7 f4 a3 ; 1041-1060
d3 55 77 51 09 ce 2a 6e d9 a2 5c 91 ed c1 14 91 0e 49 b5 4b ; 1061-1080
3c 08 3d c1 f0 dc 5d 82 48 97 be 3c eb d9 84 ce 7c 62 27 0c ; 1081-1100
b4 92 65 80 5a 3f 39 af f6 96 08 cd 40 3c e2 06 6f 36 df dc ; 1101-1120
ae 58 fb 9f fe b1 6a b1 fc 86 1d 7b 4d 7a 09 6e 6c 6e 65 74 ; 1121-1140
6c 61 62 73 02 6e 6c 00 00 2e 00 01 00 00 02 58 00 a0 00 23 ; 1141-1160
05 02 00 00 02 58 46 4e f9 ff 46 27 6c ff ab 0f 09 6e 6c 6e ; 1161-1180
65 74 6c 61 62 73 02 6e 6c 00 dc bc 30 a6 b8 6f f6 3b 07 af ; 1181-1200
cb 44 32 80 97 70 f9 f0 17 a0 cf d4 f8 cd a0 0d 8f cb 31 3b ; 1201-1220
82 b8 8d e7 f0 76 26 28 5e 7f c9 06 a7 53 f2 29 4a 06 18 54 ; 1221-1240
9b 0d 9a 18 8d c1 95 51 31 6b 4e 9e 82 c0 40 33 7e 0f d4 29 ; 1241-1260
19 b1 ee 96 41 97 ff f8 ea 14 0c d0 f2 fc 1c 41 95 c8 2f 82 ; 1261-1280
b0 8c 62 1f b7 d0 ea a4 f1 4e 35 0b 85 23 2f ba 44 bd 05 c4 ; 1281-1300
2a 47 f8 62 e1 80 d8 76 fb 8e 89 4f 87 66 19 69 7a 57 09 6e ; 1301-1320
6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 2e 00 01 00 00 46 50 ; 1321-1340
00 a0 00 2f 05 02 00 00 46 50 46 4e f9 ff 46 27 6c ff ab 0f ; 1341-1360
09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 42 6f f9 6d 68 59 ; 1361-1380
0c c9 c2 43 f4 1a fd eb f1 2b 42 48 9c 77 87 fe 92 d6 c4 3e ; 1381-1400
ba e5 03 ee 23 99 18 7f 49 46 83 d1 b0 2b f9 eb 62 5d be a5 ; 1401-1420
9f 74 43 d3 36 27 cb 61 54 20 c5 6f e7 62 17 d9 07 5f e5 bb ; 1421-1440
73 4d 93 ca d5 35 d7 06 e2 56 78 44 65 ed 08 a7 c3 e0 c5 db ; 1441-1460
fc 07 56 9b e5 0d 4b ab 53 95 11 7f 50 10 3f 78 5b 58 f6 e7 ; 1461-1480
31 35 11 80 b1 bc 99 ec a0 e6 59 dc cd 39 4f ae 31 bc df e1 ; 1481-1500
6d 0d 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 2e 00 01 ; 1501-1520
00 01 51 80 00 a0 00 30 05 02 00 01 51 80 46 4e f9 ff 46 27 ; 1521-1540
6c ff ab 0f 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 4e ca ; 1541-1560
77 bd 35 15 34 fc b0 14 74 ed 4e d0 c3 52 e8 36 d5 80 86 ec ; 1561-1580
fc 06 65 af f0 37 48 56 a1 a3 4e 25 c9 55 a6 f1 35 85 e2 75 ; 1581-1600
c1 2d 4e 28 a0 70 7d 9c 03 9f 6c d2 94 2f 7e 20 a1 9a 80 64 ; 1601-1620
22 0f 95 24 e1 ad 91 eb 5a 78 73 a5 65 3a eb 29 09 fb 37 37 ; 1621-1640
9b 7c be 32 f7 d2 ab ba 88 28 3c 4e 92 24 8d 83 0f 3a 1e 4e ; 1641-1660
60 be 00 95 6b e5 4c c2 6c df f8 93 8b da 6f f7 a7 a5 e8 11 ; 1661-1680
2c 25 df 8d d2 7f 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 ; 1681-1700
00 02 00 01 00 01 51 80 00 13 04 6f 70 65 6e 09 6e 6c 6e 65 ; 1701-1720
74 6c 61 62 73 02 6e 6c 00 09 6e 6c 6e 65 74 6c 61 62 73 02 ; 1721-1740
6e 6c 00 00 02 00 01 00 01 51 80 00 11 05 6f 6d 76 61 6c 06 ; 1741-1760
74 65 64 6e 65 74 02 6e 6c 00 09 6e 6c 6e 65 74 6c 61 62 73 ; 1761-1780
02 6e 6c 00 00 02 00 01 00 01 51 80 00 18 03 6e 73 37 0f 64 ; 1781-1800
6f 6d 61 69 6e 2d 72 65 67 69 73 74 72 79 02 6e 6c 00 03 6e ; 1801-1820
73 37 0f 64 6f 6d 61 69 6e 2d 72 65 67 69 73 74 72 79 02 6e ; 1821-1840
6c 00 00 01 00 01 00 00 44 09 00 04 3e 04 56 e6 04 6f 70 65 ; 1841-1860
6e 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 01 00 01 00 ; 1861-1880
01 51 80 00 04 d5 9a e0 01 04 6f 70 65 6e 09 6e 6c 6e 65 74 ; 1881-1900
6c 61 62 73 02 6e 6c 00 00 1c 00 01 00 01 51 80 00 10 20 01 ; 1901-1920
07 b8 02 06 00 01 00 00 00 00 00 00 00 53 04 6f 70 65 6e 09 ; 1921-1940
6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 1c 00 01 00 01 51 ; 1941-1960
80 00 10 20 01 07 b8 02 06 00 01 00 00 00 00 00 00 00 01 05 ; 1961-1980
6f 6d 76 61 6c 06 74 65 64 6e 65 74 02 6e 6c 00 00 01 00 01 ; 1981-2000
00 00 70 80 00 04 d5 9a e0 11 05 6f 6d 76 61 6c 06 74 65 64 ; 2001-2020
6e 65 74 02 6e 6c 00 00 1c 00 01 00 00 70 80 00 10 20 01 07 ; 2021-2040
b8 02 06 00 01 02 00 39 ff fe 59 b1 87
; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
;-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
56 4e 85 00 00 01 00 09 00 04 00 09 09 6e 6c 6e 65 74 6c 61 ; 1- 20
62 73 02 6e 6c 00 00 2e 00 01 09 6e 6c 6e 65 74 6c 61 62 73 ; 21- 40
02 6e 6c 00 00 2e 00 01 00 01 51 80 00 a0 00 06 05 02 00 01 ; 41- 60
51 80 46 4e f9 ff 46 27 6c ff ab 0f 09 6e 6c 6e 65 74 6c 61 ; 61- 80
62 73 02 6e 6c 00 5c 33 2b 93 5d f9 18 8f c6 7d f8 26 d2 d3 ; 81- 100
da 50 a3 60 42 df 19 1b cb e7 40 4a 7b 88 bb 41 08 68 8f 27 ; 101- 120
7d 4f 05 17 86 89 08 a1 a3 7f 56 1f f4 91 db cc 8b 9b 8e a0 ; 121- 140
03 dc 03 d8 2a 35 f7 ed 2e 01 41 9d b2 42 de 3e 50 4a ab 45 ; 141- 160
9d ac cd 1c a0 90 51 12 be 6c ae 51 20 a5 34 b0 38 e9 83 1d ; 161- 180
99 57 d2 a6 2f 53 a2 4c 4e 97 47 c7 d9 43 72 a6 4a d2 83 be ; 181- 200
ed f6 e4 34 6e 48 1b ae ed 2c c5 65 d0 ec 09 6e 6c 6e 65 74 ; 201- 220
6c 61 62 73 02 6e 6c 00 00 2e 00 01 00 01 51 80 00 a0 00 02 ; 221- 240
05 02 00 01 51 80 46 4e f9 ff 46 27 6c ff ab 0f 09 6e 6c 6e ; 241- 260
65 74 6c 61 62 73 02 6e 6c 00 81 18 16 b9 0b 65 db e0 00 19 ; 261- 280
68 06 01 11 46 67 4e 8c 51 c6 66 46 78 d7 7a ec b4 1f 8a 1e ; 281- 300
d7 3c 44 4a 55 b0 16 b5 25 b6 ad 25 2f 7d 24 16 d2 4e 08 67 ; 301- 320
ac 95 fa b3 61 cc 13 9d 72 c2 22 76 9b d4 dc 17 6b 3e 58 d5 ; 321- 340
c3 4b 6f b4 fa 60 17 68 46 57 b8 b5 f3 3d b7 f5 a5 df e3 e4 ; 341- 360
bb 8c 6f 33 07 f2 c8 8f c7 ff 6c 13 72 8d 4c 54 a4 ae 70 29 ; 361- 380
24 72 ba 7d fe e7 c7 4d 18 e4 5d f1 24 17 9a 8e 79 e4 09 6e ; 381- 400
6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 2e 00 01 00 01 51 80 ; 401- 420
00 a0 00 01 05 02 00 01 51 80 46 4e f9 ff 46 27 6c ff ab 0f ; 421- 440
09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 ca ee ca 28 cd cf ; 441- 460
f4 fd a5 6e 5c ad 3f d5 89 7c 06 69 93 30 93 f7 0f b2 43 07 ; 461- 480
eb ad ce 8e f0 da 75 b9 5e 46 d5 28 40 9d 51 17 9e 2d 3d f3 ; 481- 500
85 1b dd 85 4a 82 9d 32 5c ff 27 c9 83 8f 36 04 89 94 52 3b ; 501- 520
01 29 01 62 36 1a 66 67 f7 43 16 5b 2a 19 77 d1 cc 73 7c 86 ; 521- 540
44 4c f5 d0 db a4 f5 ea 62 98 0f 18 9f 72 2c 73 5f cb 62 c2 ; 541- 560
7f 45 91 99 53 bb 70 44 93 3a f5 ea 3c 23 80 3f a6 19 06 33 ; 561- 580
3f 69 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 2e 00 01 ; 581- 600
00 01 51 80 00 a0 00 0f 05 02 00 01 51 80 46 4e f9 ff 46 27 ; 601- 620
6c ff ab 0f 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 8f 79 ; 621- 640
3e 49 68 56 05 e7 6c 01 6d f6 cf 6f f3 5d 5b cb e8 c1 ff fd ; 641- 660
a2 45 de 61 25 44 0d 4f 47 ea 54 8a 46 0f 58 1a 43 dc b4 3b ; 661- 680
02 b4 a3 11 a2 c5 45 0a 4b b2 f1 7a 3b 39 8d b0 ad 02 2e 60 ; 681- 700
15 dd fb b5 66 3a e1 b7 6f 5c 2d ea 99 21 a1 7e d9 8c da d8 ; 701- 720
94 6f e5 fc 1c 1f 0a b2 f6 18 7f 11 66 54 37 ad 1d f1 72 32 ; 721- 740
dd db 48 6b 53 4a 39 54 77 9b dc 54 f0 da 0c ae 94 7d 82 22 ; 741- 760
05 7f ab bb 3b 79 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 ; 761- 780
00 2e 00 01 00 01 51 80 00 a0 00 10 05 02 00 01 51 80 46 4e ; 781- 800
f9 ff 46 27 6c ff ab 0f 09 6e 6c 6e 65 74 6c 61 62 73 02 6e ; 801- 820
6c 00 ce 39 43 cf 06 19 80 eb 18 77 90 6a 43 52 d6 de 3a d0 ; 821- 840
b3 5f 00 49 34 6e bd 2a 38 2b a1 4e 24 7a 59 03 c8 72 90 15 ; 841- 860
c0 59 e0 8b aa da a9 06 f5 a8 25 5d 46 fc 46 d8 63 46 56 d0 ; 861- 880
34 b4 dd ae 6f f6 e6 41 bc ca cf f7 f0 66 be ba a1 cd 2e 9f ; 881- 900
06 91 fe 3c 08 b4 5d de ce 11 ee 22 6d e9 ec 2e 3b 97 60 d4 ; 901- 920
0e f8 de 63 ff a8 42 7f ab a9 26 90 b8 72 21 5d fd 80 f3 64 ; 921- 940
09 1f 0e 9c 89 6a 91 08 46 8b 09 6e 6c 6e 65 74 6c 61 62 73 ; 941- 960
02 6e 6c 00 00 2e 00 01 00 01 51 80 00 a0 00 1c 05 02 00 01 ; 961- 980
51 80 46 4e f9 ff 46 27 6c ff ab 0f 09 6e 6c 6e 65 74 6c 61 ; 981-1000
62 73 02 6e 6c 00 9b a2 35 6e 53 03 58 22 75 43 ae 1a e2 51 ; 1001-1020
09 4e fb 37 0f 60 eb 77 0f bc 4d c0 27 e7 34 a4 3a 27 30 c0 ; 1021-1040
4d 45 ad 4b 4d a1 82 54 92 ad 47 95 2b 78 70 6b c4 c7 f4 a3 ; 1041-1060
d3 55 77 51 09 ce 2a 6e d9 a2 5c 91 ed c1 14 91 0e 49 b5 4b ; 1061-1080
3c 08 3d c1 f0 dc 5d 82 48 97 be 3c eb d9 84 ce 7c 62 27 0c ; 1081-1100
b4 92 65 80 5a 3f 39 af f6 96 08 cd 40 3c e2 06 6f 36 df dc ; 1101-1120
ae 58 fb 9f fe b1 6a b1 fc 86 1d 7b 4d 7a 09 6e 6c 6e 65 74 ; 1121-1140
6c 61 62 73 02 6e 6c 00 00 2e 00 01 00 00 02 58 00 a0 00 23 ; 1141-1160
05 02 00 00 02 58 46 4e f9 ff 46 27 6c ff ab 0f 09 6e 6c 6e ; 1161-1180
65 74 6c 61 62 73 02 6e 6c 00 dc bc 30 a6 b8 6f f6 3b 07 af ; 1181-1200
cb 44 32 80 97 70 f9 f0 17 a0 cf d4 f8 cd a0 0d 8f cb 31 3b ; 1201-1220
82 b8 8d e7 f0 76 26 28 5e 7f c9 06 a7 53 f2 29 4a 06 18 54 ; 1221-1240
9b 0d 9a 18 8d c1 95 51 31 6b 4e 9e 82 c0 40 33 7e 0f d4 29 ; 1241-1260
19 b1 ee 96 41 97 ff f8 ea 14 0c d0 f2 fc 1c 41 95 c8 2f 82 ; 1261-1280
b0 8c 62 1f b7 d0 ea a4 f1 4e 35 0b 85 23 2f ba 44 bd 05 c4 ; 1281-1300
2a 47 f8 62 e1 80 d8 76 fb 8e 89 4f 87 66 19 69 7a 57 09 6e ; 1301-1320
6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 2e 00 01 00 00 46 50 ; 1321-1340
00 a0 00 2f 05 02 00 00 46 50 46 4e f9 ff 46 27 6c ff ab 0f ; 1341-1360
09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 42 6f f9 6d 68 59 ; 1361-1380
0c c9 c2 43 f4 1a fd eb f1 2b 42 48 9c 77 87 fe 92 d6 c4 3e ; 1381-1400
ba e5 03 ee 23 99 18 7f 49 46 83 d1 b0 2b f9 eb 62 5d be a5 ; 1401-1420
9f 74 43 d3 36 27 cb 61 54 20 c5 6f e7 62 17 d9 07 5f e5 bb ; 1421-1440
73 4d 93 ca d5 35 d7 06 e2 56 78 44 65 ed 08 a7 c3 e0 c5 db ; 1441-1460
fc 07 56 9b e5 0d 4b ab 53 95 11 7f 50 10 3f 78 5b 58 f6 e7 ; 1461-1480
31 35 11 80 b1 bc 99 ec a0 e6 59 dc cd 39 4f ae 31 bc df e1 ; 1481-1500
6d 0d 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 2e 00 01 ; 1501-1520
00 01 51 80 00 a0 00 30 05 02 00 01 51 80 46 4e f9 ff 46 27 ; 1521-1540
6c ff ab 0f 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 4e ca ; 1541-1560
77 bd 35 15 34 fc b0 14 74 ed 4e d0 c3 52 e8 36 d5 80 86 ec ; 1561-1580
fc 06 65 af f0 37 48 56 a1 a3 4e 25 c9 55 a6 f1 35 85 e2 75 ; 1581-1600
c1 2d 4e 28 a0 70 7d 9c 03 9f 6c d2 94 2f 7e 20 a1 9a 80 64 ; 1601-1620
22 0f 95 24 e1 ad 91 eb 5a 78 73 a5 65 3a eb 29 09 fb 37 37 ; 1621-1640
9b 7c be 32 f7 d2 ab ba 88 28 3c 4e 92 24 8d 83 0f 3a 1e 4e ; 1641-1660
60 be 00 95 6b e5 4c c2 6c df f8 93 8b da 6f f7 a7 a5 e8 11 ; 1661-1680
2c 25 df 8d d2 7f 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 ; 1681-1700
00 02 00 01 00 01 51 80 00 18 03 6e 73 37 0f 64 6f 6d 61 69 ; 1701-1720
6e 2d 72 65 67 69 73 74 72 79 02 6e 6c 00 09 6e 6c 6e 65 74 ; 1721-1740
6c 61 62 73 02 6e 6c 00 00 02 00 01 00 01 51 80 00 13 04 6f ; 1741-1760
70 65 6e 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 09 6e 6c ; 1761-1780
6e 65 74 6c 61 62 73 02 6e 6c 00 00 02 00 01 00 01 51 80 00 ; 1781-1800
11 05 6f 6d 76 61 6c 06 74 65 64 6e 65 74 02 6e 6c 00 09 6e ; 1801-1820
6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 2e 00 01 00 01 51 80 ; 1821-1840
00 a0 00 02 05 02 00 01 51 80 46 4e f9 ff 46 27 6c ff ab 0f ; 1841-1860
09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 81 18 16 b9 0b 65 ; 1861-1880
db e0 00 19 68 06 01 11 46 67 4e 8c 51 c6 66 46 78 d7 7a ec ; 1881-1900
b4 1f 8a 1e d7 3c 44 4a 55 b0 16 b5 25 b6 ad 25 2f 7d 24 16 ; 1901-1920
d2 4e 08 67 ac 95 fa b3 61 cc 13 9d 72 c2 22 76 9b d4 dc 17 ; 1921-1940
6b 3e 58 d5 c3 4b 6f b4 fa 60 17 68 46 57 b8 b5 f3 3d b7 f5 ; 1941-1960
a5 df e3 e4 bb 8c 6f 33 07 f2 c8 8f c7 ff 6c 13 72 8d 4c 54 ; 1961-1980
a4 ae 70 29 24 72 ba 7d fe e7 c7 4d 18 e4 5d f1 24 17 9a 8e ; 1981-2000
79 e4 03 6e 73 37 0f 64 6f 6d 61 69 6e 2d 72 65 67 69 73 74 ; 2001-2020
72 79 02 6e 6c 00 00 01 00 01 00 00 43 f3 00 04 3e 04 56 e6 ; 2021-2040
04 6f 70 65 6e 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 ; 2041-2060
01 00 01 00 01 51 80 00 04 d5 9a e0 01 04 6f 70 65 6e 09 6e ; 2061-2080
6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 1c 00 01 00 01 51 80 ; 2081-2100
00 10 20 01 07 b8 02 06 00 01 00 00 00 00 00 00 00 53 04 6f ; 2101-2120
70 65 6e 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 1c 00 ; 2121-2140
01 00 01 51 80 00 10 20 01 07 b8 02 06 00 01 00 00 00 00 00 ; 2141-2160
00 00 01 05 6f 6d 76 61 6c 06 74 65 64 6e 65 74 02 6e 6c 00 ; 2161-2180
00 01 00 01 00 00 70 80 00 04 d5 9a e0 11 05 6f 6d 76 61 6c ; 2181-2200
06 74 65 64 6e 65 74 02 6e 6c 00 00 1c 00 01 00 00 70 80 00 ; 2201-2220
10 20 01 07 b8 02 06 00 01 02 00 39 ff fe 59 b1 87 04 6f 70 ; 2221-2240
65 6e 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 00 2e 00 01 ; 2241-2260
00 01 51 80 00 a0 00 01 05 03 00 01 51 80 46 4e f9 ff 46 27 ; 2261-2280
6c ff ab 0f 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 bd 11 ; 2281-2300
d7 c8 6f 7f f1 b8 d7 6c 2e c0 eb 5b 65 6c 5e 32 bc ba 0e 50 ; 2301-2320
c6 d2 b2 65 71 81 44 6e 2a 22 3c 98 39 16 71 f1 56 2d 8f 0d ; 2321-2340
02 8a e8 7d ad 93 f1 f6 85 d0 fc 19 13 26 de 5a 1f ee 33 7d ; 2341-2360
f0 9b 5b 15 63 1a a6 33 55 d4 d3 23 4f c5 ac cf 48 71 f5 ed ; 2361-2380
44 17 eb d3 db fe 98 ea 7e fb b3 7d 8f 2a 6b f7 87 af 15 aa ; 2381-2400
78 ee cb e5 24 2b 04 46 a9 e2 96 fa 41 2a 99 42 5d 3e 22 07 ; 2401-2420
b9 bc 99 62 ad 61 04 6f 70 65 6e 09 6e 6c 6e 65 74 6c 61 62 ; 2421-2440
73 02 6e 6c 00 00 2e 00 01 00 01 51 80 00 a0 00 1c 05 03 00 ; 2441-2460
01 51 80 46 4e f9 ff 46 27 6c ff ab 0f 09 6e 6c 6e 65 74 6c ; 2461-2480
61 62 73 02 6e 6c 00 a7 45 db c2 3c 05 77 76 03 b8 7e e7 9c ; 2481-2500
3d 64 12 7c 9d f9 17 f2 a0 4a 94 74 19 bd a3 6b 3e 62 da e6 ; 2501-2520
87 0e 07 1d fb 5c 5c 0e f9 ab 97 87 71 c1 78 d4 b5 b0 21 65 ; 2521-2540
fe 26 95 40 ed b4 d6 0c f5 ce a1 34 32 2a 54 1e e0 b5 34 0f ; 2541-2560
71 01 8f bf 66 48 d7 a7 12 85 a5 a0 25 d2 5c 5f 3a 15 87 b5 ; 2561-2580
bd 4a 3c 0c 34 4b 48 21 48 ac d7 92 02 6b 28 55 35 28 8b b6 ; 2581-2600
cf 72 b4 2c c3 22 88 8b b0 75 80 0c 35 13 02 00 00 29 10 00 ; 2601-2620
00 00 80 00 00 00
-56
View File
@@ -1,56 +0,0 @@
; Hand made test packets.
; By Wouter Wijngaards.
; These DNS packets contain interesting compression cases.
;
;-- next packet --
; 0. A valid packet (handmade)
; id flags qd an ns ar -- header
4242 0000 0001 0001 0000 0000
; query: qname example.com. qtype A(1) qclass IN(1)
07 6578616d706c65 03 636f6d 00 0001 0001
; answer: example.com type class ttl rdatalen 10.x address.
07 6578616d706c65 03 636f6d 00 0001 0001 00000101 0004 0a203040
;-- next packet --
; 0b. correct compression from answer to query.
4242 0000 0001 0001 0000 0000
07 6578616d706c65 03 636f6d 00 0001 0001
c00c 0001 0001 00000101 0004 0a203040
;-- next packet --
; 1. Compression from query to answer.
4242 0000 0001 0001 0000 0000
c012 0001 0001
07 6578616d706c65 03 636f6d 00 0001 0001 00000101 0004 0a203040
;-- next packet --
; 2. Compression loop answer 1 to answer 2.
4242 0000 0001 0002 0000 0000
07 6578616d706c65 03 636f6d 00 0001 0001
c02d 0001 0001 00000101 0004 0a203040
07 6578616d706c65 03 636f6d 00 0001 0001 00000101 0004 0a203050
;-- next packet --
; 2b. Compression loop answer 2 to answer 1.
4242 0000 0001 0002 0000 0000
07 6578616d706c65 03 636f6d 00 0001 0001
07 6578616d706c65 03 636f6d 00 0001 0001 00000101 0004 0a203050
c01d 0001 0001 00000101 0004 0a203040
;-- next packet --
; 3. Compression loop to self (in answer section).
4242 0000 0001 0001 0000 0000
07 6578616d706c65 03 636f6d 00 0001 0001
c01d 0001 0001 00000101 0004 0a203040
;-- next packet --
; 4. bad compression pointer - to header.
4242 0000 0001 0001 0000 0000
07 6578616d706c65 03 636f6d 00 0001 0001
c004 0001 0001 00000101 0004 0a203040
;-- next packet --
; 5. bad compression pointer - exceeds packet.
4242 0000 0001 0001 0000 0000
07 6578616d706c65 03 636f6d 00 0001 0001
c0bb 0001 0001 00000101 0004 0a203040
-74
View File
@@ -1,74 +0,0 @@
; config options
server:
hide-identity: no
hide-version: no
identity: "test-identity"
version: "test-version"
CONFIG_END
SCENARIO_BEGIN Test version.bind identity and version queries
; version.bind.
STEP 1 QUERY
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
; version.server.
STEP 3 QUERY
ENTRY_BEGIN
SECTION QUESTION
version.server. CH TXT
ENTRY_END
STEP 4 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RA
SECTION QUESTION
version.server. CH TXT
SECTION ANSWER
version.server. 0 CH TXT "test-version"
ENTRY_END
; hostname.bind.
STEP 5 QUERY
ENTRY_BEGIN
SECTION QUESTION
hostname.bind. CH TXT
ENTRY_END
STEP 6 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RA
SECTION QUESTION
hostname.bind. CH TXT
SECTION ANSWER
hostname.bind. 0 CH TXT "test-identity"
ENTRY_END
; id.server.
STEP 7 QUERY
ENTRY_BEGIN
SECTION QUESTION
id.server. CH TXT
ENTRY_END
STEP 8 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
SCENARIO_END
-67
View File
@@ -1,67 +0,0 @@
; config options
server:
hide-identity: yes
hide-version: yes
identity: "test-identity"
version: "test-version"
; we rely on the fact that there are no builtin stubs for class CH.
CONFIG_END
SCENARIO_BEGIN Test config hide options for identity and version queries
; version.bind.
STEP 1 QUERY
ENTRY_BEGIN
SECTION QUESTION
version.bind. CH TXT
ENTRY_END
STEP 2 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RA REFUSED
SECTION QUESTION
version.bind. CH TXT
ENTRY_END
; version.server.
STEP 3 QUERY
ENTRY_BEGIN
SECTION QUESTION
version.server. CH TXT
ENTRY_END
STEP 4 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RA REFUSED
SECTION QUESTION
version.server. CH TXT
ENTRY_END
; hostname.bind.
STEP 5 QUERY
ENTRY_BEGIN
SECTION QUESTION
hostname.bind. CH TXT
ENTRY_END
STEP 6 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RA REFUSED
SECTION QUESTION
hostname.bind. CH TXT
ENTRY_END
; id.server.
STEP 7 QUERY
ENTRY_BEGIN
SECTION QUESTION
id.server. CH TXT
ENTRY_END
STEP 8 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RA REFUSED
SECTION QUESTION
id.server. CH TXT
ENTRY_END
SCENARIO_END
+9 -67
View File
@@ -41,19 +41,6 @@
#include "config.h"
#include "util/alloc.h"
#include "util/data/packed_rrset.h"
/** number of bits for ID part of uint64, rest for number of threads. */
#define THRNUM_SHIFT 48 /* for 65k threads, 2^48 rrsets per thr. */
/** setup new special type */
static void
alloc_setup_special(alloc_special_t* t)
{
memset(t, 0, sizeof(*t));
lock_rw_init(&t->entry.lock);
t->entry.key = t;
}
/** prealloc some entries in the cache. To minimize contention.
* Result is 1 lock per alloc_max newly created entries.
@@ -67,27 +54,17 @@ prealloc(struct alloc_cache* alloc)
for(i=0; i<ALLOC_SPECIAL_MAX; i++) {
if(!(p = (alloc_special_t*)malloc(sizeof(alloc_special_t))))
fatal_exit("prealloc: out of memory");
alloc_setup_special(p);
alloc_set_special_next(p, alloc->quar);
alloc_special_next(p) = alloc->quar;
alloc->quar = p;
alloc->num_quar++;
}
}
void
alloc_init(struct alloc_cache* alloc, struct alloc_cache* super,
int thread_num)
alloc_init(struct alloc_cache* alloc, struct alloc_cache* super)
{
memset(alloc, 0, sizeof(*alloc));
alloc->super = super;
alloc->thread_num = thread_num;
alloc->next_id = (uint64_t)thread_num; /* in steps, so that type */
alloc->next_id <<= THRNUM_SHIFT; /* of *_id is used. */
alloc->last_id = 1; /* so no 64bit constants, */
alloc->last_id <<= THRNUM_SHIFT; /* or implicit 'int' ops. */
alloc->last_id -= 1; /* for compiler portability. */
alloc->last_id |= alloc->next_id;
alloc->next_id += 1; /* because id=0 is special. */
if(!alloc->super) {
lock_quick_init(&alloc->lock);
lock_protect(&alloc->lock, alloc, sizeof(*alloc));
@@ -109,7 +86,7 @@ alloc_clear(struct alloc_cache* alloc)
while(alloc_special_next(p)) /* find last */
p = alloc_special_next(p);
lock_quick_lock(&alloc->super->lock);
alloc_set_special_next(p, alloc->super->quar);
alloc_special_next(p) = alloc->super->quar;
alloc->super->quar = alloc->quar;
alloc->super->num_quar += alloc->num_quar;
lock_quick_unlock(&alloc->super->lock);
@@ -118,8 +95,6 @@ alloc_clear(struct alloc_cache* alloc)
p = alloc->quar;
while(p) {
np = alloc_special_next(p);
/* deinit special type */
lock_rw_destroy(&p->entry.lock);
free(p);
p = np;
}
@@ -128,18 +103,6 @@ alloc_clear(struct alloc_cache* alloc)
alloc->num_quar = 0;
}
/** get a new id */
static void
alloc_get_id(struct alloc_cache* alloc, alloc_special_t* t)
{
t->id = alloc->next_id++;
if(alloc->next_id == alloc->last_id) {
/* TODO: clear the rrset cache */
log_warn("Out of ids. Clearing cache.");
}
alloc_set_special_next(t, 0);
}
alloc_special_t*
alloc_special_obtain(struct alloc_cache* alloc)
{
@@ -150,7 +113,7 @@ alloc_special_obtain(struct alloc_cache* alloc)
p = alloc->quar;
alloc->quar = alloc_special_next(p);
alloc->num_quar--;
alloc_get_id(alloc, p);
alloc_special_clean(p);
return p;
}
/* see if in global cache */
@@ -164,7 +127,7 @@ alloc_special_obtain(struct alloc_cache* alloc)
}
lock_quick_unlock(&alloc->super->lock);
if(p) {
alloc_get_id(alloc, p);
alloc_special_clean(p);
return p;
}
}
@@ -172,8 +135,7 @@ alloc_special_obtain(struct alloc_cache* alloc)
prealloc(alloc);
if(!(p = (alloc_special_t*)malloc(sizeof(alloc_special_t))))
fatal_exit("alloc_special_obtain: out of memory");
alloc_setup_special(p);
alloc_get_id(alloc, p);
alloc_special_clean(p);
return p;
}
@@ -187,7 +149,7 @@ pushintosuper(struct alloc_cache* alloc, alloc_special_t* mem)
log_assert(alloc && alloc->super &&
alloc->num_quar >= ALLOC_SPECIAL_MAX);
/* push ALLOC_SPECIAL_MAX/2 after mem */
alloc_set_special_next(mem, alloc->quar);
alloc_special_next(mem) = alloc->quar;
for(i=1; i<ALLOC_SPECIAL_MAX/2; i++) {
p = alloc_special_next(p);
}
@@ -196,7 +158,7 @@ pushintosuper(struct alloc_cache* alloc, alloc_special_t* mem)
/* dump mem+list into the super quar list */
lock_quick_lock(&alloc->super->lock);
alloc_set_special_next(p, alloc->super->quar);
alloc_special_next(p) = alloc->super->quar;
alloc->super->quar = mem;
alloc->super->num_quar += ALLOC_SPECIAL_MAX/2 + 1;
lock_quick_unlock(&alloc->super->lock);
@@ -209,10 +171,6 @@ alloc_special_release(struct alloc_cache* alloc, alloc_special_t* mem)
log_assert(alloc);
if(!mem)
return;
if(!alloc->super) {
lock_quick_lock(&alloc->lock); /* superalloc needs locking */
}
alloc_special_clean(mem);
if(alloc->super && alloc->num_quar >= ALLOC_SPECIAL_MAX) {
/* push it to the super structure */
@@ -220,12 +178,9 @@ alloc_special_release(struct alloc_cache* alloc, alloc_special_t* mem)
return;
}
alloc_set_special_next(mem, alloc->quar);
alloc_special_next(mem) = alloc->quar;
alloc->quar = mem;
alloc->num_quar++;
if(!alloc->super) {
lock_quick_unlock(&alloc->lock);
}
}
void
@@ -234,16 +189,3 @@ alloc_stats(struct alloc_cache* alloc)
log_info("%salloc: %d in cache.", alloc->super?"":"sup",
(int)alloc->num_quar);
}
size_t alloc_get_mem(struct alloc_cache* alloc)
{
size_t s = sizeof(*alloc);
if(!alloc->super) {
lock_quick_lock(&alloc->lock); /* superalloc needs locking */
}
s += sizeof(alloc_special_t) * alloc->num_quar;
if(!alloc->super) {
lock_quick_unlock(&alloc->lock);
}
return s;
}
+4 -23
View File
@@ -49,17 +49,13 @@
#define UTIL_ALLOC_H
#include "util/locks.h"
struct ub_packed_rrset_key;
/** The special type, packed rrset. Not allowed to be used for other memory */
typedef struct ub_packed_rrset_key alloc_special_t;
typedef uint64_t alloc_special_t;
/** clean the special type. Pass pointer. */
#define alloc_special_clean(x) (x)->id = 0;
#define alloc_special_clean(x) memset(x, 0, sizeof(alloc_special_t))
/** access next pointer. (in available spot). Pass pointer. */
#define alloc_special_next(x) ((alloc_special_t*)((x)->entry.overflow_next))
/** set next pointer. (in available spot). Pass pointers. */
#define alloc_set_special_next(x, y) \
((x)->entry.overflow_next) = (struct lruhash_entry*)(y);
#define alloc_special_next(x) (*((alloc_special_t**)(x)))
/** how many blocks to cache locally. */
#define ALLOC_SPECIAL_MAX 10
@@ -77,12 +73,6 @@ struct alloc_cache {
alloc_special_t* quar;
/** number of items in quarantine. */
size_t num_quar;
/** thread number for id creation */
int thread_num;
/** next id number to pass out */
uint64_t next_id;
/** last id number possible */
uint64_t last_id;
};
/**
@@ -90,10 +80,8 @@ struct alloc_cache {
* @param alloc: this parameter is allocated by the caller.
* @param super: super to use (init that before with super_init).
* Pass this argument NULL to init the toplevel alloc structure.
* @param thread_num: thread number for id creation of special type.
*/
void alloc_init(struct alloc_cache* alloc, struct alloc_cache* super,
int thread_num);
void alloc_init(struct alloc_cache* alloc, struct alloc_cache* super);
/**
* Free the alloc. Pushes all the cached items into the super structure.
@@ -119,13 +107,6 @@ alloc_special_t* alloc_special_obtain(struct alloc_cache* alloc);
*/
void alloc_special_release(struct alloc_cache* alloc, alloc_special_t* mem);
/**
* Get memory size of alloc cache, alloc structure including special types.
* @param alloc: on what alloc.
* @return size in bytes.
*/
size_t alloc_get_mem(struct alloc_cache* alloc);
/**
* Print debug information (statistics).
* @param alloc: on what alloc.
+9 -80
View File
@@ -77,47 +77,23 @@ config_create()
cfg->do_tcp = 1;
cfg->outgoing_base_port = cfg->port + 1000;
cfg->outgoing_num_ports = 16;
cfg->outgoing_num_tcp = 10;
cfg->msg_cache_size = 4 * 1024 * 1024;
cfg->msg_cache_slabs = 4;
cfg->num_queries_per_thread = 1024;
cfg->rrset_cache_size = 4 * 1024 * 1024;
cfg->rrset_cache_slabs = 4;
cfg->host_ttl = 900;
cfg->lame_ttl = 900;
cfg->infra_cache_slabs = 4;
cfg->infra_cache_numhosts = 1000;
cfg->infra_cache_numlame = 1000;
if(!(cfg->username = strdup(""))) goto error_exit;
if(!(cfg->chrootdir = strdup(""))) goto error_exit;
if(!(cfg->directory = strdup("/etc/unbound"))) goto error_exit;
if(!(cfg->logfile = strdup(""))) goto error_exit;
if(!(cfg->pidfile = strdup("unbound.pid"))) goto error_exit;
if(!(cfg->target_fetch_policy = strdup("3 2 1 0 0"))) goto error_exit;
cfg->donotqueryaddrs = NULL;
if(!cfg_strlist_insert(&cfg->donotqueryaddrs, strdup("127.0.0.1")))
goto error_exit;
if(!cfg_strlist_insert(&cfg->donotqueryaddrs, strdup("::1")))
goto error_exit;
if(!(cfg->fwd_address = strdup(""))) {config_delete(cfg); return NULL;}
if(!(cfg->username = strdup(""))) {config_delete(cfg); return NULL;}
if(!(cfg->chrootdir = strdup(""))) {config_delete(cfg); return NULL;}
if(!(cfg->directory = strdup("/etc/unbound"))) {config_delete(cfg); return NULL;}
if(!(cfg->logfile = strdup(""))) {config_delete(cfg); return NULL;}
if(!(cfg->pidfile = strdup("unbound.pid"))) {config_delete(cfg); return NULL;}
cfg->fwd_port = UNBOUND_DNS_PORT;
cfg->do_daemonize = 1;
cfg->num_ifs = 0;
cfg->ifs = NULL;
cfg->stubs = NULL;
cfg->forwards = NULL;
cfg->harden_short_bufsize = 0;
cfg->harden_large_queries = 0;
cfg->harden_glue = 1;
cfg->hide_identity = 0;
cfg->hide_version = 0;
cfg->identity = NULL;
cfg->version = NULL;
return cfg;
error_exit:
config_delete(cfg);
return NULL;
}
/** initialize the global cfg_parser object */
/** initialize the global cfg_parser object. */
static void
create_cfg_parser(struct config_file* cfg, char* filename)
{
@@ -154,55 +130,22 @@ config_read(struct config_file* cfg, const char* filename)
return 1;
}
/** delete config strlist */
static void
config_delstrlist(struct config_strlist* p)
{
struct config_strlist *np;
while(p) {
np = p->next;
free(p->str);
free(p);
p = np;
}
}
/** delete config stublist */
static void
config_delstubs(struct config_stub* p)
{
struct config_stub* np;
while(p) {
np = p->next;
free(p->name);
config_delstrlist(p->hosts);
config_delstrlist(p->addrs);
free(p);
p = np;
}
}
void
config_delete(struct config_file* cfg)
{
if(!cfg) return;
free(cfg->fwd_address);
free(cfg->username);
free(cfg->chrootdir);
free(cfg->directory);
free(cfg->logfile);
free(cfg->pidfile);
free(cfg->target_fetch_policy);
if(cfg->ifs) {
int i;
for(i=0; i<cfg->num_ifs; i++)
free(cfg->ifs[i]);
free(cfg->ifs);
}
config_delstubs(cfg->stubs);
config_delstubs(cfg->forwards);
config_delstrlist(cfg->donotqueryaddrs);
free(cfg->identity);
free(cfg->version);
free(cfg);
}
@@ -237,17 +180,3 @@ int ub_c_wrap()
return 1;
}
int
cfg_strlist_insert(struct config_strlist** head, char* item)
{
struct config_strlist *s;
if(!item || !head)
return 0;
s = (struct config_strlist*)calloc(1, sizeof(struct config_strlist));
if(!s)
return 0;
s->str = item;
s->next = *head;
*head = s;
return 1;
}
+6 -77
View File
@@ -41,8 +41,6 @@
#ifndef UTIL_CONFIG_FILE_H
#define UTIL_CONFIG_FILE_H
struct config_stub;
struct config_strlist;
/**
* The configuration options.
@@ -70,8 +68,6 @@ struct config_file {
int outgoing_base_port;
/** outgoing port range number of ports (per thread, per if) */
int outgoing_num_ports;
/** number of outgoing tcp buffers per (per thread) */
size_t outgoing_num_tcp;
/** size of the message cache */
size_t msg_cache_size;
@@ -79,43 +75,17 @@ struct config_file {
size_t msg_cache_slabs;
/** number of queries every thread can service */
size_t num_queries_per_thread;
/** size of the rrset cache */
size_t rrset_cache_size;
/** slabs in the rrset cache */
size_t rrset_cache_slabs;
/** host cache ttl in seconds */
int host_ttl;
/** host is lame for a zone ttl, in seconds */
int lame_ttl;
/** number of slabs in the infra host cache */
size_t infra_cache_slabs;
/** max number of hosts in the infra cache */
size_t infra_cache_numhosts;
/** max number of lame zones per host in the infra cache */
size_t infra_cache_numlame;
/** the target fetch policy for the iterator */
char* target_fetch_policy;
/** forwarder address. string. If not NULL fwder mode is enabled. */
char* fwd_address;
/** forwarder port */
int fwd_port;
/** number of interfaces to open. If 0 default all interfaces. */
int num_ifs;
/** interface description strings (IP addresses) */
char **ifs;
/** the stub definitions, linked list */
struct config_stub* stubs;
/** the forward zone definitions, linked list */
struct config_stub* forwards;
/** list of donotquery addresses, linked list */
struct config_strlist* donotqueryaddrs;
/** harden against very small edns buffer sizes */
int harden_short_bufsize;
/** harden against very large query sizes */
int harden_large_queries;
/** harden against spoofed glue (out of zone data) */
int harden_glue;
/** chrootdir, if not "" or chroot will be done */
char* chrootdir;
/** username to change to, if not "". */
@@ -126,44 +96,11 @@ struct config_file {
char* logfile;
/** pidfile to write pid to. */
char* pidfile;
/** do not report identity (id.server, hostname.bind) */
int hide_identity;
/** do not report version (version.server, version.bind) */
int hide_version;
/** identity, hostname is returned if "". */
char* identity;
/** version, package version returned if "". */
char* version;
/** daemonize, i.e. fork into the background. */
int do_daemonize;
};
/**
* Stub config options
*/
struct config_stub {
/** next in list */
struct config_stub* next;
/** domain name (in text) of the stub apex domain */
char* name;
/** list of stub nameserver hosts (domain name) */
struct config_strlist* hosts;
/** list of stub nameserver addresses (IP address) */
struct config_strlist* addrs;
};
/**
* List of strings for config options
*/
struct config_strlist {
/** next item in list */
struct config_strlist* next;
/** config option string */
char* str;
};
/**
* Create config file structure. Filled with default values.
* @return: the new structure or NULL on memory error.
@@ -184,14 +121,6 @@ int config_read(struct config_file* config, const char* filename);
*/
void config_delete(struct config_file* config);
/**
* Insert string into strlist.
* @param head: pointer to strlist head variable.
* @param item: new item. malloced by caller. If NULL the insertion fails.
* @return: true on success.
*/
int cfg_strlist_insert(struct config_strlist** head, char* item);
/**
* Used during options parsing
*/
@@ -210,9 +139,9 @@ struct config_parser_state {
/** global config parser object used during config parsing */
extern struct config_parser_state* cfg_parser;
/** parsing helpers: print error with file and line numbers */
/** parsing helpers: print error with file and line numbers. */
void ub_c_error(const char* msg);
/** parsing helpers: print error with file and line numbers */
/** parsing helpers: print error with file and line numbers. */
void ub_c_error_msg(const char* fmt, ...) ATTR_FORMAT(printf, 1, 2);
#endif /* UTIL_CONFIG_FILE_H */

Some files were not shown because too many files have changed in this diff Show More