aboutsummaryrefslogtreecommitdiff
path: root/external/unbound/testcode
diff options
context:
space:
mode:
authoranonimal <anonimal@i2pmail.org>2017-06-28 21:07:24 +0000
committeranonimal <anonimal@i2pmail.org>2018-03-18 15:52:19 +0000
commit84c5a9ba481d7a33cc0fd0ca43867b61d127d907 (patch)
treef05d3d3f107da02005b4a61f0e5074c113a7165c /external/unbound/testcode
parentMerge pull request #3416 (diff)
downloadmonero-84c5a9ba481d7a33cc0fd0ca43867b61d127d907.tar.xz
Unbound: remove unbound from in-tree source
We'll instead use a git submodule to pull from our unbound repo.
Diffstat (limited to 'external/unbound/testcode')
-rw-r--r--external/unbound/testcode/asynclook.c528
-rw-r--r--external/unbound/testcode/checklocks.c859
-rw-r--r--external/unbound/testcode/checklocks.h343
-rw-r--r--external/unbound/testcode/delayer.c1185
-rwxr-xr-xexternal/unbound/testcode/do-tests.sh63
-rw-r--r--external/unbound/testcode/fake_event.c1423
-rw-r--r--external/unbound/testcode/fake_event.h75
-rw-r--r--external/unbound/testcode/lock_verify.c426
-rw-r--r--external/unbound/testcode/memstats.c249
-rwxr-xr-xexternal/unbound/testcode/mini_tpkg.sh128
-rw-r--r--external/unbound/testcode/perf.c654
-rw-r--r--external/unbound/testcode/petal.c669
-rw-r--r--external/unbound/testcode/pktview.c202
-rw-r--r--external/unbound/testcode/readhex.c85
-rw-r--r--external/unbound/testcode/readhex.h52
-rw-r--r--external/unbound/testcode/replay.c1034
-rw-r--r--external/unbound/testcode/replay.h458
-rw-r--r--external/unbound/testcode/run_vm.sh78
-rw-r--r--external/unbound/testcode/signit.c284
-rw-r--r--external/unbound/testcode/streamtcp.166
-rw-r--r--external/unbound/testcode/streamtcp.c431
-rw-r--r--external/unbound/testcode/testbound.c470
-rw-r--r--external/unbound/testcode/testpkts.c1697
-rw-r--r--external/unbound/testcode/testpkts.h290
-rw-r--r--external/unbound/testcode/unitanchor.c137
-rw-r--r--external/unbound/testcode/unitdname.c861
-rw-r--r--external/unbound/testcode/unitecs.c284
-rw-r--r--external/unbound/testcode/unitldns.c218
-rw-r--r--external/unbound/testcode/unitlruhash.c499
-rw-r--r--external/unbound/testcode/unitmain.c919
-rw-r--r--external/unbound/testcode/unitmain.h82
-rw-r--r--external/unbound/testcode/unitmsgparse.c542
-rw-r--r--external/unbound/testcode/unitneg.c543
-rw-r--r--external/unbound/testcode/unitregional.c244
-rw-r--r--external/unbound/testcode/unitslabhash.c376
-rw-r--r--external/unbound/testcode/unitverify.c545
36 files changed, 0 insertions, 16999 deletions
diff --git a/external/unbound/testcode/asynclook.c b/external/unbound/testcode/asynclook.c
deleted file mode 100644
index a2bdb6213..000000000
--- a/external/unbound/testcode/asynclook.c
+++ /dev/null
@@ -1,528 +0,0 @@
-/*
- * testcode/asynclook.c - debug program perform async libunbound queries.
- *
- * Copyright (c) 2008, 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 COPYRIGHT
- * HOLDER 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 the results from several background lookups,
- * while printing time in the foreground.
- */
-
-#include "config.h"
-#ifdef HAVE_GETOPT_H
-#include <getopt.h>
-#endif
-#include "libunbound/unbound.h"
-#include "libunbound/context.h"
-#include "util/locks.h"
-#include "util/log.h"
-#include "sldns/rrdef.h"
-#ifdef UNBOUND_ALLOC_LITE
-#undef malloc
-#undef calloc
-#undef realloc
-#undef free
-#undef strdup
-#endif
-
-/** keeping track of the async ids */
-struct track_id {
- /** the id to pass to libunbound to cancel */
- int id;
- /** true if cancelled */
- int cancel;
- /** a lock on this structure for thread safety */
- lock_basic_type lock;
-};
-
-/**
- * result list for the lookups
- */
-struct lookinfo {
- /** name to look up */
- char* name;
- /** tracking number that can be used to cancel the query */
- int async_id;
- /** error code from libunbound */
- int err;
- /** result from lookup */
- struct ub_result* result;
-};
-
-/** global variable to see how many queries we have left */
-static int num_wait = 0;
-
-/** usage information for asynclook */
-static void usage(char* argv[])
-{
- printf("usage: %s [options] name ...\n", argv[0]);
- printf("names are looked up at the same time, asynchronously.\n");
- printf(" -b : use blocking requests\n");
- printf(" -c : cancel the requests\n");
- printf(" -d : enable debug output\n");
- printf(" -f addr : use addr, forward to that server\n");
- printf(" -h : this help message\n");
- printf(" -H fname : read hosts from fname\n");
- printf(" -r fname : read resolv.conf from fname\n");
- printf(" -t : use a resolver thread instead of forking a process\n");
- printf(" -x : perform extended threaded test\n");
- exit(1);
-}
-
-/** print result from lookup nicely */
-static void
-print_result(struct lookinfo* info)
-{
- char buf[100];
- if(info->err) /* error (from libunbound) */
- printf("%s: error %s\n", info->name,
- ub_strerror(info->err));
- else if(!info->result)
- printf("%s: cancelled\n", info->name);
- else if(info->result->havedata)
- printf("%s: %s\n", info->name,
- inet_ntop(AF_INET, info->result->data[0],
- buf, (socklen_t)sizeof(buf)));
- else {
- /* there is no data, why that? */
- if(info->result->rcode == 0 /*noerror*/ ||
- info->result->nxdomain)
- printf("%s: no data %s\n", info->name,
- info->result->nxdomain?"(no such host)":
- "(no IP4 address)");
- else /* some error (from the server) */
- printf("%s: DNS error %d\n", info->name,
- info->result->rcode);
- }
-}
-
-/** this is a function of type ub_callback_t */
-static void
-lookup_is_done(void* mydata, int err, struct ub_result* result)
-{
- /* cast mydata back to the correct type */
- struct lookinfo* info = (struct lookinfo*)mydata;
- fprintf(stderr, "name %s resolved\n", info->name);
- info->err = err;
- info->result = result;
- /* one less to wait for */
- num_wait--;
-}
-
-/** check error, if bad, exit with error message */
-static void
-checkerr(const char* desc, int err)
-{
- if(err != 0) {
- printf("%s error: %s\n", desc, ub_strerror(err));
- exit(1);
- }
-}
-
-#ifdef THREADS_DISABLED
-/** only one process can communicate with async worker */
-#define NUMTHR 1
-#else /* have threads */
-/** number of threads to make in extended test */
-#define NUMTHR 10
-#endif
-
-/** struct for extended thread info */
-struct ext_thr_info {
- /** thread num for debug */
- int thread_num;
- /** thread id */
- ub_thread_type tid;
- /** context */
- struct ub_ctx* ctx;
- /** size of array to query */
- int argc;
- /** array of names to query */
- char** argv;
- /** number of queries to do */
- int numq;
-};
-
-/** if true, we are testing against 'localhost' and extra checking is done */
-static int q_is_localhost = 0;
-
-/** check result structure for the 'correct' answer */
-static void
-ext_check_result(const char* desc, int err, struct ub_result* result)
-{
- checkerr(desc, err);
- if(result == NULL) {
- printf("%s: error result is NULL.\n", desc);
- exit(1);
- }
- if(q_is_localhost) {
- if(strcmp(result->qname, "localhost") != 0) {
- printf("%s: error result has wrong qname.\n", desc);
- exit(1);
- }
- if(result->qtype != LDNS_RR_TYPE_A) {
- printf("%s: error result has wrong qtype.\n", desc);
- exit(1);
- }
- if(result->qclass != LDNS_RR_CLASS_IN) {
- printf("%s: error result has wrong qclass.\n", desc);
- exit(1);
- }
- if(result->data == NULL) {
- printf("%s: error result->data is NULL.\n", desc);
- exit(1);
- }
- if(result->len == NULL) {
- printf("%s: error result->len is NULL.\n", desc);
- exit(1);
- }
- if(result->rcode != 0) {
- printf("%s: error result->rcode is set.\n", desc);
- exit(1);
- }
- if(result->havedata == 0) {
- printf("%s: error result->havedata is unset.\n", desc);
- exit(1);
- }
- if(result->nxdomain != 0) {
- printf("%s: error result->nxdomain is set.\n", desc);
- exit(1);
- }
- if(result->secure || result->bogus) {
- printf("%s: error result->secure or bogus is set.\n",
- desc);
- exit(1);
- }
- if(result->data[0] == NULL) {
- printf("%s: error result->data[0] is NULL.\n", desc);
- exit(1);
- }
- if(result->len[0] != 4) {
- printf("%s: error result->len[0] is wrong.\n", desc);
- exit(1);
- }
- if(result->len[1] != 0 || result->data[1] != NULL) {
- printf("%s: error result->data[1] or len[1] is "
- "wrong.\n", desc);
- exit(1);
- }
- if(result->answer_packet == NULL) {
- printf("%s: error result->answer_packet is NULL.\n",
- desc);
- exit(1);
- }
- if(result->answer_len != 54) {
- printf("%s: error result->answer_len is wrong.\n",
- desc);
- exit(1);
- }
- }
-}
-
-/** extended bg result callback, this function is ub_callback_t */
-static void
-ext_callback(void* mydata, int err, struct ub_result* result)
-{
- struct track_id* my_id = (struct track_id*)mydata;
- int doprint = 0;
- if(my_id) {
- /* I have an id, make sure we are not cancelled */
- lock_basic_lock(&my_id->lock);
- if(doprint)
- printf("cb %d: ", my_id->id);
- if(my_id->cancel) {
- printf("error: query id=%d returned, but was cancelled\n",
- my_id->id);
- abort();
- exit(1);
- }
- lock_basic_unlock(&my_id->lock);
- }
- ext_check_result("ext_callback", err, result);
- log_assert(result);
- if(doprint) {
- struct lookinfo pi;
- pi.name = result?result->qname:"noname";
- pi.result = result;
- pi.err = 0;
- print_result(&pi);
- }
- ub_resolve_free(result);
-}
-
-/** extended thread worker */
-static void*
-ext_thread(void* arg)
-{
- struct ext_thr_info* inf = (struct ext_thr_info*)arg;
- int i, r;
- struct ub_result* result;
- struct track_id* async_ids = NULL;
- log_thread_set(&inf->thread_num);
- if(inf->thread_num > NUMTHR*2/3) {
- async_ids = (struct track_id*)calloc((size_t)inf->numq, sizeof(struct track_id));
- if(!async_ids) {
- printf("out of memory\n");
- exit(1);
- }
- for(i=0; i<inf->numq; i++) {
- lock_basic_init(&async_ids[i].lock);
- }
- }
- for(i=0; i<inf->numq; i++) {
- if(async_ids) {
- r = ub_resolve_async(inf->ctx,
- inf->argv[i%inf->argc], LDNS_RR_TYPE_A,
- LDNS_RR_CLASS_IN, &async_ids[i], ext_callback,
- &async_ids[i].id);
- checkerr("ub_resolve_async", r);
- if(i > 100) {
- lock_basic_lock(&async_ids[i-100].lock);
- r = ub_cancel(inf->ctx, async_ids[i-100].id);
- if(r != UB_NOID)
- async_ids[i-100].cancel=1;
- lock_basic_unlock(&async_ids[i-100].lock);
- if(r != UB_NOID)
- checkerr("ub_cancel", r);
- }
- } else if(inf->thread_num > NUMTHR/2) {
- /* async */
- r = ub_resolve_async(inf->ctx,
- inf->argv[i%inf->argc], LDNS_RR_TYPE_A,
- LDNS_RR_CLASS_IN, NULL, ext_callback, NULL);
- checkerr("ub_resolve_async", r);
- } else {
- /* blocking */
- r = ub_resolve(inf->ctx, inf->argv[i%inf->argc],
- LDNS_RR_TYPE_A, LDNS_RR_CLASS_IN, &result);
- ext_check_result("ub_resolve", r, result);
- ub_resolve_free(result);
- }
- }
- if(inf->thread_num > NUMTHR/2) {
- r = ub_wait(inf->ctx);
- checkerr("ub_ctx_wait", r);
- }
- /* if these locks are destroyed, or if the async_ids is freed, then
- a use-after-free happens in another thread.
- The allocation is only part of this test, though. */
- /*
- if(async_ids) {
- for(i=0; i<inf->numq; i++) {
- lock_basic_destroy(&async_ids[i].lock);
- }
- }
- free(async_ids);
- */
-
- return NULL;
-}
-
-/** perform extended threaded test */
-static int
-ext_test(struct ub_ctx* ctx, int argc, char** argv)
-{
- struct ext_thr_info inf[NUMTHR];
- int i;
- if(argc == 1 && strcmp(argv[0], "localhost") == 0)
- q_is_localhost = 1;
- printf("extended test start (%d threads)\n", NUMTHR);
- for(i=0; i<NUMTHR; i++) {
- /* 0 = this, 1 = library bg worker */
- inf[i].thread_num = i+2;
- inf[i].ctx = ctx;
- inf[i].argc = argc;
- inf[i].argv = argv;
- inf[i].numq = 100;
- ub_thread_create(&inf[i].tid, ext_thread, &inf[i]);
- }
- /* the work happens here */
- for(i=0; i<NUMTHR; i++) {
- ub_thread_join(inf[i].tid);
- }
- printf("extended test end\n");
- ub_ctx_delete(ctx);
- checklock_stop();
- return 0;
-}
-
-/** getopt global, in case header files fail to declare it. */
-extern int optind;
-/** getopt global, in case header files fail to declare it. */
-extern char* optarg;
-
-/** main program for asynclook */
-int main(int argc, char** argv)
-{
- int c;
- struct ub_ctx* ctx;
- struct lookinfo* lookups;
- int i, r, cancel=0, blocking=0, ext=0;
-
- /* init log now because solaris thr_key_create() is not threadsafe */
- log_init(0,0,0);
- /* lock debug start (if any) */
- checklock_start();
-
- /* create context */
- ctx = ub_ctx_create();
- if(!ctx) {
- printf("could not create context, %s\n", strerror(errno));
- return 1;
- }
-
- /* command line options */
- if(argc == 1) {
- usage(argv);
- }
- while( (c=getopt(argc, argv, "bcdf:hH:r:tx")) != -1) {
- switch(c) {
- case 'd':
- r = ub_ctx_debuglevel(ctx, 3);
- checkerr("ub_ctx_debuglevel", r);
- break;
- case 't':
- r = ub_ctx_async(ctx, 1);
- checkerr("ub_ctx_async", r);
- break;
- case 'c':
- cancel = 1;
- break;
- case 'b':
- blocking = 1;
- break;
- case 'r':
- r = ub_ctx_resolvconf(ctx, optarg);
- if(r != 0) {
- printf("ub_ctx_resolvconf "
- "error: %s : %s\n",
- ub_strerror(r),
- strerror(errno));
- return 1;
- }
- break;
- case 'H':
- r = ub_ctx_hosts(ctx, optarg);
- if(r != 0) {
- printf("ub_ctx_hosts "
- "error: %s : %s\n",
- ub_strerror(r),
- strerror(errno));
- return 1;
- }
- break;
- case 'f':
- r = ub_ctx_set_fwd(ctx, optarg);
- checkerr("ub_ctx_set_fwd", r);
- break;
- case 'x':
- ext = 1;
- break;
- case 'h':
- case '?':
- default:
- usage(argv);
- }
- }
- argc -= optind;
- argv += optind;
-
- if(ext)
- return ext_test(ctx, argc, argv);
-
- /* allocate array for results. */
- lookups = (struct lookinfo*)calloc((size_t)argc,
- sizeof(struct lookinfo));
- if(!lookups) {
- printf("out of memory\n");
- return 1;
- }
-
- /* perform asynchronous calls */
- num_wait = argc;
- for(i=0; i<argc; i++) {
- lookups[i].name = argv[i];
- if(blocking) {
- fprintf(stderr, "lookup %s\n", argv[i]);
- r = ub_resolve(ctx, argv[i], LDNS_RR_TYPE_A,
- LDNS_RR_CLASS_IN, &lookups[i].result);
- checkerr("ub_resolve", r);
- } else {
- fprintf(stderr, "start async lookup %s\n", argv[i]);
- r = ub_resolve_async(ctx, argv[i], LDNS_RR_TYPE_A,
- LDNS_RR_CLASS_IN, &lookups[i], &lookup_is_done,
- &lookups[i].async_id);
- checkerr("ub_resolve_async", r);
- }
- }
- if(blocking)
- num_wait = 0;
- else if(cancel) {
- for(i=0; i<argc; i++) {
- fprintf(stderr, "cancel %s\n", argv[i]);
- r = ub_cancel(ctx, lookups[i].async_id);
- if(r != UB_NOID)
- checkerr("ub_cancel", r);
- }
- num_wait = 0;
- }
-
- /* wait while the hostnames are looked up. Do something useful here */
- if(num_wait > 0)
- for(i=0; i<1000; i++) {
- usleep(100000);
- fprintf(stderr, "%g seconds passed\n", 0.1*(double)i);
- r = ub_process(ctx);
- checkerr("ub_process", r);
- if(num_wait == 0)
- break;
- }
- if(i>=999) {
- printf("timed out\n");
- return 0;
- }
- printf("lookup complete\n");
-
- /* print lookup results */
- for(i=0; i<argc; i++) {
- print_result(&lookups[i]);
- ub_resolve_free(lookups[i].result);
- }
-
- ub_ctx_delete(ctx);
- free(lookups);
- checklock_stop();
- return 0;
-}
diff --git a/external/unbound/testcode/checklocks.c b/external/unbound/testcode/checklocks.c
deleted file mode 100644
index 7e6f0bb5d..000000000
--- a/external/unbound/testcode/checklocks.c
+++ /dev/null
@@ -1,859 +0,0 @@
-/**
- * testcode/checklocks.c - wrapper on locks that checks access.
- *
- * 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 COPYRIGHT
- * HOLDER 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.
- */
-
-#include "config.h"
-#include <signal.h>
-#include "util/locks.h" /* include before checklocks.h */
-#include "testcode/checklocks.h"
-
-/**
- * \file
- * Locks that are checked.
- *
- * Ugly hack: uses the fact that workers start with an int thread_num, and
- * are passed to thread_create to make the thread numbers here the same as
- * those used for logging which is nice.
- *
- * Todo:
- * - debug status print, of thread lock stacks, and current waiting.
- */
-#ifdef USE_THREAD_DEBUG
-
-/** How long to wait before lock attempt is a failure. */
-#define CHECK_LOCK_TIMEOUT 120 /* seconds */
-/** How long to wait before join attempt is a failure. */
-#define CHECK_JOIN_TIMEOUT 120 /* seconds */
-
-/** if key has been created */
-static int key_created = 0;
-/** if the key was deleted, i.e. we have quit */
-static int key_deleted = 0;
-/** we hide the thread debug info with this key. */
-static ub_thread_key_type 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 = 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(void);
-
-/** 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)
-{
- log_err("lock error (description follows)");
- log_err("Created at %s %s:%d", lock->create_func,
- lock->create_file, lock->create_line);
- if(lock->holder_func && lock->holder_file)
- log_err("Previously %s %s:%d", lock->holder_func,
- lock->holder_file, lock->holder_line);
- log_err("At %s %s:%d", func, file, line);
- log_err("Error for %s lock: %s",
- (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");
-}
-
-/**
- * Obtain lock on debug lock structure. This could be a deadlock by the caller.
- * The debug code itself does not deadlock. Anyway, check with timeouts.
- * @param lock: on what to acquire lock.
- * @param func: user level caller identification.
- * @param file: user level caller identification.
- * @param line: user level caller identification.
- */
-static void
-acquire_locklock(struct checked_lock* lock,
- const char* func, const char* file, int line)
-{
- struct timespec to;
- int err;
- int contend = 0;
- /* first try; inc contention counter if not immediately */
- if((err = pthread_mutex_trylock(&lock->lock))) {
- if(err==EBUSY)
- contend++;
- else fatal_exit("error in mutex_trylock: %s", strerror(err));
- }
- if(!err)
- return; /* immediate success */
- to.tv_sec = time(NULL) + CHECK_LOCK_TIMEOUT;
- to.tv_nsec = 0;
- err = pthread_mutex_timedlock(&lock->lock, &to);
- if(err) {
- log_err("in acquiring locklock: %s", strerror(err));
- lock_error(lock, func, file, line, "acquire locklock");
- }
- /* since we hold the lock, we can edit the contention_count */
- lock->contention_count += contend;
-}
-
-/** add protected region */
-void
-lock_protect(void *p, void* area, size_t size)
-{
- struct checked_lock* lock = *(struct checked_lock**)p;
- struct protected_area* e = (struct protected_area*)malloc(
- sizeof(struct protected_area));
- if(!e)
- fatal_exit("lock_protect: out of memory");
- e->region = area;
- e->size = size;
- e->hold = malloc(size);
- if(!e->hold)
- fatal_exit("lock_protect: out of memory");
- memcpy(e->hold, e->region, e->size);
-
- acquire_locklock(lock, __func__, __FILE__, __LINE__);
- e->next = lock->prot;
- lock->prot = e;
- LOCKRET(pthread_mutex_unlock(&lock->lock));
-}
-
-/** remove protected region */
-void
-lock_unprotect(void* mangled, void* area)
-{
- struct checked_lock* lock = *(struct checked_lock**)mangled;
- struct protected_area* p, **prevp;
- if(!lock)
- return;
- acquire_locklock(lock, __func__, __FILE__, __LINE__);
- p = lock->prot;
- prevp = &lock->prot;
- while(p) {
- if(p->region == area) {
- *prevp = p->next;
- free(p->hold);
- free(p);
- LOCKRET(pthread_mutex_unlock(&lock->lock));
- return;
- }
- prevp = &p->next;
- p = p->next;
- }
- LOCKRET(pthread_mutex_unlock(&lock->lock));
-}
-
-/**
- * Check protected memory region. Memory compare. Exit on error.
- * @param lock: which lock to check.
- * @param func: location we are now (when failure is detected).
- * @param file: location we are now (when failure is detected).
- * @param line: location we are now (when failure is detected).
- */
-static void
-prot_check(struct checked_lock* lock,
- const char* func, const char* file, int line)
-{
- struct protected_area* p = lock->prot;
- while(p) {
- if(memcmp(p->hold, p->region, p->size) != 0) {
- log_hex("memory prev", p->hold, p->size);
- log_hex("memory here", p->region, p->size);
- lock_error(lock, func, file, line,
- "protected area modified");
- }
- p = p->next;
- }
-}
-
-/** Copy protected memory region */
-static void
-prot_store(struct checked_lock* lock)
-{
- struct protected_area* p = lock->prot;
- while(p) {
- memcpy(p->hold, p->region, p->size);
- p = p->next;
- }
-}
-
-/** get memory held by lock */
-size_t
-lock_get_mem(void* pp)
-{
- size_t s;
- struct checked_lock* lock = *(struct checked_lock**)pp;
- struct protected_area* p;
- s = sizeof(struct checked_lock);
- acquire_locklock(lock, __func__, __FILE__, __LINE__);
- for(p = lock->prot; p; p = p->next) {
- s += sizeof(struct protected_area);
- s += p->size;
- }
- LOCKRET(pthread_mutex_unlock(&lock->lock));
- return s;
-}
-
-/** write lock trace info to file, while you hold those locks */
-static void
-ordercheck_locklock(struct thr_check* thr, struct checked_lock* lock)
-{
- int info[4];
- if(!check_locking_order) return;
- if(!thr->holding_first) return; /* no older lock, no info */
- /* write: <lock id held> <lock id new> <file> <line> */
- info[0] = thr->holding_first->create_thread;
- info[1] = thr->holding_first->create_instance;
- info[2] = lock->create_thread;
- info[3] = lock->create_instance;
- if(fwrite(info, 4*sizeof(int), 1, thr->order_info) != 1 ||
- fwrite(lock->holder_file, strlen(lock->holder_file)+1, 1,
- thr->order_info) != 1 ||
- fwrite(&lock->holder_line, sizeof(int), 1,
- thr->order_info) != 1)
- log_err("fwrite: %s", strerror(errno));
-}
-
-/** write ordercheck lock creation details to file */
-static void
-ordercheck_lockcreate(struct thr_check* thr, struct checked_lock* lock)
-{
- /* write: <ffff = create> <lock id> <file> <line> */
- int cmd = -1;
- if(!check_locking_order) return;
-
- if( fwrite(&cmd, sizeof(int), 1, thr->order_info) != 1 ||
- fwrite(&lock->create_thread, sizeof(int), 1,
- thr->order_info) != 1 ||
- fwrite(&lock->create_instance, sizeof(int), 1,
- thr->order_info) != 1 ||
- fwrite(lock->create_file, strlen(lock->create_file)+1, 1,
- thr->order_info) != 1 ||
- fwrite(&lock->create_line, sizeof(int), 1,
- thr->order_info) != 1)
- log_err("fwrite: %s", strerror(errno));
-}
-
-/** alloc struct, init lock empty */
-void
-checklock_init(enum check_lock_type type, struct checked_lock** lock,
- const char* func, const char* file, int line)
-{
- struct checked_lock* e = (struct checked_lock*)calloc(1,
- sizeof(struct checked_lock));
- struct thr_check *thr = (struct thr_check*)pthread_getspecific(
- thr_debug_key);
- if(!e)
- fatal_exit("%s %s %d: out of memory", func, file, line);
- if(!thr) {
- /* this is called when log_init() calls lock_init()
- * functions, and the test check code has not yet
- * been initialised. But luckily, the checklock_start()
- * routine can be called multiple times without ill effect.
- */
- checklock_start();
- thr = (struct thr_check*)pthread_getspecific(thr_debug_key);
- }
- if(!thr)
- fatal_exit("%s %s %d: lock_init no thread info", func, file,
- line);
- *lock = e;
- e->type = type;
- e->create_func = func;
- e->create_file = file;
- e->create_line = line;
- e->create_thread = thr->num;
- e->create_instance = thr->locks_created++;
- ordercheck_lockcreate(thr, e);
- LOCKRET(pthread_mutex_init(&e->lock, NULL));
- switch(e->type) {
- case check_lock_mutex:
- LOCKRET(pthread_mutex_init(&e->u.mutex, NULL));
- break;
- case check_lock_spinlock:
- LOCKRET(pthread_spin_init(&e->u.spinlock, PTHREAD_PROCESS_PRIVATE));
- break;
- case check_lock_rwlock:
- LOCKRET(pthread_rwlock_init(&e->u.rwlock, NULL));
- break;
- default:
- log_assert(0);
- }
-}
-
-/** delete prot items */
-static void
-prot_clear(struct checked_lock* lock)
-{
- struct protected_area* p=lock->prot, *np;
- while(p) {
- np = p->next;
- free(p->hold);
- free(p);
- p = np;
- }
-}
-
-/** check if type is OK for the lock given */
-static void
-checktype(enum check_lock_type type, struct checked_lock* lock,
- const char* func, const char* file, int line)
-{
- if(!lock)
- fatal_exit("use of null/deleted lock at %s %s:%d",
- func, file, line);
- if(type != lock->type) {
- lock_error(lock, func, file, line, "wrong lock type");
- }
-}
-
-/** check if OK, free struct */
-void
-checklock_destroy(enum check_lock_type type, struct checked_lock** lock,
- const char* func, const char* file, int line)
-{
- const size_t contention_interest = 1; /* promille contented locks */
- struct checked_lock* e;
- if(!lock)
- return;
- e = *lock;
- if(!e)
- return;
- checktype(type, e, func, file, line);
-
- /* check if delete is OK */
- acquire_locklock(e, func, file, line);
- if(e->hold_count != 0)
- lock_error(e, func, file, line, "delete while locked.");
- if(e->wait_count != 0)
- lock_error(e, func, file, line, "delete while waited on.");
- prot_check(e, func, file, line);
- *lock = NULL; /* use after free will fail */
- LOCKRET(pthread_mutex_unlock(&e->lock));
-
- /* contention, look at fraction in trouble. */
- if(e->history_count > 1 &&
- 1000*e->contention_count/e->history_count > contention_interest) {
- log_info("lock created %s %s %d has contention %u of %u (%d%%)",
- e->create_func, e->create_file, e->create_line,
- (unsigned int)e->contention_count,
- (unsigned int)e->history_count,
- (int)(100*e->contention_count/e->history_count));
- }
-
- /* delete it */
- LOCKRET(pthread_mutex_destroy(&e->lock));
- prot_clear(e);
- /* since nobody holds the lock - see check above, no need to unlink
- * from the thread-held locks list. */
- switch(e->type) {
- case check_lock_mutex:
- LOCKRET(pthread_mutex_destroy(&e->u.mutex));
- break;
- case check_lock_spinlock:
- LOCKRET(pthread_spin_destroy(&e->u.spinlock));
- break;
- case check_lock_rwlock:
- LOCKRET(pthread_rwlock_destroy(&e->u.rwlock));
- break;
- default:
- log_assert(0);
- }
- memset(e, 0, sizeof(struct checked_lock));
- free(e);
-}
-
-/** 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)
-{
- thr->waiting = NULL;
- lock->wait_count --;
- lock->holder = thr;
- lock->hold_count ++;
- lock->holder_func = func;
- lock->holder_file = file;
- lock->holder_line = line;
- ordercheck_locklock(thr, lock);
-
- /* insert in thread lock list, as first */
- lock->prev_held_lock[thr->num] = NULL;
- lock->next_held_lock[thr->num] = thr->holding_first;
- if(thr->holding_first)
- /* no need to lock it, since this thread already holds the
- * lock (since it is on this list) and we only edit thr->num
- * member in array. So it is safe. */
- thr->holding_first->prev_held_lock[thr->num] = lock;
- else thr->holding_last = lock;
- thr->holding_first = lock;
-}
-
-/**
- * Locking routine.
- * @param type: as passed by user.
- * @param lock: as passed by user.
- * @param func: caller location.
- * @param file: caller location.
- * @param line: caller location.
- * @param tryfunc: the pthread_mutex_trylock or similar function.
- * @param timedfunc: the pthread_mutex_timedlock or similar function.
- * Uses absolute timeout value.
- * @param arg: what to pass to tryfunc and timedlock.
- * @param exclusive: if lock must be exclusive (only one allowed).
- * @param getwr: if attempts to get writelock (or readlock) for rwlocks.
- */
-static void
-checklock_lockit(enum check_lock_type type, struct checked_lock* lock,
- const char* func, const char* file, int line,
- int (*tryfunc)(void*), int (*timedfunc)(void*, struct timespec*),
- void* arg, int exclusive, int getwr)
-{
- int err;
- int contend = 0;
- struct thr_check *thr = (struct thr_check*)pthread_getspecific(
- thr_debug_key);
- checktype(type, lock, func, file, line);
- if(!thr) lock_error(lock, func, file, line, "no thread info");
-
- acquire_locklock(lock, func, file, line);
- lock->wait_count ++;
- thr->waiting = lock;
- if(exclusive && lock->hold_count > 0 && lock->holder == thr)
- lock_error(lock, func, file, line, "thread already owns lock");
- if(type==check_lock_rwlock && getwr && lock->writeholder == thr)
- lock_error(lock, func, file, line, "thread already has wrlock");
- LOCKRET(pthread_mutex_unlock(&lock->lock));
-
- /* first try; if busy increase contention counter */
- if((err=tryfunc(arg))) {
- struct timespec to;
- if(err != EBUSY) log_err("trylock: %s", strerror(err));
- to.tv_sec = time(NULL) + CHECK_LOCK_TIMEOUT;
- to.tv_nsec = 0;
- if((err=timedfunc(arg, &to))) {
- if(err == ETIMEDOUT)
- lock_error(lock, func, file, line,
- "timeout possible deadlock");
- log_err("timedlock: %s", strerror(err));
- }
- contend ++;
- }
- /* got the lock */
-
- acquire_locklock(lock, func, file, line);
- lock->contention_count += contend;
- lock->history_count++;
- if(exclusive && lock->hold_count > 0)
- lock_error(lock, func, file, line, "got nonexclusive lock");
- if(type==check_lock_rwlock && getwr && lock->writeholder)
- lock_error(lock, func, file, line, "got nonexclusive wrlock");
- if(type==check_lock_rwlock && getwr)
- lock->writeholder = thr;
- /* check the memory areas for unauthorized changes,
- * between last unlock time and current lock time.
- * we check while holding the lock (threadsafe).
- */
- if(getwr || exclusive)
- prot_check(lock, func, file, line);
- finish_acquire_lock(thr, lock, func, file, line);
- LOCKRET(pthread_mutex_unlock(&lock->lock));
-}
-
-/** helper for rdlock: try */
-static int try_rd(void* arg)
-{ return pthread_rwlock_tryrdlock((pthread_rwlock_t*)arg); }
-/** helper for rdlock: timed */
-static int timed_rd(void* arg, struct timespec* to)
-{ return pthread_rwlock_timedrdlock((pthread_rwlock_t*)arg, to); }
-
-/** check if OK, lock */
-void
-checklock_rdlock(enum check_lock_type type, struct checked_lock* lock,
- const char* func, const char* file, int line)
-{
- if(key_deleted)
- return;
-
- log_assert(type == check_lock_rwlock);
- checklock_lockit(type, lock, func, file, line,
- try_rd, timed_rd, &lock->u.rwlock, 0, 0);
-}
-
-/** helper for wrlock: try */
-static int try_wr(void* arg)
-{ return pthread_rwlock_trywrlock((pthread_rwlock_t*)arg); }
-/** helper for wrlock: timed */
-static int timed_wr(void* arg, struct timespec* to)
-{ return pthread_rwlock_timedwrlock((pthread_rwlock_t*)arg, to); }
-
-/** check if OK, lock */
-void
-checklock_wrlock(enum check_lock_type type, struct checked_lock* lock,
- const char* func, const char* file, int line)
-{
- if(key_deleted)
- return;
- log_assert(type == check_lock_rwlock);
- checklock_lockit(type, lock, func, file, line,
- try_wr, timed_wr, &lock->u.rwlock, 0, 1);
-}
-
-/** helper for lock mutex: try */
-static int try_mutex(void* arg)
-{ return pthread_mutex_trylock((pthread_mutex_t*)arg); }
-/** helper for lock mutex: timed */
-static int timed_mutex(void* arg, struct timespec* to)
-{ return pthread_mutex_timedlock((pthread_mutex_t*)arg, to); }
-
-/** helper for lock spinlock: try */
-static int try_spinlock(void* arg)
-{ return pthread_spin_trylock((pthread_spinlock_t*)arg); }
-/** helper for lock spinlock: timed */
-static int timed_spinlock(void* arg, struct timespec* to)
-{
- int err;
- /* spin for 5 seconds. (ouch for the CPU, but it beats forever) */
- while( (err=try_spinlock(arg)) == EBUSY) {
-#ifndef S_SPLINT_S
- if(time(NULL) >= to->tv_sec)
- return ETIMEDOUT;
- usleep(1000); /* in 1/1000000s of a second */
-#endif
- }
- return err;
-}
-
-/** check if OK, lock */
-void
-checklock_lock(enum check_lock_type type, struct checked_lock* lock,
- const char* func, const char* file, int line)
-{
- if(key_deleted)
- return;
- log_assert(type != check_lock_rwlock);
- switch(type) {
- case check_lock_mutex:
- checklock_lockit(type, lock, func, file, line,
- try_mutex, timed_mutex, &lock->u.mutex, 1, 0);
- break;
- case check_lock_spinlock:
- /* void* cast needed because 'volatile' on some OS */
- checklock_lockit(type, lock, func, file, line,
- try_spinlock, timed_spinlock,
- (void*)&lock->u.spinlock, 1, 0);
- break;
- default:
- log_assert(0);
- }
-}
-
-/** check if OK, unlock */
-void
-checklock_unlock(enum check_lock_type type, struct checked_lock* lock,
- const char* func, const char* file, int line)
-{
- struct thr_check *thr;
- if(key_deleted)
- return;
- thr = (struct thr_check*)pthread_getspecific(thr_debug_key);
- checktype(type, lock, func, file, line);
- if(!thr) lock_error(lock, func, file, line, "no thread info");
-
- acquire_locklock(lock, func, file, line);
- /* was this thread even holding this lock? */
- if(thr->holding_first != lock &&
- lock->prev_held_lock[thr->num] == NULL) {
- lock_error(lock, func, file, line, "unlock nonlocked lock");
- }
- if(lock->hold_count <= 0)
- lock_error(lock, func, file, line, "too many unlocks");
-
- /* store this point as last touched by */
- lock->holder = thr;
- lock->hold_count --;
- lock->holder_func = func;
- lock->holder_file = file;
- lock->holder_line = line;
-
- /* delete from thread holder list */
- /* no need to lock other lockstructs, because they are all on the
- * held-locks list, and this thread holds their locks.
- * we only touch the thr->num members, so it is safe. */
- if(thr->holding_first == lock)
- thr->holding_first = lock->next_held_lock[thr->num];
- if(thr->holding_last == lock)
- thr->holding_last = lock->prev_held_lock[thr->num];
- if(lock->next_held_lock[thr->num])
- lock->next_held_lock[thr->num]->prev_held_lock[thr->num] =
- lock->prev_held_lock[thr->num];
- if(lock->prev_held_lock[thr->num])
- lock->prev_held_lock[thr->num]->next_held_lock[thr->num] =
- lock->next_held_lock[thr->num];
- lock->next_held_lock[thr->num] = NULL;
- lock->prev_held_lock[thr->num] = NULL;
-
- if(type==check_lock_rwlock && lock->writeholder == thr) {
- lock->writeholder = NULL;
- prot_store(lock);
- } else if(type != check_lock_rwlock) {
- /* store memory areas that are protected, for later checks */
- prot_store(lock);
- }
- LOCKRET(pthread_mutex_unlock(&lock->lock));
-
- /* unlock it */
- switch(type) {
- case check_lock_mutex:
- LOCKRET(pthread_mutex_unlock(&lock->u.mutex));
- break;
- case check_lock_spinlock:
- LOCKRET(pthread_spin_unlock(&lock->u.spinlock));
- break;
- case check_lock_rwlock:
- LOCKRET(pthread_rwlock_unlock(&lock->u.rwlock));
- break;
- default:
- log_assert(0);
- }
-}
-
-/** open order info debug file, thr->num must be valid */
-static void
-open_lockorder(struct thr_check* thr)
-{
- char buf[24];
- time_t t;
- snprintf(buf, sizeof(buf), "ublocktrace.%d", thr->num);
- thr->order_info = fopen(buf, "w");
- if(!thr->order_info)
- fatal_exit("could not open %s: %s", buf, strerror(errno));
- thr->locks_created = 0;
- t = time(NULL);
- /* write: <time_stamp> <runpid> <thread_num> */
- if(fwrite(&t, sizeof(t), 1, thr->order_info) != 1 ||
- fwrite(&thr->num, sizeof(thr->num), 1, thr->order_info) != 1 ||
- fwrite(&check_lock_pid, sizeof(check_lock_pid), 1,
- thr->order_info) != 1)
- log_err("fwrite: %s", strerror(errno));
-}
-
-/** checklock thread main, Inits thread structure */
-static void* checklock_main(void* arg)
-{
- struct thr_check* thr = (struct thr_check*)arg;
- void* ret;
- thr->id = pthread_self();
- /* Hack to get same numbers as in log file */
- thr->num = *(int*)(thr->arg);
- log_assert(thr->num < THRDEBUG_MAX_THREADS);
- /* as an aside, due to this, won't work for libunbound bg thread */
- if(thread_infos[thr->num] != NULL)
- log_warn("thread warning, thr->num %d not NULL", thr->num);
- thread_infos[thr->num] = thr;
- LOCKRET(pthread_setspecific(thr_debug_key, thr));
- if(check_locking_order)
- open_lockorder(thr);
- ret = thr->func(thr->arg);
- thread_infos[thr->num] = NULL;
- if(check_locking_order)
- fclose(thr->order_info);
- free(thr);
- return ret;
-}
-
-/** init the main thread */
-void checklock_start(void)
-{
- if(key_deleted)
- return;
- if(!key_created) {
- struct thr_check* thisthr = (struct thr_check*)calloc(1,
- sizeof(struct thr_check));
- if(!thisthr)
- fatal_exit("thrcreate: out of memory");
- key_created = 1;
- check_lock_pid = getpid();
- LOCKRET(pthread_key_create(&thr_debug_key, NULL));
- LOCKRET(pthread_setspecific(thr_debug_key, thisthr));
- thread_infos[0] = thisthr;
- if(check_locking_order)
- open_lockorder(thisthr);
- }
-}
-
-/** stop checklocks */
-void checklock_stop(void)
-{
- if(key_created) {
- int i;
- key_deleted = 1;
- if(check_locking_order)
- fclose(thread_infos[0]->order_info);
- free(thread_infos[0]);
- thread_infos[0] = NULL;
- for(i = 0; i < THRDEBUG_MAX_THREADS; i++)
- log_assert(thread_infos[i] == NULL);
- /* should have been cleaned up. */
- LOCKRET(pthread_key_delete(thr_debug_key));
- key_created = 0;
- }
-}
-
-/** allocate debug info and create thread */
-void
-checklock_thrcreate(pthread_t* id, void* (*func)(void*), void* arg)
-{
- struct thr_check* thr = (struct thr_check*)calloc(1,
- sizeof(struct thr_check));
- if(!thr)
- fatal_exit("thrcreate: out of memory");
- if(!key_created) {
- checklock_start();
- }
- thr->func = func;
- thr->arg = arg;
- LOCKRET(pthread_create(id, NULL, checklock_main, thr));
-}
-
-/** count number of thread infos */
-static int
-count_thread_infos(void)
-{
- 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 %llx, %d %d create %s %s %d",
- (unsigned long long)(size_t)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 %llx", (unsigned long long)(size_t)thr->func);
- log_info("thread arg is %llx (%d)",
- (unsigned long long)(size_t)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 %llx", w?"yes":"no",
- (unsigned long long)(size_t)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(void)
-{
- 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 */
-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 */
-void
-checklock_thrjoin(pthread_t thread)
-{
- /* wait with a timeout */
- if(signal(SIGALRM, joinalarm) == SIG_ERR)
- fatal_exit("signal(): %s", strerror(errno));
- (void)alarm(CHECK_JOIN_TIMEOUT);
- LOCKRET(pthread_join(thread, NULL));
- (void)alarm(0);
-}
-
-#endif /* USE_THREAD_DEBUG */
diff --git a/external/unbound/testcode/checklocks.h b/external/unbound/testcode/checklocks.h
deleted file mode 100644
index 182a93858..000000000
--- a/external/unbound/testcode/checklocks.h
+++ /dev/null
@@ -1,343 +0,0 @@
-/**
- * testcode/checklocks.h - wrapper on locks that checks access.
- *
- * 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 COPYRIGHT
- * HOLDER 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.
- */
-
-#ifndef TESTCODE_CHECK_LOCKS_H
-#define TESTCODE_CHECK_LOCKS_H
-
-/**
- * \file
- * Locks that are checked.
- *
- * Holds information per lock and per thread.
- * That information is protected by a mutex (unchecked).
- *
- * Checks:
- * o which func, file, line created the lock.
- * o contention count, measures amount of contention on the lock.
- * o the memory region(s) that the lock protects are
- * memcmp'ed to ascertain no race conditions.
- * o checks that locks are unlocked properly (before deletion).
- * keeps which func, file, line that locked it.
- * o checks deadlocks with timeout so it can print errors for them.
- *
- * Limitations:
- * o Detects unprotected memory access when the lock is locked or freed,
- * which detects races only if they happen, and only if in protected
- * memory areas.
- * o Detects deadlocks by timeout, so approximately, as they happen.
- * o Does not check order of locking.
- * o Uses a lot of memory.
- * o The checks use locks themselves, changing scheduling,
- * thus changing what races you see.
- */
-
-#ifdef USE_THREAD_DEBUG
-#ifndef HAVE_PTHREAD
-/* we need the *timed*lock() routines to use for deadlock detection. */
-#error "Need pthreads for checked locks"
-#endif
-/******************* THREAD DEBUG ************************/
-#include <pthread.h>
-
-/** How many threads to allocate for */
-#define THRDEBUG_MAX_THREADS 32 /* threads */
-/** do we check locking order */
-extern int check_locking_order;
-
-/**
- * Protection memory area.
- * It is copied to a holding buffer to compare against later.
- * Note that it may encompass the lock structure.
- */
-struct protected_area {
- /** where the memory region starts */
- void* region;
- /** size of the region */
- size_t size;
- /** backbuffer that holds a copy, of same size. */
- void* hold;
- /** next protected area in list */
- struct protected_area* next;
-};
-
-/**
- * Per thread information for locking debug wrappers.
- */
-struct thr_check {
- /** thread id */
- pthread_t id;
- /** real thread func */
- void* (*func)(void*);
- /** func user arg */
- void* arg;
- /** number of thread in list structure */
- int num;
- /** instance number - how many locks have been created by thread */
- int locks_created;
- /** file to write locking order information to */
- FILE* order_info;
- /**
- * List of locks that this thread is holding, double
- * linked list. The first element is the most recent lock acquired.
- * So it represents the stack of locks acquired. (of all types).
- */
- struct checked_lock *holding_first, *holding_last;
- /** if the thread is currently waiting for a lock, which one */
- struct checked_lock* waiting;
-};
-
-/**
- * One structure for all types of locks.
- */
-struct checked_lock {
- /** mutex for exclusive access to this structure */
- pthread_mutex_t lock;
- /** list of memory regions protected by this checked lock */
- struct protected_area* prot;
- /** where was this lock created */
- const char* create_func, *create_file;
- /** where was this lock created */
- int create_line;
- /** unique instance identifier */
- int create_thread, create_instance;
- /** contention count */
- size_t contention_count;
- /** number of times locked, ever */
- size_t history_count;
- /** hold count (how many threads are holding this lock) */
- int hold_count;
- /** how many threads are waiting for this lock */
- int wait_count;
- /** who touched it last */
- const char* holder_func, *holder_file;
- /** who touched it last */
- int holder_line;
- /** who owns the lock now */
- struct thr_check* holder;
- /** for rwlocks, the writelock holder */
- struct thr_check* writeholder;
-
- /** next lock a thread is holding (less recent) */
- struct checked_lock* next_held_lock[THRDEBUG_MAX_THREADS];
- /** prev lock a thread is holding (more recent) */
- struct checked_lock* prev_held_lock[THRDEBUG_MAX_THREADS];
-
- /** type of lock */
- enum check_lock_type {
- /** basic mutex */
- check_lock_mutex,
- /** fast spinlock */
- check_lock_spinlock,
- /** rwlock */
- check_lock_rwlock
- } type;
- /** the lock itself, see type to disambiguate the union */
- union {
- /** mutex */
- pthread_mutex_t mutex;
- /** spinlock */
- pthread_spinlock_t spinlock;
- /** rwlock */
- pthread_rwlock_t rwlock;
- } u;
-};
-
-/**
- * Additional call for the user to specify what areas are protected
- * @param lock: the lock that protects the area. It can be inside the area.
- * The lock must be inited. Call with user lock. (any type).
- * It demangles the lock itself (struct checked_lock**).
- * @param area: ptr to mem.
- * @param size: length of area.
- * You can call it multiple times with the same lock to give several areas.
- * Call it when you are done initialising the area, since it will be copied
- * at this time and protected right away against unauthorised changes until
- * the next lock() call is done.
- */
-void lock_protect(void* lock, void* area, size_t size);
-
-/**
- * Remove protected area from lock.
- * No need to call this when deleting the lock.
- * @param lock: the lock, any type, (struct checked_lock**).
- * @param area: pointer to memory.
- */
-void lock_unprotect(void* lock, void* area);
-
-/**
- * Get memory associated with a checked lock
- * @param lock: the checked lock, any type. (struct checked_lock**).
- * @return: in bytes, including protected areas.
- */
-size_t lock_get_mem(void* lock);
-
-/**
- * Initialise checklock. Sets up internal debug structures.
- */
-void checklock_start(void);
-
-/**
- * Cleanup internal debug state.
- */
-void checklock_stop(void);
-
-/**
- * Init locks.
- * @param type: what type of lock this is.
- * @param lock: ptr to user alloced ptr structure. This is inited.
- * So an alloc is done and the ptr is stored as result.
- * @param func: caller function name.
- * @param file: caller file name.
- * @param line: caller line number.
- */
-void checklock_init(enum check_lock_type type, struct checked_lock** lock,
- const char* func, const char* file, int line);
-
-/**
- * Destroy locks. Free the structure.
- * @param type: what type of lock this is.
- * @param lock: ptr to user alloced structure. This is destroyed.
- * @param func: caller function name.
- * @param file: caller file name.
- * @param line: caller line number.
- */
-void checklock_destroy(enum check_lock_type type, struct checked_lock** lock,
- const char* func, const char* file, int line);
-
-/**
- * Acquire readlock.
- * @param type: what type of lock this is. Had better be a rwlock.
- * @param lock: ptr to lock.
- * @param func: caller function name.
- * @param file: caller file name.
- * @param line: caller line number.
- */
-void checklock_rdlock(enum check_lock_type type, struct checked_lock* lock,
- const char* func, const char* file, int line);
-
-/**
- * Acquire writelock.
- * @param type: what type of lock this is. Had better be a rwlock.
- * @param lock: ptr to lock.
- * @param func: caller function name.
- * @param file: caller file name.
- * @param line: caller line number.
- */
-void checklock_wrlock(enum check_lock_type type, struct checked_lock* lock,
- const char* func, const char* file, int line);
-
-/**
- * Locks.
- * @param type: what type of lock this is. Had better be mutex or spinlock.
- * @param lock: the lock.
- * @param func: caller function name.
- * @param file: caller file name.
- * @param line: caller line number.
- */
-void checklock_lock(enum check_lock_type type, struct checked_lock* lock,
- const char* func, const char* file, int line);
-
-/**
- * Unlocks.
- * @param type: what type of lock this is.
- * @param lock: the lock.
- * @param func: caller function name.
- * @param file: caller file name.
- * @param line: caller line number.
- */
-void checklock_unlock(enum check_lock_type type, struct checked_lock* lock,
- const char* func, const char* file, int line);
-
-/**
- * Create thread.
- * @param thr: Thread id, where to store result.
- * @param func: thread start function.
- * @param arg: user argument.
- */
-void checklock_thrcreate(pthread_t* thr, void* (*func)(void*), void* arg);
-
-/**
- * Wait for thread to exit. Returns thread return value.
- * @param thread: thread to wait for.
- */
-void checklock_thrjoin(pthread_t thread);
-
-/** structures to enable compiler type checking on the locks.
- * Also the pointer makes it so that the lock can be part of the protected
- * region without any possible problem (since the ptr will stay the same.)
- * i.e. there can be contention and readlocks stored in checked_lock, while
- * the protected area stays the same, even though it contains (ptr to) lock.
- */
-struct checked_lock_rw { struct checked_lock* c_rw; };
-/** structures to enable compiler type checking on the locks. */
-struct checked_lock_mutex { struct checked_lock* c_m; };
-/** structures to enable compiler type checking on the locks. */
-struct checked_lock_spl { struct checked_lock* c_spl; };
-
-/** debugging rwlock */
-typedef struct checked_lock_rw lock_rw_type;
-#define lock_rw_init(lock) checklock_init(check_lock_rwlock, &((lock)->c_rw), __func__, __FILE__, __LINE__)
-#define lock_rw_destroy(lock) checklock_destroy(check_lock_rwlock, &((lock)->c_rw), __func__, __FILE__, __LINE__)
-#define lock_rw_rdlock(lock) checklock_rdlock(check_lock_rwlock, (lock)->c_rw, __func__, __FILE__, __LINE__)
-#define lock_rw_wrlock(lock) checklock_wrlock(check_lock_rwlock, (lock)->c_rw, __func__, __FILE__, __LINE__)
-#define lock_rw_unlock(lock) checklock_unlock(check_lock_rwlock, (lock)->c_rw, __func__, __FILE__, __LINE__)
-
-/** debugging mutex */
-typedef struct checked_lock_mutex lock_basic_type;
-#define lock_basic_init(lock) checklock_init(check_lock_mutex, &((lock)->c_m), __func__, __FILE__, __LINE__)
-#define lock_basic_destroy(lock) checklock_destroy(check_lock_mutex, &((lock)->c_m), __func__, __FILE__, __LINE__)
-#define lock_basic_lock(lock) checklock_lock(check_lock_mutex, (lock)->c_m, __func__, __FILE__, __LINE__)
-#define lock_basic_unlock(lock) checklock_unlock(check_lock_mutex, (lock)->c_m, __func__, __FILE__, __LINE__)
-
-/** debugging spinlock */
-typedef struct checked_lock_spl lock_quick_type;
-#define lock_quick_init(lock) checklock_init(check_lock_spinlock, &((lock)->c_spl), __func__, __FILE__, __LINE__)
-#define lock_quick_destroy(lock) checklock_destroy(check_lock_spinlock, &((lock)->c_spl), __func__, __FILE__, __LINE__)
-#define lock_quick_lock(lock) checklock_lock(check_lock_spinlock, (lock)->c_spl, __func__, __FILE__, __LINE__)
-#define lock_quick_unlock(lock) checklock_unlock(check_lock_spinlock, (lock)->c_spl, __func__, __FILE__, __LINE__)
-
-/** we use the pthread id, our thr_check structure is kept behind the scenes */
-typedef pthread_t ub_thread_type;
-#define ub_thread_create(thr, func, arg) checklock_thrcreate(thr, func, arg)
-#define ub_thread_self() pthread_self()
-#define ub_thread_join(thread) checklock_thrjoin(thread)
-
-typedef pthread_key_t ub_thread_key_type;
-#define ub_thread_key_create(key, f) LOCKRET(pthread_key_create(key, f))
-#define ub_thread_key_set(key, v) LOCKRET(pthread_setspecific(key, v))
-#define ub_thread_key_get(key) pthread_getspecific(key)
-
-#endif /* USE_THREAD_DEBUG */
-#endif /* TESTCODE_CHECK_LOCKS_H */
diff --git a/external/unbound/testcode/delayer.c b/external/unbound/testcode/delayer.c
deleted file mode 100644
index 5489b591e..000000000
--- a/external/unbound/testcode/delayer.c
+++ /dev/null
@@ -1,1185 +0,0 @@
-/*
- * testcode/delayer.c - debug program that delays queries to a server.
- *
- * Copyright (c) 2008, 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 COPYRIGHT
- * HOLDER 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 delays queries made. It performs as a proxy to another
- * server and delays queries to it.
- */
-
-#include "config.h"
-#ifdef HAVE_GETOPT_H
-#include <getopt.h>
-#endif
-#ifdef HAVE_TIME_H
-#include <time.h>
-#endif
-#include <sys/time.h>
-#include "util/net_help.h"
-#include "util/config_file.h"
-#include "sldns/sbuffer.h"
-#include <signal.h>
-
-/** number of reads per select for delayer */
-#define TRIES_PER_SELECT 100
-
-/**
- * The ring buffer
- */
-struct ringbuf {
- /** base of buffer */
- uint8_t* buf;
- /** size of buffer */
- size_t size;
- /** low mark, items start here */
- size_t low;
- /** high mark, items end here */
- size_t high;
-};
-
-/**
- * List of proxy fds that return replies from the server to our clients.
- */
-struct proxy {
- /** the fd to listen for replies from server */
- int s;
- /** last time this was used */
- struct timeval lastuse;
- /** remote address */
- struct sockaddr_storage addr;
- /** length of addr */
- socklen_t addr_len;
- /** number of queries waiting (in total) */
- size_t numwait;
- /** number of queries sent to server (in total) */
- size_t numsent;
- /** numberof answers returned to client (in total) */
- size_t numreturn;
- /** how many times repurposed */
- size_t numreuse;
- /** next in proxylist */
- struct proxy* next;
-};
-
-/**
- * An item that has to be TCP relayed
- */
-struct tcp_send_list {
- /** the data item */
- uint8_t* item;
- /** size of item */
- size_t len;
- /** time when the item can be transmitted on */
- struct timeval wait;
- /** how much of the item has already been transmitted */
- size_t done;
- /** next in list */
- struct tcp_send_list* next;
-};
-
-/**
- * List of TCP proxy fd pairs to TCP connect client to server
- */
-struct tcp_proxy {
- /** the fd to listen for client query */
- int client_s;
- /** the fd to listen for server answer */
- int server_s;
-
- /** remote client address */
- struct sockaddr_storage addr;
- /** length of address */
- socklen_t addr_len;
- /** timeout on this entry */
- struct timeval timeout;
-
- /** list of query items to send to server */
- struct tcp_send_list* querylist;
- /** last in query list */
- struct tcp_send_list* querylast;
- /** list of answer items to send to client */
- struct tcp_send_list* answerlist;
- /** last in answerlist */
- struct tcp_send_list* answerlast;
-
- /** next in list */
- struct tcp_proxy* next;
-};
-
-/** usage information for delayer */
-static void usage(char* argv[])
-{
- printf("usage: %s [options]\n", argv[0]);
- printf(" -f addr : use addr, forward to that server, @port.\n");
- printf(" -b addr : bind to this address to listen.\n");
- printf(" -p port : bind to this port (use 0 for random).\n");
- printf(" -m mem : use this much memory for waiting queries.\n");
- printf(" -d delay: UDP queries are delayed n milliseconds.\n");
- printf(" TCP is delayed twice (on send, on recv).\n");
- printf(" -h : this help message\n");
- exit(1);
-}
-
-/** timeval compare, t1 < t2 */
-static int
-dl_tv_smaller(struct timeval* t1, const struct timeval* t2)
-{
-#ifndef S_SPLINT_S
- if(t1->tv_sec < t2->tv_sec)
- return 1;
- if(t1->tv_sec == t2->tv_sec &&
- t1->tv_usec < t2->tv_usec)
- return 1;
-#endif
- return 0;
-}
-
-/** timeval add, t1 += t2 */
-static void
-dl_tv_add(struct timeval* t1, const struct timeval* t2)
-{
-#ifndef S_SPLINT_S
- t1->tv_sec += t2->tv_sec;
- t1->tv_usec += t2->tv_usec;
- while(t1->tv_usec > 1000000) {
- t1->tv_usec -= 1000000;
- t1->tv_sec++;
- }
-#endif
-}
-
-/** timeval subtract, t1 -= t2 */
-static void
-dl_tv_subtract(struct timeval* t1, const struct timeval* t2)
-{
-#ifndef S_SPLINT_S
- t1->tv_sec -= t2->tv_sec;
- if(t1->tv_usec >= t2->tv_usec) {
- t1->tv_usec -= t2->tv_usec;
- } else {
- t1->tv_sec--;
- t1->tv_usec = 1000000-(t2->tv_usec-t1->tv_usec);
- }
-#endif
-}
-
-
-/** create new ring buffer */
-static struct ringbuf*
-ring_create(size_t sz)
-{
- struct ringbuf* r = (struct ringbuf*)calloc(1, sizeof(*r));
- if(!r) fatal_exit("out of memory");
- r->buf = (uint8_t*)malloc(sz);
- if(!r->buf) fatal_exit("out of memory");
- r->size = sz;
- r->low = 0;
- r->high = 0;
- return r;
-}
-
-/** delete ring buffer */
-static void
-ring_delete(struct ringbuf* r)
-{
- if(!r) return;
- free(r->buf);
- free(r);
-}
-
-/** add entry to ringbuffer */
-static void
-ring_add(struct ringbuf* r, sldns_buffer* pkt, struct timeval* now,
- struct timeval* delay, struct proxy* p)
-{
- /* time -- proxy* -- 16bitlen -- message */
- uint16_t len = (uint16_t)sldns_buffer_limit(pkt);
- struct timeval when;
- size_t needed;
- uint8_t* where = NULL;
- log_assert(sldns_buffer_limit(pkt) <= 65535);
- needed = sizeof(when) + sizeof(p) + sizeof(len) + len;
- /* put item into ringbuffer */
- if(r->low < r->high) {
- /* used part is in the middle */
- if(r->size - r->high >= needed) {
- where = r->buf + r->high;
- r->high += needed;
- } else if(r->low > needed) {
- /* wrap around ringbuffer */
- /* make sure r->low == r->high means empty */
- /* so r->low == r->high cannot be used to signify
- * a completely full ringbuf */
- if(r->size - r->high > sizeof(when)+sizeof(p)) {
- /* zero entry at end of buffer */
- memset(r->buf+r->high, 0,
- sizeof(when)+sizeof(p));
- }
- where = r->buf;
- r->high = needed;
- } else {
- /* drop message */
- log_warn("warning: mem full, dropped message");
- return;
- }
- } else {
- /* empty */
- if(r->high == r->low) {
- where = r->buf;
- r->low = 0;
- r->high = needed;
- /* unused part is in the middle */
- /* so ringbuffer has wrapped around */
- } else if(r->low - r->high > needed) {
- where = r->buf + r->high;
- r->high += needed;
- } else {
- log_warn("warning: mem full, dropped message");
- return;
- }
- }
- when = *now;
- dl_tv_add(&when, delay);
- /* copy it at where part */
- log_assert(where != NULL);
- memmove(where, &when, sizeof(when));
- memmove(where+sizeof(when), &p, sizeof(p));
- memmove(where+sizeof(when)+sizeof(p), &len, sizeof(len));
- memmove(where+sizeof(when)+sizeof(p)+sizeof(len),
- sldns_buffer_begin(pkt), len);
-}
-
-/** see if the ringbuffer is empty */
-static int
-ring_empty(struct ringbuf* r)
-{
- return (r->low == r->high);
-}
-
-/** peek at timevalue for next item in ring */
-static struct timeval*
-ring_peek_time(struct ringbuf* r)
-{
- if(ring_empty(r))
- return NULL;
- return (struct timeval*)&r->buf[r->low];
-}
-
-/** get entry from ringbuffer */
-static int
-ring_pop(struct ringbuf* r, sldns_buffer* pkt, struct timeval* tv,
- struct proxy** p)
-{
- /* time -- proxy* -- 16bitlen -- message */
- uint16_t len;
- uint8_t* where = NULL;
- size_t done;
- if(r->low == r->high)
- return 0;
- where = r->buf + r->low;
- memmove(tv, where, sizeof(*tv));
- memmove(p, where+sizeof(*tv), sizeof(*p));
- memmove(&len, where+sizeof(*tv)+sizeof(*p), sizeof(len));
- memmove(sldns_buffer_begin(pkt),
- where+sizeof(*tv)+sizeof(*p)+sizeof(len), len);
- sldns_buffer_set_limit(pkt, (size_t)len);
- done = sizeof(*tv)+sizeof(*p)+sizeof(len)+len;
- /* move lowmark */
- if(r->low < r->high) {
- /* used part in middle */
- log_assert(r->high - r->low >= done);
- r->low += done;
- } else {
- /* unused part in middle */
- log_assert(r->size - r->low >= done);
- r->low += done;
- if(r->size - r->low > sizeof(*tv)+sizeof(*p)) {
- /* see if it is zeroed; means end of buffer */
- struct proxy* pz;
- memmove(&pz, r->buf+r->low+sizeof(*tv), sizeof(pz));
- if(pz == NULL)
- r->low = 0;
- } else r->low = 0;
- }
- if(r->low == r->high) {
- r->low = 0; /* reset if empty */
- r->high = 0;
- }
- return 1;
-}
-
-/** signal handler global info */
-static volatile int do_quit = 0;
-
-/** signal handler for user quit */
-static RETSIGTYPE delayer_sigh(int sig)
-{
- printf("exit on signal %d\n", sig);
- do_quit = 1;
-}
-
-/** send out waiting packets */
-static void
-service_send(struct ringbuf* ring, struct timeval* now, sldns_buffer* pkt,
- struct sockaddr_storage* srv_addr, socklen_t srv_len)
-{
- struct proxy* p;
- struct timeval tv;
- ssize_t sent;
- while(!ring_empty(ring) &&
- dl_tv_smaller(ring_peek_time(ring), now)) {
- /* this items needs to be sent out */
- if(!ring_pop(ring, pkt, &tv, &p))
- fatal_exit("ringbuf error: pop failed");
- verbose(1, "send out query %d.%6.6d",
- (unsigned)tv.tv_sec, (unsigned)tv.tv_usec);
- log_addr(1, "from client", &p->addr, p->addr_len);
- /* send it */
- sent = sendto(p->s, (void*)sldns_buffer_begin(pkt),
- sldns_buffer_limit(pkt), 0,
- (struct sockaddr*)srv_addr, srv_len);
- if(sent == -1) {
-#ifndef USE_WINSOCK
- log_err("sendto: %s", strerror(errno));
-#else
- log_err("sendto: %s", wsa_strerror(WSAGetLastError()));
-#endif
- } else if(sent != (ssize_t)sldns_buffer_limit(pkt)) {
- log_err("sendto: partial send");
- }
- p->lastuse = *now;
- p->numsent++;
- }
-}
-
-/** do proxy for one readable client */
-static void
-do_proxy(struct proxy* p, int retsock, sldns_buffer* pkt)
-{
- int i;
- ssize_t r;
- for(i=0; i<TRIES_PER_SELECT; i++) {
- r = recv(p->s, (void*)sldns_buffer_begin(pkt),
- sldns_buffer_capacity(pkt), 0);
- if(r == -1) {
-#ifndef USE_WINSOCK
- if(errno == EAGAIN || errno == EINTR)
- return;
- log_err("recv: %s", strerror(errno));
-#else
- if(WSAGetLastError() == WSAEINPROGRESS ||
- WSAGetLastError() == WSAEWOULDBLOCK)
- return;
- log_err("recv: %s", wsa_strerror(WSAGetLastError()));
-#endif
- return;
- }
- sldns_buffer_set_limit(pkt, (size_t)r);
- log_addr(1, "return reply to client", &p->addr, p->addr_len);
- /* send reply back to the real client */
- p->numreturn++;
- r = sendto(retsock, (void*)sldns_buffer_begin(pkt), (size_t)r,
- 0, (struct sockaddr*)&p->addr, p->addr_len);
- if(r == -1) {
-#ifndef USE_WINSOCK
- log_err("sendto: %s", strerror(errno));
-#else
- log_err("sendto: %s", wsa_strerror(WSAGetLastError()));
-#endif
- }
- }
-}
-
-/** proxy return replies to clients */
-static void
-service_proxy(fd_set* rset, int retsock, struct proxy* proxies,
- sldns_buffer* pkt, struct timeval* now)
-{
- struct proxy* p;
- for(p = proxies; p; p = p->next) {
- if(FD_ISSET(p->s, rset)) {
- p->lastuse = *now;
- do_proxy(p, retsock, pkt);
- }
- }
-}
-
-/** find or else create proxy for this remote client */
-static struct proxy*
-find_create_proxy(struct sockaddr_storage* from, socklen_t from_len,
- fd_set* rorig, int* max, struct proxy** proxies, int serv_ip6,
- struct timeval* now, struct timeval* reuse_timeout)
-{
- struct proxy* p;
- struct timeval t;
- for(p = *proxies; p; p = p->next) {
- if(sockaddr_cmp(from, from_len, &p->addr, p->addr_len)==0)
- return p;
- }
- /* possibly: reuse lapsed entries */
- for(p = *proxies; p; p = p->next) {
- if(p->numwait > p->numsent || p->numsent > p->numreturn)
- continue;
- t = *now;
- dl_tv_subtract(&t, &p->lastuse);
- if(dl_tv_smaller(&t, reuse_timeout))
- continue;
- /* yes! */
- verbose(1, "reuse existing entry");
- memmove(&p->addr, from, from_len);
- p->addr_len = from_len;
- p->numreuse++;
- return p;
- }
- /* create new */
- p = (struct proxy*)calloc(1, sizeof(*p));
- if(!p) fatal_exit("out of memory");
- p->s = socket(serv_ip6?AF_INET6:AF_INET, SOCK_DGRAM, 0);
- if(p->s == -1) {
-#ifndef USE_WINSOCK
- fatal_exit("socket: %s", strerror(errno));
-#else
- fatal_exit("socket: %s", wsa_strerror(WSAGetLastError()));
-#endif
- }
- fd_set_nonblock(p->s);
- memmove(&p->addr, from, from_len);
- p->addr_len = from_len;
- p->next = *proxies;
- *proxies = p;
- FD_SET(FD_SET_T p->s, rorig);
- if(p->s+1 > *max)
- *max = p->s+1;
- return p;
-}
-
-/** recv new waiting packets */
-static void
-service_recv(int s, struct ringbuf* ring, sldns_buffer* pkt,
- fd_set* rorig, int* max, struct proxy** proxies,
- struct sockaddr_storage* srv_addr, socklen_t srv_len,
- struct timeval* now, struct timeval* delay, struct timeval* reuse)
-{
- int i;
- struct sockaddr_storage from;
- socklen_t from_len;
- ssize_t len;
- struct proxy* p;
- for(i=0; i<TRIES_PER_SELECT; i++) {
- from_len = (socklen_t)sizeof(from);
- len = recvfrom(s, (void*)sldns_buffer_begin(pkt),
- sldns_buffer_capacity(pkt), 0,
- (struct sockaddr*)&from, &from_len);
- if(len < 0) {
-#ifndef USE_WINSOCK
- if(errno == EAGAIN || errno == EINTR)
- return;
- fatal_exit("recvfrom: %s", strerror(errno));
-#else
- if(WSAGetLastError() == WSAEWOULDBLOCK ||
- WSAGetLastError() == WSAEINPROGRESS)
- return;
- fatal_exit("recvfrom: %s",
- wsa_strerror(WSAGetLastError()));
-#endif
- }
- sldns_buffer_set_limit(pkt, (size_t)len);
- /* find its proxy element */
- p = find_create_proxy(&from, from_len, rorig, max, proxies,
- addr_is_ip6(srv_addr, srv_len), now, reuse);
- if(!p) fatal_exit("error: cannot find or create proxy");
- p->lastuse = *now;
- ring_add(ring, pkt, now, delay, p);
- p->numwait++;
- log_addr(1, "recv from client", &p->addr, p->addr_len);
- }
-}
-
-/** delete tcp proxy */
-static void
-tcp_proxy_delete(struct tcp_proxy* p)
-{
- struct tcp_send_list* s, *sn;
- if(!p)
- return;
- log_addr(1, "delete tcp proxy", &p->addr, p->addr_len);
- s = p->querylist;
- while(s) {
- sn = s->next;
- free(s->item);
- free(s);
- s = sn;
- }
- s = p->answerlist;
- while(s) {
- sn = s->next;
- free(s->item);
- free(s);
- s = sn;
- }
-#ifndef USE_WINSOCK
- close(p->client_s);
- if(p->server_s != -1)
- close(p->server_s);
-#else
- closesocket(p->client_s);
- if(p->server_s != -1)
- closesocket(p->server_s);
-#endif
- free(p);
-}
-
-/** accept new TCP connections, and set them up */
-static void
-service_tcp_listen(int s, fd_set* rorig, int* max, struct tcp_proxy** proxies,
- struct sockaddr_storage* srv_addr, socklen_t srv_len,
- struct timeval* now, struct timeval* tcp_timeout)
-{
- int newfd;
- struct sockaddr_storage addr;
- struct tcp_proxy* p;
- socklen_t addr_len;
- newfd = accept(s, (struct sockaddr*)&addr, &addr_len);
- if(newfd == -1) {
-#ifndef USE_WINSOCK
- if(errno == EAGAIN || errno == EINTR)
- return;
- fatal_exit("accept: %s", strerror(errno));
-#else
- if(WSAGetLastError() == WSAEWOULDBLOCK ||
- WSAGetLastError() == WSAEINPROGRESS ||
- WSAGetLastError() == WSAECONNRESET)
- return;
- fatal_exit("accept: %s", wsa_strerror(WSAGetLastError()));
-#endif
- }
- p = (struct tcp_proxy*)calloc(1, sizeof(*p));
- if(!p) fatal_exit("out of memory");
- memmove(&p->addr, &addr, addr_len);
- p->addr_len = addr_len;
- log_addr(1, "new tcp proxy", &p->addr, p->addr_len);
- p->client_s = newfd;
- p->server_s = socket(addr_is_ip6(srv_addr, srv_len)?AF_INET6:AF_INET,
- SOCK_STREAM, 0);
- if(p->server_s == -1) {
-#ifndef USE_WINSOCK
- fatal_exit("tcp socket: %s", strerror(errno));
-#else
- fatal_exit("tcp socket: %s", wsa_strerror(WSAGetLastError()));
-#endif
- }
- fd_set_nonblock(p->client_s);
- fd_set_nonblock(p->server_s);
- if(connect(p->server_s, (struct sockaddr*)srv_addr, srv_len) == -1) {
-#ifndef USE_WINSOCK
- if(errno != EINPROGRESS) {
- log_err("tcp connect: %s", strerror(errno));
- close(p->server_s);
- close(p->client_s);
-#else
- if(WSAGetLastError() != WSAEWOULDBLOCK &&
- WSAGetLastError() != WSAEINPROGRESS) {
- log_err("tcp connect: %s",
- wsa_strerror(WSAGetLastError()));
- closesocket(p->server_s);
- closesocket(p->client_s);
-#endif
- free(p);
- return;
- }
- }
- p->timeout = *now;
- dl_tv_add(&p->timeout, tcp_timeout);
-
- /* listen to client and server */
- FD_SET(FD_SET_T p->client_s, rorig);
- FD_SET(FD_SET_T p->server_s, rorig);
- if(p->client_s+1 > *max)
- *max = p->client_s+1;
- if(p->server_s+1 > *max)
- *max = p->server_s+1;
-
- /* add into proxy list */
- p->next = *proxies;
- *proxies = p;
-}
-
-/** relay TCP, read a part */
-static int
-tcp_relay_read(int s, struct tcp_send_list** first,
- struct tcp_send_list** last, struct timeval* now,
- struct timeval* delay, sldns_buffer* pkt)
-{
- struct tcp_send_list* item;
- ssize_t r = recv(s, (void*)sldns_buffer_begin(pkt),
- sldns_buffer_capacity(pkt), 0);
- if(r == -1) {
-#ifndef USE_WINSOCK
- if(errno == EINTR || errno == EAGAIN)
- return 1;
- log_err("tcp read: %s", strerror(errno));
-#else
- if(WSAGetLastError() == WSAEINPROGRESS ||
- WSAGetLastError() == WSAEWOULDBLOCK)
- return 1;
- log_err("tcp read: %s", wsa_strerror(WSAGetLastError()));
-#endif
- return 0;
- } else if(r == 0) {
- /* connection closed */
- return 0;
- }
- item = (struct tcp_send_list*)malloc(sizeof(*item));
- if(!item) {
- log_err("out of memory");
- return 0;
- }
- verbose(1, "read item len %d", (int)r);
- item->len = (size_t)r;
- item->item = memdup(sldns_buffer_begin(pkt), item->len);
- if(!item->item) {
- free(item);
- log_err("out of memory");
- return 0;
- }
- item->done = 0;
- item->wait = *now;
- dl_tv_add(&item->wait, delay);
- item->next = NULL;
-
- /* link in */
- if(*first) {
- (*last)->next = item;
- } else {
- *first = item;
- }
- *last = item;
- return 1;
-}
-
-/** relay TCP, write a part */
-static int
-tcp_relay_write(int s, struct tcp_send_list** first,
- struct tcp_send_list** last, struct timeval* now)
-{
- ssize_t r;
- struct tcp_send_list* p;
- while(*first) {
- p = *first;
- /* is the item ready? */
- if(!dl_tv_smaller(&p->wait, now))
- return 1;
- /* write it */
- r = send(s, (void*)(p->item + p->done), p->len - p->done, 0);
- if(r == -1) {
-#ifndef USE_WINSOCK
- if(errno == EAGAIN || errno == EINTR)
- return 1;
- log_err("tcp write: %s", strerror(errno));
-#else
- if(WSAGetLastError() == WSAEWOULDBLOCK ||
- WSAGetLastError() == WSAEINPROGRESS)
- return 1;
- log_err("tcp write: %s",
- wsa_strerror(WSAGetLastError()));
-#endif
- return 0;
- } else if(r == 0) {
- /* closed */
- return 0;
- }
- /* account it */
- p->done += (size_t)r;
- verbose(1, "write item %d of %d", (int)p->done, (int)p->len);
- if(p->done >= p->len) {
- free(p->item);
- *first = p->next;
- if(!*first)
- *last = NULL;
- free(p);
- } else {
- /* partial write */
- return 1;
- }
- }
- return 1;
-}
-
-/** perform TCP relaying */
-static void
-service_tcp_relay(struct tcp_proxy** tcp_proxies, struct timeval* now,
- struct timeval* delay, struct timeval* tcp_timeout, sldns_buffer* pkt,
- fd_set* rset, fd_set* rorig, fd_set* worig)
-{
- struct tcp_proxy* p, **prev;
- struct timeval tout;
- int delete_it;
- p = *tcp_proxies;
- prev = tcp_proxies;
- tout = *now;
- dl_tv_add(&tout, tcp_timeout);
-
- while(p) {
- delete_it = 0;
- /* can we receive further queries? */
- if(!delete_it && FD_ISSET(p->client_s, rset)) {
- p->timeout = tout;
- log_addr(1, "read tcp query", &p->addr, p->addr_len);
- if(!tcp_relay_read(p->client_s, &p->querylist,
- &p->querylast, now, delay, pkt))
- delete_it = 1;
- }
- /* can we receive further answers? */
- if(!delete_it && p->server_s != -1 &&
- FD_ISSET(p->server_s, rset)) {
- p->timeout = tout;
- log_addr(1, "read tcp answer", &p->addr, p->addr_len);
- if(!tcp_relay_read(p->server_s, &p->answerlist,
- &p->answerlast, now, delay, pkt)) {
-#ifndef USE_WINSOCK
- close(p->server_s);
-#else
- closesocket(p->server_s);
-#endif
- FD_CLR(FD_SET_T p->server_s, worig);
- FD_CLR(FD_SET_T p->server_s, rorig);
- p->server_s = -1;
- }
- }
- /* can we send on further queries */
- if(!delete_it && p->querylist && p->server_s != -1) {
- p->timeout = tout;
- if(dl_tv_smaller(&p->querylist->wait, now))
- log_addr(1, "write tcp query",
- &p->addr, p->addr_len);
- if(!tcp_relay_write(p->server_s, &p->querylist,
- &p->querylast, now))
- delete_it = 1;
- if(p->querylist && p->server_s != -1 &&
- dl_tv_smaller(&p->querylist->wait, now))
- FD_SET(FD_SET_T p->server_s, worig);
- else FD_CLR(FD_SET_T p->server_s, worig);
- }
-
- /* can we send on further answers */
- if(!delete_it && p->answerlist) {
- p->timeout = tout;
- if(dl_tv_smaller(&p->answerlist->wait, now))
- log_addr(1, "write tcp answer",
- &p->addr, p->addr_len);
- if(!tcp_relay_write(p->client_s, &p->answerlist,
- &p->answerlast, now))
- delete_it = 1;
- if(p->answerlist && dl_tv_smaller(&p->answerlist->wait,
- now))
- FD_SET(FD_SET_T p->client_s, worig);
- else FD_CLR(FD_SET_T p->client_s, worig);
- if(!p->answerlist && p->server_s == -1)
- delete_it = 1;
- }
-
- /* does this entry timeout? (unused too long) */
- if(dl_tv_smaller(&p->timeout, now)) {
- delete_it = 1;
- }
- if(delete_it) {
- struct tcp_proxy* np = p->next;
- *prev = np;
- FD_CLR(FD_SET_T p->client_s, rorig);
- FD_CLR(FD_SET_T p->client_s, worig);
- if(p->server_s != -1) {
- FD_CLR(FD_SET_T p->server_s, rorig);
- FD_CLR(FD_SET_T p->server_s, worig);
- }
- tcp_proxy_delete(p);
- p = np;
- continue;
- }
-
- prev = &p->next;
- p = p->next;
- }
-}
-
-/** find waiting time */
-static int
-service_findwait(struct timeval* now, struct timeval* wait,
- struct ringbuf* ring, struct tcp_proxy* tcplist)
-{
- /* first item is the time to wait */
- struct timeval* peek = ring_peek_time(ring);
- struct timeval tcv;
- int have_tcpval = 0;
- struct tcp_proxy* p;
-
- /* also for TCP list the first in sendlists is the time to wait */
- for(p=tcplist; p; p=p->next) {
- if(!have_tcpval)
- tcv = p->timeout;
- have_tcpval = 1;
- if(dl_tv_smaller(&p->timeout, &tcv))
- tcv = p->timeout;
- if(p->querylist && dl_tv_smaller(&p->querylist->wait, &tcv))
- tcv = p->querylist->wait;
- if(p->answerlist && dl_tv_smaller(&p->answerlist->wait, &tcv))
- tcv = p->answerlist->wait;
- }
- if(peek) {
- /* peek can be unaligned */
- /* use wait as a temp variable */
- memmove(wait, peek, sizeof(*wait));
- if(!have_tcpval)
- tcv = *wait;
- else if(dl_tv_smaller(wait, &tcv))
- tcv = *wait;
- have_tcpval = 1;
- }
- if(have_tcpval) {
- *wait = tcv;
- dl_tv_subtract(wait, now);
- return 1;
- }
- /* nothing, block */
- return 0;
-}
-
-/** clear proxy list */
-static void
-proxy_list_clear(struct proxy* p)
-{
- char from[109];
- struct proxy* np;
- int i=0, port;
- while(p) {
- np = p->next;
- port = (int)ntohs(((struct sockaddr_in*)&p->addr)->sin_port);
- if(addr_is_ip6(&p->addr, p->addr_len)) {
- if(inet_ntop(AF_INET6,
- &((struct sockaddr_in6*)&p->addr)->sin6_addr,
- from, (socklen_t)sizeof(from)) == 0)
- (void)strlcpy(from, "err", sizeof(from));
- } else {
- if(inet_ntop(AF_INET,
- &((struct sockaddr_in*)&p->addr)->sin_addr,
- from, (socklen_t)sizeof(from)) == 0)
- (void)strlcpy(from, "err", sizeof(from));
- }
- printf("client[%d]: last %s@%d of %d : %u in, %u out, "
- "%u returned\n", i++, from, port, (int)p->numreuse+1,
- (unsigned)p->numwait, (unsigned)p->numsent,
- (unsigned)p->numreturn);
-#ifndef USE_WINSOCK
- close(p->s);
-#else
- closesocket(p->s);
-#endif
- free(p);
- p = np;
- }
-}
-
-/** clear TCP proxy list */
-static void
-tcp_proxy_list_clear(struct tcp_proxy* p)
-{
- struct tcp_proxy* np;
- while(p) {
- np = p->next;
- tcp_proxy_delete(p);
- p = np;
- }
-}
-
-/** delayer service loop */
-static void
-service_loop(int udp_s, int listen_s, struct ringbuf* ring,
- struct timeval* delay, struct timeval* reuse,
- struct sockaddr_storage* srv_addr, socklen_t srv_len,
- sldns_buffer* pkt)
-{
- fd_set rset, rorig;
- fd_set wset, worig;
- struct timeval now, wait;
- int max, have_wait = 0;
- struct proxy* proxies = NULL;
- struct tcp_proxy* tcp_proxies = NULL;
- struct timeval tcp_timeout;
- tcp_timeout.tv_sec = 120;
- tcp_timeout.tv_usec = 0;
-#ifndef S_SPLINT_S
- FD_ZERO(&rorig);
- FD_ZERO(&worig);
- FD_SET(FD_SET_T udp_s, &rorig);
- FD_SET(FD_SET_T listen_s, &rorig);
-#endif
- max = udp_s + 1;
- if(listen_s + 1 > max) max = listen_s + 1;
- while(!do_quit) {
- /* wait for events */
- rset = rorig;
- wset = worig;
- if(have_wait)
- verbose(1, "wait for %d.%6.6d",
- (unsigned)wait.tv_sec, (unsigned)wait.tv_usec);
- else verbose(1, "wait");
- if(select(max, &rset, &wset, NULL, have_wait?&wait:NULL) < 0) {
- if(errno == EAGAIN || errno == EINTR)
- continue;
- fatal_exit("select: %s", strerror(errno));
- }
- /* get current time */
- if(gettimeofday(&now, NULL) < 0) {
- if(errno == EAGAIN || errno == EINTR)
- continue;
- fatal_exit("gettimeofday: %s", strerror(errno));
- }
- verbose(1, "process at %u.%6.6u\n",
- (unsigned)now.tv_sec, (unsigned)now.tv_usec);
- /* sendout delayed queries to master server (frees up buffer)*/
- service_send(ring, &now, pkt, srv_addr, srv_len);
- /* proxy return replies */
- service_proxy(&rset, udp_s, proxies, pkt, &now);
- /* see what can be received to start waiting */
- service_recv(udp_s, ring, pkt, &rorig, &max, &proxies,
- srv_addr, srv_len, &now, delay, reuse);
- /* see if there are new tcp connections */
- service_tcp_listen(listen_s, &rorig, &max, &tcp_proxies,
- srv_addr, srv_len, &now, &tcp_timeout);
- /* service tcp connections */
- service_tcp_relay(&tcp_proxies, &now, delay, &tcp_timeout,
- pkt, &rset, &rorig, &worig);
- /* see what next timeout is (if any) */
- have_wait = service_findwait(&now, &wait, ring, tcp_proxies);
- }
- proxy_list_clear(proxies);
- tcp_proxy_list_clear(tcp_proxies);
-}
-
-/** delayer main service routine */
-static void
-service(const char* bind_str, int bindport, const char* serv_str,
- size_t memsize, int delay_msec)
-{
- struct sockaddr_storage bind_addr, srv_addr;
- socklen_t bind_len, srv_len;
- struct ringbuf* ring = ring_create(memsize);
- struct timeval delay, reuse;
- sldns_buffer* pkt;
- int i, s, listen_s;
-#ifndef S_SPLINT_S
- delay.tv_sec = delay_msec / 1000;
- delay.tv_usec = (delay_msec % 1000)*1000;
-#endif
- reuse = delay; /* reuse is max(4*delay, 1 second) */
- dl_tv_add(&reuse, &delay);
- dl_tv_add(&reuse, &delay);
- dl_tv_add(&reuse, &delay);
- if(reuse.tv_sec == 0)
- reuse.tv_sec = 1;
- if(!extstrtoaddr(serv_str, &srv_addr, &srv_len)) {
- printf("cannot parse forward address: %s\n", serv_str);
- exit(1);
- }
- pkt = sldns_buffer_new(65535);
- if(!pkt)
- fatal_exit("out of memory");
- if( signal(SIGINT, delayer_sigh) == SIG_ERR ||
-#ifdef SIGHUP
- signal(SIGHUP, delayer_sigh) == SIG_ERR ||
-#endif
-#ifdef SIGQUIT
- signal(SIGQUIT, delayer_sigh) == SIG_ERR ||
-#endif
-#ifdef SIGBREAK
- signal(SIGBREAK, delayer_sigh) == SIG_ERR ||
-#endif
-#ifdef SIGALRM
- signal(SIGALRM, delayer_sigh) == SIG_ERR ||
-#endif
- signal(SIGTERM, delayer_sigh) == SIG_ERR)
- fatal_exit("could not bind to signal");
- /* bind UDP port */
- if((s = socket(str_is_ip6(bind_str)?AF_INET6:AF_INET,
- SOCK_DGRAM, 0)) == -1) {
-#ifndef USE_WINSOCK
- fatal_exit("socket: %s", strerror(errno));
-#else
- fatal_exit("socket: %s", wsa_strerror(WSAGetLastError()));
-#endif
- }
- i=0;
- if(bindport == 0) {
- bindport = 1024 + arc4random()%64000;
- i = 100;
- }
- while(1) {
- if(!ipstrtoaddr(bind_str, bindport, &bind_addr, &bind_len)) {
- printf("cannot parse listen address: %s\n", bind_str);
- exit(1);
- }
- if(bind(s, (struct sockaddr*)&bind_addr, bind_len) == -1) {
-#ifndef USE_WINSOCK
- log_err("bind: %s", strerror(errno));
-#else
- log_err("bind: %s", wsa_strerror(WSAGetLastError()));
-#endif
- if(i--==0)
- fatal_exit("cannot bind any port");
- bindport = 1024 + arc4random()%64000;
- } else break;
- }
- fd_set_nonblock(s);
- /* and TCP port */
- if((listen_s = socket(str_is_ip6(bind_str)?AF_INET6:AF_INET,
- SOCK_STREAM, 0)) == -1) {
-#ifndef USE_WINSOCK
- fatal_exit("tcp socket: %s", strerror(errno));
-#else
- fatal_exit("tcp socket: %s", wsa_strerror(WSAGetLastError()));
-#endif
- }
-#ifdef SO_REUSEADDR
- if(1) {
- int on = 1;
- if(setsockopt(listen_s, SOL_SOCKET, SO_REUSEADDR, (void*)&on,
- (socklen_t)sizeof(on)) < 0)
-#ifndef USE_WINSOCK
- fatal_exit("setsockopt(.. SO_REUSEADDR ..) failed: %s",
- strerror(errno));
-#else
- fatal_exit("setsockopt(.. SO_REUSEADDR ..) failed: %s",
- wsa_strerror(WSAGetLastError()));
-#endif
- }
-#endif
- if(bind(listen_s, (struct sockaddr*)&bind_addr, bind_len) == -1) {
-#ifndef USE_WINSOCK
- fatal_exit("tcp bind: %s", strerror(errno));
-#else
- fatal_exit("tcp bind: %s", wsa_strerror(WSAGetLastError()));
-#endif
- }
- if(listen(listen_s, 5) == -1) {
-#ifndef USE_WINSOCK
- fatal_exit("tcp listen: %s", strerror(errno));
-#else
- fatal_exit("tcp listen: %s", wsa_strerror(WSAGetLastError()));
-#endif
- }
- fd_set_nonblock(listen_s);
- printf("listening on port: %d\n", bindport);
-
- /* process loop */
- do_quit = 0;
- service_loop(s, listen_s, ring, &delay, &reuse, &srv_addr, srv_len,
- pkt);
-
- /* cleanup */
- verbose(1, "cleanup");
-#ifndef USE_WINSOCK
- close(s);
- close(listen_s);
-#else
- closesocket(s);
- closesocket(listen_s);
-#endif
- sldns_buffer_free(pkt);
- ring_delete(ring);
-}
-
-/** getopt global, in case header files fail to declare it. */
-extern int optind;
-/** getopt global, in case header files fail to declare it. */
-extern char* optarg;
-
-/** main program for delayer */
-int main(int argc, char** argv)
-{
- int c; /* defaults */
- const char* server = "127.0.0.1@53";
- const char* bindto = "0.0.0.0";
- int bindport = 0;
- size_t memsize = 10*1024*1024;
- int delay = 100;
-
- verbosity = 0;
- log_init(0, 0, 0);
- log_ident_set("delayer");
- if(argc == 1) usage(argv);
- while( (c=getopt(argc, argv, "b:d:f:hm:p:")) != -1) {
- switch(c) {
- case 'b':
- bindto = optarg;
- break;
- case 'd':
- if(atoi(optarg)==0 && strcmp(optarg,"0")!=0) {
- printf("bad delay: %s\n", optarg);
- return 1;
- }
- delay = atoi(optarg);
- break;
- case 'f':
- server = optarg;
- break;
- case 'm':
- if(!cfg_parse_memsize(optarg, &memsize)) {
- printf("bad memsize: %s\n", optarg);
- return 1;
- }
- break;
- case 'p':
- if(atoi(optarg)==0 && strcmp(optarg,"0")!=0) {
- printf("bad port nr: %s\n", optarg);
- return 1;
- }
- bindport = atoi(optarg);
- break;
- case 'h':
- case '?':
- default:
- usage(argv);
- }
- }
- argc -= optind;
- argv += optind;
- if(argc != 0)
- usage(argv);
-
- printf("bind to %s @ %d and forward to %s after %d msec\n",
- bindto, bindport, server, delay);
- service(bindto, bindport, server, memsize, delay);
- return 0;
-}
diff --git a/external/unbound/testcode/do-tests.sh b/external/unbound/testcode/do-tests.sh
deleted file mode 100755
index e356d4fc3..000000000
--- a/external/unbound/testcode/do-tests.sh
+++ /dev/null
@@ -1,63 +0,0 @@
-#!/usr/bin/env bash
-. testdata/common.sh
-
-NEED_SPLINT='00-lint.tpkg'
-NEED_DOXYGEN='01-doc.tpkg'
-NEED_XXD='fwd_compress_c00c.tpkg fwd_zero.tpkg'
-NEED_NC='fwd_compress_c00c.tpkg fwd_zero.tpkg'
-NEED_CURL='06-ianaports.tpkg root_anchor.tpkg'
-NEED_WHOAMI='07-confroot.tpkg'
-NEED_IPV6='fwd_ancil.tpkg fwd_tcp_tc6.tpkg stub_udp6.tpkg edns_cache.tpkg'
-NEED_NOMINGW='tcp_sigpipe.tpkg 07-confroot.tpkg 08-host-lib.tpkg fwd_ancil.tpkg'
-NEED_DNSCRYPT_PROXY='dnscrypt_queries.tpkg'
-
-# test if dig and ldns-testns are available.
-test_tool_avail "dig"
-test_tool_avail "ldns-testns"
-
-# test for ipv6, uses streamtcp peculiarity.
-if ./streamtcp -f ::1 2>&1 | grep "not supported" >/dev/null 2>&1; then
- HAVE_IPV6=no
-else
- HAVE_IPV6=yes
-fi
-
-# test mingw. no signals and so on.
-if uname | grep MINGW >/dev/null; then
- HAVE_MINGW=yes
-else
- HAVE_MINGW=no
-fi
-
-cd testdata;
-sh ../testcode/mini_tpkg.sh clean
-rm -f .perfstats.txt
-for test in `ls *.tpkg`; do
- SKIP=0
- skip_if_in_list $test "$NEED_SPLINT" "splint"
- skip_if_in_list $test "$NEED_DOXYGEN" "doxygen"
- skip_if_in_list $test "$NEED_CURL" "curl"
- skip_if_in_list $test "$NEED_XXD" "xxd"
- skip_if_in_list $test "$NEED_NC" "nc"
- skip_if_in_list $test "$NEED_WHOAMI" "whoami"
- skip_if_in_list $test "$NEED_DNSCRYPT_PROXY" "dnscrypt-proxy"
-
- if echo $NEED_IPV6 | grep $test >/dev/null; then
- if test "$HAVE_IPV6" = no; then
- SKIP=1;
- fi
- fi
- if echo $NEED_NOMINGW | grep $test >/dev/null; then
- if test "$HAVE_MINGW" = yes; then
- SKIP=1;
- fi
- fi
- if test $SKIP -eq 0; then
- echo $test
- sh ../testcode/mini_tpkg.sh -a ../.. exe $test
- else
- echo "skip $test"
- fi
-done
-sh ../testcode/mini_tpkg.sh report
-cat .perfstats.txt
diff --git a/external/unbound/testcode/fake_event.c b/external/unbound/testcode/fake_event.c
deleted file mode 100644
index 154013a8c..000000000
--- a/external/unbound/testcode/fake_event.c
+++ /dev/null
@@ -1,1423 +0,0 @@
-/*
- * testcode/fake_event.c - fake event handling that replays existing scenario.
- *
- * 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 COPYRIGHT
- * HOLDER 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
- * Event service that replays a scenario.
- * This implements the same exported symbols as the files:
- * util/netevent.c
- * services/listen_dnsport.c
- * services/outside_network.c
- * But these do not actually access the network or events, instead
- * the scenario is played.
- */
-
-#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 "util/data/dname.h"
-#include "util/config_file.h"
-#include "services/listen_dnsport.h"
-#include "services/outside_network.h"
-#include "services/cache/infra.h"
-#include "testcode/replay.h"
-#include "testcode/testpkts.h"
-#include "util/log.h"
-#include "util/fptr_wlist.h"
-#include "sldns/sbuffer.h"
-#include "sldns/wire2str.h"
-#include "sldns/str2wire.h"
-#include <signal.h>
-struct worker;
-struct daemon_remote;
-
-/** Global variable: the scenario. Saved here for when event_init is done. */
-static struct replay_scenario* saved_scenario = NULL;
-
-/** add timers and the values do not overflow or become negative */
-static void
-timeval_add(struct timeval* d, const struct timeval* add)
-{
-#ifndef S_SPLINT_S
- d->tv_sec += add->tv_sec;
- d->tv_usec += add->tv_usec;
- if(d->tv_usec > 1000000) {
- d->tv_usec -= 1000000;
- d->tv_sec++;
- }
-#endif
-}
-
-void
-fake_temp_file(const char* adj, const char* id, char* buf, size_t len)
-{
-#ifdef USE_WINSOCK
- snprintf(buf, len, "testbound_%u%s%s.tmp",
- (unsigned)getpid(), adj, id);
-#else
- snprintf(buf, len, "/tmp/testbound_%u%s%s.tmp",
- (unsigned)getpid(), adj, id);
-#endif
-}
-
-void
-fake_event_init(struct replay_scenario* scen)
-{
- saved_scenario = scen;
-}
-
-void
-fake_event_cleanup(void)
-{
- replay_scenario_delete(saved_scenario);
- saved_scenario = NULL;
-}
-
-/** helper function that logs a sldns_pkt packet to logfile */
-static void
-log_pkt(const char* desc, uint8_t* pkt, size_t len)
-{
- char* str = sldns_wire2str_pkt(pkt, len);
- if(!str)
- fatal_exit("%s: (failed out of memory wire2str_pkt)", desc);
- else {
- log_info("%s%s", desc, str);
- free(str);
- }
-}
-
-/**
- * Returns a string describing the event type.
- */
-static const char*
-repevt_string(enum replay_event_type t)
-{
- switch(t) {
- case repevt_nothing: return "NOTHING";
- case repevt_front_query: return "QUERY";
- case repevt_front_reply: return "CHECK_ANSWER";
- case repevt_timeout: return "TIMEOUT";
- case repevt_time_passes: return "TIME_PASSES";
- case repevt_back_reply: return "REPLY";
- case repevt_back_query: return "CHECK_OUT_QUERY";
- case repevt_autotrust_check: return "CHECK_AUTOTRUST";
- case repevt_error: return "ERROR";
- case repevt_assign: return "ASSIGN";
- case repevt_traffic: return "TRAFFIC";
- case repevt_infra_rtt: return "INFRA_RTT";
- default: return "UNKNOWN";
- }
-}
-
-/** delete a fake pending */
-static void
-delete_fake_pending(struct fake_pending* pend)
-{
- if(!pend)
- return;
- free(pend->zone);
- sldns_buffer_free(pend->buffer);
- free(pend->pkt);
- free(pend);
-}
-
-/** delete a replay answer */
-static void
-delete_replay_answer(struct replay_answer* a)
-{
- if(!a)
- return;
- if(a->repinfo.c) {
- sldns_buffer_free(a->repinfo.c->buffer);
- free(a->repinfo.c);
- }
- free(a->pkt);
- free(a);
-}
-
-/**
- * return: true if pending query matches the now event.
- */
-static int
-pending_matches_current(struct replay_runtime* runtime,
- struct entry** entry, struct fake_pending **pend)
-{
- struct fake_pending* p;
- struct entry* e;
- if(!runtime->now || runtime->now->evt_type != repevt_back_query
- || !runtime->pending_list)
- 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->pkt_len,
- p->transport))) {
- *entry = e;
- *pend = p;
- return 1;
- }
- }
- return 0;
-}
-
-/**
- * Find the range that matches this pending message.
- * @param runtime: runtime with current moment, and range list.
- * @param entry: returns the pointer to entry that matches.
- * @param pend: the pending that the entry must match.
- * @return: true if a match is found.
- */
-static int
-pending_find_match(struct replay_runtime* runtime, struct entry** entry,
- struct fake_pending* pend)
-{
- int timenow = runtime->now->time_step;
- 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->pkt_len,
- 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(0, "matched ip", &p->addr, p->addrlen);
- log_pkt("matched pkt: ",
- (*entry)->reply_list->reply_pkt,
- (*entry)->reply_list->reply_len);
- return 1;
- }
- p = p->next_range;
- }
- return 0;
-}
-
-/**
- * See if outgoing pending query matches an entry.
- * @param runtime: runtime.
- * @param entry: if true, the entry that matches is returned.
- * @param pend: if true, the outgoing message that matches is returned.
- * @return: true if pending query matches the now event.
- */
-static int
-pending_matches_range(struct replay_runtime* runtime,
- struct entry** entry, struct fake_pending** pend)
-{
- 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;
- }
- p = p->next;
- }
- return 0;
-}
-
-/**
- * Remove the item from the pending list.
- */
-static void
-pending_list_delete(struct replay_runtime* runtime, struct fake_pending* pend)
-{
- struct fake_pending** prev = &runtime->pending_list;
- struct fake_pending* p = runtime->pending_list;
-
- while(p) {
- if(p == pend) {
- *prev = p->next;
- delete_fake_pending(pend);
- return;
- }
-
- prev = &p->next;
- p = p->next;
- }
-}
-
-/**
- * Fill buffer with reply from the entry.
- */
-static void
-fill_buffer_with_reply(sldns_buffer* buffer, struct entry* entry, uint8_t* q,
- size_t qlen)
-{
- uint8_t* c;
- size_t clen;
- log_assert(entry && entry->reply_list);
- sldns_buffer_clear(buffer);
- if(entry->reply_list->reply_from_hex) {
- c = sldns_buffer_begin(entry->reply_list->reply_from_hex);
- clen = sldns_buffer_limit(entry->reply_list->reply_from_hex);
- if(!c) fatal_exit("out of memory");
- } else {
- c = entry->reply_list->reply_pkt;
- clen = entry->reply_list->reply_len;
- }
- if(c) {
- if(q) adjust_packet(entry, &c, &clen, q, qlen);
- sldns_buffer_write(buffer, c, clen);
- if(q) free(c);
- }
- sldns_buffer_flip(buffer);
-}
-
-/**
- * Perform range entry on pending message.
- * @param runtime: runtime buffer size preference.
- * @param entry: entry that codes for the reply to do.
- * @param pend: pending query that is answered, callback called.
- */
-static void
-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_type* cb = pend->callback;
-
- memset(&c, 0, sizeof(c));
- c.fd = -1;
- c.buffer = sldns_buffer_new(runtime->bufsize);
- c.type = comm_udp;
- if(pend->transport == transport_tcp)
- c.type = comm_tcp;
- fill_buffer_with_reply(c.buffer, entry, pend->pkt, pend->pkt_len);
- 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)) {
- fatal_exit("testbound: unexpected: callback returned 1");
- }
- sldns_buffer_free(c.buffer);
-}
-
-/** Check the now moment answer check event */
-static void
-answer_check_it(struct replay_runtime* runtime)
-{
- struct replay_answer* ans = runtime->answer_list,
- *prev = NULL;
- log_assert(runtime && runtime->now &&
- runtime->now->evt_type == repevt_front_reply);
- while(ans) {
- 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,
- ans->pkt_len, tr)) {
- log_info("testbound matched event entry from line %d",
- runtime->now->match->lineno);
- log_info("testbound: do STEP %d %s",
- runtime->now->time_step,
- repevt_string(runtime->now->evt_type));
- if(prev)
- prev->next = ans->next;
- else runtime->answer_list = ans->next;
- if(!ans->next)
- runtime->answer_last = prev;
- delete_replay_answer(ans);
- return;
- } else {
- prev = ans;
- ans = ans->next;
- }
- }
- log_info("testbound: do STEP %d %s", runtime->now->time_step,
- repevt_string(runtime->now->evt_type));
- fatal_exit("testbound: not matched");
-}
-
-/**
- * Create commpoint (as return address) for a fake incoming query.
- */
-static void
-fake_front_query(struct replay_runtime* runtime, struct replay_moment *todo)
-{
- struct comm_reply repinfo;
- 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 = sldns_buffer_new(runtime->bufsize);
- if(todo->match->match_transport == transport_tcp)
- repinfo.c->type = comm_tcp;
- else repinfo.c->type = comm_udp;
- fill_buffer_with_reply(repinfo.c->buffer, todo->match, NULL, 0);
- log_info("testbound: incoming QUERY");
- log_pkt("query pkt", todo->match->reply_list->reply_pkt,
- todo->match->reply_list->reply_len);
- /* call the callback for incoming queries */
- if((*runtime->callback_query)(repinfo.c, runtime->cb_arg,
- NETEVENT_NOERROR, &repinfo)) {
- /* send immediate reply */
- comm_point_send_reply(&repinfo);
- }
- /* clear it again, in case copy not done properly */
- memset(&repinfo, 0, sizeof(repinfo));
-}
-
-/**
- * Perform callback for fake pending message.
- */
-static void
-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;
- void* cb_arg;
- comm_point_callback_type* cb;
-
- memset(&c, 0, sizeof(c));
- if(!p) fatal_exit("No pending queries.");
- cb_arg = p->cb_arg;
- cb = p->callback;
- c.buffer = sldns_buffer_new(runtime->bufsize);
- c.type = comm_udp;
- if(p->transport == transport_tcp)
- c.type = comm_tcp;
- if(todo->evt_type == repevt_back_reply && todo->match) {
- fill_buffer_with_reply(c.buffer, todo->match, p->pkt,
- p->pkt_len);
- }
- repinfo.c = &c;
- repinfo.addrlen = p->addrlen;
- memcpy(&repinfo.addr, &p->addr, p->addrlen);
- if(!p->serviced)
- pending_list_delete(runtime, p);
- if((*cb)(&c, cb_arg, error, &repinfo)) {
- fatal_exit("unexpected: pending callback returned 1");
- }
- /* delete the pending item. */
- sldns_buffer_free(c.buffer);
-}
-
-/** pass time */
-static void
-moment_assign(struct replay_runtime* runtime, struct replay_moment* mom)
-{
- char* value = macro_process(runtime->vars, runtime, mom->string);
- if(!value)
- fatal_exit("could not process macro step %d", mom->time_step);
- log_info("assign %s = %s", mom->variable, value);
- if(!macro_assign(runtime->vars, mom->variable, value))
- fatal_exit("out of memory storing macro");
- free(value);
- if(verbosity >= VERB_ALGO)
- macro_print_debug(runtime->vars);
-}
-
-/** pass time */
-static void
-time_passes(struct replay_runtime* runtime, struct replay_moment* mom)
-{
- struct fake_timer *t;
- struct timeval tv = mom->elapse;
- if(mom->string) {
- char* xp = macro_process(runtime->vars, runtime, mom->string);
- double sec;
- if(!xp) fatal_exit("could not macro expand %s", mom->string);
- verbose(VERB_ALGO, "EVAL %s", mom->string);
- sec = atof(xp);
- free(xp);
-#ifndef S_SPLINT_S
- tv.tv_sec = sec;
- tv.tv_usec = (int)((sec - (double)tv.tv_sec) *1000000. + 0.5);
-#endif
- }
- timeval_add(&runtime->now_tv, &tv);
- runtime->now_secs = (time_t)runtime->now_tv.tv_sec;
-#ifndef S_SPLINT_S
- log_info("elapsed %d.%6.6d now %d.%6.6d",
- (int)tv.tv_sec, (int)tv.tv_usec,
- (int)runtime->now_tv.tv_sec, (int)runtime->now_tv.tv_usec);
-#endif
- /* see if any timers have fired; and run them */
- while( (t=replay_get_oldest_timer(runtime)) ) {
- t->enabled = 0;
- log_info("fake_timer callback");
- fptr_ok(fptr_whitelist_comm_timer(t->cb));
- (*t->cb)(t->cb_arg);
- }
-}
-
-/** check autotrust file contents */
-static void
-autotrust_check(struct replay_runtime* runtime, struct replay_moment* mom)
-{
- char name[1024], line[1024];
- FILE *in;
- int lineno = 0, oke=1;
- char* expanded;
- struct config_strlist* p;
- line[sizeof(line)-1] = 0;
- log_assert(mom->autotrust_id);
- fake_temp_file("_auto_", mom->autotrust_id, name, sizeof(name));
- in = fopen(name, "r");
- if(!in) fatal_exit("could not open %s: %s", name, strerror(errno));
- for(p=mom->file_content; p; p=p->next) {
- lineno++;
- if(!fgets(line, (int)sizeof(line)-1, in)) {
- log_err("autotrust check failed, could not read line");
- log_err("file %s, line %d", name, lineno);
- log_err("should be: %s", p->str);
- fatal_exit("autotrust_check failed");
- }
- if(line[0]) line[strlen(line)-1] = 0; /* remove newline */
- expanded = macro_process(runtime->vars, runtime, p->str);
- if(!expanded)
- fatal_exit("could not expand macro line %d", lineno);
- if(verbosity >= 7 && strcmp(p->str, expanded) != 0)
- log_info("expanded '%s' to '%s'", p->str, expanded);
- if(strcmp(expanded, line) != 0) {
- log_err("mismatch in file %s, line %d", name, lineno);
- log_err("file has : %s", line);
- log_err("should be: %s", expanded);
- free(expanded);
- oke = 0;
- continue;
- }
- free(expanded);
- fprintf(stderr, "%s:%2d ok : %s\n", name, lineno, line);
- }
- if(fgets(line, (int)sizeof(line)-1, in)) {
- log_err("autotrust check failed, extra lines in %s after %d",
- name, lineno);
- do {
- fprintf(stderr, "file has: %s", line);
- } while(fgets(line, (int)sizeof(line)-1, in));
- oke = 0;
- }
- fclose(in);
- if(!oke)
- fatal_exit("autotrust_check STEP %d failed", mom->time_step);
- log_info("autotrust %s is OK", mom->autotrust_id);
-}
-
-/** Store RTT in infra cache */
-static void
-do_infra_rtt(struct replay_runtime* runtime)
-{
- struct replay_moment* now = runtime->now;
- int rto;
- size_t dplen = 0;
- uint8_t* dp = sldns_str2wire_dname(now->variable, &dplen);
- if(!dp) fatal_exit("cannot parse %s", now->variable);
- rto = infra_rtt_update(runtime->infra, &now->addr, now->addrlen,
- dp, dplen, LDNS_RR_TYPE_A, atoi(now->string),
- -1, runtime->now_secs);
- log_addr(0, "INFRA_RTT for", &now->addr, now->addrlen);
- log_info("INFRA_RTT(%s roundtrip %d): rto of %d", now->variable,
- atoi(now->string), rto);
- if(rto == 0) fatal_exit("infra_rtt_update failed");
- free(dp);
-}
-
-/** perform exponential backoff on the timeout */
-static void
-expon_timeout_backoff(struct replay_runtime* runtime)
-{
- struct fake_pending* p = runtime->pending_list;
- int rtt, vs;
- uint8_t edns_lame_known;
- int last_rtt, rto;
- if(!p) return; /* no pending packet to backoff */
- if(!infra_host(runtime->infra, &p->addr, p->addrlen, p->zone,
- p->zonelen, runtime->now_secs, &vs, &edns_lame_known, &rtt))
- return;
- last_rtt = rtt;
- rto = infra_rtt_update(runtime->infra, &p->addr, p->addrlen, p->zone,
- p->zonelen, p->qtype, -1, last_rtt, runtime->now_secs);
- log_info("infra_rtt_update returned rto %d", rto);
-}
-
-/**
- * Advance to the next moment.
- */
-static void
-advance_moment(struct replay_runtime* runtime)
-{
- if(!runtime->now)
- runtime->now = runtime->scenario->mom_first;
- else runtime->now = runtime->now->mom_next;
-}
-
-/**
- * Perform actions or checks determined by the moment.
- * Also advances the time by one step.
- * @param runtime: scenario runtime information.
- */
-static void
-do_moment_and_advance(struct replay_runtime* runtime)
-{
- struct replay_moment* mom;
- if(!runtime->now) {
- advance_moment(runtime);
- return;
- }
- log_info("testbound: do STEP %d %s", runtime->now->time_step,
- repevt_string(runtime->now->evt_type));
- switch(runtime->now->evt_type) {
- case repevt_nothing:
- advance_moment(runtime);
- break;
- case repevt_front_query:
- /* advance moment before doing the step, so that the next
- moment which may check some result of the mom step
- can catch those results. */
- mom = runtime->now;
- advance_moment(runtime);
- fake_front_query(runtime, mom);
- break;
- case repevt_front_reply:
- if(runtime->answer_list)
- log_err("testbound: There are unmatched answers.");
- fatal_exit("testbound: query answer not matched");
- break;
- case repevt_timeout:
- mom = runtime->now;
- advance_moment(runtime);
- expon_timeout_backoff(runtime);
- fake_pending_callback(runtime, mom, NETEVENT_TIMEOUT);
- break;
- case repevt_back_reply:
- mom = runtime->now;
- advance_moment(runtime);
- fake_pending_callback(runtime, mom, NETEVENT_NOERROR);
- break;
- case repevt_back_query:
- /* Back queries are matched when they are sent out. */
- log_err("No query matching the current moment was sent.");
- fatal_exit("testbound: back query not matched");
- break;
- case repevt_error:
- mom = runtime->now;
- advance_moment(runtime);
- fake_pending_callback(runtime, mom, NETEVENT_CLOSED);
- break;
- case repevt_time_passes:
- time_passes(runtime, runtime->now);
- advance_moment(runtime);
- break;
- case repevt_autotrust_check:
- autotrust_check(runtime, runtime->now);
- advance_moment(runtime);
- break;
- case repevt_assign:
- moment_assign(runtime, runtime->now);
- advance_moment(runtime);
- break;
- case repevt_traffic:
- advance_moment(runtime);
- break;
- case repevt_infra_rtt:
- do_infra_rtt(runtime);
- advance_moment(runtime);
- break;
- default:
- fatal_exit("testbound: unknown event type %d",
- runtime->now->evt_type);
- }
-}
-
-/** run the scenario in event callbacks */
-static void
-run_scenario(struct replay_runtime* runtime)
-{
- struct entry* entry = NULL;
- struct fake_pending* pending = NULL;
- int max_rounds = 5000;
- int rounds = 0;
- runtime->now = runtime->scenario->mom_first;
- log_info("testbound: entering fake runloop");
- do {
- /* if moment matches pending query do it. */
- /* else if moment matches given answer, do it */
- /* else if precoded_range matches pending, do it */
- /* else do the current moment */
- if(pending_matches_current(runtime, &entry, &pending)) {
- log_info("testbound: do STEP %d CHECK_OUT_QUERY",
- runtime->now->time_step);
- advance_moment(runtime);
- if(entry->copy_id)
- answer_callback_from_entry(runtime, entry,
- pending);
- } else if(runtime->answer_list && runtime->now &&
- runtime->now->evt_type == repevt_front_reply) {
- answer_check_it(runtime);
- advance_moment(runtime);
- } else if(pending_matches_range(runtime, &entry, &pending)) {
- answer_callback_from_entry(runtime, entry, pending);
- } else {
- do_moment_and_advance(runtime);
- }
- log_info("testbound: end of event stage");
- rounds++;
- if(rounds > max_rounds)
- fatal_exit("testbound: too many rounds, it loops.");
- } 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, p->pkt_len);
- log_addr(0, "pending to", &p->addr, p->addrlen);
- }
- fatal_exit("testbound: there are still messages pending.");
- }
- if(runtime->answer_list) {
- fatal_exit("testbound: there are unmatched answers.");
- }
- log_info("testbound: exiting fake runloop.");
- runtime->exit_cleanly = 1;
-}
-
-/*********** Dummy routines ***********/
-
-struct listen_dnsport*
-listen_create(struct comm_base* base, struct listen_port* ATTR_UNUSED(ports),
- size_t bufsize, int ATTR_UNUSED(tcp_accept_count),
- void* ATTR_UNUSED(sslctx), struct dt_env* ATTR_UNUSED(dtenv),
- comm_point_callback_type* cb, void* cb_arg)
-{
- struct replay_runtime* runtime = (struct replay_runtime*)base;
- struct listen_dnsport* l= calloc(1, sizeof(struct listen_dnsport));
- if(!l)
- return NULL;
- l->base = base;
- l->udp_buff = sldns_buffer_new(bufsize);
- if(!l->udp_buff) {
- free(l);
- return NULL;
- }
- runtime->callback_query = cb;
- runtime->cb_arg = cb_arg;
- runtime->bufsize = bufsize;
- return l;
-}
-
-void
-listen_delete(struct listen_dnsport* listen)
-{
- if(!listen)
- return;
- sldns_buffer_free(listen->udp_buff);
- free(listen);
-}
-
-struct comm_base*
-comm_base_create(int ATTR_UNUSED(sigs))
-{
- /* we return the runtime structure instead. */
- struct replay_runtime* runtime = (struct replay_runtime*)
- calloc(1, sizeof(struct replay_runtime));
- runtime->scenario = saved_scenario;
- runtime->vars = macro_store_create();
- if(!runtime->vars) fatal_exit("out of memory");
- return (struct comm_base*)runtime;
-}
-
-void
-comm_base_delete(struct comm_base* b)
-{
- struct replay_runtime* runtime = (struct replay_runtime*)b;
- struct fake_pending* p, *np;
- struct replay_answer* a, *na;
- struct fake_timer* t, *nt;
- if(!runtime)
- return;
- runtime->scenario= NULL;
- p = runtime->pending_list;
- while(p) {
- np = p->next;
- delete_fake_pending(p);
- p = np;
- }
- a = runtime->answer_list;
- while(a) {
- na = a->next;
- delete_replay_answer(a);
- a = na;
- }
- t = runtime->timer_list;
- while(t) {
- nt = t->next;
- free(t);
- t = nt;
- }
- macro_store_delete(runtime->vars);
- free(runtime);
-}
-
-void
-comm_base_timept(struct comm_base* b, time_t** tt, struct timeval** tv)
-{
- struct replay_runtime* runtime = (struct replay_runtime*)b;
- *tt = &runtime->now_secs;
- *tv = &runtime->now_tv;
-}
-
-void
-comm_base_dispatch(struct comm_base* b)
-{
- struct replay_runtime* runtime = (struct replay_runtime*)b;
- run_scenario(runtime);
- if(runtime->sig_cb)
- (*runtime->sig_cb)(SIGTERM, runtime->sig_cb_arg);
- else exit(0); /* OK exit when LIBEVENT_SIGNAL_PROBLEM exists */
-}
-
-void
-comm_base_exit(struct comm_base* b)
-{
- struct replay_runtime* runtime = (struct replay_runtime*)b;
- if(!runtime->exit_cleanly) {
- /* some sort of failure */
- fatal_exit("testbound: comm_base_exit was called.");
- }
-}
-
-struct comm_signal*
-comm_signal_create(struct comm_base* base,
- void (*callback)(int, void*), void* cb_arg)
-{
- struct replay_runtime* runtime = (struct replay_runtime*)base;
- runtime->sig_cb = callback;
- runtime->sig_cb_arg = cb_arg;
- return calloc(1, sizeof(struct comm_signal));
-}
-
-int
-comm_signal_bind(struct comm_signal* ATTR_UNUSED(comsig), int
- ATTR_UNUSED(sig))
-{
- return 1;
-}
-
-void
-comm_signal_delete(struct comm_signal* comsig)
-{
- free(comsig);
-}
-
-void
-comm_point_send_reply(struct comm_reply* repinfo)
-{
- struct replay_answer* ans = (struct replay_answer*)calloc(1,
- sizeof(struct replay_answer));
- struct replay_runtime* runtime = (struct replay_runtime*)repinfo->c->ev;
- log_info("testbound: comm_point_send_reply fake");
- /* dump it into the todo list */
- log_assert(ans);
- memcpy(&ans->repinfo, repinfo, sizeof(struct comm_reply));
- ans->next = NULL;
- if(runtime->answer_last)
- runtime->answer_last->next = ans;
- else runtime->answer_list = ans;
- runtime->answer_last = ans;
-
- /* try to parse packet */
- ans->pkt = memdup(sldns_buffer_begin(ans->repinfo.c->buffer),
- sldns_buffer_limit(ans->repinfo.c->buffer));
- ans->pkt_len = sldns_buffer_limit(ans->repinfo.c->buffer);
- if(!ans->pkt) fatal_exit("out of memory");
- log_pkt("reply pkt: ", ans->pkt, ans->pkt_len);
-}
-
-void
-comm_point_drop_reply(struct comm_reply* repinfo)
-{
- log_info("comm_point_drop_reply fake");
- if(repinfo->c) {
- sldns_buffer_free(repinfo->c->buffer);
- free(repinfo->c);
- }
-}
-
-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), size_t ATTR_UNUSED(num_tcp),
- struct infra_cache* infra,
- struct ub_randstate* ATTR_UNUSED(rnd),
- int ATTR_UNUSED(use_caps_for_id), int* ATTR_UNUSED(availports),
- int ATTR_UNUSED(numavailports), size_t ATTR_UNUSED(unwanted_threshold),
- int ATTR_UNUSED(outgoing_tcp_mss),
- void (*unwanted_action)(void*), void* ATTR_UNUSED(unwanted_param),
- int ATTR_UNUSED(do_udp), void* ATTR_UNUSED(sslctx),
- int ATTR_UNUSED(delayclose), struct dt_env* ATTR_UNUSED(dtenv))
-{
- struct replay_runtime* runtime = (struct replay_runtime*)base;
- struct outside_network* outnet = calloc(1,
- sizeof(struct outside_network));
- (void)unwanted_action;
- if(!outnet)
- return NULL;
- runtime->infra = infra;
- outnet->base = base;
- outnet->udp_buff = sldns_buffer_new(bufsize);
- if(!outnet->udp_buff) {
- free(outnet);
- return NULL;
- }
- return outnet;
-}
-
-void
-outside_network_delete(struct outside_network* outnet)
-{
- if(!outnet)
- return;
- sldns_buffer_free(outnet->udp_buff);
- free(outnet);
-}
-
-void
-outside_network_quit_prepare(struct outside_network* ATTR_UNUSED(outnet))
-{
-}
-
-struct pending*
-pending_udp_query(struct serviced_query* sq, sldns_buffer* packet,
- int timeout, comm_point_callback_type* callback, void* callback_arg)
-{
- struct replay_runtime* runtime = (struct replay_runtime*)
- sq->outnet->base;
- struct fake_pending* pend = (struct fake_pending*)calloc(1,
- sizeof(struct fake_pending));
- log_assert(pend);
- pend->buffer = sldns_buffer_new(sldns_buffer_capacity(packet));
- log_assert(pend->buffer);
- sldns_buffer_write(pend->buffer, sldns_buffer_begin(packet),
- sldns_buffer_limit(packet));
- sldns_buffer_flip(pend->buffer);
- memcpy(&pend->addr, &sq->addr, sq->addrlen);
- pend->addrlen = sq->addrlen;
- pend->callback = callback;
- pend->cb_arg = callback_arg;
- pend->timeout = timeout/1000;
- pend->transport = transport_udp;
- pend->pkt = NULL;
- pend->zone = NULL;
- pend->serviced = 0;
- pend->runtime = runtime;
- pend->pkt_len = sldns_buffer_limit(packet);
- pend->pkt = memdup(sldns_buffer_begin(packet), pend->pkt_len);
- if(!pend->pkt) fatal_exit("out of memory");
- log_pkt("pending udp pkt: ", pend->pkt, pend->pkt_len);
-
- /* 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->pkt_len,
- 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 pending*)pend;
-}
-
-struct waiting_tcp*
-pending_tcp_query(struct serviced_query* sq, sldns_buffer* packet,
- int timeout, comm_point_callback_type* callback, void* callback_arg)
-{
- struct replay_runtime* runtime = (struct replay_runtime*)
- sq->outnet->base;
- struct fake_pending* pend = (struct fake_pending*)calloc(1,
- sizeof(struct fake_pending));
- log_assert(pend);
- pend->buffer = sldns_buffer_new(sldns_buffer_capacity(packet));
- log_assert(pend->buffer);
- sldns_buffer_write(pend->buffer, sldns_buffer_begin(packet),
- sldns_buffer_limit(packet));
- sldns_buffer_flip(pend->buffer);
- memcpy(&pend->addr, &sq->addr, sq->addrlen);
- pend->addrlen = sq->addrlen;
- pend->callback = callback;
- pend->cb_arg = callback_arg;
- pend->timeout = timeout;
- pend->transport = transport_tcp;
- pend->pkt = NULL;
- pend->zone = NULL;
- pend->runtime = runtime;
- pend->serviced = 0;
- pend->pkt_len = sldns_buffer_limit(packet);
- pend->pkt = memdup(sldns_buffer_begin(packet), pend->pkt_len);
- if(!pend->pkt) fatal_exit("out of memory");
- log_pkt("pending tcp pkt: ", pend->pkt, pend->pkt_len);
-
- /* 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->pkt_len,
- 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,
- struct query_info* qinfo, uint16_t flags, int dnssec,
- int ATTR_UNUSED(want_dnssec), int ATTR_UNUSED(nocaps),
- int ATTR_UNUSED(tcp_upstream), int ATTR_UNUSED(ssl_upstream),
- struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
- size_t zonelen, struct module_qstate* qstate,
- comm_point_callback_type* callback, void* callback_arg,
- sldns_buffer* ATTR_UNUSED(buff), struct module_env* ATTR_UNUSED(env))
-{
- struct replay_runtime* runtime = (struct replay_runtime*)outnet->base;
- struct fake_pending* pend = (struct fake_pending*)calloc(1,
- sizeof(struct fake_pending));
- char z[256];
- log_assert(pend);
- log_nametypeclass(VERB_OPS, "pending serviced query",
- qinfo->qname, qinfo->qtype, qinfo->qclass);
- dname_str(zone, z);
- verbose(VERB_OPS, "pending serviced query zone %s flags%s%s%s%s",
- z, (flags&BIT_RD)?" RD":"", (flags&BIT_CD)?" CD":"",
- (flags&~(BIT_RD|BIT_CD))?" MORE":"", (dnssec)?" DO":"");
-
- /* create packet with EDNS */
- pend->buffer = sldns_buffer_new(512);
- log_assert(pend->buffer);
- sldns_buffer_write_u16(pend->buffer, 0); /* id */
- sldns_buffer_write_u16(pend->buffer, flags);
- sldns_buffer_write_u16(pend->buffer, 1); /* qdcount */
- sldns_buffer_write_u16(pend->buffer, 0); /* ancount */
- sldns_buffer_write_u16(pend->buffer, 0); /* nscount */
- sldns_buffer_write_u16(pend->buffer, 0); /* arcount */
- sldns_buffer_write(pend->buffer, qinfo->qname, qinfo->qname_len);
- sldns_buffer_write_u16(pend->buffer, qinfo->qtype);
- sldns_buffer_write_u16(pend->buffer, qinfo->qclass);
- sldns_buffer_flip(pend->buffer);
- if(1) {
- struct edns_data edns;
- if(!inplace_cb_query_call(env, qinfo, flags, addr, addrlen,
- zone, zonelen, qstate, qstate->region)) {
- free(pend);
- return NULL;
- }
- /* add edns */
- edns.edns_present = 1;
- edns.ext_rcode = 0;
- edns.edns_version = EDNS_ADVERTISED_VERSION;
- edns.udp_size = EDNS_ADVERTISED_SIZE;
- edns.bits = 0;
- edns.opt_list = qstate->edns_opts_back_out;
- if(dnssec)
- edns.bits = EDNS_DO;
- attach_edns_record(pend->buffer, &edns);
- }
- memcpy(&pend->addr, addr, addrlen);
- pend->addrlen = addrlen;
- pend->zone = memdup(zone, zonelen);
- pend->zonelen = zonelen;
- pend->qtype = (int)qinfo->qtype;
- log_assert(pend->zone);
- pend->callback = callback;
- pend->cb_arg = callback_arg;
- pend->timeout = UDP_AUTH_QUERY_TIMEOUT;
- pend->transport = transport_udp; /* pretend UDP */
- pend->pkt = NULL;
- pend->runtime = runtime;
- pend->serviced = 1;
- pend->pkt_len = sldns_buffer_limit(pend->buffer);
- pend->pkt = memdup(sldns_buffer_begin(pend->buffer), pend->pkt_len);
- if(!pend->pkt) fatal_exit("out of memory");
- /*log_pkt("pending serviced query: ", pend->pkt, pend->pkt_len);*/
-
- /* 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->pkt_len,
- 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);
- (void)cb_arg;
- log_info("serviced pending delete");
- if(prev)
- prev->next = p->next;
- else runtime->pending_list = p->next;
- sldns_buffer_free(p->buffer);
- free(p->pkt);
- free(p->zone);
- 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),
- int* ATTR_UNUSED(reuseport))
-{
- return calloc(1, 1);
-}
-
-void listening_ports_free(struct listen_port* list)
-{
- free(list);
-}
-
-struct comm_point* comm_point_create_local(struct comm_base* ATTR_UNUSED(base),
- int ATTR_UNUSED(fd), size_t ATTR_UNUSED(bufsize),
- comm_point_callback_type* ATTR_UNUSED(callback),
- void* ATTR_UNUSED(callback_arg))
-{
- return calloc(1, 1);
-}
-
-struct comm_point* comm_point_create_raw(struct comm_base* ATTR_UNUSED(base),
- int ATTR_UNUSED(fd), int ATTR_UNUSED(writing),
- comm_point_callback_type* ATTR_UNUSED(callback),
- void* ATTR_UNUSED(callback_arg))
-{
- /* no pipe comm possible */
- return calloc(1, 1);
-}
-
-void comm_point_start_listening(struct comm_point* ATTR_UNUSED(c),
- int ATTR_UNUSED(newfd), int ATTR_UNUSED(sec))
-{
- /* no bg write pipe comm possible */
-}
-
-void comm_point_stop_listening(struct comm_point* ATTR_UNUSED(c))
-{
- /* no bg write pipe comm possible */
-}
-
-/* only cmd com _local gets deleted */
-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;
-}
-
-size_t serviced_get_mem(struct serviced_query* ATTR_UNUSED(c))
-{
- return 0;
-}
-
-/* fake for fptr wlist */
-int outnet_udp_cb(struct comm_point* ATTR_UNUSED(c),
- void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
- struct comm_reply *ATTR_UNUSED(reply_info))
-{
- log_assert(0);
- return 0;
-}
-
-int outnet_tcp_cb(struct comm_point* ATTR_UNUSED(c),
- void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
- struct comm_reply *ATTR_UNUSED(reply_info))
-{
- log_assert(0);
- return 0;
-}
-
-void pending_udp_timer_cb(void *ATTR_UNUSED(arg))
-{
- log_assert(0);
-}
-
-void pending_udp_timer_delay_cb(void *ATTR_UNUSED(arg))
-{
- log_assert(0);
-}
-
-void outnet_tcptimer(void* ATTR_UNUSED(arg))
-{
- log_assert(0);
-}
-
-void comm_point_udp_callback(int ATTR_UNUSED(fd), short ATTR_UNUSED(event),
- void* ATTR_UNUSED(arg))
-{
- log_assert(0);
-}
-
-void comm_point_udp_ancil_callback(int ATTR_UNUSED(fd),
- short ATTR_UNUSED(event), void* ATTR_UNUSED(arg))
-{
- log_assert(0);
-}
-
-void comm_point_tcp_accept_callback(int ATTR_UNUSED(fd),
- short ATTR_UNUSED(event), void* ATTR_UNUSED(arg))
-{
- log_assert(0);
-}
-
-void comm_point_tcp_handle_callback(int ATTR_UNUSED(fd),
- short ATTR_UNUSED(event), void* ATTR_UNUSED(arg))
-{
- log_assert(0);
-}
-
-void comm_timer_callback(int ATTR_UNUSED(fd),
- short ATTR_UNUSED(event), void* ATTR_UNUSED(arg))
-{
- log_assert(0);
-}
-
-void comm_signal_callback(int ATTR_UNUSED(fd),
- short ATTR_UNUSED(event), void* ATTR_UNUSED(arg))
-{
- log_assert(0);
-}
-
-void comm_point_local_handle_callback(int ATTR_UNUSED(fd),
- short ATTR_UNUSED(event), void* ATTR_UNUSED(arg))
-{
- log_assert(0);
-}
-
-void comm_point_raw_handle_callback(int ATTR_UNUSED(fd),
- short ATTR_UNUSED(event), void* ATTR_UNUSED(arg))
-{
- log_assert(0);
-}
-
-void comm_base_handle_slow_accept(int ATTR_UNUSED(fd),
- short ATTR_UNUSED(event), void* ATTR_UNUSED(arg))
-{
- log_assert(0);
-}
-
-int serviced_udp_callback(struct comm_point* ATTR_UNUSED(c),
- void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
- struct comm_reply* ATTR_UNUSED(reply_info))
-{
- log_assert(0);
- return 0;
-}
-
-int serviced_tcp_callback(struct comm_point* ATTR_UNUSED(c),
- void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
- struct comm_reply* ATTR_UNUSED(reply_info))
-{
- log_assert(0);
- return 0;
-}
-
-int pending_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
-{
- log_assert(0);
- return 0;
-}
-
-int serviced_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
-{
- log_assert(0);
- return 0;
-}
-
-/* timers in testbound for autotrust. statistics tested in tpkg. */
-struct comm_timer* comm_timer_create(struct comm_base* base,
- void (*cb)(void*), void* cb_arg)
-{
- struct replay_runtime* runtime = (struct replay_runtime*)base;
- struct fake_timer* t = (struct fake_timer*)calloc(1, sizeof(*t));
- t->cb = cb;
- t->cb_arg = cb_arg;
- fptr_ok(fptr_whitelist_comm_timer(t->cb)); /* check in advance */
- t->runtime = runtime;
- t->next = runtime->timer_list;
- runtime->timer_list = t;
- return (struct comm_timer*)t;
-}
-
-void comm_timer_disable(struct comm_timer* timer)
-{
- struct fake_timer* t = (struct fake_timer*)timer;
- log_info("fake timer disabled");
- t->enabled = 0;
-}
-
-void comm_timer_set(struct comm_timer* timer, struct timeval* tv)
-{
- struct fake_timer* t = (struct fake_timer*)timer;
- t->enabled = 1;
- t->tv = *tv;
- log_info("fake timer set %d.%6.6d",
- (int)t->tv.tv_sec, (int)t->tv.tv_usec);
- timeval_add(&t->tv, &t->runtime->now_tv);
-}
-
-void comm_timer_delete(struct comm_timer* timer)
-{
- struct fake_timer* t = (struct fake_timer*)timer;
- struct fake_timer** pp, *p;
- if(!t) return;
-
- /* remove from linked list */
- pp = &t->runtime->timer_list;
- p = t->runtime->timer_list;
- while(p) {
- if(p == t) {
- /* snip from list */
- *pp = p->next;
- break;
- }
- pp = &p->next;
- p = p->next;
- }
-
- free(timer);
-}
-
-void comm_base_set_slow_accept_handlers(struct comm_base* ATTR_UNUSED(b),
- void (*stop_acc)(void*), void (*start_acc)(void*),
- void* ATTR_UNUSED(arg))
-{
- /* ignore this */
- (void)stop_acc;
- (void)start_acc;
-}
-
-struct ub_event_base* comm_base_internal(struct comm_base* ATTR_UNUSED(b))
-{
- /* no pipe comm possible in testbound */
- return NULL;
-}
-
-void daemon_remote_exec(struct worker* ATTR_UNUSED(worker))
-{
-}
-
-void listen_start_accept(struct listen_dnsport* ATTR_UNUSED(listen))
-{
-}
-
-void listen_stop_accept(struct listen_dnsport* ATTR_UNUSED(listen))
-{
-}
-
-void daemon_remote_start_accept(struct daemon_remote* ATTR_UNUSED(rc))
-{
-}
-
-void daemon_remote_stop_accept(struct daemon_remote* ATTR_UNUSED(rc))
-{
-}
-
-/*********** End of Dummy routines ***********/
diff --git a/external/unbound/testcode/fake_event.h b/external/unbound/testcode/fake_event.h
deleted file mode 100644
index 97ebb41cb..000000000
--- a/external/unbound/testcode/fake_event.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * testcode/fake_event.h - fake event handling that replays existing scenario.
- *
- * 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 COPYRIGHT
- * HOLDER 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
- * Event service that replays a scenario.
- * This implements the same exported symbols as the files:
- * util/netevent.c
- * services/listen_dnsport.c
- * services/outside_network.c
- * But these do not actually access the network or events, instead
- * the scenario is played.
- */
-
-#ifndef TESTCODE_FAKE_EVENT_H
-#define TESTCODE_FAKE_EVENT_H
-struct replay_scenario;
-
-/**
- * Initialise fake event services.
- *
- * The fake event services will automatically start when the main program
- * calls netevent.h functions, such as comm_base_dispatch().
- *
- * @param scen: Set the scenario to use for upcoming event handling.
- */
-void fake_event_init(struct replay_scenario* scen);
-
-/**
- * Deinit fake event services.
- */
-void fake_event_cleanup(void);
-
-/**
- * Get filename to store temporary config stuff. The pid is added. in /tmp.
- * @param adj: adjective, like "_cfg_", "_auto_"
- * @param id: identifier, like "example.com".
- * @param buf: where to store.
- * @param len: length of buf.
- */
-void fake_temp_file(const char* adj, const char* id, char* buf, size_t len);
-
-#endif /* TESTCODE_FAKE_EVENT_H */
diff --git a/external/unbound/testcode/lock_verify.c b/external/unbound/testcode/lock_verify.c
deleted file mode 100644
index 666a7029d..000000000
--- a/external/unbound/testcode/lock_verify.c
+++ /dev/null
@@ -1,426 +0,0 @@
-/*
- * testcode/lock_verify.c - verifier program for lock traces, checks order.
- *
- * 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 COPYRIGHT
- * HOLDER 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 checks the lock traces generated by checklock.c.
- * Checks if locks are consistently locked in the same order.
- * If not, this can lead to deadlock if threads execute the different
- * ordering at the same time.
- *
- */
-
-#include "config.h"
-#ifdef HAVE_TIME_H
-#include <time.h>
-#endif
-#include "util/log.h"
-#include "util/rbtree.h"
-#include "util/locks.h"
-#include "util/fptr_wlist.h"
-
-/* --- data structures --- */
-struct lock_ref;
-
-/** keep track of lock id in lock-verify application
- * Also defined in smallapp/worker_cb.c for fptr_wlist encapsulation
- * breakage (the security tests break encapsulation for this test app) */
-struct order_id {
- /** the thread id that created it */
- int thr;
- /** the instance number of creation */
- int instance;
-};
-
-/** a lock */
-struct order_lock {
- /** rbnode in all tree */
- rbnode_type node;
- /** lock id */
- struct order_id id;
- /** the creation file */
- char* create_file;
- /** creation line */
- int create_line;
- /** set of all locks that are smaller than this one (locked earlier) */
- rbtree_type* smaller;
- /** during depthfirstsearch, this is a linked list of the stack
- * of locks. points to the next lock bigger than this one. */
- struct lock_ref* dfs_next;
- /** if lock has been visited (all smaller locks have been compared to
- * this lock), only need to compare this with all unvisited(bigger)
- * locks */
- int visited;
-};
-
-/** reference to a lock in a rbtree set */
-struct lock_ref {
- /** rbnode, key is an order_id ptr */
- rbnode_type node;
- /** the lock referenced */
- struct order_lock* lock;
- /** why is this ref */
- char* file;
- /** line number */
- int line;
-};
-
-/** count of errors detected */
-static int errors_detected = 0;
-/** verbose? */
-static int verb = 0;
-
-/** print program usage help */
-static void
-usage(void)
-{
- printf("lock_verify <trace files>\n");
-}
-
-/** read header entry.
- * @param in: file to read header of.
- * @return: False if it does not belong to the rest. */
-static int
-read_header(FILE* in)
-{
- time_t t;
- pid_t p;
- int thrno;
- static int have_values = 0;
- static time_t the_time;
- static pid_t the_pid;
- static int threads[256];
-
- if(fread(&t, sizeof(t), 1, in) != 1 ||
- fread(&thrno, sizeof(thrno), 1, in) != 1 ||
- fread(&p, sizeof(p), 1, in) != 1) {
- fatal_exit("fread failed");
- }
- /* check these values are sorta OK */
- if(!have_values) {
- 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,
- (unsigned)p, ctime(&t));
- } else {
- if(the_pid != p) {
- printf(" has pid %u, not %u. Skipped.\n",
- (unsigned)p, (unsigned)the_pid);
- return 0;
- }
- if(threads[thrno])
- fatal_exit("same threadno in two files");
- threads[thrno] = 1;
- if( abs((int)(the_time - t)) > 3600)
- fatal_exit("input files from different times: %u %u",
- (unsigned)the_time, (unsigned)t);
- printf(" trace of thread %u:%d\n", (unsigned)p, thrno);
- }
- return 1;
-}
-
-/** max length of strings: filenames and function names. */
-#define STRMAX 1024
-/** read a string from file, false on error */
-static int readup_str(char** str, FILE* in)
-{
- char buf[STRMAX];
- int len = 0;
- int c;
- /* ends in zero */
- while( (c = fgetc(in)) != 0) {
- if(c == EOF)
- fatal_exit("eof in readstr, file too short");
- buf[len++] = c;
- if(len == STRMAX) {
- fatal_exit("string too long, bad file format");
- }
- }
- buf[len] = 0;
- *str = strdup(buf);
- return 1;
-}
-
-/** read creation entry */
-static void read_create(rbtree_type* all, FILE* in)
-{
- struct order_lock* o = calloc(1, sizeof(struct order_lock));
- if(!o) fatal_exit("malloc failure");
- if(fread(&o->id.thr, sizeof(int), 1, in) != 1 ||
- fread(&o->id.instance, sizeof(int), 1, in) != 1 ||
- !readup_str(&o->create_file, in) ||
- fread(&o->create_line, sizeof(int), 1, in) != 1)
- fatal_exit("fread failed");
- o->smaller = rbtree_create(order_lock_cmp);
- o->node.key = &o->id;
- if(!rbtree_insert(all, &o->node)) {
- /* already inserted */
- struct order_lock* a = (struct order_lock*)rbtree_search(all,
- &o->id);
- log_assert(a);
- a->create_file = o->create_file;
- a->create_line = o->create_line;
- free(o->smaller);
- free(o);
- o = a;
- }
- if(verb) printf("read create %u %u %s %d\n",
- (unsigned)o->id.thr, (unsigned)o->id.instance,
- o->create_file, o->create_line);
-}
-
-/** insert lock entry (empty) into list */
-static struct order_lock*
-insert_lock(rbtree_type* all, struct order_id* id)
-{
- struct order_lock* o = calloc(1, sizeof(struct order_lock));
- if(!o) fatal_exit("malloc failure");
- o->smaller = rbtree_create(order_lock_cmp);
- o->id = *id;
- o->node.key = &o->id;
- if(!rbtree_insert(all, &o->node))
- fatal_exit("insert fail should not happen");
- return o;
-}
-
-/** read lock entry */
-static void read_lock(rbtree_type* all, FILE* in, int val)
-{
- struct order_id prev_id, now_id;
- struct lock_ref* ref;
- struct order_lock* prev, *now;
- ref = (struct lock_ref*)calloc(1, sizeof(struct lock_ref));
- if(!ref) fatal_exit("malloc failure");
- prev_id.thr = val;
- if(fread(&prev_id.instance, sizeof(int), 1, in) != 1 ||
- fread(&now_id.thr, sizeof(int), 1, in) != 1 ||
- fread(&now_id.instance, sizeof(int), 1, in) != 1 ||
- !readup_str(&ref->file, in) ||
- fread(&ref->line, sizeof(int), 1, in) != 1)
- fatal_exit("fread failed");
- if(verb) printf("read lock %u %u %u %u %s %d\n",
- (unsigned)prev_id.thr, (unsigned)prev_id.instance,
- (unsigned)now_id.thr, (unsigned)now_id.instance,
- ref->file, ref->line);
- /* find the two locks involved */
- prev = (struct order_lock*)rbtree_search(all, &prev_id);
- now = (struct order_lock*)rbtree_search(all, &now_id);
- /* if not there - insert 'em */
- if(!prev) prev = insert_lock(all, &prev_id);
- if(!now) now = insert_lock(all, &now_id);
- ref->lock = prev;
- ref->node.key = &prev->id;
- if(!rbtree_insert(now->smaller, &ref->node)) {
- free(ref->file);
- free(ref);
- }
-}
-
-/** read input file */
-static void readinput(rbtree_type* all, char* file)
-{
- FILE *in = fopen(file, "r");
- int fst;
- if(!in) {
- perror(file);
- exit(1);
- }
- printf("file %s", file);
- if(!read_header(in)) {
- fclose(in);
- return;
- }
- while(fread(&fst, sizeof(fst), 1, in) == 1) {
- if(fst == -1)
- read_create(all, in);
- else read_lock(all, in, fst);
- }
- fclose(in);
-}
-
-/** print cycle message */
-static void found_cycle(struct lock_ref* visit, int level)
-{
- struct lock_ref* p;
- int i = 0;
- errors_detected++;
- printf("Found inconsistent locking order of length %d\n", level);
- printf("for lock %d %d created %s %d\n",
- visit->lock->id.thr, visit->lock->id.instance,
- visit->lock->create_file, visit->lock->create_line);
- printf("sequence is:\n");
- p = visit;
- while(p) {
- struct order_lock* next =
- p->lock->dfs_next?p->lock->dfs_next->lock:visit->lock;
- printf("[%d] is locked at line %s %d before lock %d %d\n",
- i, p->file, p->line, next->id.thr, next->id.instance);
- printf("[%d] lock %d %d is created at %s %d\n",
- i, next->id.thr, next->id.instance,
- next->create_file, next->create_line);
- i++;
- p = p->lock->dfs_next;
- if(p && p->lock == visit->lock)
- break;
- }
-}
-
-/** 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;
- while(p) {
- if(p->lock == visit->lock)
- return 1;
- p = p->lock->dfs_next;
- }
- return 0;
-}
-
-/** recursive function to depth first search for cycles.
- * @param visit: the lock visited at this step.
- * its dfs_next pointer gives the visited lock up in recursion.
- * same as lookfor at level 0.
- * @param level: depth of recursion. 0 is start.
- * @param from: search for matches from unvisited node upwards.
- */
-static void search_cycle(struct lock_ref* visit, int level,
- struct lock_ref* from)
-{
- struct lock_ref* ref;
- /* check for cycle */
- if(detect_cycle(visit, from) && level != 0) {
- found_cycle(visit, level);
- fatal_exit("found lock order cycle");
- }
- /* recurse */
- if(!visit->lock->visited)
- from = visit;
- if(verb > 1) fprintf(stderr, "[%d] visit lock %u %u %s %d\n", level,
- (unsigned)visit->lock->id.thr,
- (unsigned)visit->lock->id.instance,
- visit->lock->create_file, visit->lock->create_line);
- RBTREE_FOR(ref, struct lock_ref*, visit->lock->smaller) {
- ref->lock->dfs_next = visit;
- search_cycle(ref, level+1, from);
- }
- visit->lock->visited = 1;
-}
-
-/** Check ordering of one lock */
-static void check_order_lock(struct order_lock* lock)
-{
- struct lock_ref start;
- if(lock->visited) return;
-
- start.node.key = &lock->id;
- start.lock = lock;
- start.file = lock->create_file;
- start.line = lock->create_line;
-
- if(!lock->create_file)
- log_err("lock %u %u does not have create info",
- (unsigned)lock->id.thr, (unsigned)lock->id.instance);
-
- /* depth first search to find cycle with this lock at head */
- lock->dfs_next = NULL;
- search_cycle(&start, 0, &start);
-}
-
-/** Check ordering of locks */
-static void check_order(rbtree_type* all_locks)
-{
- /* check each lock */
- struct order_lock* lock;
- int i=0;
- RBTREE_FOR(lock, struct order_lock*, all_locks) {
- if(verb)
- printf("[%d/%d] Checking lock %d %d %s %d\n",
- 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)
- fprintf(stderr, ".");
- i++;
- check_order_lock(lock);
- }
- fprintf(stderr, "\n");
-}
-
-/** main program to verify all traces passed */
-int
-main(int argc, char* argv[])
-{
- rbtree_type* all_locks;
- int i;
- time_t starttime = time(NULL);
-#ifdef USE_THREAD_DEBUG
- /* do not overwrite the ublocktrace files with the ones generated
- * by this program (i.e. when the log code creates a lock) */
- check_locking_order = 0;
-#endif
- if(argc <= 1) {
- usage();
- return 1;
- }
- log_init(NULL, 0, NULL);
- log_ident_set("lock-verify");
- /* init */
- all_locks = rbtree_create(order_lock_cmp);
- errors_detected = 0;
-
- /* read the input files */
- for(i=1; i<argc; i++) {
- readinput(all_locks, argv[i]);
- }
-
- /* check ordering */
- check_order(all_locks);
-
- /* do not free a thing, OS will do it */
- printf("checked %d locks in %d seconds with %d errors.\n",
- (int)all_locks->count, (int)(time(NULL)-starttime),
- errors_detected);
- if(errors_detected) return 1;
- return 0;
-}
diff --git a/external/unbound/testcode/memstats.c b/external/unbound/testcode/memstats.c
deleted file mode 100644
index dc29058ad..000000000
--- a/external/unbound/testcode/memstats.c
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * testcode/memstats.c - debug tool to show memory allocation statistics.
- *
- * 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 COPYRIGHT
- * HOLDER 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 reads a log file and prints the memory allocation summed
- * up.
- */
-#include "config.h"
-#include "util/log.h"
-#include "util/rbtree.h"
-#include "util/locks.h"
-#include "util/fptr_wlist.h"
-#include <sys/stat.h>
-
-/**
- * The allocation statistics block
- */
-struct codeline {
- /** rbtree node */
- rbnode_type node;
- /** the name of the file:linenumber */
- char* codeline;
- /** the name of the function */
- char* func;
- /** number of bytes allocated */
- uint64_t alloc;
- /** number of bytes freed */
- uint64_t free;
- /** number allocations and frees */
- uint64_t calls;
-};
-
-/** print usage and exit */
-static void
-usage(void)
-{
- printf("usage: memstats <logfile>\n");
- printf("statistics are printed on stdout.\n");
- exit(1);
-}
-
-/** match logfile line to see if it needs accounting processing */
-static int
-match(char* line)
-{
- /* f.e.:
- * [1187340064] unbound[24604:0] info: ul/rb.c:81 r_create malloc(12)
- * 0123456789 123456789 123456789 123456789
- * But now also:
- * Sep 16 15:18:20 unbound[1:0] info: ul/nh.c:143 memdup malloc(11)
- */
- if(strlen(line) < 32) /* up to 'info: ' */
- return 0;
- if(!strstr(line, " info: "))
- return 0;
- if(strstr(line, "info: stat "))
- return 0; /* skip the hex dumps */
- if(strstr(line+30, "malloc("))
- return 1;
- else if(strstr(line+30, "calloc("))
- return 1;
- /* skip reallocs */
- return 0;
-}
-
-/** find or alloc codeline in tree */
-static struct codeline*
-get_codeline(rbtree_type* tree, char* key, char* func)
-{
- struct codeline* cl = (struct codeline*)rbtree_search(tree, key);
- if(!cl) {
- cl = calloc(1, sizeof(*cl));
- if(!cl) return 0;
- cl->codeline = strdup(key);
- if(!cl->codeline) return 0;
- cl->func = strdup(func);
- if(!cl->func) return 0;
- cl->alloc = 0;
- cl->node.key = cl->codeline;
- (void)rbtree_insert(tree, &cl->node);
- }
- return cl;
-}
-
-/** read up the malloc stats */
-static void
-read_malloc_stat(char* line, rbtree_type* tree)
-{
- char codeline[10240];
- char name[10240];
- int skip = 0;
- long num = 0;
- struct codeline* cl = 0;
- line = strstr(line, "info: ")+6;
- if(sscanf(line, "%s %s %n", codeline, name, &skip) != 2) {
- printf("%s\n", line);
- fatal_exit("unhandled malloc");
- }
- if(sscanf(line+skip+7, "%ld", &num) != 1) {
- printf("%s\n%s\n", line, line+skip+7);
- fatal_exit("unhandled malloc");
- }
- cl = get_codeline(tree, codeline, name);
- if(!cl)
- fatal_exit("alloc failure");
- cl->alloc += num;
- cl->calls ++;
-}
-
-/** read up the calloc stats */
-static void
-read_calloc_stat(char* line, rbtree_type* tree)
-{
- char codeline[10240];
- char name[10240];
- int skip = 0;
- long num = 0, sz = 0;
- struct codeline* cl = 0;
- line = strstr(line, "info: ")+6;
- if(sscanf(line, "%s %s %n", codeline, name, &skip) != 2) {
- printf("%s\n", line);
- fatal_exit("unhandled calloc");
- }
- if(sscanf(line+skip+7, "%ld, %ld", &num, &sz) != 2) {
- printf("%s\n%s\n", line, line+skip+7);
- fatal_exit("unhandled calloc");
- }
-
- cl = get_codeline(tree, codeline, name);
- if(!cl)
- fatal_exit("alloc failure");
- cl->alloc += num*sz;
- cl->calls ++;
-}
-
-/** get size of file */
-static off_t
-get_file_size(const char* fname)
-{
- struct stat s;
- if(stat(fname, &s) < 0) {
- fatal_exit("could not stat %s: %s", fname, strerror(errno));
- }
- return s.st_size;
-}
-
-/** read the logfile */
-static void
-readfile(rbtree_type* tree, const char* fname)
-{
- off_t total = get_file_size(fname);
- off_t done = (off_t)0;
- int report = 0;
- FILE* in = fopen(fname, "r");
- char buf[102400];
- if(!in)
- fatal_exit("could not open %s: %s", fname, strerror(errno));
- printf("Reading %s of size " ARG_LL "d\n", fname, (long long)total);
- while(fgets(buf, 102400, in)) {
- buf[102400-1] = 0;
- done += (off_t)strlen(buf);
- /* progress count */
- if((int)(((double)done / (double)total)*100.) > report) {
- report = (int)(((double)done / (double)total)*100.);
- fprintf(stderr, " %d%%", report);
- }
-
- if(!match(buf))
- continue;
- else if(strstr(buf+30, "malloc("))
- read_malloc_stat(buf, tree);
- else if(strstr(buf+30, "calloc("))
- read_calloc_stat(buf, tree);
- else {
- printf("%s\n", buf);
- fatal_exit("unhandled input");
- }
- }
- fprintf(stderr, " done\n");
- fclose(in);
-}
-
-/** print memory stats */
-static void
-printstats(rbtree_type* tree)
-{
- struct codeline* cl;
- uint64_t total = 0, tcalls = 0;
- RBTREE_FOR(cl, struct codeline*, tree) {
- printf("%12lld / %8lld in %s %s\n", (long long)cl->alloc,
- (long long)cl->calls, cl->codeline, cl->func);
- total += cl->alloc;
- tcalls += cl->calls;
- }
- printf("------------\n");
- printf("%12lld / %8lld total in %ld code lines\n", (long long)total,
- (long long)tcalls, (long)tree->count);
- printf("\n");
-}
-
-/** main program */
-int main(int argc, const char* argv[])
-{
- rbtree_type* tree = 0;
- log_init(NULL, 0, 0);
- if(argc != 2) {
- usage();
- }
- tree = rbtree_create(codeline_cmp);
- if(!tree)
- fatal_exit("alloc failure");
- readfile(tree, argv[1]);
- printstats(tree);
- return 0;
-}
diff --git a/external/unbound/testcode/mini_tpkg.sh b/external/unbound/testcode/mini_tpkg.sh
deleted file mode 100755
index ebf27a7d4..000000000
--- a/external/unbound/testcode/mini_tpkg.sh
+++ /dev/null
@@ -1,128 +0,0 @@
-# tpkg that only exes the files.
-args="../.."
-if test "$1" = "-a"; then
- args=$2
- shift
- shift
-fi
-
-if test "$1" = "clean"; then
- echo "rm -f result.* .done* .tpkg.var.master .tpkg.var.test"
- rm -f result.* .done* .tpkg.var.master .tpkg.var.test
- exit 0
-fi
-if test "$1" = "fake"; then
- echo "minitpkg fake $2"
- echo "fake" > .done-`basename $2 .tpkg`
- exit 0
-fi
-if test "$1" = "report" || test "$2" = "report"; then
- echo "Minitpkg Report"
- for result in *.tpkg; do
- name=`basename $result .tpkg`
- if test -f ".done-$name"; then
- if test "$1" != "-q"; then
- echo "** PASSED ** : $name"
- fi
- else
- if test -f "result.$name"; then
- echo "!! FAILED !! : $name"
- else
- echo ">> SKIPPED<< : $name"
- fi
- fi
- done
- exit 0
-fi
-
-if test "$1" != 'exe'; then
- # usage
- echo "mini tpkg. Reduced functionality for old shells."
- echo " tpkg exe <file>"
- echo " tpkg fake <file>"
- echo " tpkg clean"
- echo " tpkg [-q] report"
- exit 1
-fi
-shift
-
-# do not execute if the disk is too full
-#DISKLIMIT=100000
-# This check is not portable (to Solaris 10).
-#avail=`df . | tail -1 | awk '{print $4}'`
-#if test "$avail" -lt "$DISKLIMIT"; then
- #echo "minitpkg: The disk is too full! Only $avail."
- #exit 1
-#fi
-
-name=`basename $1 .tpkg`
-dir=$name.$$
-result=result.$name
-done=.done-$name
-success="no"
-if test -x "`which bash`"; then
- shell="bash"
-else
- shell="sh"
-fi
-
-# check already done
-if test -f .done-$name; then
- echo "minitpkg .done-$name exists. skip test."
- exit 0
-fi
-
-# Extract
-echo "minitpkg extract $1 to $dir"
-mkdir $dir
-gzip -cd $name.tpkg | (cd $dir; tar xf -)
-cd $dir
-mv $name.dir/* .
-
-# EXE
-echo "minitpkg exe $name" > $result
-grep "Description:" $name.dsc >> $result 2>&1
-echo "DateRunStart: "`date "+%s" 2>/dev/null` >> $result
-if test -f $name.pre; then
- echo "minitpkg exe $name.pre"
- echo "minitpkg exe $name.pre" >> $result
- $shell $name.pre $args >> $result
- if test $? -ne 0; then
- echo "Warning: $name.pre did not exit successfully"
- fi
-fi
-if test -f $name.test; then
- echo "minitpkg exe $name.test"
- echo "minitpkg exe $name.test" >> $result
- $shell $name.test $args >>$result 2>&1
- if test $? -ne 0; then
- echo "$name: FAILED" >> $result
- echo "$name: FAILED"
- success="no"
- else
- echo "$name: PASSED" >> $result
- echo "$name: PASSED" > ../.done-$name
- echo "$name: PASSED"
- success="yes"
- fi
-fi
-if test -f $name.post; then
- echo "minitpkg exe $name.post"
- echo "minitpkg exe $name.post" >> $result
- $shell $name.post $args >> $result
- if test $? -ne 0; then
- echo "Warning: $name.post did not exit successfully"
- fi
-fi
-echo "DateRunEnd: "`date "+%s" 2>/dev/null` >> $result
-
-mv $result ..
-cd ..
-rm -rf $dir
-# compat for windows where deletion may not succeed initially (files locked
-# by processes that still have to exit).
-if test $? -eq 1; then
- echo "minitpkg waiting for processes to terminate"
- sleep 2 # some time to exit, and try again
- rm -rf $dir
-fi
diff --git a/external/unbound/testcode/perf.c b/external/unbound/testcode/perf.c
deleted file mode 100644
index d11357c4a..000000000
--- a/external/unbound/testcode/perf.c
+++ /dev/null
@@ -1,654 +0,0 @@
-/*
- * testcode/perf.c - debug program to estimate name server performance.
- *
- * Copyright (c) 2008, 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 COPYRIGHT
- * HOLDER 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 estimates DNS name server performance.
- */
-
-#include "config.h"
-#ifdef HAVE_GETOPT_H
-#include <getopt.h>
-#endif
-#include <signal.h>
-#include "util/log.h"
-#include "util/locks.h"
-#include "util/net_help.h"
-#include "util/data/msgencode.h"
-#include "util/data/msgreply.h"
-#include "util/data/msgparse.h"
-#include "sldns/sbuffer.h"
-#include "sldns/wire2str.h"
-#include "sldns/str2wire.h"
-#include <sys/time.h>
-
-/** usage information for perf */
-static void usage(char* nm)
-{
- printf("usage: %s [options] server\n", nm);
- printf("server: ip address of server, IP4 or IP6.\n");
- printf(" If not on port %d add @port.\n", UNBOUND_DNS_PORT);
- printf("-d sec duration of test in whole seconds (0: wait for ^C)\n");
- printf("-a str query to ask, interpreted as a line from qfile\n");
- printf("-f fnm query list to read from file\n");
- printf(" every line has format: qname qclass qtype [+-]{E}\n");
- printf(" where + means RD set, E means EDNS enabled\n");
- printf("-q quiet mode, print only final qps\n");
- exit(1);
-}
-
-struct perfinfo;
-struct perfio;
-
-/** Global info for perf */
-struct perfinfo {
- /** need to exit */
- volatile int exit;
- /** all purpose buffer (for UDP send and receive) */
- sldns_buffer* buf;
-
- /** destination */
- struct sockaddr_storage dest;
- /** length of dest socket addr */
- socklen_t destlen;
-
- /** when did this time slice start */
- struct timeval since;
- /** number of queries received in that time */
- size_t numrecv;
- /** number of queries sent out in that time */
- size_t numsent;
-
- /** duration of test in seconds */
- int duration;
- /** quiet mode? */
- int quiet;
-
- /** when did the total test start */
- struct timeval start;
- /** total number recvd */
- size_t total_recv;
- /** total number sent */
- size_t total_sent;
- /** numbers by rcode */
- size_t by_rcode[32];
-
- /** number of I/O ports */
- size_t io_num;
- /** I/O ports array */
- struct perfio* io;
- /** max fd value in io ports */
- int maxfd;
- /** readset */
- fd_set rset;
-
- /** size of querylist */
- size_t qlist_size;
- /** allocated size of qlist array */
- size_t qlist_capacity;
- /** list of query packets (data) */
- uint8_t** qlist_data;
- /** list of query packets (length of a packet) */
- size_t* qlist_len;
- /** index into querylist, for walking the list */
- size_t qlist_idx;
-};
-
-/** I/O port for perf */
-struct perfio {
- /** id number */
- size_t id;
- /** file descriptor of socket */
- int fd;
- /** timeout value */
- struct timeval timeout;
- /** ptr back to perfinfo */
- struct perfinfo* info;
-};
-
-/** number of msec between starting io ports */
-#define START_IO_INTERVAL 10
-/** number of msec timeout on io ports */
-#define IO_TIMEOUT 10
-
-/** signal handler global info */
-static struct perfinfo* sig_info;
-
-/** signal handler for user quit */
-static RETSIGTYPE perf_sigh(int sig)
-{
- log_assert(sig_info);
- if(!sig_info->quiet)
- printf("exit on signal %d\n", sig);
- sig_info->exit = 1;
-}
-
-/** timeval compare, t1 < t2 */
-static int
-perf_tv_smaller(struct timeval* t1, struct timeval* t2)
-{
-#ifndef S_SPLINT_S
- if(t1->tv_sec < t2->tv_sec)
- return 1;
- if(t1->tv_sec == t2->tv_sec &&
- t1->tv_usec < t2->tv_usec)
- return 1;
-#endif
- return 0;
-}
-
-/** timeval add, t1 += t2 */
-static void
-perf_tv_add(struct timeval* t1, struct timeval* t2)
-{
-#ifndef S_SPLINT_S
- t1->tv_sec += t2->tv_sec;
- t1->tv_usec += t2->tv_usec;
- while(t1->tv_usec > 1000000) {
- t1->tv_usec -= 1000000;
- t1->tv_sec++;
- }
-#endif
-}
-
-/** timeval subtract, t1 -= t2 */
-static void
-perf_tv_subtract(struct timeval* t1, struct timeval* t2)
-{
-#ifndef S_SPLINT_S
- t1->tv_sec -= t2->tv_sec;
- if(t1->tv_usec >= t2->tv_usec) {
- t1->tv_usec -= t2->tv_usec;
- } else {
- t1->tv_sec--;
- t1->tv_usec = 1000000-(t2->tv_usec-t1->tv_usec);
- }
-#endif
-}
-
-
-/** setup perf test environment */
-static void
-perfsetup(struct perfinfo* info)
-{
- size_t i;
- if(gettimeofday(&info->start, NULL) < 0)
- fatal_exit("gettimeofday: %s", strerror(errno));
- sig_info = info;
- if( signal(SIGINT, perf_sigh) == SIG_ERR ||
-#ifdef SIGQUIT
- signal(SIGQUIT, perf_sigh) == SIG_ERR ||
-#endif
-#ifdef SIGHUP
- signal(SIGHUP, perf_sigh) == SIG_ERR ||
-#endif
-#ifdef SIGBREAK
- signal(SIGBREAK, perf_sigh) == SIG_ERR ||
-#endif
- signal(SIGTERM, perf_sigh) == SIG_ERR)
- fatal_exit("could not bind to signal");
- info->io = (struct perfio*)calloc(sizeof(struct perfio), info->io_num);
- if(!info->io) fatal_exit("out of memory");
-#ifndef S_SPLINT_S
- FD_ZERO(&info->rset);
-#endif
- info->since = info->start;
- for(i=0; i<info->io_num; i++) {
- info->io[i].id = i;
- info->io[i].info = info;
- info->io[i].fd = socket(
- addr_is_ip6(&info->dest, info->destlen)?
- AF_INET6:AF_INET, SOCK_DGRAM, 0);
- if(info->io[i].fd == -1) {
-#ifndef USE_WINSOCK
- fatal_exit("socket: %s", strerror(errno));
-#else
- fatal_exit("socket: %s",
- wsa_strerror(WSAGetLastError()));
-#endif
- }
- if(info->io[i].fd > info->maxfd)
- info->maxfd = info->io[i].fd;
-#ifndef S_SPLINT_S
- FD_SET(FD_SET_T info->io[i].fd, &info->rset);
- info->io[i].timeout.tv_usec = ((START_IO_INTERVAL*i)%1000)
- *1000;
- info->io[i].timeout.tv_sec = (START_IO_INTERVAL*i)/1000;
- perf_tv_add(&info->io[i].timeout, &info->since);
-#endif
- }
-}
-
-/** cleanup perf test environment */
-static void
-perffree(struct perfinfo* info)
-{
- size_t i;
- if(!info) return;
- if(info->io) {
- for(i=0; i<info->io_num; i++) {
-#ifndef USE_WINSOCK
- close(info->io[i].fd);
-#else
- closesocket(info->io[i].fd);
-#endif
- }
- free(info->io);
- }
- for(i=0; i<info->qlist_size; i++)
- free(info->qlist_data[i]);
- free(info->qlist_data);
- free(info->qlist_len);
-}
-
-/** send new query for io */
-static void
-perfsend(struct perfinfo* info, size_t n, struct timeval* now)
-{
- ssize_t r;
- r = sendto(info->io[n].fd, (void*)info->qlist_data[info->qlist_idx],
- info->qlist_len[info->qlist_idx], 0,
- (struct sockaddr*)&info->dest, info->destlen);
- /*log_hex("send", info->qlist_data[info->qlist_idx],
- info->qlist_len[info->qlist_idx]);*/
- if(r == -1) {
-#ifndef USE_WINSOCK
- log_err("sendto: %s", strerror(errno));
-#else
- log_err("sendto: %s", wsa_strerror(WSAGetLastError()));
-#endif
- } else if(r != (ssize_t)info->qlist_len[info->qlist_idx]) {
- log_err("partial sendto");
- }
- info->qlist_idx = (info->qlist_idx+1) % info->qlist_size;
- info->numsent++;
-
- info->io[n].timeout.tv_sec = IO_TIMEOUT/1000;
- info->io[n].timeout.tv_usec = (IO_TIMEOUT%1000)*1000;
- perf_tv_add(&info->io[n].timeout, now);
-}
-
-/** got reply for io */
-static void
-perfreply(struct perfinfo* info, size_t n, struct timeval* now)
-{
- ssize_t r;
- r = recv(info->io[n].fd, (void*)sldns_buffer_begin(info->buf),
- sldns_buffer_capacity(info->buf), 0);
- if(r == -1) {
-#ifndef USE_WINSOCK
- log_err("recv: %s", strerror(errno));
-#else
- log_err("recv: %s", wsa_strerror(WSAGetLastError()));
-#endif
- } else {
- info->by_rcode[LDNS_RCODE_WIRE(sldns_buffer_begin(
- info->buf))]++;
- info->numrecv++;
- }
- /*sldns_buffer_set_limit(info->buf, r);
- log_buf(0, "reply", info->buf);*/
- perfsend(info, n, now);
-}
-
-/** got timeout for io */
-static void
-perftimeout(struct perfinfo* info, size_t n, struct timeval* now)
-{
- /* may not be a dropped packet, this is also used to start
- * up the sending IOs */
- perfsend(info, n, now);
-}
-
-/** print nice stats about qps */
-static void
-stat_printout(struct perfinfo* info, struct timeval* now,
- struct timeval* elapsed)
-{
- /* calculate qps */
- double dt, qps = 0;
-#ifndef S_SPLINT_S
- dt = (double)(elapsed->tv_sec*1000000 + elapsed->tv_usec) / 1000000;
-#endif
- if(dt > 0.001)
- qps = (double)(info->numrecv) / dt;
- if(!info->quiet)
- printf("qps: %g\n", qps);
- /* setup next slice */
- info->since = *now;
- info->total_sent += info->numsent;
- info->total_recv += info->numrecv;
- info->numrecv = 0;
- info->numsent = 0;
-}
-
-/** wait for new events for performance test */
-static void
-perfselect(struct perfinfo* info)
-{
- fd_set rset = info->rset;
- struct timeval timeout, now;
- int num;
- size_t i;
- if(gettimeofday(&now, NULL) < 0)
- fatal_exit("gettimeofday: %s", strerror(errno));
- /* time to exit? */
- if(info->duration > 0) {
- timeout = now;
- perf_tv_subtract(&timeout, &info->start);
- if((int)timeout.tv_sec >= info->duration) {
- info->exit = 1;
- return;
- }
- }
- /* time for stats printout? */
- timeout = now;
- perf_tv_subtract(&timeout, &info->since);
- if(timeout.tv_sec > 0) {
- stat_printout(info, &now, &timeout);
- }
- /* see what is closest port to timeout; or if there is a timeout */
- timeout = info->io[0].timeout;
- for(i=0; i<info->io_num; i++) {
- if(perf_tv_smaller(&info->io[i].timeout, &now)) {
- perftimeout(info, i, &now);
- return;
- }
- if(perf_tv_smaller(&info->io[i].timeout, &timeout)) {
- timeout = info->io[i].timeout;
- }
- }
- perf_tv_subtract(&timeout, &now);
-
- num = select(info->maxfd+1, &rset, NULL, NULL, &timeout);
- if(num == -1) {
- if(errno == EAGAIN || errno == EINTR)
- return;
- log_err("select: %s", strerror(errno));
- }
-
- /* handle new events */
- for(i=0; num && i<info->io_num; i++) {
- if(FD_ISSET(info->io[i].fd, &rset)) {
- perfreply(info, i, &now);
- num--;
- }
- }
-}
-
-/** show end stats */
-static void
-perfendstats(struct perfinfo* info)
-{
- double dt, qps;
- struct timeval timeout, now;
- int i, lost;
- if(gettimeofday(&now, NULL) < 0)
- fatal_exit("gettimeofday: %s", strerror(errno));
- timeout = now;
- perf_tv_subtract(&timeout, &info->since);
- stat_printout(info, &now, &timeout);
-
- timeout = now;
- perf_tv_subtract(&timeout, &info->start);
- dt = (double)(timeout.tv_sec*1000000 + timeout.tv_usec) / 1000000.0;
- qps = (double)(info->total_recv) / dt;
- lost = (int)(info->total_sent - info->total_recv) - (int)info->io_num;
- if(!info->quiet) {
- printf("overall time: %g sec\n",
- (double)timeout.tv_sec +
- (double)timeout.tv_usec/1000000.);
- if(lost > 0)
- printf("Packets lost: %d\n", (int)lost);
-
- for(i=0; i<(int)(sizeof(info->by_rcode)/sizeof(size_t)); i++)
- {
- if(info->by_rcode[i] > 0) {
- char rc[16];
- sldns_wire2str_rcode_buf(i, rc, sizeof(rc));
- printf("%d(%5s): %u replies\n",
- i, rc, (unsigned)info->by_rcode[i]);
- }
- }
- }
- printf("average qps: %g\n", qps);
-}
-
-/** perform the performance test */
-static void
-perfmain(struct perfinfo* info)
-{
- perfsetup(info);
- while(!info->exit) {
- perfselect(info);
- }
- perfendstats(info);
- perffree(info);
-}
-
-/** parse a query line to a packet into buffer */
-static int
-qlist_parse_line(sldns_buffer* buf, char* p)
-{
- char nm[1024], cl[1024], tp[1024], fl[1024];
- int r;
- int rec = 1, edns = 0;
- struct query_info qinfo;
- nm[0] = 0; cl[0] = 0; tp[0] = 0; fl[0] = 0;
- r = sscanf(p, " %1023s %1023s %1023s %1023s", nm, cl, tp, fl);
- if(r != 3 && r != 4)
- return 0;
- /*printf("nm='%s', cl='%s', tp='%s', fl='%s'\n", nm, cl, tp, fl);*/
- if(strcmp(tp, "IN") == 0 || strcmp(tp, "CH") == 0) {
- qinfo.qtype = sldns_get_rr_type_by_name(cl);
- qinfo.qclass = sldns_get_rr_class_by_name(tp);
- } else {
- qinfo.qtype = sldns_get_rr_type_by_name(tp);
- qinfo.qclass = sldns_get_rr_class_by_name(cl);
- }
- if(fl[0] == '+') rec = 1;
- else if(fl[0] == '-') rec = 0;
- else if(fl[0] == 'E') edns = 1;
- if((fl[0] == '+' || fl[0] == '-') && fl[1] == 'E')
- edns = 1;
- qinfo.qname = sldns_str2wire_dname(nm, &qinfo.qname_len);
- if(!qinfo.qname)
- return 0;
- qinfo.local_alias = NULL;
- qinfo_query_encode(buf, &qinfo);
- sldns_buffer_write_u16_at(buf, 0, 0); /* zero ID */
- if(rec) LDNS_RD_SET(sldns_buffer_begin(buf));
- if(edns) {
- struct edns_data ed;
- memset(&ed, 0, sizeof(ed));
- ed.edns_present = 1;
- ed.udp_size = EDNS_ADVERTISED_SIZE;
- /* Set DO bit in all EDNS datagrams ... */
- ed.bits = EDNS_DO;
- attach_edns_record(buf, &ed);
- }
- free(qinfo.qname);
- return 1;
-}
-
-/** grow query list capacity */
-static void
-qlist_grow_capacity(struct perfinfo* info)
-{
- size_t newcap = (size_t)((info->qlist_capacity==0)?16:
- info->qlist_capacity*2);
- uint8_t** d = (uint8_t**)calloc(sizeof(uint8_t*), newcap);
- size_t* l = (size_t*)calloc(sizeof(size_t), newcap);
- if(!d || !l) fatal_exit("out of memory");
- memcpy(d, info->qlist_data, sizeof(uint8_t*)*
- info->qlist_capacity);
- memcpy(l, info->qlist_len, sizeof(size_t)*
- info->qlist_capacity);
- free(info->qlist_data);
- free(info->qlist_len);
- info->qlist_data = d;
- info->qlist_len = l;
- info->qlist_capacity = newcap;
-}
-
-/** setup query list in info */
-static void
-qlist_add_line(struct perfinfo* info, char* line, int no)
-{
- if(!qlist_parse_line(info->buf, line)) {
- printf("error parsing query %d: %s\n", no, line);
- exit(1);
- }
- sldns_buffer_write_u16_at(info->buf, 0, (uint16_t)info->qlist_size);
- if(info->qlist_size + 1 > info->qlist_capacity) {
- qlist_grow_capacity(info);
- }
- info->qlist_len[info->qlist_size] = sldns_buffer_limit(info->buf);
- info->qlist_data[info->qlist_size] = memdup(
- sldns_buffer_begin(info->buf), sldns_buffer_limit(info->buf));
- if(!info->qlist_data[info->qlist_size])
- fatal_exit("out of memory");
- info->qlist_size ++;
-}
-
-/** setup query list in info */
-static void
-qlist_read_file(struct perfinfo* info, char* fname)
-{
- char buf[1024];
- char *p;
- FILE* in = fopen(fname, "r");
- int lineno = 0;
- if(!in) {
- perror(fname);
- exit(1);
- }
- while(fgets(buf, (int)sizeof(buf), in)) {
- lineno++;
- buf[sizeof(buf)-1] = 0;
- p = buf;
- while(*p == ' ' || *p == '\t')
- p++;
- if(p[0] == 0 || p[0] == '\n' || p[0] == ';' || p[0] == '#')
- continue;
- qlist_add_line(info, p, lineno);
- }
- printf("Read %s, got %u queries\n", fname, (unsigned)info->qlist_size);
- fclose(in);
-}
-
-/** getopt global, in case header files fail to declare it. */
-extern int optind;
-/** getopt global, in case header files fail to declare it. */
-extern char* optarg;
-
-/** main program for perf */
-int main(int argc, char* argv[])
-{
- char* nm = argv[0];
- int c;
- struct perfinfo info;
-#ifdef USE_WINSOCK
- int r;
- WSADATA wsa_data;
-#endif
-
- /* defaults */
- memset(&info, 0, sizeof(info));
- info.io_num = 16;
-
- log_init(NULL, 0, NULL);
- log_ident_set("perf");
- checklock_start();
-#ifdef USE_WINSOCK
- if((r = WSAStartup(MAKEWORD(2,2), &wsa_data)) != 0)
- fatal_exit("WSAStartup failed: %s", wsa_strerror(r));
-#endif
-
- info.buf = sldns_buffer_new(65553);
- if(!info.buf) fatal_exit("out of memory");
-
- /* parse the options */
- while( (c=getopt(argc, argv, "d:ha:f:q")) != -1) {
- switch(c) {
- case 'q':
- info.quiet = 1;
- break;
- case 'd':
- if(atoi(optarg)==0 && strcmp(optarg, "0")!=0) {
- printf("-d not a number %s", optarg);
- return 1;
- }
- info.duration = atoi(optarg);
- break;
- case 'a':
- qlist_add_line(&info, optarg, 0);
- break;
- case 'f':
- qlist_read_file(&info, optarg);
- break;
- case '?':
- case 'h':
- default:
- usage(nm);
- }
- }
- argc -= optind;
- argv += optind;
-
- if(argc != 1) {
- printf("error: pass server IP address on commandline.\n");
- usage(nm);
- }
- if(!extstrtoaddr(argv[0], &info.dest, &info.destlen)) {
- printf("Could not parse ip: %s\n", argv[0]);
- return 1;
- }
- if(info.qlist_size == 0) {
- printf("No queries to make, use -f or -a.\n");
- return 1;
- }
-
- /* do the performance test */
- perfmain(&info);
-
- sldns_buffer_free(info.buf);
-#ifdef USE_WINSOCK
- WSACleanup();
-#endif
- checklock_stop();
- return 0;
-}
diff --git a/external/unbound/testcode/petal.c b/external/unbound/testcode/petal.c
deleted file mode 100644
index b30549365..000000000
--- a/external/unbound/testcode/petal.c
+++ /dev/null
@@ -1,669 +0,0 @@
-/*
- * petal.c - https daemon that is small and beautiful.
- *
- * Copyright (c) 2010, 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 COPYRIGHT
- * HOLDER 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
- *
- * HTTP1.1/SSL server.
- */
-
-#include "config.h"
-#ifdef HAVE_GETOPT_H
-#include <getopt.h>
-#endif
-#ifdef HAVE_OPENSSL_SSL_H
-#include <openssl/ssl.h>
-#endif
-#ifdef HAVE_OPENSSL_ERR_H
-#include <openssl/err.h>
-#endif
-#ifdef HAVE_OPENSSL_RAND_H
-#include <openssl/rand.h>
-#endif
-#include <openssl/x509.h>
-#include <openssl/pem.h>
-#include <ctype.h>
-#include <signal.h>
-#if defined(UNBOUND_ALLOC_LITE) || defined(UNBOUND_ALLOC_STATS)
-#ifdef malloc
-#undef malloc
-#endif
-#ifdef free
-#undef free
-#endif
-#endif /* alloc lite or alloc stats */
-
-/** verbosity for this application */
-static int verb = 0;
-
-/** Give petal usage, and exit (1). */
-static void
-usage(void)
-{
- printf("Usage: petal [opts]\n");
- printf(" https daemon serves files from ./'host'/filename\n");
- printf(" (no hostname: from the 'default' directory)\n");
- printf("-a addr bind to this address, 127.0.0.1\n");
- printf("-p port port number, default 443\n");
- printf("-k keyfile SSL private key file (PEM), petal.key\n");
- printf("-c certfile SSL certificate file (PEM), petal.pem\n");
- printf("-v more verbose\n");
- printf("-h show this usage help\n");
- printf("Version %s\n", PACKAGE_VERSION);
- printf("BSD licensed, see LICENSE in source package for details.\n");
- printf("Report bugs to %s\n", PACKAGE_BUGREPORT);
- exit(1);
-}
-
-/** fatal exit */
-static void print_exit(const char* str) {printf("error %s\n", str); exit(1);}
-/** print errno */
-static void log_errno(const char* str)
-{printf("error %s: %s\n", str, strerror(errno));}
-
-/** parse a text IP address into a sockaddr */
-static int
-parse_ip_addr(char* str, int port, struct sockaddr_storage* ret, socklen_t* l)
-{
- socklen_t len = 0;
- struct sockaddr_storage* addr = NULL;
- struct sockaddr_in6 a6;
- struct sockaddr_in a;
- uint16_t p = (uint16_t)port;
- int fam = 0;
- memset(&a6, 0, sizeof(a6));
- memset(&a, 0, sizeof(a));
-
- if(inet_pton(AF_INET6, str, &a6.sin6_addr) > 0) {
- /* it is an IPv6 */
- fam = AF_INET6;
- a6.sin6_family = AF_INET6;
- a6.sin6_port = (in_port_t)htons(p);
- addr = (struct sockaddr_storage*)&a6;
- len = (socklen_t)sizeof(struct sockaddr_in6);
- }
- if(inet_pton(AF_INET, str, &a.sin_addr) > 0) {
- /* it is an IPv4 */
- fam = AF_INET;
- a.sin_family = AF_INET;
- a.sin_port = (in_port_t)htons(p);
- addr = (struct sockaddr_storage*)&a;
- len = (socklen_t)sizeof(struct sockaddr_in);
- }
- if(!len) print_exit("cannot parse addr");
- *l = len;
- memmove(ret, addr, len);
- return fam;
-}
-
-/** close the fd */
-static void
-fd_close(int fd)
-{
-#ifndef USE_WINSOCK
- close(fd);
-#else
- closesocket(fd);
-#endif
-}
-
-/**
- * Read one line from SSL
- * zero terminates.
- * skips "\r\n" (but not copied to buf).
- * @param ssl: the SSL connection to read from (blocking).
- * @param buf: buffer to return line in.
- * @param len: size of the buffer.
- * @return 0 on error, 1 on success.
- */
-static int
-read_ssl_line(SSL* ssl, char* buf, size_t len)
-{
- size_t n = 0;
- int r;
- int endnl = 0;
- while(1) {
- if(n >= len) {
- if(verb) printf("line too long\n");
- return 0;
- }
- if((r = SSL_read(ssl, buf+n, 1)) <= 0) {
- if(SSL_get_error(ssl, r) == SSL_ERROR_ZERO_RETURN) {
- /* EOF */
- break;
- }
- if(verb) printf("could not SSL_read\n");
- return 0;
- }
- if(endnl && buf[n] == '\n') {
- break;
- } else if(endnl) {
- /* bad data */
- if(verb) printf("error: stray linefeeds\n");
- return 0;
- } else if(buf[n] == '\r') {
- /* skip \r, and also \n on the wire */
- endnl = 1;
- continue;
- } else if(buf[n] == '\n') {
- /* skip the \n, we are done */
- break;
- } else n++;
- }
- buf[n] = 0;
- return 1;
-}
-
-/** process one http header */
-static int
-process_one_header(char* buf, char* file, size_t flen, char* host, size_t hlen,
- int* vs)
-{
- if(strncasecmp(buf, "GET ", 4) == 0) {
- char* e = strstr(buf, " HTTP/1.1");
- if(!e) e = strstr(buf, " http/1.1");
- if(!e) {
- e = strstr(buf, " HTTP/1.0");
- if(!e) e = strstr(buf, " http/1.0");
- if(!e) e = strrchr(buf, ' ');
- if(!e) e = strrchr(buf, '\t');
- if(e) *vs = 10;
- }
- if(e) *e = 0;
- if(strlen(buf) < 4) return 0;
- (void)strlcpy(file, buf+4, flen);
- } else if(strncasecmp(buf, "Host: ", 6) == 0) {
- (void)strlcpy(host, buf+6, hlen);
- }
- return 1;
-}
-
-/** read http headers and process them */
-static int
-read_http_headers(SSL* ssl, char* file, size_t flen, char* host, size_t hlen,
- int* vs)
-{
- char buf[1024];
- file[0] = 0;
- host[0] = 0;
- while(read_ssl_line(ssl, buf, sizeof(buf))) {
- if(verb>=2) printf("read: %s\n", buf);
- if(buf[0] == 0)
- return 1;
- if(!process_one_header(buf, file, flen, host, hlen, vs))
- return 0;
- }
- return 0;
-}
-
-/** setup SSL context */
-static SSL_CTX*
-setup_ctx(char* key, char* cert)
-{
- SSL_CTX* ctx = SSL_CTX_new(SSLv23_server_method());
- if(!ctx) print_exit("out of memory");
- (void)SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2);
- (void)SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3);
- if(!SSL_CTX_use_certificate_chain_file(ctx, cert))
- print_exit("cannot read cert");
- if(!SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM))
- print_exit("cannot read key");
- if(!SSL_CTX_check_private_key(ctx))
- print_exit("private key is not correct");
-#if HAVE_DECL_SSL_CTX_SET_ECDH_AUTO
- if (!SSL_CTX_set_ecdh_auto(ctx,1))
- if(verb>=1) printf("failed to set_ecdh_auto, not enabling ECDHE\n");
-#elif defined(USE_ECDSA)
- if(1) {
- EC_KEY *ecdh = EC_KEY_new_by_curve_name (NID_X9_62_prime256v1);
- if (!ecdh) {
- if(verb>=1) printf("could not find p256, not enabling ECDHE\n");
- } else {
- if (1 != SSL_CTX_set_tmp_ecdh (ctx, ecdh)) {
- if(verb>=1) printf("Error in SSL_CTX_set_tmp_ecdh, not enabling ECDHE\n");
- }
- EC_KEY_free(ecdh);
- }
- }
-#endif
- if(!SSL_CTX_load_verify_locations(ctx, cert, NULL))
- print_exit("cannot load cert verify locations");
- return ctx;
-}
-
-/** setup listening TCP */
-static int
-setup_fd(char* addr, int port)
-{
- struct sockaddr_storage ad;
- socklen_t len;
- int fd;
- int c = 1;
- int fam = parse_ip_addr(addr, port, &ad, &len);
- fd = socket(fam, SOCK_STREAM, 0);
- if(fd == -1) {
- log_errno("socket");
- return -1;
- }
- if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
- (void*)&c, (socklen_t) sizeof(int)) < 0) {
- log_errno("setsockopt(SOL_SOCKET, SO_REUSEADDR)");
- }
- if(bind(fd, (struct sockaddr*)&ad, len) == -1) {
- log_errno("bind");
- fd_close(fd);
- return -1;
- }
- if(listen(fd, 5) == -1) {
- log_errno("listen");
- fd_close(fd);
- return -1;
- }
- return fd;
-}
-
-/** setup SSL connection to the client */
-static SSL*
-setup_ssl(int s, SSL_CTX* ctx)
-{
- SSL* ssl = SSL_new(ctx);
- if(!ssl) return NULL;
- SSL_set_accept_state(ssl);
- (void)SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
- if(!SSL_set_fd(ssl, s)) {
- SSL_free(ssl);
- return NULL;
- }
- return ssl;
-}
-
-/** check a file name for safety */
-static int
-file_name_is_safe(char* s)
-{
- size_t l = strlen(s);
- if(s[0] != '/')
- return 0; /* must start with / */
- if(strstr(s, "/../"))
- return 0; /* no updirs in URL */
- if(l>=3 && s[l-1]=='.' && s[l-2]=='.' && s[l-3]=='/')
- return 0; /* ends with /.. */
- return 1;
-}
-
-/** adjust host and filename */
-static void
-adjust_host_file(char* host, char* file)
-{
- size_t i, len;
- /* remove a port number if present */
- if(strrchr(host, ':'))
- *strrchr(host, ':') = 0;
- /* lowercase */
- len = strlen(host);
- for(i=0; i<len; i++)
- host[i] = tolower((unsigned char)host[i]);
- len = strlen(file);
- for(i=0; i<len; i++)
- file[i] = tolower((unsigned char)file[i]);
-}
-
-/** check a host name for safety */
-static int
-host_name_is_safe(char* s)
-{
- if(strchr(s, '/'))
- return 0;
- if(strcmp(s, "..") == 0)
- return 0;
- if(strcmp(s, ".") == 0)
- return 0;
- return 1;
-}
-
-/** provide file in whole transfer */
-static void
-provide_file_10(SSL* ssl, char* fname)
-{
- char* buf, *at;
- size_t len, avail, header_reserve=1024;
- FILE* in = fopen(fname,
-#ifndef USE_WINSOCK
- "r"
-#else
- "rb"
-#endif
- );
- size_t r;
- const char* rcode = "200 OK";
- if(!in) {
- char hdr[1024];
- rcode = "404 File not found";
- snprintf(hdr, sizeof(hdr), "HTTP/1.1 %s\r\n\r\n", rcode);
- r = strlen(hdr);
- if(SSL_write(ssl, hdr, (int)r) <= 0) {
- /* write failure */
- }
- return;
- }
- fseek(in, 0, SEEK_END);
- len = (size_t)ftell(in);
- fseek(in, 0, SEEK_SET);
- /* plus some space for the header */
- buf = (char*)malloc(len+header_reserve);
- if(!buf) {
- fclose(in);
- return;
- }
- avail = len+header_reserve;
- at = buf;
- snprintf(at, avail, "HTTP/1.1 %s\r\n", rcode);
- r = strlen(at);
- at += r;
- avail -= r;
- snprintf(at, avail, "Server: petal/%s\r\n", PACKAGE_VERSION);
- r = strlen(at);
- at += r;
- avail -= r;
- snprintf(at, avail, "Content-Length: %u\r\n", (unsigned)len);
- r = strlen(at);
- at += r;
- avail -= r;
- snprintf(at, avail, "\r\n");
- r = strlen(at);
- at += r;
- avail -= r;
- if(avail < len) { /* robust */
- free(buf);
- fclose(in);
- return;
- }
- if(fread(at, 1, len, in) != len) {
- free(buf);
- fclose(in);
- return;
- }
- fclose(in);
- at += len;
- avail -= len;
- if(SSL_write(ssl, buf, at-buf) <= 0) {
- /* write failure */
- }
- free(buf);
-}
-
-/** provide file over SSL, chunked encoding */
-static void
-provide_file_chunked(SSL* ssl, char* fname)
-{
- char buf[16384];
- char* tmpbuf = NULL;
- char* at = buf;
- size_t avail = sizeof(buf);
- size_t r;
- FILE* in = fopen(fname,
-#ifndef USE_WINSOCK
- "r"
-#else
- "rb"
-#endif
- );
- const char* rcode = "200 OK";
- if(!in) {
- rcode = "404 File not found";
- }
-
- /* print headers */
- snprintf(at, avail, "HTTP/1.1 %s\r\n", rcode);
- r = strlen(at);
- at += r;
- avail -= r;
- snprintf(at, avail, "Server: petal/%s\r\n", PACKAGE_VERSION);
- r = strlen(at);
- at += r;
- avail -= r;
- snprintf(at, avail, "Transfer-Encoding: chunked\r\n");
- r = strlen(at);
- at += r;
- avail -= r;
- snprintf(at, avail, "Connection: close\r\n");
- r = strlen(at);
- at += r;
- avail -= r;
- snprintf(at, avail, "\r\n");
- r = strlen(at);
- at += r;
- avail -= r;
- if(avail < 16) { /* robust */
- if(in) fclose(in);
- return;
- }
-
- do {
- size_t red;
- free(tmpbuf);
- tmpbuf = malloc(avail-16);
- if(!tmpbuf)
- break;
- /* read chunk; space-16 for xxxxCRLF..CRLF0CRLFCRLF (3 spare)*/
- red = in?fread(tmpbuf, 1, avail-16, in):0;
- /* prepare chunk */
- snprintf(at, avail, "%x\r\n", (unsigned)red);
- r = strlen(at);
- if(verb >= 3)
- {printf("chunk len %x\n", (unsigned)red); fflush(stdout);}
- at += r;
- avail -= r;
- if(red != 0) {
- if(red > avail) break; /* robust */
- memmove(at, tmpbuf, red);
- at += red;
- avail -= red;
- snprintf(at, avail, "\r\n");
- r = strlen(at);
- at += r;
- avail -= r;
- }
- if(in && feof(in) && red != 0) {
- snprintf(at, avail, "0\r\n");
- r = strlen(at);
- at += r;
- avail -= r;
- }
- if(!in || feof(in)) {
- snprintf(at, avail, "\r\n");
- r = strlen(at);
- at += r;
- avail -= r;
- }
- /* send chunk */
- if(SSL_write(ssl, buf, at-buf) <= 0) {
- /* SSL error */
- break;
- }
-
- /* setup for next chunk */
- at = buf;
- avail = sizeof(buf);
- } while(in && !feof(in) && !ferror(in));
-
- free(tmpbuf);
- if(in) fclose(in);
-}
-
-/** provide service to the ssl descriptor */
-static void
-service_ssl(SSL* ssl, struct sockaddr_storage* from, socklen_t falen)
-{
- char file[1024];
- char host[1024];
- char combined[2048];
- int vs = 11;
- if(!read_http_headers(ssl, file, sizeof(file), host, sizeof(host),
- &vs))
- return;
- adjust_host_file(host, file);
- if(host[0] == 0 || !host_name_is_safe(host))
- (void)strlcpy(host, "default", sizeof(host));
- if(!file_name_is_safe(file)) {
- return;
- }
- snprintf(combined, sizeof(combined), "%s%s", host, file);
- if(verb) {
- char out[100];
- void* a = &((struct sockaddr_in*)from)->sin_addr;
- if(falen != (socklen_t)sizeof(struct sockaddr_in))
- a = &((struct sockaddr_in6*)from)->sin6_addr;
- out[0]=0;
- (void)inet_ntop((int)((struct sockaddr_in*)from)->sin_family,
- a, out, (socklen_t)sizeof(out));
- printf("%s requests %s\n", out, combined);
- fflush(stdout);
- }
- if(vs == 10)
- provide_file_10(ssl, combined);
- else provide_file_chunked(ssl, combined);
-}
-
-/** provide ssl service */
-static void
-do_service(char* addr, int port, char* key, char* cert)
-{
- SSL_CTX* sslctx = setup_ctx(key, cert);
- int fd = setup_fd(addr, port);
- int go = 1;
- if(fd == -1) print_exit("could not setup sockets");
- if(verb) {printf("petal start\n"); fflush(stdout);}
- while(go) {
- struct sockaddr_storage from;
- socklen_t flen = (socklen_t)sizeof(from);
- int s = accept(fd, (struct sockaddr*)&from, &flen);
- if(verb) fflush(stdout);
- if(s != -1) {
- SSL* ssl = setup_ssl(s, sslctx);
- if(verb) fflush(stdout);
- if(ssl) {
- service_ssl(ssl, &from, flen);
- if(verb) fflush(stdout);
- SSL_shutdown(ssl);
- SSL_free(ssl);
- }
- fd_close(s);
- } else if (verb >=2) log_errno("accept");
- if(verb) fflush(stdout);
- }
- /* if we get a kill signal, the process dies and the OS reaps us */
- if(verb) printf("petal end\n");
- fd_close(fd);
- SSL_CTX_free(sslctx);
-}
-
-/** getopt global, in case header files fail to declare it. */
-extern int optind;
-/** getopt global, in case header files fail to declare it. */
-extern char* optarg;
-
-/** Main routine for petal */
-int main(int argc, char* argv[])
-{
- int c;
- int port = 443;
- char* addr = "127.0.0.1", *key = "petal.key", *cert = "petal.pem";
-#ifdef USE_WINSOCK
- WSADATA wsa_data;
- if((c=WSAStartup(MAKEWORD(2,2), &wsa_data)) != 0)
- { printf("WSAStartup failed\n"); exit(1); }
- atexit((void (*)(void))WSACleanup);
-#endif
-
- /* parse the options */
- while( (c=getopt(argc, argv, "a:c:k:hp:v")) != -1) {
- switch(c) {
- case 'a':
- addr = optarg;
- break;
- case 'c':
- cert = optarg;
- break;
- case 'k':
- key = optarg;
- break;
- case 'p':
- port = atoi(optarg);
- break;
- case 'v':
- verb++;
- break;
- case '?':
- case 'h':
- default:
- usage();
- }
- }
- argc -= optind;
- argv += optind;
- if(argc != 0)
- usage();
-
-#ifdef SIGPIPE
- (void)signal(SIGPIPE, SIG_IGN);
-#endif
-#ifdef HAVE_ERR_LOAD_CRYPTO_STRINGS
- ERR_load_crypto_strings();
-#endif
- ERR_load_SSL_strings();
-#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_CRYPTO)
- OpenSSL_add_all_algorithms();
-#else
- OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
- | OPENSSL_INIT_ADD_ALL_DIGESTS
- | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
-#endif
-#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
- (void)SSL_library_init();
-#else
- (void)OPENSSL_init_ssl(0, NULL);
-#endif
-
- do_service(addr, port, key, cert);
-
-#ifdef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA
- CRYPTO_cleanup_all_ex_data();
-#endif
-#ifdef HAVE_ERR_FREE_STRINGS
- ERR_free_strings();
-#endif
- return 0;
-}
diff --git a/external/unbound/testcode/pktview.c b/external/unbound/testcode/pktview.c
deleted file mode 100644
index 12e0d8edb..000000000
--- a/external/unbound/testcode/pktview.c
+++ /dev/null
@@ -1,202 +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 COPYRIGHT
- * HOLDER 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"
-#include "sldns/sbuffer.h"
-#include "sldns/parseutil.h"
-
-/** usage information for pktview */
-static void usage(char* argv[])
-{
- printf("usage: %s\n", argv[0]);
- printf("present hex packet on stdin.\n");
- exit(1);
-}
-
-/** read hex input */
-static void read_input(sldns_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 */
-static void analyze_dname(sldns_buffer* pkt)
-{
- size_t oldpos = sldns_buffer_position(pkt);
- size_t len;
- printf("[pos %d] dname: ", (int)oldpos);
- dname_print(stdout, pkt, sldns_buffer_current(pkt));
- len = pkt_dname_len(pkt);
- printf(" len=%d", (int)len);
- if(sldns_buffer_position(pkt)-oldpos != len)
- printf(" comprlen=%d\n",
- (int)(sldns_buffer_position(pkt)-oldpos));
- else printf("\n");
-}
-
-/** analyze rdata in packet */
-static void analyze_rdata(sldns_buffer*pkt, const sldns_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 = sldns_buffer_position(pkt);
- analyze_dname(pkt);
- rdlen -= sldns_buffer_position(pkt)-oldpos;
- count --;
- len = 0;
- break;
- case LDNS_RDF_TYPE_STR:
- len = sldns_buffer_current(pkt)[0] + 1;
- break;
- default:
- len = get_rdf_size(desc->_wireformat[rdf]);
- }
- if(len) {
- printf(" wf[%d]", (int)len);
- sldns_buffer_skip(pkt, (ssize_t)len);
- rdlen -= len;
- }
- rdf++;
- }
- if(rdlen) {
- size_t i;
- printf(" remain[%d]\n", (int)rdlen);
- for(i=0; i<rdlen; i++)
- printf(" %2.2X", (unsigned)sldns_buffer_current(pkt)[i]);
- printf("\n");
- }
- else printf("\n");
- sldns_buffer_skip(pkt, (ssize_t)rdlen);
-}
-
-/** analyze rr in packet */
-static void analyze_rr(sldns_buffer* pkt, int q)
-{
- uint16_t type, dclass, len;
- uint32_t ttl;
- analyze_dname(pkt);
- type = sldns_buffer_read_u16(pkt);
- dclass = sldns_buffer_read_u16(pkt);
- printf("type %s(%d)", sldns_rr_descript(type)?
- sldns_rr_descript(type)->_name: "??" , (int)type);
- printf(" class %s(%d) ", sldns_lookup_by_id(sldns_rr_classes,
- (int)dclass)?sldns_lookup_by_id(sldns_rr_classes,
- (int)dclass)->name:"??", (int)dclass);
- if(q) {
- printf("\n");
- } else {
- ttl = sldns_buffer_read_u32(pkt);
- printf(" ttl %d (0x%x)", (int)ttl, (unsigned)ttl);
- len = sldns_buffer_read_u16(pkt);
- printf(" rdata len %d:\n", (int)len);
- if(sldns_rr_descript(type))
- analyze_rdata(pkt, sldns_rr_descript(type), len);
- else sldns_buffer_skip(pkt, (ssize_t)len);
- }
-}
-
-/** analyse pkt */
-static void analyze(sldns_buffer* pkt)
-{
- uint16_t i, f, qd, an, ns, ar;
- int rrnum = 0;
- printf("packet length %d\n", (int)sldns_buffer_limit(pkt));
- if(sldns_buffer_limit(pkt) < 12) return;
-
- i = sldns_buffer_read_u16(pkt);
- printf("id (hostorder): %d (0x%x)\n", (int)i, (unsigned)i);
- f = sldns_buffer_read_u16(pkt);
- printf("flags: 0x%x\n", (unsigned)f);
- qd = sldns_buffer_read_u16(pkt);
- printf("qdcount: %d\n", (int)qd);
- an = sldns_buffer_read_u16(pkt);
- printf("ancount: %d\n", (int)an);
- ns = sldns_buffer_read_u16(pkt);
- printf("nscount: %d\n", (int)ns);
- ar = sldns_buffer_read_u16(pkt);
- printf("arcount: %d\n", (int)ar);
-
- printf(";-- query section\n");
- while(sldns_buffer_remaining(pkt) > 0) {
- if(rrnum == (int)qd)
- printf(";-- answer section\n");
- if(rrnum == (int)qd+(int)an)
- printf(";-- authority section\n");
- if(rrnum == (int)qd+(int)an+(int)ns)
- printf(";-- additional section\n");
- printf("rr %d ", rrnum);
- analyze_rr(pkt, rrnum < (int)qd);
- rrnum++;
- }
-}
-
-/** main program for pktview */
-int main(int argc, char* argv[])
-{
- sldns_buffer* pkt = sldns_buffer_new(65553);
- if(argc != 1) {
- usage(argv);
- }
- if(!pkt) fatal_exit("out of memory");
-
- read_input(pkt, stdin);
- analyze(pkt);
-
- sldns_buffer_free(pkt);
- return 0;
-}
diff --git a/external/unbound/testcode/readhex.c b/external/unbound/testcode/readhex.c
deleted file mode 100644
index e871def0e..000000000
--- a/external/unbound/testcode/readhex.c
+++ /dev/null
@@ -1,85 +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 COPYRIGHT
- * HOLDER 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 <ctype.h>
-#include "testcode/readhex.h"
-#include "util/log.h"
-#include "sldns/sbuffer.h"
-#include "sldns/parseutil.h"
-
-/** skip whitespace */
-static void
-skip_whites(const char** p)
-{
- while(1) {
- while(isspace((unsigned char)**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(sldns_buffer* pkt, const char* hex)
-{
- const char* p = hex;
- int val;
- sldns_buffer_clear(pkt);
- while(*p) {
- skip_whites(&p);
- if(sldns_buffer_position(pkt) == sldns_buffer_limit(pkt))
- fatal_exit("hex_to_buf: buffer too small");
- if(!isalnum((unsigned char)*p))
- break;
- val = sldns_hexdigit_to_int(*p++) << 4;
- skip_whites(&p);
- log_assert(*p && isalnum((unsigned char)*p));
- val |= sldns_hexdigit_to_int(*p++);
- sldns_buffer_write_u8(pkt, (uint8_t)val);
- skip_whites(&p);
- }
- sldns_buffer_flip(pkt);
-}
-
diff --git a/external/unbound/testcode/readhex.h b/external/unbound/testcode/readhex.h
deleted file mode 100644
index be6424539..000000000
--- a/external/unbound/testcode/readhex.h
+++ /dev/null
@@ -1,52 +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 COPYRIGHT
- * HOLDER 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
-struct sldns_buffer;
-
-/**
- * Helper to convert hex string to packet buffer.
- * @param pkt: buffer to put result in.
- * @param hex: string of hex data. Spaces and ';...' comments are skipped.
- */
-void hex_to_buf(struct sldns_buffer* pkt, const char* hex);
-
-#endif /* TESTCODE_READHEX_H */
diff --git a/external/unbound/testcode/replay.c b/external/unbound/testcode/replay.c
deleted file mode 100644
index b45bde806..000000000
--- a/external/unbound/testcode/replay.c
+++ /dev/null
@@ -1,1034 +0,0 @@
-/*
- * testcode/replay.c - store and use a replay of events for the DNS resolver.
- *
- * 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 COPYRIGHT
- * HOLDER 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
- * Store and use a replay of events for the DNS resolver.
- * Used to test known scenarios to get known outcomes.
- */
-
-#include "config.h"
-/* for strtod prototype */
-#include <math.h>
-#include <ctype.h>
-#include <time.h>
-#include "util/log.h"
-#include "util/net_help.h"
-#include "util/config_file.h"
-#include "testcode/replay.h"
-#include "testcode/testpkts.h"
-#include "testcode/fake_event.h"
-#include "sldns/str2wire.h"
-
-/** max length of lines in file */
-#define MAX_LINE_LEN 10240
-
-/**
- * Expand a macro
- * @param store: value storage
- * @param runtime: replay runtime for other stuff.
- * @param text: the macro text, after the ${, Updated to after the } when
- * done (successfully).
- * @return expanded text, malloced. NULL on failure.
- */
-static char* macro_expand(rbtree_type* store,
- struct replay_runtime* runtime, char** text);
-
-/** compare of time values */
-static int
-timeval_smaller(const struct timeval* x, const struct timeval* y)
-{
-#ifndef S_SPLINT_S
- if(x->tv_sec < y->tv_sec)
- return 1;
- else if(x->tv_sec == y->tv_sec) {
- if(x->tv_usec <= y->tv_usec)
- return 1;
- else return 0;
- }
- else return 0;
-#endif
-}
-
-/** parse keyword in string.
- * @param line: if found, the line is advanced to after the keyword.
- * @param keyword: string.
- * @return: true if found, false if not.
- */
-static int
-parse_keyword(char** line, const char* keyword)
-{
- size_t len = (size_t)strlen(keyword);
- if(strncmp(*line, keyword, len) == 0) {
- *line += len;
- return 1;
- }
- return 0;
-}
-
-/** delete moment */
-static void
-replay_moment_delete(struct replay_moment* mom)
-{
- if(!mom)
- return;
- if(mom->match) {
- delete_entry(mom->match);
- }
- free(mom->autotrust_id);
- free(mom->string);
- free(mom->variable);
- config_delstrlist(mom->file_content);
- free(mom);
-}
-
-/** delete range */
-static void
-replay_range_delete(struct replay_range* rng)
-{
- if(!rng)
- return;
- delete_entry(rng->match);
- 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((unsigned char)p[i-1]))
- p[i-1] = 0;
- else return;
- }
-}
-
-/**
- * Read a range from file.
- * @param remain: Rest of line (after RANGE keyword).
- * @param in: file to read from.
- * @param name: name to print in errors.
- * @param pstate: read state structure with
- * with lineno : incremented as lines are read.
- * ttl, origin, prev for readentry.
- * @param line: line buffer.
- * @return: range object to add to list, or NULL on error.
- */
-static struct replay_range*
-replay_range_read(char* remain, FILE* in, const char* name,
- struct sldns_file_parse_state* pstate, char* line)
-{
- struct replay_range* rng = (struct replay_range*)malloc(
- sizeof(struct replay_range));
- off_t pos;
- char *parse;
- struct entry* entry, *last = NULL;
- if(!rng)
- return NULL;
- memset(rng, 0, sizeof(*rng));
- /* read time range */
- if(sscanf(remain, " %d %d", &rng->start_step, &rng->end_step)!=2) {
- log_err("Could not read time range: %s", line);
- free(rng);
- return NULL;
- }
- /* read entries */
- pos = ftello(in);
- while(fgets(line, MAX_LINE_LEN-1, in)) {
- pstate->lineno++;
- parse = line;
- while(isspace((unsigned char)*parse))
- parse++;
- if(!*parse || *parse == ';') {
- pos = ftello(in);
- continue;
- }
- if(parse_keyword(&parse, "ADDRESS")) {
- while(isspace((unsigned char)*parse))
- parse++;
- strip_end_white(parse);
- if(!extstrtoaddr(parse, &rng->addr, &rng->addrlen)) {
- log_err("Line %d: could not read ADDRESS: %s",
- pstate->lineno, parse);
- free(rng);
- return NULL;
- }
- pos = ftello(in);
- continue;
- }
- if(parse_keyword(&parse, "RANGE_END")) {
- return rng;
- }
- /* set position before line; read entry */
- pstate->lineno--;
- fseeko(in, pos, SEEK_SET);
- entry = read_entry(in, name, pstate, 1);
- if(!entry)
- fatal_exit("%d: bad entry", pstate->lineno);
- entry->next = NULL;
- if(last)
- last->next = entry;
- else rng->match = entry;
- last = entry;
-
- pos = ftello(in);
- }
- replay_range_delete(rng);
- return NULL;
-}
-
-/** Read FILE match content */
-static void
-read_file_content(FILE* in, int* lineno, struct replay_moment* mom)
-{
- char line[MAX_LINE_LEN];
- char* remain = line;
- struct config_strlist** last = &mom->file_content;
- line[MAX_LINE_LEN-1]=0;
- if(!fgets(line, MAX_LINE_LEN-1, in))
- fatal_exit("FILE_BEGIN expected at line %d", *lineno);
- if(!parse_keyword(&remain, "FILE_BEGIN"))
- fatal_exit("FILE_BEGIN expected at line %d", *lineno);
- while(fgets(line, MAX_LINE_LEN-1, in)) {
- (*lineno)++;
- if(strncmp(line, "FILE_END", 8) == 0) {
- return;
- }
- if(line[0]) line[strlen(line)-1] = 0; /* remove newline */
- if(!cfg_strlist_insert(last, strdup(line)))
- fatal_exit("malloc failure");
- last = &( (*last)->next );
- }
- fatal_exit("no FILE_END in input file");
-}
-
-/** read assign step info */
-static void
-read_assign_step(char* remain, struct replay_moment* mom)
-{
- char buf[1024];
- char eq;
- int skip;
- buf[sizeof(buf)-1]=0;
- if(sscanf(remain, " %1023s %c %n", buf, &eq, &skip) != 2)
- fatal_exit("cannot parse assign: %s", remain);
- mom->variable = strdup(buf);
- if(eq != '=')
- fatal_exit("no '=' in assign: %s", remain);
- remain += skip;
- if(remain[0]) remain[strlen(remain)-1]=0; /* remove newline */
- mom->string = strdup(remain);
- if(!mom->variable || !mom->string)
- fatal_exit("out of memory");
-}
-
-/**
- * Read a replay moment 'STEP' from file.
- * @param remain: Rest of line (after STEP keyword).
- * @param in: file to read from.
- * @param name: name to print in errors.
- * @param pstate: with lineno, ttl, origin, prev for parse state.
- * lineno is incremented.
- * @return: range object to add to list, or NULL on error.
- */
-static struct replay_moment*
-replay_moment_read(char* remain, FILE* in, const char* name,
- struct sldns_file_parse_state* pstate)
-{
- struct replay_moment* mom = (struct replay_moment*)malloc(
- sizeof(struct replay_moment));
- int skip = 0;
- int readentry = 0;
- if(!mom)
- return NULL;
- memset(mom, 0, sizeof(*mom));
- if(sscanf(remain, " %d%n", &mom->time_step, &skip) != 1) {
- log_err("%d: cannot read number: %s", pstate->lineno, remain);
- free(mom);
- return NULL;
- }
- remain += skip;
- while(isspace((unsigned char)*remain))
- remain++;
- if(parse_keyword(&remain, "NOTHING")) {
- mom->evt_type = repevt_nothing;
- } else if(parse_keyword(&remain, "QUERY")) {
- mom->evt_type = repevt_front_query;
- readentry = 1;
- if(!extstrtoaddr("127.0.0.1", &mom->addr, &mom->addrlen))
- fatal_exit("internal error");
- } else if(parse_keyword(&remain, "CHECK_ANSWER")) {
- mom->evt_type = repevt_front_reply;
- readentry = 1;
- } else if(parse_keyword(&remain, "CHECK_OUT_QUERY")) {
- mom->evt_type = repevt_back_query;
- readentry = 1;
- } else if(parse_keyword(&remain, "REPLY")) {
- mom->evt_type = repevt_back_reply;
- readentry = 1;
- } else if(parse_keyword(&remain, "TIMEOUT")) {
- mom->evt_type = repevt_timeout;
- } else if(parse_keyword(&remain, "TIME_PASSES")) {
- mom->evt_type = repevt_time_passes;
- while(isspace((unsigned char)*remain))
- remain++;
- if(parse_keyword(&remain, "EVAL")) {
- while(isspace((unsigned char)*remain))
- remain++;
- mom->string = strdup(remain);
- if(!mom->string) fatal_exit("out of memory");
- if(strlen(mom->string)>0)
- mom->string[strlen(mom->string)-1]=0;
- remain += strlen(mom->string);
- }
- } else if(parse_keyword(&remain, "CHECK_AUTOTRUST")) {
- mom->evt_type = repevt_autotrust_check;
- while(isspace((unsigned char)*remain))
- remain++;
- if(strlen(remain)>0 && remain[strlen(remain)-1]=='\n')
- remain[strlen(remain)-1] = 0;
- mom->autotrust_id = strdup(remain);
- if(!mom->autotrust_id) fatal_exit("out of memory");
- read_file_content(in, &pstate->lineno, mom);
- } else if(parse_keyword(&remain, "ERROR")) {
- mom->evt_type = repevt_error;
- } else if(parse_keyword(&remain, "TRAFFIC")) {
- mom->evt_type = repevt_traffic;
- } else if(parse_keyword(&remain, "ASSIGN")) {
- mom->evt_type = repevt_assign;
- read_assign_step(remain, mom);
- } else if(parse_keyword(&remain, "INFRA_RTT")) {
- char *s, *m;
- mom->evt_type = repevt_infra_rtt;
- while(isspace((unsigned char)*remain))
- remain++;
- s = remain;
- remain = strchr(s, ' ');
- if(!remain) fatal_exit("expected three args for INFRA_RTT");
- remain[0] = 0;
- remain++;
- while(isspace((unsigned char)*remain))
- remain++;
- m = strchr(remain, ' ');
- if(!m) fatal_exit("expected three args for INFRA_RTT");
- m[0] = 0;
- m++;
- while(isspace((unsigned char)*m))
- m++;
- if(!extstrtoaddr(s, &mom->addr, &mom->addrlen))
- fatal_exit("bad infra_rtt address %s", s);
- if(strlen(m)>0 && m[strlen(m)-1]=='\n')
- m[strlen(m)-1] = 0;
- mom->variable = strdup(remain);
- mom->string = strdup(m);
- if(!mom->string) fatal_exit("out of memory");
- if(!mom->variable) fatal_exit("out of memory");
- } else {
- log_err("%d: unknown event type %s", pstate->lineno, remain);
- free(mom);
- return NULL;
- }
- while(isspace((unsigned char)*remain))
- remain++;
- if(parse_keyword(&remain, "ADDRESS")) {
- while(isspace((unsigned char)*remain))
- remain++;
- if(strlen(remain) > 0) /* remove \n */
- remain[strlen(remain)-1] = 0;
- if(!extstrtoaddr(remain, &mom->addr, &mom->addrlen)) {
- log_err("line %d: could not parse ADDRESS: %s",
- pstate->lineno, remain);
- free(mom);
- return NULL;
- }
- }
- if(parse_keyword(&remain, "ELAPSE")) {
- double sec;
- errno = 0;
- sec = strtod(remain, &remain);
- if(sec == 0. && errno != 0) {
- log_err("line %d: could not parse ELAPSE: %s (%s)",
- pstate->lineno, remain, strerror(errno));
- free(mom);
- return NULL;
- }
-#ifndef S_SPLINT_S
- mom->elapse.tv_sec = (int)sec;
- mom->elapse.tv_usec = (int)((sec - (double)mom->elapse.tv_sec)
- *1000000. + 0.5);
-#endif
- }
-
- if(readentry) {
- mom->match = read_entry(in, name, pstate, 1);
- if(!mom->match) {
- free(mom);
- return NULL;
- }
- }
-
- return mom;
-}
-
-/** makes scenario with title on rest of line */
-static struct replay_scenario*
-make_scenario(char* line)
-{
- struct replay_scenario* scen;
- while(isspace((unsigned char)*line))
- line++;
- if(!*line) {
- log_err("scenario: no title given");
- return NULL;
- }
- scen = (struct replay_scenario*)malloc(sizeof(struct replay_scenario));
- if(!scen)
- return NULL;
- memset(scen, 0, sizeof(*scen));
- scen->title = strdup(line);
- if(!scen->title) {
- free(scen);
- return NULL;
- }
- return scen;
-}
-
-struct replay_scenario*
-replay_scenario_read(FILE* in, const char* name, int* lineno)
-{
- char line[MAX_LINE_LEN];
- char *parse;
- struct replay_scenario* scen = NULL;
- struct sldns_file_parse_state pstate;
- line[MAX_LINE_LEN-1]=0;
- memset(&pstate, 0, sizeof(pstate));
- pstate.default_ttl = 3600;
- pstate.lineno = *lineno;
-
- while(fgets(line, MAX_LINE_LEN-1, in)) {
- parse=line;
- pstate.lineno++;
- (*lineno)++;
- while(isspace((unsigned char)*parse))
- parse++;
- if(!*parse)
- continue; /* empty line */
- if(parse_keyword(&parse, ";"))
- continue; /* comment */
- if(parse_keyword(&parse, "SCENARIO_BEGIN")) {
- scen = make_scenario(parse);
- if(!scen)
- fatal_exit("%d: could not make scen", *lineno);
- continue;
- }
- if(!scen)
- fatal_exit("%d: expected SCENARIO", *lineno);
- if(parse_keyword(&parse, "RANGE_BEGIN")) {
- struct replay_range* newr = replay_range_read(parse,
- in, name, &pstate, line);
- if(!newr)
- fatal_exit("%d: bad range", pstate.lineno);
- *lineno = pstate.lineno;
- newr->next_range = scen->range_list;
- scen->range_list = newr;
- } else if(parse_keyword(&parse, "STEP")) {
- struct replay_moment* mom = replay_moment_read(parse,
- in, name, &pstate);
- if(!mom)
- fatal_exit("%d: bad moment", pstate.lineno);
- *lineno = pstate.lineno;
- if(scen->mom_last &&
- scen->mom_last->time_step >= mom->time_step)
- fatal_exit("%d: time goes backwards", *lineno);
- if(scen->mom_last)
- scen->mom_last->mom_next = mom;
- else scen->mom_first = mom;
- scen->mom_last = mom;
- } else if(parse_keyword(&parse, "SCENARIO_END")) {
- struct replay_moment *p = scen->mom_first;
- int num = 0;
- while(p) {
- num++;
- p = p->mom_next;
- }
- log_info("Scenario has %d steps", num);
- return scen;
- }
- }
- replay_scenario_delete(scen);
- return NULL;
-}
-
-void
-replay_scenario_delete(struct replay_scenario* scen)
-{
- struct replay_moment* mom, *momn;
- struct replay_range* rng, *rngn;
- if(!scen)
- return;
- free(scen->title);
- mom = scen->mom_first;
- while(mom) {
- momn = mom->mom_next;
- replay_moment_delete(mom);
- mom = momn;
- }
- rng = scen->range_list;
- while(rng) {
- rngn = rng->next_range;
- replay_range_delete(rng);
- rng = rngn;
- }
- free(scen);
-}
-
-/** fetch oldest timer in list that is enabled */
-static struct fake_timer*
-first_timer(struct replay_runtime* runtime)
-{
- struct fake_timer* p, *res = NULL;
- for(p=runtime->timer_list; p; p=p->next) {
- if(!p->enabled)
- continue;
- if(!res)
- res = p;
- else if(timeval_smaller(&p->tv, &res->tv))
- res = p;
- }
- return res;
-}
-
-struct fake_timer*
-replay_get_oldest_timer(struct replay_runtime* runtime)
-{
- struct fake_timer* t = first_timer(runtime);
- if(t && timeval_smaller(&t->tv, &runtime->now_tv))
- return t;
- return NULL;
-}
-
-int
-replay_var_compare(const void* a, const void* b)
-{
- struct replay_var* x = (struct replay_var*)a;
- struct replay_var* y = (struct replay_var*)b;
- return strcmp(x->name, y->name);
-}
-
-rbtree_type*
-macro_store_create(void)
-{
- return rbtree_create(&replay_var_compare);
-}
-
-/** helper function to delete macro values */
-static void
-del_macro(rbnode_type* x, void* ATTR_UNUSED(arg))
-{
- struct replay_var* v = (struct replay_var*)x;
- free(v->name);
- free(v->value);
- free(v);
-}
-
-void
-macro_store_delete(rbtree_type* store)
-{
- if(!store)
- return;
- traverse_postorder(store, del_macro, NULL);
- free(store);
-}
-
-/** return length of macro */
-static size_t
-macro_length(char* text)
-{
- /* we are after ${, looking for } */
- int depth = 0;
- size_t len = 0;
- while(*text) {
- len++;
- if(*text == '}') {
- if(depth == 0)
- break;
- depth--;
- } else if(text[0] == '$' && text[1] == '{') {
- depth++;
- }
- text++;
- }
- return len;
-}
-
-/** insert new stuff at start of buffer */
-static int
-do_buf_insert(char* buf, size_t remain, char* after, char* inserted)
-{
- char* save = strdup(after);
- size_t len;
- if(!save) return 0;
- if(strlen(inserted) > remain) {
- free(save);
- return 0;
- }
- len = strlcpy(buf, inserted, remain);
- buf += len;
- remain -= len;
- (void)strlcpy(buf, save, remain);
- free(save);
- return 1;
-}
-
-/** do macro recursion */
-static char*
-do_macro_recursion(rbtree_type* store, struct replay_runtime* runtime,
- char* at, size_t remain)
-{
- char* after = at+2;
- char* expand = macro_expand(store, runtime, &after);
- if(!expand)
- return NULL; /* expansion failed */
- if(!do_buf_insert(at, remain, after, expand)) {
- free(expand);
- return NULL;
- }
- free(expand);
- return at; /* and parse over the expanded text to see if again */
-}
-
-/** get var from store */
-static struct replay_var*
-macro_getvar(rbtree_type* store, char* name)
-{
- struct replay_var k;
- k.node.key = &k;
- k.name = name;
- return (struct replay_var*)rbtree_search(store, &k);
-}
-
-/** do macro variable */
-static char*
-do_macro_variable(rbtree_type* store, char* buf, size_t remain)
-{
- struct replay_var* v;
- char* at = buf+1;
- char* name = at;
- char sv;
- if(at[0]==0)
- return NULL; /* no variable name after $ */
- while(*at && (isalnum((unsigned char)*at) || *at=='_')) {
- at++;
- }
- /* terminator, we are working in macro_expand() buffer */
- sv = *at;
- *at = 0;
- v = macro_getvar(store, name);
- *at = sv;
-
- if(!v) {
- log_err("variable is not defined: $%s", name);
- return NULL; /* variable undefined is error for now */
- }
-
- /* insert the variable contents */
- if(!do_buf_insert(buf, remain, at, v->value))
- return NULL;
- return buf; /* and expand the variable contents */
-}
-
-/** do ctime macro on argument */
-static char*
-do_macro_ctime(char* arg)
-{
- char buf[32];
- time_t tt = (time_t)atoi(arg);
- if(tt == 0 && strcmp(arg, "0") != 0) {
- log_err("macro ctime: expected number, not: %s", arg);
- return NULL;
- }
- ctime_r(&tt, buf);
- if(buf[0]) buf[strlen(buf)-1]=0; /* remove trailing newline */
- return strdup(buf);
-}
-
-/** perform arithmetic operator */
-static double
-perform_arith(double x, char op, double y, double* res)
-{
- switch(op) {
- case '+':
- *res = x+y;
- break;
- case '-':
- *res = x-y;
- break;
- case '/':
- *res = x/y;
- break;
- case '*':
- *res = x*y;
- break;
- default:
- return 0;
- }
-
- return 1;
-}
-
-/** do macro arithmetic on two numbers and operand */
-static char*
-do_macro_arith(char* orig, size_t remain, char** arithstart)
-{
- double x, y, result;
- char operator;
- int skip;
- char buf[32];
- char* at;
- /* not yet done? we want number operand number expanded first. */
- if(!*arithstart) {
- /* remember start pos of expr, skip the first number */
- at = orig;
- *arithstart = at;
- while(*at && (isdigit((unsigned char)*at) || *at == '.'))
- at++;
- return at;
- }
- /* move back to start */
- remain += (size_t)(orig - *arithstart);
- at = *arithstart;
-
- /* parse operands */
- if(sscanf(at, " %lf %c %lf%n", &x, &operator, &y, &skip) != 3) {
- *arithstart = NULL;
- return do_macro_arith(orig, remain, arithstart);
- }
- if(isdigit((unsigned char)operator)) {
- *arithstart = orig;
- return at+skip; /* do nothing, but setup for later number */
- }
-
- /* calculate result */
- if(!perform_arith(x, operator, y, &result)) {
- log_err("unknown operator: %s", at);
- return NULL;
- }
-
- /* put result back in buffer */
- snprintf(buf, sizeof(buf), "%.12g", result);
- if(!do_buf_insert(at, remain, at+skip, buf))
- return NULL;
-
- /* the result can be part of another expression, restart that */
- *arithstart = NULL;
- return at;
-}
-
-/** Do range macro on expanded buffer */
-static char*
-do_macro_range(char* buf)
-{
- double x, y, z;
- if(sscanf(buf, " %lf %lf %lf", &x, &y, &z) != 3) {
- log_err("range func requires 3 args: %s", buf);
- return NULL;
- }
- if(x <= y && y <= z) {
- char res[1024];
- snprintf(res, sizeof(res), "%.24g", y);
- return strdup(res);
- }
- fatal_exit("value %.24g not in range [%.24g, %.24g]", y, x, z);
- return NULL;
-}
-
-static char*
-macro_expand(rbtree_type* store, struct replay_runtime* runtime, char** text)
-{
- char buf[10240];
- char* at = *text;
- size_t len = macro_length(at);
- int dofunc = 0;
- char* arithstart = NULL;
- if(len >= sizeof(buf))
- return NULL; /* too long */
- buf[0] = 0;
- (void)strlcpy(buf, at, len+1-1); /* do not copy last '}' character */
- at = buf;
-
- /* check for functions */
- if(strcmp(buf, "time") == 0) {
- snprintf(buf, sizeof(buf), ARG_LL "d", (long long)runtime->now_secs);
- *text += len;
- return strdup(buf);
- } else if(strcmp(buf, "timeout") == 0) {
- time_t res = 0;
- struct fake_timer* t = first_timer(runtime);
- if(t && (time_t)t->tv.tv_sec >= runtime->now_secs)
- res = (time_t)t->tv.tv_sec - runtime->now_secs;
- snprintf(buf, sizeof(buf), ARG_LL "d", (long long)res);
- *text += len;
- return strdup(buf);
- } else if(strncmp(buf, "ctime ", 6) == 0 ||
- strncmp(buf, "ctime\t", 6) == 0) {
- at += 6;
- dofunc = 1;
- } else if(strncmp(buf, "range ", 6) == 0 ||
- strncmp(buf, "range\t", 6) == 0) {
- at += 6;
- dofunc = 1;
- }
-
- /* actual macro text expansion */
- while(*at) {
- size_t remain = sizeof(buf)-strlen(buf);
- if(strncmp(at, "${", 2) == 0) {
- at = do_macro_recursion(store, runtime, at, remain);
- } else if(*at == '$') {
- at = do_macro_variable(store, at, remain);
- } else if(isdigit((unsigned char)*at)) {
- at = do_macro_arith(at, remain, &arithstart);
- } else {
- /* copy until whitespace or operator */
- if(*at && (isalnum((unsigned char)*at) || *at=='_')) {
- at++;
- while(*at && (isalnum((unsigned char)*at) || *at=='_'))
- at++;
- } else at++;
- }
- if(!at) return NULL; /* failure */
- }
- *text += len;
- if(dofunc) {
- /* post process functions, buf has the argument(s) */
- if(strncmp(buf, "ctime", 5) == 0) {
- return do_macro_ctime(buf+6);
- } else if(strncmp(buf, "range", 5) == 0) {
- return do_macro_range(buf+6);
- }
- }
- return strdup(buf);
-}
-
-char*
-macro_process(rbtree_type* store, struct replay_runtime* runtime, char* text)
-{
- char buf[10240];
- char* next, *expand;
- char* at = text;
- if(!strstr(text, "${"))
- return strdup(text); /* no macros */
- buf[0] = 0;
- buf[sizeof(buf)-1]=0;
- while( (next=strstr(at, "${")) ) {
- /* copy text before next macro */
- if((size_t)(next-at) >= sizeof(buf)-strlen(buf))
- return NULL; /* string too long */
- (void)strlcpy(buf+strlen(buf), at, (size_t)(next-at+1));
- /* process the macro itself */
- next += 2;
- expand = macro_expand(store, runtime, &next);
- if(!expand) return NULL; /* expansion failed */
- (void)strlcpy(buf+strlen(buf), expand, sizeof(buf)-strlen(buf));
- free(expand);
- at = next;
- }
- /* copy remainder fixed text */
- (void)strlcpy(buf+strlen(buf), at, sizeof(buf)-strlen(buf));
- return strdup(buf);
-}
-
-char*
-macro_lookup(rbtree_type* store, char* name)
-{
- struct replay_var* x = macro_getvar(store, name);
- if(!x) return strdup("");
- return strdup(x->value);
-}
-
-void macro_print_debug(rbtree_type* store)
-{
- struct replay_var* x;
- RBTREE_FOR(x, struct replay_var*, store) {
- log_info("%s = %s", x->name, x->value);
- }
-}
-
-int
-macro_assign(rbtree_type* store, char* name, char* value)
-{
- struct replay_var* x = macro_getvar(store, name);
- if(x) {
- free(x->value);
- } else {
- x = (struct replay_var*)malloc(sizeof(*x));
- if(!x) return 0;
- x->node.key = x;
- x->name = strdup(name);
- if(!x->name) {
- free(x);
- return 0;
- }
- (void)rbtree_insert(store, &x->node);
- }
- x->value = strdup(value);
- return x->value != NULL;
-}
-
-/* testbound assert function for selftest. counts the number of tests */
-#define tb_assert(x) \
- do { if(!(x)) fatal_exit("%s:%d: %s: assertion %s failed", \
- __FILE__, __LINE__, __func__, #x); \
- num_asserts++; \
- } while(0);
-
-void testbound_selftest(void)
-{
- /* test the macro store */
- rbtree_type* store = macro_store_create();
- char* v;
- int r;
- int num_asserts = 0;
- tb_assert(store);
-
- v = macro_lookup(store, "bla");
- tb_assert(strcmp(v, "") == 0);
- free(v);
-
- v = macro_lookup(store, "vlerk");
- tb_assert(strcmp(v, "") == 0);
- free(v);
-
- r = macro_assign(store, "bla", "waarde1");
- tb_assert(r);
-
- v = macro_lookup(store, "vlerk");
- tb_assert(strcmp(v, "") == 0);
- free(v);
-
- v = macro_lookup(store, "bla");
- tb_assert(strcmp(v, "waarde1") == 0);
- free(v);
-
- r = macro_assign(store, "vlerk", "kanteel");
- tb_assert(r);
-
- v = macro_lookup(store, "bla");
- tb_assert(strcmp(v, "waarde1") == 0);
- free(v);
-
- v = macro_lookup(store, "vlerk");
- tb_assert(strcmp(v, "kanteel") == 0);
- free(v);
-
- r = macro_assign(store, "bla", "ww");
- tb_assert(r);
-
- v = macro_lookup(store, "bla");
- tb_assert(strcmp(v, "ww") == 0);
- free(v);
-
- tb_assert( macro_length("}") == 1);
- tb_assert( macro_length("blabla}") == 7);
- tb_assert( macro_length("bla${zoink}bla}") == 7+8);
- tb_assert( macro_length("bla${zoink}${bla}bla}") == 7+8+6);
-
- v = macro_process(store, NULL, "");
- tb_assert( v && strcmp(v, "") == 0);
- free(v);
-
- v = macro_process(store, NULL, "${}");
- tb_assert( v && strcmp(v, "") == 0);
- free(v);
-
- v = macro_process(store, NULL, "blabla ${} dinges");
- tb_assert( v && strcmp(v, "blabla dinges") == 0);
- free(v);
-
- v = macro_process(store, NULL, "1${$bla}2${$bla}3");
- tb_assert( v && strcmp(v, "1ww2ww3") == 0);
- free(v);
-
- v = macro_process(store, NULL, "it is ${ctime 123456}");
- tb_assert( v && strcmp(v, "it is Fri Jan 2 10:17:36 1970") == 0);
- free(v);
-
- r = macro_assign(store, "t1", "123456");
- tb_assert(r);
- v = macro_process(store, NULL, "it is ${ctime ${$t1}}");
- tb_assert( v && strcmp(v, "it is Fri Jan 2 10:17:36 1970") == 0);
- free(v);
-
- v = macro_process(store, NULL, "it is ${ctime $t1}");
- tb_assert( v && strcmp(v, "it is Fri Jan 2 10:17:36 1970") == 0);
- free(v);
-
- r = macro_assign(store, "x", "1");
- tb_assert(r);
- r = macro_assign(store, "y", "2");
- tb_assert(r);
- v = macro_process(store, NULL, "${$x + $x}");
- tb_assert( v && strcmp(v, "2") == 0);
- free(v);
- v = macro_process(store, NULL, "${$x - $x}");
- tb_assert( v && strcmp(v, "0") == 0);
- free(v);
- v = macro_process(store, NULL, "${$y * $y}");
- tb_assert( v && strcmp(v, "4") == 0);
- free(v);
- v = macro_process(store, NULL, "${32 / $y + $x + $y}");
- tb_assert( v && strcmp(v, "19") == 0);
- free(v);
-
- v = macro_process(store, NULL, "${32 / ${$y+$y} + ${${100*3}/3}}");
- tb_assert( v && strcmp(v, "108") == 0);
- free(v);
-
- v = macro_process(store, NULL, "${1 2 33 2 1}");
- tb_assert( v && strcmp(v, "1 2 33 2 1") == 0);
- free(v);
-
- v = macro_process(store, NULL, "${123 3 + 5}");
- tb_assert( v && strcmp(v, "123 8") == 0);
- free(v);
-
- v = macro_process(store, NULL, "${123 glug 3 + 5}");
- tb_assert( v && strcmp(v, "123 glug 8") == 0);
- free(v);
-
- macro_store_delete(store);
- printf("selftest successful (%d checks).\n", num_asserts);
-}
diff --git a/external/unbound/testcode/replay.h b/external/unbound/testcode/replay.h
deleted file mode 100644
index b33950304..000000000
--- a/external/unbound/testcode/replay.h
+++ /dev/null
@@ -1,458 +0,0 @@
-/*
- * testcode/replay.h - store and use a replay of events for the DNS resolver.
- *
- * 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 COPYRIGHT
- * HOLDER 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
- * Store and use a replay of events for the DNS resolver.
- * Used to test known scenarios to get known outcomes.
- *
- * <pre>
- * File format for replay files.
- *
- * ; unbound.conf options.
- * ; ...
- * ; additional commandline options to pass to unbound
- * COMMANDLINE cmdline_option
- * ; autotrust key file contents, also adds auto-trust-anchor-file: "x" to cfg
- * AUTOTRUST_FILE id
- * ; contents of that file
- * AUTOTRUST_END
- * CONFIG_END
- * ; 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]
- * ; event_type can be:
- * o NOTHING - nothing
- * o QUERY - followed by entry
- * o CHECK_ANSWER - followed by entry
- * o CHECK_OUT_QUERY - followed by entry (if copy-id it is also reply).
- * o REPLY - followed by entry
- * o TIMEOUT
- * o TIME_PASSES ELAPSE [seconds] - increase 'now' time counter, can be
- * a floating point number.
- * TIME_PASSES EVAL [macro] - expanded for seconds to move time.
- * o TRAFFIC - like CHECK_ANSWER, causes traffic to flow.
- * actually the traffic flows before this step is taken.
- * the step waits for traffic to stop.
- * o CHECK_AUTOTRUST [id] - followed by FILE_BEGIN [to match] FILE_END.
- * The file contents is macro expanded before match.
- * o INFRA_RTT [ip] [dp] [rtt] - update infra cache entry with rtt.
- * o ERROR
- * ; following entry starts on the next line, ENTRY_BEGIN.
- * ; more STEP items
- * SCENARIO_END
- *
- * Calculations, a macro-like system: ${$myvar + 3600}
- * STEP 10 ASSIGN myvar = 3600
- * ; ASSIGN event. '=' is syntactic sugar here. 3600 is some expression.
- * ${..} is macro expanded from its expression. Text substitution.
- * o $var replaced with its value. var is identifier [azAZ09_]*
- * o number is that number.
- * o ${variables and arithmetic }
- * o +, -, / and *. Note, evaluated left-to-right. Use ${} for brackets.
- * So again, no precedence rules, so 2+3*4 == ${2+3}*4 = 20.
- * Do 2+${3*4} to get 24.
- * o ${function params}
- * o ${time} is the current time for the simulated unbound.
- * o ${ctime value} is the text ctime(value), Fri 3 Aug 2009, ...
- * o ${timeout} is the time until next timeout in comm_timer list.
- * o ${range lower value upper} checks if lower<=value<=upper
- * returns value if check succeeds.
- *
- * ; Example file
- * SCENARIO_BEGIN Example scenario
- * RANGE_BEGIN 0 100
- * ENTRY_BEGIN
- * ; precoded answers to queries.
- * ENTRY_END
- * END_RANGE
- * STEP 0 QUERY
- * ENTRY_BEGIN
- * ; query
- * ENTRY_END
- * ; a query is sent out to the network by resolver.
- * ; precoded answer from range is returned.
- * ; algorithm will do precoded answers from RANGE immediately, except if
- * ; the next step specifically checks for that OUT_QUERY.
- * ; or if none of the precoded answers match.
- * STEP 1 CHECK_ANSWER
- * ENTRY_BEGIN
- * ; what the reply should look like
- * ENTRY_END
- * ; successful termination. (if the answer was OK).
- * ; also, all answers must have been checked with CHECK_ANSWER.
- * ; and, no more pending out_queries (that have not been checked).
- * SCENARIO_END
- *
- * </pre>
- */
-
-#ifndef TESTCODE_REPLAY_H
-#define TESTCODE_REPLAY_H
-#include "util/netevent.h"
-#include "testcode/testpkts.h"
-#include "util/rbtree.h"
-struct replay_answer;
-struct replay_moment;
-struct replay_range;
-struct fake_pending;
-struct fake_timer;
-struct replay_var;
-struct infra_cache;
-struct sldns_buffer;
-
-/**
- * A replay scenario.
- */
-struct replay_scenario {
- /** name of replay scenario. malloced string. */
- char* title;
-
- /** The list of replay moments. Linked list. Time increases in list. */
- struct replay_moment* mom_first;
- /** The last element in list of replay moments. */
- struct replay_moment* mom_last;
-
- /**
- * List of matching answers. This is to ease replay scenario
- * creation. It lists queries (to the network) and what answer
- * should be returned. The matching answers are valid for a range
- * of time steps.
- * So: timestep, parts of query, destination --> answer.
- */
- struct replay_range* range_list;
-};
-
-/**
- * A replay moment.
- * Basically, it consists of events to a fake select() call.
- * This is a recording of an event that happens.
- * And if output is presented, what is done with that.
- */
-struct replay_moment {
- /**
- * The replay time step number. Starts at 0, time is incremented
- * every time the fake select() is run.
- */
- int time_step;
- /** Next replay moment in list of replay moments. */
- struct replay_moment* mom_next;
-
- /** what happens this moment? */
- enum replay_event_type {
- /** nothing happens, as if this event is not there. */
- repevt_nothing,
- /** incoming query */
- repevt_front_query,
- /** test fails if reply to query does not match */
- repevt_front_reply,
- /** timeout */
- repevt_timeout,
- /** time passes */
- repevt_time_passes,
- /** reply arrives from the network */
- repevt_back_reply,
- /** test fails if query to the network does not match */
- repevt_back_query,
- /** check autotrust key file */
- repevt_autotrust_check,
- /** an error happens to outbound query */
- repevt_error,
- /** assignment to a variable */
- repevt_assign,
- /** store infra rtt cache entry: addr and string (int) */
- repevt_infra_rtt,
- /** cause traffic to flow */
- repevt_traffic
- }
- /** variable with what is to happen this moment */
- evt_type;
-
- /** The sent packet must match this. Incoming events, the data. */
- struct entry* match;
-
- /** the amount of time that passes */
- struct timeval elapse;
-
- /** 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;
-
- /** macro name, for assign. */
- char* variable;
- /** string argument, for assign. */
- char* string;
-
- /** the autotrust file id to check */
- char* autotrust_id;
- /** file contents to match, one string per line */
- struct config_strlist* file_content;
-};
-
-/**
- * Range of timesteps, and canned replies to matching queries.
- */
-struct replay_range {
- /** time range when this is valid. Including start and end step. */
- 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;
-
- /** next in list of time ranges. */
- struct replay_range* next_range;
-};
-
-/**
- * Replay storage of runtime information.
- */
-struct replay_runtime {
- /**
- * The scenario
- */
- struct replay_scenario* scenario;
- /**
- * Current moment.
- */
- struct replay_moment* now;
-
- /**
- * List of pending queries in order they were sent out. First
- * one has been sent out most recently. Last one in list is oldest.
- */
- struct fake_pending* pending_list;
-
- /**
- * List of answers to queries from clients. These need to be checked.
- */
- struct replay_answer* answer_list;
-
- /** last element in answer list. */
- struct replay_answer* answer_last;
-
- /** list of fake timer callbacks that are pending */
- struct fake_timer* timer_list;
-
- /** callback to call for incoming queries */
- comm_point_callback_type* callback_query;
- /** user argument for incoming query callback */
- void *cb_arg;
-
- /** ref the infra cache (was passed to outside_network_create) */
- struct infra_cache* infra;
-
- /** the current time in seconds */
- time_t now_secs;
- /** the current time in microseconds */
- struct timeval now_tv;
-
- /** signal handler callback */
- void (*sig_cb)(int, void*);
- /** signal handler user arg */
- void *sig_cb_arg;
- /** time to exit cleanly */
- int exit_cleanly;
-
- /** size of buffers */
- size_t bufsize;
-
- /**
- * Tree of macro values. Of type replay_var
- */
- rbtree_type* vars;
-};
-
-/**
- * Pending queries to network, fake replay version.
- */
-struct fake_pending {
- /** what is important only that we remember the query, copied here. */
- struct sldns_buffer* buffer;
- /** and to what address this is sent to. */
- struct sockaddr_storage addr;
- /** len of addr */
- socklen_t addrlen;
- /** zone name, uncompressed wire format (as used when sent) */
- uint8_t* zone;
- /** length of zone name */
- size_t zonelen;
- /** qtype */
- int qtype;
- /** The callback function to call when answer arrives (or timeout) */
- comm_point_callback_type* callback;
- /** callback user argument */
- void* cb_arg;
- /** original timeout in seconds from 'then' */
- int timeout;
-
- /** next in pending list */
- struct fake_pending* next;
- /** the buffer parsed into a sldns_pkt */
- uint8_t* pkt;
- size_t pkt_len;
- /** 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;
-};
-
-/**
- * An answer that is pending to happen.
- */
-struct replay_answer {
- /** Next in list */
- struct replay_answer* next;
- /** reply information */
- struct comm_reply repinfo;
- /** the answer preparsed as ldns pkt */
- uint8_t* pkt;
- size_t pkt_len;
-};
-
-/**
- * Timers with callbacks, fake replay version.
- */
-struct fake_timer {
- /** next in list */
- struct fake_timer* next;
- /** the runtime structure this is part of */
- struct replay_runtime* runtime;
- /** the callback to call */
- void (*cb)(void*);
- /** the callback user argument */
- void* cb_arg;
- /** if timer is enabled */
- int enabled;
- /** when the timer expires */
- struct timeval tv;
-};
-
-/**
- * Replay macro variable. And its value.
- */
-struct replay_var {
- /** rbtree node. Key is this structure. Sorted by name. */
- rbnode_type node;
- /** the variable name */
- char* name;
- /** the variable value */
- char* value;
-};
-
-/**
- * Read a replay scenario from the file.
- * @param in: file to read from.
- * @param name: name to print in errors.
- * @param lineno: incremented for every line read.
- * @return: Scenario. NULL if no scenario read.
- */
-struct replay_scenario* replay_scenario_read(FILE* in, const char* name,
- int* lineno);
-
-/**
- * Delete scenario.
- * @param scen: to delete.
- */
-void replay_scenario_delete(struct replay_scenario* scen);
-
-/** compare two replay_vars */
-int replay_var_compare(const void* a, const void* b);
-
-/** get oldest enabled fake timer */
-struct fake_timer* replay_get_oldest_timer(struct replay_runtime* runtime);
-
-/**
- * Create variable storage
- * @return new or NULL on failure.
- */
-rbtree_type* macro_store_create(void);
-
-/**
- * Delete variable storage
- * @param store: the macro storage to free up.
- */
-void macro_store_delete(rbtree_type* store);
-
-/**
- * Apply macro substitution to string.
- * @param store: variable store.
- * @param runtime: the runtime to look up values as needed.
- * @param text: string to work on.
- * @return newly malloced string with result.
- */
-char* macro_process(rbtree_type* store, struct replay_runtime* runtime,
- char* text);
-
-/**
- * Look up a macro value. Like calling ${$name}.
- * @param store: variable store
- * @param name: macro name
- * @return newly malloced string with result or strdup("") if not found.
- * or NULL on malloc failure.
- */
-char* macro_lookup(rbtree_type* store, char* name);
-
-/**
- * Set macro value.
- * @param store: variable store
- * @param name: macro name
- * @param value: text to set it to. Not expanded.
- * @return false on failure.
- */
-int macro_assign(rbtree_type* store, char* name, char* value);
-
-/** Print macro variables stored as debug info */
-void macro_print_debug(rbtree_type* store);
-
-/** testbounds self test */
-void testbound_selftest(void);
-
-#endif /* TESTCODE_REPLAY_H */
diff --git a/external/unbound/testcode/run_vm.sh b/external/unbound/testcode/run_vm.sh
deleted file mode 100644
index 78649f07a..000000000
--- a/external/unbound/testcode/run_vm.sh
+++ /dev/null
@@ -1,78 +0,0 @@
-#!/usr/local/bin/bash
-# run tpkg tests from within a VM. Looks for loopback addr.
-# if run not from within a VM, runs the tests as usual.
-# with one argument: run that tpkg, otherwise, run all tpkgs.
-
-get_lo0_ip4() {
- if test -x /sbin/ifconfig
- then
- LO0_IP4=`/sbin/ifconfig lo0 | grep '[^0-9]127\.' | sed -e 's/^[^1]*\(127\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\)[^0-9]*.*$/\1/g'`
- if ( echo $LO0_IP4 | grep '^127\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*$' > /dev/null )
- then
- return
- fi
- fi
- LO0_IP4=127.0.0.1
-}
-get_lo0_ip4
-export LO0_IP4
-if test "x$LO0_IP4" = "x127.0.0.1"
-then
- ALT_LOOPBACK=false
-else
- ALT_LOOPBACK=true
-fi
-cd testdata
-TPKG=../testcode/mini_tpkg.sh
-#RUNLIST=`(ls -1 *.tpkg|grep -v '^0[016]')`
-RUNLIST=`(ls -1 *.tpkg)`
-if test "$#" = "1"; then RUNLIST="$1"; fi
-
-# fix up tpkg that was edited on keyboard interrupt.
-cleanup() {
- echo cleanup
- if test -f "$t.bak"; then mv "$t.bak" "$t"; fi
- exit 0
-}
-trap cleanup SIGINT
-
-for t in $RUNLIST
-do
- if ! $ALT_LOOPBACK
- then
- $TPKG exe $t
- continue
- fi
- # We have alternative 127.0.0.1 number
- if ( echo $t | grep '6\.tpkg$' ) # skip IPv6 tests
- then
- continue
- elif test "$t" = "edns_cache.tpkg" # This one is IPv6 too!
- then
- continue
- fi
- cp -p "$t" "$t.bak"
- tar xzf $t
- find "${t%.tpkg}.dir" -type f \
- -exec grep -q -e '127\.0\.0\.1' -e '@localhost' {} \; -print | {
- while read f
- do
- sed "s/127\.0\.0\.1/${LO0_IP4}/g" "$f" > "$f._"
- mv "$f._" "$f"
- sed "s/@localhost/@${LO0_IP4}/g" "$f" > "$f._"
- mv "$f._" "$f"
- done
- }
- find "${t%.tpkg}.dir" -type d -name "127.0.0.1" -print | {
- while read d
- do
- mv -v "$d" "${d%127.0.0.1}${LO0_IP4}"
- done
- }
- tar czf $t "${t%.tpkg}.dir"
- rm -fr "${t%.tpkg}.dir"
- $TPKG exe $t
- mv "$t.bak" "$t"
-done
-# get out of testdata/
-cd ..
diff --git a/external/unbound/testcode/signit.c b/external/unbound/testcode/signit.c
deleted file mode 100644
index 0eca0e088..000000000
--- a/external/unbound/testcode/signit.c
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * testcode/signit.c - debug tool to sign rrsets with given keys.
- *
- * 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 COPYRIGHT
- * HOLDER 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 signs rrsets with the given keys. It can be used to
- * construct input to test the validator with.
- */
-#include "config.h"
-#include <ldns/ldns.h>
-#include <assert.h>
-
-#define DNSKEY_BIT_ZSK 0x0100
-
-/**
- * Key settings
- */
-struct keysets {
- /** signature inception */
- uint32_t incep;
- /** signature expiration */
- uint32_t expi;
- /** owner name */
- char* owner;
- /** keytag */
- uint16_t keytag;
- /** DNSKEY flags */
- uint16_t flags;
-};
-
-/** print usage and exit */
-static void
-usage(void)
-{
- printf("usage: signit expi ince keytag owner keyfile\n");
- printf("present rrset data on stdin.\n");
- printf("signed data is printed to stdout.\n");
- printf("\n");
- printf("Or use: signit NSEC3PARAM hash flags iter salt\n");
- printf("present names on stdin, hashed names are printed to stdout.\n");
- exit(1);
-}
-
-static time_t
-convert_timeval(const char* str)
-{
- time_t t;
- struct tm tm;
- memset(&tm, 0, sizeof(tm));
- if(strlen(str) < 14)
- return 0;
- if(sscanf(str, "%4d%2d%2d%2d%2d%2d", &tm.tm_year, &tm.tm_mon,
- &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6)
- return 0;
- tm.tm_year -= 1900;
- tm.tm_mon--;
- /* Check values */
- if (tm.tm_year < 70) return 0;
- if (tm.tm_mon < 0 || tm.tm_mon > 11) return 0;
- if (tm.tm_mday < 1 || tm.tm_mday > 31) return 0;
- if (tm.tm_hour < 0 || tm.tm_hour > 23) return 0;
- if (tm.tm_min < 0 || tm.tm_min > 59) return 0;
- if (tm.tm_sec < 0 || tm.tm_sec > 59) return 0;
- /* call ldns conversion function */
- t = ldns_mktime_from_utc(&tm);
- return t;
-}
-
-static void fatal_exit(const char* format, ...)
-{
- va_list args;
- va_start(args, format);
- printf("fatal exit: ");
- vprintf(format, args);
- va_end(args);
- exit(1);
-}
-
-/** read expi ince keytag owner from cmdline */
-static void
-parse_cmdline(char *argv[], struct keysets* s)
-{
- s->expi = convert_timeval(argv[1]);
- s->incep = convert_timeval(argv[2]);
- s->keytag = (uint16_t)atoi(argv[3]);
- s->owner = argv[4];
- s->flags = DNSKEY_BIT_ZSK; /* to enforce signing */
-}
-
-/** read all key files, exit on error */
-static ldns_key_list*
-read_keys(int num, char* names[], struct keysets* set)
-{
- int i;
- ldns_key_list* keys = ldns_key_list_new();
- ldns_key* k;
- ldns_rdf* rdf;
- ldns_status s;
- int b;
- FILE* in;
-
- if(!keys) fatal_exit("alloc failure");
- for(i=0; i<num; i++) {
- printf("read keyfile %s\n", names[i]);
- in = fopen(names[i], "r");
- if(!in) fatal_exit("could not open %s: %s", names[i],
- strerror(errno));
- s = ldns_key_new_frm_fp(&k, in);
- fclose(in);
- if(s != LDNS_STATUS_OK)
- fatal_exit("bad keyfile %s: %s", names[i],
- ldns_get_errorstr_by_id(s));
- ldns_key_set_expiration(k, set->expi);
- ldns_key_set_inception(k, set->incep);
- s = ldns_str2rdf_dname(&rdf, set->owner);
- if(s != LDNS_STATUS_OK)
- fatal_exit("bad owner name %s: %s", set->owner,
- ldns_get_errorstr_by_id(s));
- ldns_key_set_pubkey_owner(k, rdf);
- ldns_key_set_flags(k, set->flags);
- ldns_key_set_keytag(k, set->keytag);
- b = ldns_key_list_push_key(keys, k);
- assert(b);
- }
- return keys;
-}
-
-/** read list of rrs from the file */
-static ldns_rr_list*
-read_rrs(FILE* in)
-{
- uint32_t my_ttl = 3600;
- ldns_rdf *my_origin = NULL;
- ldns_rdf *my_prev = NULL;
- ldns_status s;
- int line_nr = 1;
- int b;
-
- ldns_rr_list* list;
- ldns_rr *rr;
-
- list = ldns_rr_list_new();
- if(!list) fatal_exit("alloc error");
-
- while(!feof(in)) {
- s = ldns_rr_new_frm_fp_l(&rr, in, &my_ttl, &my_origin,
- &my_prev, &line_nr);
- if(s == LDNS_STATUS_SYNTAX_TTL ||
- s == LDNS_STATUS_SYNTAX_ORIGIN ||
- s == LDNS_STATUS_SYNTAX_EMPTY)
- continue;
- else if(s != LDNS_STATUS_OK)
- fatal_exit("parse error in line %d: %s", line_nr,
- ldns_get_errorstr_by_id(s));
- b = ldns_rr_list_push_rr(list, rr);
- assert(b);
- }
- printf("read %d lines\n", line_nr);
-
- return list;
-}
-
-/** sign the rrs with the keys */
-static void
-signit(ldns_rr_list* rrs, ldns_key_list* keys)
-{
- ldns_rr_list* rrset;
- ldns_rr_list* sigs;
-
- while(ldns_rr_list_rr_count(rrs) > 0) {
- rrset = ldns_rr_list_pop_rrset(rrs);
- if(!rrset) fatal_exit("copy alloc failure");
- sigs = ldns_sign_public(rrset, keys);
- if(!sigs) fatal_exit("failed to sign");
- ldns_rr_list_print(stdout, rrset);
- ldns_rr_list_print(stdout, sigs);
- printf("\n");
- ldns_rr_list_free(rrset);
- ldns_rr_list_free(sigs);
- }
-}
-
-/** process keys and signit */
-static void
-process_keys(int argc, char* argv[])
-{
- ldns_rr_list* rrs;
- ldns_key_list* keys;
- struct keysets settings;
- assert(argc == 6);
-
- parse_cmdline(argv, &settings);
- keys = read_keys(1, argv+5, &settings);
- rrs = read_rrs(stdin);
- signit(rrs, keys);
-
- ldns_rr_list_deep_free(rrs);
- ldns_key_list_free(keys);
-}
-
-/** process nsec3 params and perform hashing */
-static void
-process_nsec3(int argc, char* argv[])
-{
- char line[10240];
- ldns_rdf* salt;
- ldns_rdf* in, *out;
- ldns_status status;
- status = ldns_str2rdf_nsec3_salt(&salt, argv[5]);
- if(status != LDNS_STATUS_OK)
- fatal_exit("Could not parse salt %s: %s", argv[5],
- ldns_get_errorstr_by_id(status));
- assert(argc == 6);
- while(fgets(line, (int)sizeof(line), stdin)) {
- if(strlen(line) > 0)
- line[strlen(line)-1] = 0; /* remove trailing newline */
- if(line[0]==0)
- continue;
- status = ldns_str2rdf_dname(&in, line);
- if(status != LDNS_STATUS_OK)
- fatal_exit("Could not parse name %s: %s", line,
- ldns_get_errorstr_by_id(status));
- ldns_rdf_print(stdout, in);
- printf(" -> ");
- /* arg 3 is flags, unused */
- out = ldns_nsec3_hash_name(in, (uint8_t)atoi(argv[2]),
- (uint16_t)atoi(argv[4]),
- ldns_rdf_data(salt)[0], ldns_rdf_data(salt)+1);
- if(!out)
- fatal_exit("Could not hash %s", line);
- ldns_rdf_print(stdout, out);
- printf("\n");
- ldns_rdf_deep_free(in);
- ldns_rdf_deep_free(out);
- }
- ldns_rdf_deep_free(salt);
-}
-
-/** main program */
-int main(int argc, char* argv[])
-{
- if(argc != 6) {
- usage();
- }
- if(strcmp(argv[1], "NSEC3PARAM") == 0) {
- process_nsec3(argc, argv);
- return 0;
- }
- process_keys(argc, argv);
- return 0;
-}
diff --git a/external/unbound/testcode/streamtcp.1 b/external/unbound/testcode/streamtcp.1
deleted file mode 100644
index 7c738d9d2..000000000
--- a/external/unbound/testcode/streamtcp.1
+++ /dev/null
@@ -1,66 +0,0 @@
-.TH "unbound\-streamtcp" "1" "Mar 21, 2013" "NLnet Labs" "unbound"
-.\"
-.\" unbound-streamtcp.1 -- unbound DNS lookup utility
-.\"
-.SH "NAME"
-.LP
-.B unbound\-streamtcp
-\- unbound DNS lookup utility
-.SH "SYNOPSIS"
-.LP
-.B unbound\-streamtcp
-.RB [ \-unsh ]
-.RB [ \-f
-.IR ipaddr[@port] ]
-.I name
-.I type
-.I class
-.SH "DESCRIPTION"
-.LP
-.B unbound\-streamtcp
-sends a DNS Query of the given \fBtype\fR and \fBclass\fR for the given \fBname\fR
-to the DNS server over TCP and displays the response.
-.P
-If the server to query is not given using the \fB\-f\fR option then localhost
-(127.0.0.1) is used. More queries can be given on one commandline, they
-are resolved in sequence.
-.P
-The available options are:
-.TP
-.I name
-This name is resolved (looked up in the DNS).
-.TP
-.I type
-Specify the type of data to lookup.
-.TP
-.I class
-Specify the class to lookup for.
-.TP
-.B \-u
-Use UDP instead of TCP. No retries are attempted.
-.TP
-.B \-n
-Do not wait for the answer.
-.TP
-.B \-s
-Use SSL.
-.TP
-.B \-h
-Print program usage.
-.TP
-.B \-f \fIipaddr[@port]
-Specify the server to send the queries to. If not specified localhost (127.0.0.1) is used.
-.SH "EXAMPLES"
-.LP
-Some examples of use.
-.P
-$ unbound\-streamtcp www.example.com A IN
-.P
-$ unbound\-streamtcp \-f 192.168.1.1 www.example.com SOA IN
-.P
-$ unbound\-streamtcp \-f 192.168.1.1@1234 153.1.168.192.in\-addr.arpa. PTR IN
-.SH "EXIT CODE"
-The unbound\-streamtcp program exits with status code 1 on error,
-0 on no error.
-.SH "AUTHOR"
-This manual page was written by Tomas Hozza <thozza@redhat.com>.
diff --git a/external/unbound/testcode/streamtcp.c b/external/unbound/testcode/streamtcp.c
deleted file mode 100644
index 34b5c0281..000000000
--- a/external/unbound/testcode/streamtcp.c
+++ /dev/null
@@ -1,431 +0,0 @@
-/*
- * testcode/streamtcp.c - debug program perform multiple DNS queries on tcp.
- *
- * Copyright (c) 2008, 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 COPYRIGHT
- * HOLDER 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 performs multiple DNS queries on a TCP stream.
- */
-
-#include "config.h"
-#ifdef HAVE_GETOPT_H
-#include <getopt.h>
-#endif
-#include <signal.h>
-#include "util/locks.h"
-#include "util/log.h"
-#include "util/net_help.h"
-#include "util/data/msgencode.h"
-#include "util/data/msgparse.h"
-#include "util/data/msgreply.h"
-#include "util/data/dname.h"
-#include "sldns/sbuffer.h"
-#include "sldns/str2wire.h"
-#include "sldns/wire2str.h"
-#include <openssl/ssl.h>
-#include <openssl/rand.h>
-#include <openssl/err.h>
-
-#ifndef PF_INET6
-/** define in case streamtcp is compiled on legacy systems */
-#define PF_INET6 10
-#endif
-
-/** usage information for streamtcp */
-static void usage(char* argv[])
-{
- printf("usage: %s [options] name type class ...\n", argv[0]);
- printf(" sends the name-type-class queries over TCP.\n");
- printf("-f server what ipaddr@portnr to send the queries to\n");
- printf("-u use UDP. No retries are attempted.\n");
- printf("-n do not wait for an answer.\n");
- printf("-s use ssl\n");
- printf("-h this help text\n");
- exit(1);
-}
-
-/** open TCP socket to svr */
-static int
-open_svr(const char* svr, int udp)
-{
- struct sockaddr_storage addr;
- socklen_t addrlen;
- int fd = -1;
- /* svr can be ip@port */
- memset(&addr, 0, sizeof(addr));
- if(!extstrtoaddr(svr, &addr, &addrlen)) {
- printf("fatal: bad server specs '%s'\n", svr);
- exit(1);
- }
- fd = socket(addr_is_ip6(&addr, addrlen)?PF_INET6:PF_INET,
- udp?SOCK_DGRAM:SOCK_STREAM, 0);
- if(fd == -1) {
-#ifndef USE_WINSOCK
- perror("socket() error");
-#else
- printf("socket: %s\n", wsa_strerror(WSAGetLastError()));
-#endif
- exit(1);
- }
- if(connect(fd, (struct sockaddr*)&addr, addrlen) < 0) {
-#ifndef USE_WINSOCK
- perror("connect() error");
-#else
- printf("connect: %s\n", wsa_strerror(WSAGetLastError()));
-#endif
- exit(1);
- }
- return fd;
-}
-
-/** write a query over the TCP fd */
-static void
-write_q(int fd, int udp, SSL* ssl, sldns_buffer* buf, uint16_t id,
- const char* strname, const char* strtype, const char* strclass)
-{
- struct query_info qinfo;
- uint16_t len;
- /* qname */
- qinfo.qname = sldns_str2wire_dname(strname, &qinfo.qname_len);
- if(!qinfo.qname) {
- printf("cannot parse query name: '%s'\n", strname);
- exit(1);
- }
-
- /* qtype and qclass */
- qinfo.qtype = sldns_get_rr_type_by_name(strtype);
- qinfo.qclass = sldns_get_rr_class_by_name(strclass);
-
- /* clear local alias */
- qinfo.local_alias = NULL;
-
- /* make query */
- qinfo_query_encode(buf, &qinfo);
- sldns_buffer_write_u16_at(buf, 0, id);
- sldns_buffer_write_u16_at(buf, 2, BIT_RD);
-
- if(1) {
- /* add EDNS DO */
- struct edns_data edns;
- memset(&edns, 0, sizeof(edns));
- edns.edns_present = 1;
- edns.bits = EDNS_DO;
- edns.udp_size = 4096;
- attach_edns_record(buf, &edns);
- }
-
- /* send it */
- if(!udp) {
- len = (uint16_t)sldns_buffer_limit(buf);
- len = htons(len);
- if(ssl) {
- if(SSL_write(ssl, (void*)&len, (int)sizeof(len)) <= 0) {
- log_crypto_err("cannot SSL_write");
- exit(1);
- }
- } else {
- if(send(fd, (void*)&len, sizeof(len), 0) <
- (ssize_t)sizeof(len)){
-#ifndef USE_WINSOCK
- perror("send() len failed");
-#else
- printf("send len: %s\n",
- wsa_strerror(WSAGetLastError()));
-#endif
- exit(1);
- }
- }
- }
- if(ssl) {
- if(SSL_write(ssl, (void*)sldns_buffer_begin(buf),
- (int)sldns_buffer_limit(buf)) <= 0) {
- log_crypto_err("cannot SSL_write");
- exit(1);
- }
- } else {
- if(send(fd, (void*)sldns_buffer_begin(buf),
- sldns_buffer_limit(buf), 0) <
- (ssize_t)sldns_buffer_limit(buf)) {
-#ifndef USE_WINSOCK
- perror("send() data failed");
-#else
- printf("send data: %s\n", wsa_strerror(WSAGetLastError()));
-#endif
- exit(1);
- }
- }
-
- free(qinfo.qname);
-}
-
-/** receive DNS datagram over TCP and print it */
-static void
-recv_one(int fd, int udp, SSL* ssl, sldns_buffer* buf)
-{
- char* pktstr;
- uint16_t len;
- if(!udp) {
- if(ssl) {
- if(SSL_read(ssl, (void*)&len, (int)sizeof(len)) <= 0) {
- log_crypto_err("could not SSL_read");
- exit(1);
- }
- } else {
- if(recv(fd, (void*)&len, sizeof(len), 0) <
- (ssize_t)sizeof(len)) {
-#ifndef USE_WINSOCK
- perror("read() len failed");
-#else
- printf("read len: %s\n",
- wsa_strerror(WSAGetLastError()));
-#endif
- exit(1);
- }
- }
- len = ntohs(len);
- sldns_buffer_clear(buf);
- sldns_buffer_set_limit(buf, len);
- if(ssl) {
- int r = SSL_read(ssl, (void*)sldns_buffer_begin(buf),
- (int)len);
- if(r <= 0) {
- log_crypto_err("could not SSL_read");
- exit(1);
- }
- if(r != (int)len)
- fatal_exit("ssl_read %d of %d", r, len);
- } else {
- if(recv(fd, (void*)sldns_buffer_begin(buf), len, 0) <
- (ssize_t)len) {
-#ifndef USE_WINSOCK
- perror("read() data failed");
-#else
- printf("read data: %s\n",
- wsa_strerror(WSAGetLastError()));
-#endif
- exit(1);
- }
- }
- } else {
- ssize_t l;
- sldns_buffer_clear(buf);
- if((l=recv(fd, (void*)sldns_buffer_begin(buf),
- sldns_buffer_capacity(buf), 0)) < 0) {
-#ifndef USE_WINSOCK
- perror("read() data failed");
-#else
- printf("read data: %s\n",
- wsa_strerror(WSAGetLastError()));
-#endif
- exit(1);
- }
- sldns_buffer_set_limit(buf, (size_t)l);
- len = (size_t)l;
- }
- printf("\nnext received packet\n");
- log_buf(0, "data", buf);
-
- pktstr = sldns_wire2str_pkt(sldns_buffer_begin(buf), len);
- printf("%s", pktstr);
- free(pktstr);
-}
-
-static int get_random(void)
-{
- int r;
- if (RAND_bytes((unsigned char*)&r, (int)sizeof(r)) == 1) {
- return r;
- }
- return arc4random();
-}
-
-/** send the TCP queries and print answers */
-static void
-send_em(const char* svr, int udp, int usessl, int noanswer, int num, char** qs)
-{
- sldns_buffer* buf = sldns_buffer_new(65553);
- int fd = open_svr(svr, udp);
- int i;
- SSL_CTX* ctx = NULL;
- SSL* ssl = NULL;
- if(!buf) fatal_exit("out of memory");
- if(usessl) {
- ctx = connect_sslctx_create(NULL, NULL, NULL);
- if(!ctx) fatal_exit("cannot create ssl ctx");
- ssl = outgoing_ssl_fd(ctx, fd);
- if(!ssl) fatal_exit("cannot create ssl");
- while(1) {
- int r;
- ERR_clear_error();
- if( (r=SSL_do_handshake(ssl)) == 1)
- break;
- r = SSL_get_error(ssl, r);
- if(r != SSL_ERROR_WANT_READ &&
- r != SSL_ERROR_WANT_WRITE) {
- log_crypto_err("could not ssl_handshake");
- exit(1);
- }
- }
- if(1) {
- X509* x = SSL_get_peer_certificate(ssl);
- if(!x) printf("SSL: no peer certificate\n");
- else {
- X509_print_fp(stdout, x);
- X509_free(x);
- }
- }
- }
- for(i=0; i<num; i+=3) {
- printf("\nNext query is %s %s %s\n", qs[i], qs[i+1], qs[i+2]);
- write_q(fd, udp, ssl, buf, (uint16_t)get_random(), qs[i],
- qs[i+1], qs[i+2]);
- /* print at least one result */
- if(!noanswer)
- recv_one(fd, udp, ssl, buf);
- }
-
- if(usessl) {
- SSL_shutdown(ssl);
- SSL_free(ssl);
- SSL_CTX_free(ctx);
- }
-#ifndef USE_WINSOCK
- close(fd);
-#else
- closesocket(fd);
-#endif
- sldns_buffer_free(buf);
- printf("orderly exit\n");
-}
-
-#ifdef SIGPIPE
-/** SIGPIPE handler */
-static RETSIGTYPE sigh(int sig)
-{
- if(sig == SIGPIPE) {
- printf("got SIGPIPE, remote connection gone\n");
- exit(1);
- }
- printf("Got unhandled signal %d\n", sig);
- exit(1);
-}
-#endif /* SIGPIPE */
-
-/** getopt global, in case header files fail to declare it. */
-extern int optind;
-/** getopt global, in case header files fail to declare it. */
-extern char* optarg;
-
-/** main program for streamtcp */
-int main(int argc, char** argv)
-{
- int c;
- const char* svr = "127.0.0.1";
- int udp = 0;
- int noanswer = 0;
- int usessl = 0;
-
-#ifdef USE_WINSOCK
- WSADATA wsa_data;
- if(WSAStartup(MAKEWORD(2,2), &wsa_data) != 0) {
- printf("WSAStartup failed\n");
- return 1;
- }
-#endif
-
- /* lock debug start (if any) */
- log_init(0, 0, 0);
- checklock_start();
-
-#ifdef SIGPIPE
- if(signal(SIGPIPE, &sigh) == SIG_ERR) {
- perror("could not install signal handler");
- return 1;
- }
-#endif
-
- /* command line options */
- if(argc == 1) {
- usage(argv);
- }
- while( (c=getopt(argc, argv, "f:hnsu")) != -1) {
- switch(c) {
- case 'f':
- svr = optarg;
- break;
- case 'n':
- noanswer = 1;
- break;
- case 'u':
- udp = 1;
- break;
- case 's':
- usessl = 1;
- break;
- case 'h':
- case '?':
- default:
- usage(argv);
- }
- }
- argc -= optind;
- argv += optind;
-
- if(argc % 3 != 0) {
- printf("queries must be multiples of name,type,class\n");
- return 1;
- }
- if(usessl) {
- ERR_load_SSL_strings();
-#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_CRYPTO)
- OpenSSL_add_all_algorithms();
-#else
- OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
- | OPENSSL_INIT_ADD_ALL_DIGESTS
- | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
-#endif
-#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
- (void)SSL_library_init();
-#else
- (void)OPENSSL_init_ssl(0, NULL);
-#endif
- }
- send_em(svr, udp, usessl, noanswer, argc, argv);
- checklock_stop();
-#ifdef USE_WINSOCK
- WSACleanup();
-#endif
- return 0;
-}
diff --git a/external/unbound/testcode/testbound.c b/external/unbound/testcode/testbound.c
deleted file mode 100644
index 180b2c256..000000000
--- a/external/unbound/testcode/testbound.c
+++ /dev/null
@@ -1,470 +0,0 @@
-/*
- * testcode/testbound.c - test program for unbound.
- *
- * 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 COPYRIGHT
- * HOLDER 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
- * Exits with code 1 on a failure. 0 if all unit tests are successful.
- */
-
-#include "config.h"
-#ifdef HAVE_TIME_H
-# include <time.h>
-#endif
-#include "testcode/testpkts.h"
-#include "testcode/replay.h"
-#include "testcode/fake_event.h"
-#include "daemon/remote.h"
-#include "util/config_file.h"
-#include "sldns/keyraw.h"
-#include <ctype.h>
-
-/** signal that this is a testbound compile */
-#define unbound_testbound 1
-/**
- * include the main program from the unbound daemon.
- * rename main to daemon_main to call it
- */
-#define main daemon_main
-#include "daemon/unbound.c"
-#undef main
-
-/** maximum line length for lines in the replay file. */
-#define MAX_LINE_LEN 1024
-/** config files (removed at exit) */
-static struct config_strlist* cfgfiles = NULL;
-
-/** give commandline usage for testbound. */
-static void
-testbound_usage(void)
-{
- printf("usage: testbound [options]\n");
- printf("\ttest the unbound daemon.\n");
- printf("-h this help\n");
- printf("-p file playback text file\n");
- printf("-1 detect SHA1 support (exit code 0 or 1)\n");
- printf("-2 detect SHA256 support (exit code 0 or 1)\n");
- printf("-g detect GOST support (exit code 0 or 1)\n");
- printf("-e detect ECDSA support (exit code 0 or 1)\n");
- printf("-c detect CLIENT_SUBNET support (exit code 0 or 1)\n");
- printf("-s testbound self-test - unit test of testbound parts.\n");
- printf("-o str unbound commandline options separated by spaces.\n");
- printf("Version %s\n", PACKAGE_VERSION);
- printf("BSD licensed, see LICENSE file in source package.\n");
- printf("Report bugs to %s.\n", PACKAGE_BUGREPORT);
-}
-
-/** Max number of arguments to pass to unbound. */
-#define MAXARG 100
-
-/**
- * Add options from string to passed argc. splits on whitespace.
- * @param args: the option argument, "-v -p 12345" or so.
- * @param pass_argc: ptr to the argc for unbound. Modified.
- * @param pass_argv: the argv to pass to unbound. Modified.
- */
-static void
-add_opts(const char* args, int* pass_argc, char* pass_argv[])
-{
- const char *p = args, *np;
- size_t len;
- while(p && isspace((unsigned char)*p))
- p++;
- while(p && *p) {
- /* find location of next string and length of this one */
- if((np = strchr(p, ' ')))
- len = (size_t)(np-p);
- else len = strlen(p);
- /* allocate and copy option */
- if(*pass_argc >= MAXARG-1)
- fatal_exit("too many arguments: '%s'", p);
- pass_argv[*pass_argc] = (char*)malloc(len+1);
- if(!pass_argv[*pass_argc])
- fatal_exit("add_opts: out of memory");
- memcpy(pass_argv[*pass_argc], p, len);
- pass_argv[*pass_argc][len] = 0;
- (*pass_argc)++;
- /* go to next option */
- p = np;
- while(p && isspace((unsigned char)*p))
- p++;
- }
-}
-
-/** pretty print commandline for unbound in this test */
-static void
-echo_cmdline(int argc, char* argv[])
-{
- int i;
- fprintf(stderr, "testbound is starting:");
- for(i=0; i<argc; i++) {
- fprintf(stderr, " [%s]", argv[i]);
- }
- fprintf(stderr, "\n");
-}
-
-/** spool autotrust file */
-static void
-spool_auto_file(FILE* in, int* lineno, FILE* cfg, char* id)
-{
- char line[MAX_LINE_LEN];
- char* parse;
- FILE* spool;
- /* find filename for new file */
- while(isspace((unsigned char)*id))
- id++;
- if(*id == '\0')
- fatal_exit("AUTROTRUST_FILE must have id, line %d", *lineno);
- id[strlen(id)-1]=0; /* remove newline */
- fake_temp_file("_auto_", id, line, sizeof(line));
- /* add option for the file */
- fprintf(cfg, "server: auto-trust-anchor-file: \"%s\"\n", line);
- /* open file and spool to it */
- spool = fopen(line, "w");
- if(!spool) fatal_exit("could not open %s: %s", line, strerror(errno));
- fprintf(stderr, "testbound is spooling key file: %s\n", line);
- if(!cfg_strlist_insert(&cfgfiles, strdup(line)))
- fatal_exit("out of memory");
- line[sizeof(line)-1] = 0;
- while(fgets(line, MAX_LINE_LEN-1, in)) {
- parse = line;
- (*lineno)++;
- while(isspace((unsigned char)*parse))
- parse++;
- if(strncmp(parse, "AUTOTRUST_END", 13) == 0) {
- fclose(spool);
- return;
- }
- fputs(line, spool);
- }
- fatal_exit("no AUTOTRUST_END in input file");
-}
-
-/** process config elements */
-static void
-setup_config(FILE* in, int* lineno, int* pass_argc, char* pass_argv[])
-{
- char configfile[MAX_LINE_LEN];
- char line[MAX_LINE_LEN];
- char* parse;
- FILE* cfg;
- fake_temp_file("_cfg", "", configfile, sizeof(configfile));
- add_opts("-c", pass_argc, pass_argv);
- add_opts(configfile, pass_argc, pass_argv);
- cfg = fopen(configfile, "w");
- if(!cfg) fatal_exit("could not open %s: %s",
- configfile, strerror(errno));
- if(!cfg_strlist_insert(&cfgfiles, strdup(configfile)))
- fatal_exit("out of memory");
- line[sizeof(line)-1] = 0;
- /* some basic settings to not pollute the host system */
- fprintf(cfg, "server: use-syslog: no\n");
- fprintf(cfg, " directory: \"\"\n");
- fprintf(cfg, " chroot: \"\"\n");
- fprintf(cfg, " username: \"\"\n");
- fprintf(cfg, " pidfile: \"\"\n");
- fprintf(cfg, " val-log-level: 2\n");
- fprintf(cfg, "remote-control: control-enable: no\n");
- while(fgets(line, MAX_LINE_LEN-1, in)) {
- parse = line;
- (*lineno)++;
- while(isspace((unsigned char)*parse))
- parse++;
- if(!*parse || parse[0] == ';')
- continue;
- if(strncmp(parse, "COMMANDLINE", 11) == 0) {
- parse[strlen(parse)-1] = 0; /* strip off \n */
- add_opts(parse+11, pass_argc, pass_argv);
- continue;
- }
- if(strncmp(parse, "AUTOTRUST_FILE", 14) == 0) {
- spool_auto_file(in, lineno, cfg, parse+14);
- continue;
- }
- if(strncmp(parse, "CONFIG_END", 10) == 0) {
- fclose(cfg);
- return;
- }
- fputs(line, cfg);
- }
- fatal_exit("No CONFIG_END in input file");
-
-}
-
-/** read playback file */
-static struct replay_scenario*
-setup_playback(const char* filename, int* pass_argc, char* pass_argv[])
-{
- struct replay_scenario* scen = NULL;
- int lineno = 0;
-
- if(filename) {
- FILE *in = fopen(filename, "rb");
- if(!in) {
- perror(filename);
- exit(1);
- }
- setup_config(in, &lineno, pass_argc, pass_argv);
- scen = replay_scenario_read(in, filename, &lineno);
- fclose(in);
- if(!scen)
- fatal_exit("Could not read: %s", filename);
- }
- else fatal_exit("need a playback file (-p)");
- log_info("Scenario: %s", scen->title);
- return scen;
-}
-
-/** remove config file at exit */
-void remove_configfile(void)
-{
- struct config_strlist* p;
- for(p=cfgfiles; p; p=p->next)
- unlink(p->str);
- config_delstrlist(cfgfiles);
- cfgfiles = NULL;
-}
-
-/**
- * Main fake event test program. Setup, teardown and report errors.
- * @param argc: arg count.
- * @param argv: array of commandline arguments.
- * @return program failure if test fails.
- */
-int
-main(int argc, char* argv[])
-{
- int c, res;
- int pass_argc = 0;
- char* pass_argv[MAXARG];
- char* playback_file = NULL;
- int init_optind = optind;
- char* init_optarg = optarg;
- struct replay_scenario* scen = NULL;
-
- /* we do not want the test to depend on the timezone */
- (void)putenv("TZ=UTC");
-
- log_init(NULL, 0, NULL);
- /* determine commandline options for the daemon */
- pass_argc = 1;
- pass_argv[0] = "unbound";
- add_opts("-d", &pass_argc, pass_argv);
- while( (c=getopt(argc, argv, "12egho:p:s")) != -1) {
- switch(c) {
- case 's':
- free(pass_argv[1]);
- testbound_selftest();
- exit(0);
- case '1':
-#ifdef USE_SHA1
- printf("SHA1 supported\n");
- exit(0);
-#else
- printf("SHA1 not supported\n");
- exit(1);
-#endif
- break;
- case '2':
-#if (defined(HAVE_EVP_SHA256) || defined(HAVE_NSS) || defined(HAVE_NETTLE)) && defined(USE_SHA2)
- printf("SHA256 supported\n");
- exit(0);
-#else
- printf("SHA256 not supported\n");
- exit(1);
-#endif
- break;
- case 'e':
-#if defined(USE_ECDSA)
- printf("ECDSA supported\n");
- exit(0);
-#else
- printf("ECDSA not supported\n");
- exit(1);
-#endif
- break;
- case 'g':
-#ifdef USE_GOST
- if(sldns_key_EVP_load_gost_id()) {
- printf("GOST supported\n");
- exit(0);
- } else {
- printf("GOST not supported\n");
- exit(1);
- }
-#else
- printf("GOST not supported\n");
- exit(1);
-#endif
- break;
- case 'c':
-#ifdef CLIENT_SUBNET
- printf("CLIENT_SUBNET supported\n");
- exit(0);
-#else
- printf("CLIENT_SUBNET not supported\n");
- exit(1);
-#endif
- break;
- case 'p':
- playback_file = optarg;
- break;
- case 'o':
- add_opts(optarg, &pass_argc, pass_argv);
- break;
- case '?':
- case 'h':
- default:
- testbound_usage();
- return 1;
- }
- }
- argc -= optind;
- argv += optind;
- if(argc != 0) {
- testbound_usage();
- return 1;
- }
- log_info("Start of %s testbound program.", PACKAGE_STRING);
- if(atexit(&remove_configfile) != 0)
- fatal_exit("atexit() failed: %s", strerror(errno));
-
- /* setup test environment */
- scen = setup_playback(playback_file, &pass_argc, pass_argv);
- /* init fake event backend */
- fake_event_init(scen);
-
- pass_argv[pass_argc] = NULL;
- echo_cmdline(pass_argc, pass_argv);
-
- /* reset getopt processing */
- optind = init_optind;
- optarg = init_optarg;
-
- /* run the normal daemon */
- res = daemon_main(pass_argc, pass_argv);
-
- fake_event_cleanup();
- for(c=1; c<pass_argc; c++)
- free(pass_argv[c]);
- if(res == 0) {
- log_info("Testbound Exit Success");
-#ifdef HAVE_PTHREAD
- /* dlopen frees its thread state (dlopen of gost engine) */
- pthread_exit(NULL);
-#endif
- }
- return res;
-}
-
-/* fake remote control */
-struct listen_port* daemon_remote_open_ports(struct config_file*
- ATTR_UNUSED(cfg))
-{
- return NULL;
-}
-
-struct daemon_remote* daemon_remote_create(struct config_file* ATTR_UNUSED(cfg))
-{
- return (struct daemon_remote*)calloc(1,1);
-}
-
-void daemon_remote_delete(struct daemon_remote* rc)
-{
- free(rc);
-}
-
-void daemon_remote_clear(struct daemon_remote* ATTR_UNUSED(rc))
-{
- /* nothing */
-}
-
-int daemon_remote_open_accept(struct daemon_remote* ATTR_UNUSED(rc),
- struct listen_port* ATTR_UNUSED(ports),
- struct worker* ATTR_UNUSED(worker))
-{
- return 1;
-}
-
-int remote_accept_callback(struct comm_point* ATTR_UNUSED(c),
- void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
- struct comm_reply* ATTR_UNUSED(repinfo))
-{
- log_assert(0);
- return 0;
-}
-
-int remote_control_callback(struct comm_point* ATTR_UNUSED(c),
- void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
- struct comm_reply* ATTR_UNUSED(repinfo))
-{
- log_assert(0);
- return 0;
-}
-
-void remote_get_opt_ssl(char* ATTR_UNUSED(str), void* ATTR_UNUSED(arg))
-{
- log_assert(0);
-}
-
-void wsvc_command_option(const char* ATTR_UNUSED(wopt),
- const char* ATTR_UNUSED(cfgfile), int ATTR_UNUSED(v),
- int ATTR_UNUSED(c))
-{
- log_assert(0);
-}
-
-void wsvc_setup_worker(struct worker* ATTR_UNUSED(worker))
-{
- /* do nothing */
-}
-
-void wsvc_desetup_worker(struct worker* ATTR_UNUSED(worker))
-{
- /* do nothing */
-}
-
-#ifdef UB_ON_WINDOWS
-void worker_win_stop_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
- void* ATTR_UNUSED(arg))
-{
- log_assert(0);
-}
-
-void wsvc_cron_cb(void* ATTR_UNUSED(arg))
-{
- log_assert(0);
-}
-#endif /* UB_ON_WINDOWS */
-
diff --git a/external/unbound/testcode/testpkts.c b/external/unbound/testcode/testpkts.c
deleted file mode 100644
index e1a7768ab..000000000
--- a/external/unbound/testcode/testpkts.c
+++ /dev/null
@@ -1,1697 +0,0 @@
-/*
- * testpkts. Data file parse for test packets, and query matching.
- *
- * Data storage for specially crafted replies for testing purposes.
- *
- * (c) NLnet Labs, 2005, 2006, 2007, 2008
- * See the file LICENSE for the license
- */
-
-/**
- * \file
- * This is a debugging aid. It is not efficient, especially
- * with a long config file, but it can give any reply to any query.
- * This can help the developer pre-script replies for queries.
- *
- * You can specify a packet RR by RR with header flags to return.
- *
- * Missing features:
- * - matching content different from reply content.
- * - find way to adjust mangled packets?
- */
-
-#include "config.h"
-struct sockaddr_storage;
-#include <errno.h>
-#include <stdarg.h>
-#include <ctype.h>
-#include "testcode/testpkts.h"
-#include "util/net_help.h"
-#include "sldns/sbuffer.h"
-#include "sldns/rrdef.h"
-#include "sldns/pkthdr.h"
-#include "sldns/str2wire.h"
-#include "sldns/wire2str.h"
-
-/** max size of a packet */
-#define MAX_PACKETLEN 65536
-/** max line length */
-#define MAX_LINE 10240
-/** string to show in warnings and errors */
-static const char* prog_name = "testpkts";
-
-#ifndef UTIL_LOG_H
-/** verbosity definition for compat */
-enum verbosity_value { NO_VERBOSE=0 };
-#endif
-/** logging routine, provided by caller */
-void verbose(enum verbosity_value lvl, const char* msg, ...) ATTR_FORMAT(printf, 2, 3);
-
-/** print error and exit */
-static void error(const char* msg, ...)
-{
- va_list args;
- va_start(args, msg);
- fprintf(stderr, "%s error: ", prog_name);
- vfprintf(stderr, msg, args);
- fprintf(stderr, "\n");
- fflush(stderr);
- va_end(args);
- exit(EXIT_FAILURE);
-}
-
-/** return if string is empty or comment */
-static int isendline(char c)
-{
- if(c == ';' || c == '#'
- || c == '\n' || c == 0)
- return 1;
- return 0;
-}
-
-/** true if the string starts with the keyword given. Moves the str ahead.
- * @param str: before keyword, afterwards after keyword and spaces.
- * @param keyword: the keyword to match
- * @return: true if keyword present. False otherwise, and str unchanged.
-*/
-static int str_keyword(char** str, const char* keyword)
-{
- size_t len = strlen(keyword);
- assert(str && keyword);
- if(strncmp(*str, keyword, len) != 0)
- return 0;
- *str += len;
- while(isspace((unsigned char)**str))
- (*str)++;
- return 1;
-}
-
-/** Add reply packet to entry */
-static struct reply_packet*
-entry_add_reply(struct entry* entry)
-{
- struct reply_packet* pkt = (struct reply_packet*)malloc(
- sizeof(struct reply_packet));
- struct reply_packet ** p = &entry->reply_list;
- if(!pkt) error("out of memory");
- pkt->next = NULL;
- pkt->packet_sleep = 0;
- pkt->reply_pkt = NULL;
- pkt->reply_from_hex = NULL;
- pkt->raw_ednsdata = NULL;
- /* link at end */
- while(*p)
- p = &((*p)->next);
- *p = pkt;
- return pkt;
-}
-
-/** parse MATCH line */
-static void matchline(char* line, struct entry* e)
-{
- char* parse = line;
- while(*parse) {
- if(isendline(*parse))
- return;
- if(str_keyword(&parse, "opcode")) {
- e->match_opcode = 1;
- } else if(str_keyword(&parse, "qtype")) {
- e->match_qtype = 1;
- } else if(str_keyword(&parse, "qname")) {
- e->match_qname = 1;
- } else if(str_keyword(&parse, "rcode")) {
- e->match_rcode = 1;
- } else if(str_keyword(&parse, "question")) {
- e->match_question = 1;
- } else if(str_keyword(&parse, "answer")) {
- e->match_answer = 1;
- } else if(str_keyword(&parse, "subdomain")) {
- e->match_subdomain = 1;
- } else if(str_keyword(&parse, "all")) {
- e->match_all = 1;
- } else if(str_keyword(&parse, "ttl")) {
- e->match_ttl = 1;
- } else if(str_keyword(&parse, "DO")) {
- e->match_do = 1;
- } else if(str_keyword(&parse, "noedns")) {
- e->match_noedns = 1;
- } else if(str_keyword(&parse, "ednsdata")) {
- e->match_ednsdata_raw = 1;
- } else if(str_keyword(&parse, "UDP")) {
- e->match_transport = transport_udp;
- } else if(str_keyword(&parse, "TCP")) {
- e->match_transport = transport_tcp;
- } else if(str_keyword(&parse, "serial")) {
- e->match_serial = 1;
- if(*parse != '=' && *parse != ':')
- error("expected = or : in MATCH: %s", line);
- parse++;
- e->ixfr_soa_serial = (uint32_t)strtol(parse, (char**)&parse, 10);
- while(isspace((unsigned char)*parse))
- parse++;
- } else {
- error("could not parse MATCH: '%s'", parse);
- }
- }
-}
-
-/** parse REPLY line */
-static void replyline(char* line, uint8_t* reply, size_t reply_len,
- int* do_flag)
-{
- char* parse = line;
- if(reply_len < LDNS_HEADER_SIZE) error("packet too short for header");
- while(*parse) {
- if(isendline(*parse))
- return;
- /* opcodes */
- if(str_keyword(&parse, "QUERY")) {
- LDNS_OPCODE_SET(reply, LDNS_PACKET_QUERY);
- } else if(str_keyword(&parse, "IQUERY")) {
- LDNS_OPCODE_SET(reply, LDNS_PACKET_IQUERY);
- } else if(str_keyword(&parse, "STATUS")) {
- LDNS_OPCODE_SET(reply, LDNS_PACKET_STATUS);
- } else if(str_keyword(&parse, "NOTIFY")) {
- LDNS_OPCODE_SET(reply, LDNS_PACKET_NOTIFY);
- } else if(str_keyword(&parse, "UPDATE")) {
- LDNS_OPCODE_SET(reply, LDNS_PACKET_UPDATE);
- /* rcodes */
- } else if(str_keyword(&parse, "NOERROR")) {
- LDNS_RCODE_SET(reply, LDNS_RCODE_NOERROR);
- } else if(str_keyword(&parse, "FORMERR")) {
- LDNS_RCODE_SET(reply, LDNS_RCODE_FORMERR);
- } else if(str_keyword(&parse, "SERVFAIL")) {
- LDNS_RCODE_SET(reply, LDNS_RCODE_SERVFAIL);
- } else if(str_keyword(&parse, "NXDOMAIN")) {
- LDNS_RCODE_SET(reply, LDNS_RCODE_NXDOMAIN);
- } else if(str_keyword(&parse, "NOTIMPL")) {
- LDNS_RCODE_SET(reply, LDNS_RCODE_NOTIMPL);
- } else if(str_keyword(&parse, "REFUSED")) {
- LDNS_RCODE_SET(reply, LDNS_RCODE_REFUSED);
- } else if(str_keyword(&parse, "YXDOMAIN")) {
- LDNS_RCODE_SET(reply, LDNS_RCODE_YXDOMAIN);
- } else if(str_keyword(&parse, "YXRRSET")) {
- LDNS_RCODE_SET(reply, LDNS_RCODE_YXRRSET);
- } else if(str_keyword(&parse, "NXRRSET")) {
- LDNS_RCODE_SET(reply, LDNS_RCODE_NXRRSET);
- } else if(str_keyword(&parse, "NOTAUTH")) {
- LDNS_RCODE_SET(reply, LDNS_RCODE_NOTAUTH);
- } else if(str_keyword(&parse, "NOTZONE")) {
- LDNS_RCODE_SET(reply, LDNS_RCODE_NOTZONE);
- /* flags */
- } else if(str_keyword(&parse, "QR")) {
- LDNS_QR_SET(reply);
- } else if(str_keyword(&parse, "AA")) {
- LDNS_AA_SET(reply);
- } else if(str_keyword(&parse, "TC")) {
- LDNS_TC_SET(reply);
- } else if(str_keyword(&parse, "RD")) {
- LDNS_RD_SET(reply);
- } else if(str_keyword(&parse, "CD")) {
- LDNS_CD_SET(reply);
- } else if(str_keyword(&parse, "RA")) {
- LDNS_RA_SET(reply);
- } else if(str_keyword(&parse, "AD")) {
- LDNS_AD_SET(reply);
- } else if(str_keyword(&parse, "DO")) {
- *do_flag = 1;
- } else {
- error("could not parse REPLY: '%s'", parse);
- }
- }
-}
-
-/** parse ADJUST line */
-static void adjustline(char* line, struct entry* e,
- struct reply_packet* pkt)
-{
- char* parse = line;
- while(*parse) {
- if(isendline(*parse))
- return;
- if(str_keyword(&parse, "copy_id")) {
- e->copy_id = 1;
- } else if(str_keyword(&parse, "copy_query")) {
- e->copy_query = 1;
- } else if(str_keyword(&parse, "copy_ednsdata_assume_clientsubnet")) {
- e->copy_ednsdata_assume_clientsubnet = 1;
- } else if(str_keyword(&parse, "sleep=")) {
- e->sleeptime = (unsigned int) strtol(parse, (char**)&parse, 10);
- while(isspace((unsigned char)*parse))
- parse++;
- } else if(str_keyword(&parse, "packet_sleep=")) {
- pkt->packet_sleep = (unsigned int) strtol(parse, (char**)&parse, 10);
- while(isspace((unsigned char)*parse))
- parse++;
- } else {
- error("could not parse ADJUST: '%s'", parse);
- }
- }
-}
-
-/** create new entry */
-static struct entry* new_entry(void)
-{
- struct entry* e = (struct entry*)malloc(sizeof(struct entry));
- if(!e) error("out of memory");
- memset(e, 0, sizeof(*e));
- e->match_opcode = 0;
- e->match_qtype = 0;
- e->match_qname = 0;
- e->match_rcode = 0;
- e->match_question = 0;
- e->match_answer = 0;
- e->match_subdomain = 0;
- e->match_all = 0;
- e->match_ttl = 0;
- e->match_do = 0;
- e->match_noedns = 0;
- e->match_serial = 0;
- e->ixfr_soa_serial = 0;
- e->match_transport = transport_any;
- e->reply_list = NULL;
- e->copy_id = 0;
- e->copy_query = 0;
- e->copy_ednsdata_assume_clientsubnet = 0;
- e->sleeptime = 0;
- e->next = NULL;
- return e;
-}
-
-/**
- * Converts a hex string to binary data
- * @param hexstr: string of hex.
- * @param len: is the length of the string
- * @param buf: is the buffer to store the result in
- * @param offset: is the starting position in the result buffer
- * @param buf_len: is the length of buf.
- * @return This function returns the length of the result
- */
-static size_t
-hexstr2bin(char *hexstr, int len, uint8_t *buf, size_t offset, size_t buf_len)
-{
- char c;
- int i;
- uint8_t int8 = 0;
- int sec = 0;
- size_t bufpos = 0;
-
- if (len % 2 != 0) {
- return 0;
- }
-
- for (i=0; i<len; i++) {
- c = hexstr[i];
-
- /* case insensitive, skip spaces */
- if (c != ' ') {
- if (c >= '0' && c <= '9') {
- int8 += c & 0x0f;
- } else if (c >= 'a' && c <= 'z') {
- int8 += (c & 0x0f) + 9;
- } else if (c >= 'A' && c <= 'Z') {
- int8 += (c & 0x0f) + 9;
- } else {
- return 0;
- }
-
- if (sec == 0) {
- int8 = int8 << 4;
- sec = 1;
- } else {
- if (bufpos + offset + 1 <= buf_len) {
- buf[bufpos+offset] = int8;
- int8 = 0;
- sec = 0;
- bufpos++;
- } else {
- fprintf(stderr, "Buffer too small in hexstr2bin");
- }
- }
- }
- }
- return bufpos;
-}
-
-/** convert hex buffer to binary buffer */
-static sldns_buffer *
-hex_buffer2wire(sldns_buffer *data_buffer)
-{
- sldns_buffer *wire_buffer = NULL;
- int c;
-
- /* stat hack
- * 0 = normal
- * 1 = comment (skip to end of line)
- * 2 = unprintable character found, read binary data directly
- */
- size_t data_buf_pos = 0;
- int state = 0;
- uint8_t *hexbuf;
- int hexbufpos = 0;
- size_t wirelen;
- uint8_t *data_wire = (uint8_t *) sldns_buffer_begin(data_buffer);
- uint8_t *wire = (uint8_t*)malloc(MAX_PACKETLEN);
- if(!wire) error("out of memory");
-
- hexbuf = (uint8_t*)malloc(MAX_PACKETLEN);
- if(!hexbuf) error("out of memory");
- for (data_buf_pos = 0; data_buf_pos < sldns_buffer_position(data_buffer); data_buf_pos++) {
- c = (int) data_wire[data_buf_pos];
-
- if (state < 2 && !isascii((unsigned char)c)) {
- /*verbose("non ascii character found in file: (%d) switching to raw mode\n", c);*/
- state = 2;
- }
- switch (state) {
- case 0:
- if ( (c >= '0' && c <= '9') ||
- (c >= 'a' && c <= 'f') ||
- (c >= 'A' && c <= 'F') )
- {
- if (hexbufpos >= MAX_PACKETLEN) {
- error("buffer overflow");
- free(hexbuf);
- return 0;
-
- }
- hexbuf[hexbufpos] = (uint8_t) c;
- hexbufpos++;
- } else if (c == ';') {
- state = 1;
- } else if (c == ' ' || c == '\t' || c == '\n') {
- /* skip whitespace */
- }
- break;
- case 1:
- if (c == '\n' || c == EOF) {
- state = 0;
- }
- break;
- case 2:
- if (hexbufpos >= MAX_PACKETLEN) {
- error("buffer overflow");
- free(hexbuf);
- return 0;
- }
- hexbuf[hexbufpos] = (uint8_t) c;
- hexbufpos++;
- break;
- }
- }
-
- if (hexbufpos >= MAX_PACKETLEN) {
- /*verbose("packet size reached\n");*/
- }
-
- /* lenient mode: length must be multiple of 2 */
- if (hexbufpos % 2 != 0) {
- if (hexbufpos >= MAX_PACKETLEN) {
- error("buffer overflow");
- free(hexbuf);
- return 0;
- }
- hexbuf[hexbufpos] = (uint8_t) '0';
- hexbufpos++;
- }
-
- if (state < 2) {
- wirelen = hexstr2bin((char *) hexbuf, hexbufpos, wire, 0, MAX_PACKETLEN);
- wire_buffer = sldns_buffer_new(wirelen);
- sldns_buffer_new_frm_data(wire_buffer, wire, wirelen);
- } else {
- error("Incomplete hex data, not at byte boundary\n");
- }
- free(wire);
- free(hexbuf);
- return wire_buffer;
-}
-
-/** parse ORIGIN */
-static void
-get_origin(const char* name, struct sldns_file_parse_state* pstate, char* parse)
-{
- /* snip off rest of the text so as to make the parse work in ldns */
- char* end;
- char store;
- int status;
-
- end=parse;
- while(!isspace((unsigned char)*end) && !isendline(*end))
- end++;
- store = *end;
- *end = 0;
- verbose(3, "parsing '%s'\n", parse);
- status = sldns_str2wire_dname_buf(parse, pstate->origin,
- &pstate->origin_len);
- *end = store;
- if(status != 0)
- error("%s line %d:\n\t%s: %s", name, pstate->lineno,
- sldns_get_errorstr_parse(status), parse);
-}
-
-/** add RR to packet */
-static void add_rr(char* rrstr, uint8_t* pktbuf, size_t pktsize,
- size_t* pktlen, struct sldns_file_parse_state* pstate,
- sldns_pkt_section add_section, const char* fname)
-{
- /* it must be a RR, parse and add to packet. */
- size_t rr_len = pktsize - *pktlen;
- size_t dname_len = 0;
- int status;
- uint8_t* origin = pstate->origin_len?pstate->origin:0;
- uint8_t* prev = pstate->prev_rr_len?pstate->prev_rr:0;
- if(*pktlen > pktsize || *pktlen < LDNS_HEADER_SIZE)
- error("packet overflow");
-
- /* parse RR */
- if(add_section == LDNS_SECTION_QUESTION)
- status = sldns_str2wire_rr_question_buf(rrstr, pktbuf+*pktlen,
- &rr_len, &dname_len, origin, pstate->origin_len,
- prev, pstate->prev_rr_len);
- else status = sldns_str2wire_rr_buf(rrstr, pktbuf+*pktlen, &rr_len,
- &dname_len, pstate->default_ttl, origin,
- pstate->origin_len, prev, pstate->prev_rr_len);
- if(status != 0)
- error("%s line %d:%d %s\n\t%s", fname, pstate->lineno,
- LDNS_WIREPARSE_OFFSET(status),
- sldns_get_errorstr_parse(status), rrstr);
- *pktlen += rr_len;
-
- /* increase RR count */
- if(add_section == LDNS_SECTION_QUESTION)
- sldns_write_uint16(pktbuf+4, LDNS_QDCOUNT(pktbuf)+1);
- else if(add_section == LDNS_SECTION_ANSWER)
- sldns_write_uint16(pktbuf+6, LDNS_ANCOUNT(pktbuf)+1);
- else if(add_section == LDNS_SECTION_AUTHORITY)
- sldns_write_uint16(pktbuf+8, LDNS_NSCOUNT(pktbuf)+1);
- else if(add_section == LDNS_SECTION_ADDITIONAL)
- sldns_write_uint16(pktbuf+10, LDNS_ARCOUNT(pktbuf)+1);
- else error("internal error bad section %d", (int)add_section);
-}
-
-/* add EDNS 4096 opt record */
-static void
-add_edns(uint8_t* pktbuf, size_t pktsize, int do_flag, uint8_t *ednsdata,
- uint16_t ednslen, size_t* pktlen)
-{
- uint8_t edns[] = {0x00, /* root label */
- 0x00, LDNS_RR_TYPE_OPT, /* type */
- 0x10, 0x00, /* class is UDPSIZE 4096 */
- 0x00, /* TTL[0] is ext rcode */
- 0x00, /* TTL[1] is edns version */
- (uint8_t)(do_flag?0x80:0x00), 0x00, /* TTL[2-3] is edns flags, DO */
- (uint8_t)((ednslen >> 8) & 0xff),
- (uint8_t)(ednslen & 0xff), /* rdatalength */
- };
- if(*pktlen < LDNS_HEADER_SIZE)
- return;
- if(*pktlen + sizeof(edns) + ednslen > pktsize)
- error("not enough space for EDNS OPT record");
- memmove(pktbuf+*pktlen, edns, sizeof(edns));
- memmove(pktbuf+*pktlen+sizeof(edns), ednsdata, ednslen);
- sldns_write_uint16(pktbuf+10, LDNS_ARCOUNT(pktbuf)+1);
- *pktlen += (sizeof(edns) + ednslen);
-}
-
-/* Reads one entry from file. Returns entry or NULL on error. */
-struct entry*
-read_entry(FILE* in, const char* name, struct sldns_file_parse_state* pstate,
- int skip_whitespace)
-{
- struct entry* current = NULL;
- char line[MAX_LINE];
- char* parse;
- sldns_pkt_section add_section = LDNS_SECTION_QUESTION;
- struct reply_packet *cur_reply = NULL;
- int reading_hex = 0;
- int reading_hex_ednsdata = 0;
- sldns_buffer* hex_data_buffer = NULL;
- sldns_buffer* hex_ednsdata_buffer = NULL;
- uint8_t pktbuf[MAX_PACKETLEN];
- size_t pktlen = LDNS_HEADER_SIZE;
- int do_flag = 0; /* DO flag in EDNS */
- memset(pktbuf, 0, pktlen); /* ID = 0, FLAGS="", and rr counts 0 */
-
- while(fgets(line, (int)sizeof(line), in) != NULL) {
- line[MAX_LINE-1] = 0;
- parse = line;
- pstate->lineno++;
-
- while(isspace((unsigned char)*parse))
- parse++;
- /* test for keywords */
- if(isendline(*parse))
- continue; /* skip comment and empty lines */
- if(str_keyword(&parse, "ENTRY_BEGIN")) {
- if(current) {
- error("%s line %d: previous entry does not ENTRY_END",
- name, pstate->lineno);
- }
- current = new_entry();
- current->lineno = pstate->lineno;
- cur_reply = entry_add_reply(current);
- continue;
- } else if(str_keyword(&parse, "$ORIGIN")) {
- get_origin(name, pstate, parse);
- continue;
- } else if(str_keyword(&parse, "$TTL")) {
- pstate->default_ttl = (uint32_t)atoi(parse);
- continue;
- }
-
- /* working inside an entry */
- if(!current) {
- error("%s line %d: expected ENTRY_BEGIN but got %s",
- name, pstate->lineno, line);
- }
- if(str_keyword(&parse, "MATCH")) {
- matchline(parse, current);
- } else if(str_keyword(&parse, "REPLY")) {
- replyline(parse, pktbuf, pktlen, &do_flag);
- } else if(str_keyword(&parse, "ADJUST")) {
- adjustline(parse, current, cur_reply);
- } else if(str_keyword(&parse, "EXTRA_PACKET")) {
- cur_reply = entry_add_reply(current);
- } else if(str_keyword(&parse, "SECTION")) {
- if(str_keyword(&parse, "QUESTION"))
- add_section = LDNS_SECTION_QUESTION;
- else if(str_keyword(&parse, "ANSWER"))
- add_section = LDNS_SECTION_ANSWER;
- else if(str_keyword(&parse, "AUTHORITY"))
- add_section = LDNS_SECTION_AUTHORITY;
- else if(str_keyword(&parse, "ADDITIONAL"))
- add_section = LDNS_SECTION_ADDITIONAL;
- else error("%s line %d: bad section %s", name, pstate->lineno, parse);
- } else if(str_keyword(&parse, "HEX_ANSWER_BEGIN")) {
- hex_data_buffer = sldns_buffer_new(MAX_PACKETLEN);
- reading_hex = 1;
- } else if(str_keyword(&parse, "HEX_ANSWER_END")) {
- if(!reading_hex) {
- error("%s line %d: HEX_ANSWER_END read but no HEX_ANSWER_BEGIN keyword seen", name, pstate->lineno);
- }
- reading_hex = 0;
- cur_reply->reply_from_hex = hex_buffer2wire(hex_data_buffer);
- sldns_buffer_free(hex_data_buffer);
- hex_data_buffer = NULL;
- } else if(reading_hex) {
- sldns_buffer_printf(hex_data_buffer, "%s", line);
- } else if(str_keyword(&parse, "HEX_EDNSDATA_BEGIN")) {
- hex_ednsdata_buffer = sldns_buffer_new(MAX_PACKETLEN);
- reading_hex_ednsdata = 1;
- } else if(str_keyword(&parse, "HEX_EDNSDATA_END")) {
- if (!reading_hex_ednsdata) {
- error("%s line %d: HEX_EDNSDATA_END read but no"
- "HEX_EDNSDATA_BEGIN keyword seen", name, pstate->lineno);
- }
- reading_hex_ednsdata = 0;
- cur_reply->raw_ednsdata = hex_buffer2wire(hex_ednsdata_buffer);
- sldns_buffer_free(hex_ednsdata_buffer);
- hex_ednsdata_buffer = NULL;
- } else if(reading_hex_ednsdata) {
- sldns_buffer_printf(hex_ednsdata_buffer, "%s", line);
- } else if(str_keyword(&parse, "ENTRY_END")) {
- if(hex_data_buffer)
- sldns_buffer_free(hex_data_buffer);
- if(hex_ednsdata_buffer)
- sldns_buffer_free(hex_ednsdata_buffer);
- if(pktlen != 0) {
- if(do_flag || cur_reply->raw_ednsdata) {
- if(cur_reply->raw_ednsdata &&
- sldns_buffer_limit(cur_reply->raw_ednsdata))
- add_edns(pktbuf, sizeof(pktbuf), do_flag,
- sldns_buffer_begin(cur_reply->raw_ednsdata),
- (uint16_t)sldns_buffer_limit(cur_reply->raw_ednsdata),
- &pktlen);
- else
- add_edns(pktbuf, sizeof(pktbuf), do_flag,
- NULL, 0, &pktlen);
- }
- cur_reply->reply_pkt = memdup(pktbuf, pktlen);
- cur_reply->reply_len = pktlen;
- if(!cur_reply->reply_pkt)
- error("out of memory");
- }
- return current;
- } else {
- add_rr(skip_whitespace?parse:line, pktbuf,
- sizeof(pktbuf), &pktlen, pstate, add_section,
- name);
- }
-
- }
- if(reading_hex) {
- error("%s: End of file reached while still reading hex, "
- "missing HEX_ANSWER_END\n", name);
- }
- if(reading_hex_ednsdata) {
- error("%s: End of file reached while still reading edns data, "
- "missing HEX_EDNSDATA_END\n", name);
- }
- if(current) {
- error("%s: End of file reached while reading entry. "
- "missing ENTRY_END\n", name);
- }
- return 0;
-}
-
-/* reads the canned reply file and returns a list of structs */
-struct entry*
-read_datafile(const char* name, int skip_whitespace)
-{
- struct entry* list = NULL;
- struct entry* last = NULL;
- struct entry* current = NULL;
- FILE *in;
- struct sldns_file_parse_state pstate;
- int entry_num = 0;
- memset(&pstate, 0, sizeof(pstate));
-
- if((in=fopen(name, "r")) == NULL) {
- error("could not open file %s: %s", name, strerror(errno));
- }
-
- while((current = read_entry(in, name, &pstate, skip_whitespace)))
- {
- if(last)
- last->next = current;
- else list = current;
- last = current;
- entry_num ++;
- }
- verbose(1, "%s: Read %d entries\n", prog_name, entry_num);
-
- fclose(in);
- return list;
-}
-
-/** get qtype from packet */
-static sldns_rr_type get_qtype(uint8_t* pkt, size_t pktlen)
-{
- uint8_t* d;
- size_t dl, sl=0;
- char* snull = NULL;
- if(pktlen < LDNS_HEADER_SIZE)
- return 0;
- if(LDNS_QDCOUNT(pkt) == 0)
- return 0;
- /* skip over dname with dname-scan routine */
- d = pkt+LDNS_HEADER_SIZE;
- dl = pktlen-LDNS_HEADER_SIZE;
- (void)sldns_wire2str_dname_scan(&d, &dl, &snull, &sl, pkt, pktlen);
- if(dl < 2)
- return 0;
- return sldns_read_uint16(d);
-}
-
-/** get qtype from packet */
-static size_t get_qname_len(uint8_t* pkt, size_t pktlen)
-{
- uint8_t* d;
- size_t dl, sl=0;
- char* snull = NULL;
- if(pktlen < LDNS_HEADER_SIZE)
- return 0;
- if(LDNS_QDCOUNT(pkt) == 0)
- return 0;
- /* skip over dname with dname-scan routine */
- d = pkt+LDNS_HEADER_SIZE;
- dl = pktlen-LDNS_HEADER_SIZE;
- (void)sldns_wire2str_dname_scan(&d, &dl, &snull, &sl, pkt, pktlen);
- return pktlen-dl-LDNS_HEADER_SIZE;
-}
-
-/** returns owner from packet */
-static uint8_t* get_qname(uint8_t* pkt, size_t pktlen)
-{
- if(pktlen < LDNS_HEADER_SIZE)
- return NULL;
- if(LDNS_QDCOUNT(pkt) == 0)
- return NULL;
- return pkt+LDNS_HEADER_SIZE;
-}
-
-/** returns opcode from packet */
-static int get_opcode(uint8_t* pkt, size_t pktlen)
-{
- if(pktlen < LDNS_HEADER_SIZE)
- return 0;
- return (int)LDNS_OPCODE_WIRE(pkt);
-}
-
-/** returns rcode from packet */
-static int get_rcode(uint8_t* pkt, size_t pktlen)
-{
- if(pktlen < LDNS_HEADER_SIZE)
- return 0;
- return (int)LDNS_RCODE_WIRE(pkt);
-}
-
-/** get authority section SOA serial value */
-static uint32_t get_serial(uint8_t* p, size_t plen)
-{
- uint8_t* walk = p;
- size_t walk_len = plen, sl=0;
- char* snull = NULL;
- uint16_t i;
-
- if(walk_len < LDNS_HEADER_SIZE)
- return 0;
- walk += LDNS_HEADER_SIZE;
- walk_len -= LDNS_HEADER_SIZE;
-
- /* skip other records with wire2str_scan */
- for(i=0; i < LDNS_QDCOUNT(p); i++)
- (void)sldns_wire2str_rrquestion_scan(&walk, &walk_len,
- &snull, &sl, p, plen);
- for(i=0; i < LDNS_ANCOUNT(p); i++)
- (void)sldns_wire2str_rr_scan(&walk, &walk_len, &snull, &sl,
- p, plen);
-
- /* walk through authority section */
- for(i=0; i < LDNS_NSCOUNT(p); i++) {
- /* if this is SOA then get serial, skip compressed dname */
- uint8_t* dstart = walk;
- size_t dlen = walk_len;
- (void)sldns_wire2str_dname_scan(&dstart, &dlen, &snull, &sl,
- p, plen);
- if(dlen >= 2 && sldns_read_uint16(dstart) == LDNS_RR_TYPE_SOA) {
- /* skip type, class, TTL, rdatalen */
- if(dlen < 10)
- return 0;
- if(dlen < 10 + (size_t)sldns_read_uint16(dstart+8))
- return 0;
- dstart += 10;
- dlen -= 10;
- /* check third rdf */
- (void)sldns_wire2str_dname_scan(&dstart, &dlen, &snull,
- &sl, p, plen);
- (void)sldns_wire2str_dname_scan(&dstart, &dlen, &snull,
- &sl, p, plen);
- if(dlen < 4)
- return 0;
- verbose(3, "found serial %u in msg. ",
- (int)sldns_read_uint32(dstart));
- return sldns_read_uint32(dstart);
- }
- /* move to next RR */
- (void)sldns_wire2str_rr_scan(&walk, &walk_len, &snull, &sl,
- p, plen);
- }
- return 0;
-}
-
-/** get ptr to EDNS OPT record (and remaining length); behind the type u16 */
-static int
-pkt_find_edns_opt(uint8_t** p, size_t* plen)
-{
- /* walk over the packet with scan routines */
- uint8_t* w = *p;
- size_t wlen = *plen, sl=0;
- char* snull = NULL;
- uint16_t i;
-
- if(wlen < LDNS_HEADER_SIZE)
- return 0;
- w += LDNS_HEADER_SIZE;
- wlen -= LDNS_HEADER_SIZE;
-
- /* skip other records with wire2str_scan */
- for(i=0; i < LDNS_QDCOUNT(*p); i++)
- (void)sldns_wire2str_rrquestion_scan(&w, &wlen, &snull, &sl,
- *p, *plen);
- for(i=0; i < LDNS_ANCOUNT(*p); i++)
- (void)sldns_wire2str_rr_scan(&w, &wlen, &snull, &sl, *p, *plen);
- for(i=0; i < LDNS_NSCOUNT(*p); i++)
- (void)sldns_wire2str_rr_scan(&w, &wlen, &snull, &sl, *p, *plen);
-
- /* walk through additional section */
- for(i=0; i < LDNS_ARCOUNT(*p); i++) {
- /* if this is OPT then done */
- uint8_t* dstart = w;
- size_t dlen = wlen;
- (void)sldns_wire2str_dname_scan(&dstart, &dlen, &snull, &sl,
- *p, *plen);
- if(dlen >= 2 && sldns_read_uint16(dstart) == LDNS_RR_TYPE_OPT) {
- *p = dstart+2;
- *plen = dlen-2;
- return 1;
- }
- /* move to next RR */
- (void)sldns_wire2str_rr_scan(&w, &wlen, &snull, &sl, *p, *plen);
- }
- return 0;
-}
-
-/** return true if the packet has EDNS OPT record */
-static int
-get_has_edns(uint8_t* pkt, size_t len)
-{
- /* use arguments as temporary variables */
- return pkt_find_edns_opt(&pkt, &len);
-}
-
-/** return true if the DO flag is set */
-static int
-get_do_flag(uint8_t* pkt, size_t len)
-{
- uint16_t edns_bits;
- uint8_t* walk = pkt;
- size_t walk_len = len;
- if(!pkt_find_edns_opt(&walk, &walk_len)) {
- return 0;
- }
- if(walk_len < 6)
- return 0; /* malformed */
- edns_bits = sldns_read_uint16(walk+4);
- return (int)(edns_bits&LDNS_EDNS_MASK_DO_BIT);
-}
-
-/** zero TTLs in packet */
-static void
-zerottls(uint8_t* pkt, size_t pktlen)
-{
- uint8_t* walk = pkt;
- size_t walk_len = pktlen, sl=0;
- char* snull = NULL;
- uint16_t i;
- uint16_t num = LDNS_ANCOUNT(pkt)+LDNS_NSCOUNT(pkt)+LDNS_ARCOUNT(pkt);
- if(walk_len < LDNS_HEADER_SIZE)
- return;
- walk += LDNS_HEADER_SIZE;
- walk_len -= LDNS_HEADER_SIZE;
- for(i=0; i < LDNS_QDCOUNT(pkt); i++)
- (void)sldns_wire2str_rrquestion_scan(&walk, &walk_len,
- &snull, &sl, pkt, pktlen);
- for(i=0; i < num; i++) {
- /* wipe TTL */
- uint8_t* dstart = walk;
- size_t dlen = walk_len;
- (void)sldns_wire2str_dname_scan(&dstart, &dlen, &snull, &sl,
- pkt, pktlen);
- if(dlen < 8)
- return;
- sldns_write_uint32(dstart+4, 0);
- /* go to next RR */
- (void)sldns_wire2str_rr_scan(&walk, &walk_len, &snull, &sl,
- pkt, pktlen);
- }
-}
-
-/** get one line (\n) from a string, move next to after the \n, zero \n */
-static int
-get_line(char** s, char** n)
-{
- /* at end of string? end */
- if(*n == NULL || **n == 0)
- return 0;
- /* result starts at next string */
- *s = *n;
- /* find \n after that */
- *n = strchr(*s, '\n');
- if(*n && **n != 0) {
- /* terminate line */
- (*n)[0] = 0;
- (*n)++;
- }
- return 1;
-}
-
-/** match two RR sections without ordering */
-static int
-match_noloc_section(char** q, char** nq, char** p, char** np, uint16_t num)
-{
- /* for max number of RRs in packet */
- const uint16_t numarray = 3000;
- char* qlines[numarray], *plines[numarray];
- uint16_t i, j, numq=0, nump=0;
- if(num > numarray) fatal_exit("too many RRs");
- /* gather lines */
- for(i=0; i<num; i++) {
- get_line(q, nq);
- get_line(p, np);
- qlines[numq++] = *q;
- plines[nump++] = *p;
- }
- /* see if they are all present in the other */
- for(i=0; i<num; i++) {
- int found = 0;
- for(j=0; j<num; j++) {
- if(strcmp(qlines[i], plines[j]) == 0) {
- found = 1;
- break;
- }
- }
- if(!found) {
- verbose(3, "comparenoloc: failed for %s", qlines[i]);
- return 0;
- }
- }
- return 1;
-}
-
-/** match two strings for unordered equality of RRs and everything else */
-static int
-match_noloc(char* q, char* p, uint8_t* q_pkt, size_t q_pkt_len,
- uint8_t* p_pkt, size_t p_pkt_len)
-{
- char* nq = q, *np = p;
- /* if no header, compare bytes */
- if(p_pkt_len < LDNS_HEADER_SIZE || q_pkt_len < LDNS_HEADER_SIZE) {
- if(p_pkt_len != q_pkt_len) return 0;
- return memcmp(p, q, p_pkt_len);
- }
- /* compare RR counts */
- if(LDNS_QDCOUNT(p_pkt) != LDNS_QDCOUNT(q_pkt))
- return 0;
- if(LDNS_ANCOUNT(p_pkt) != LDNS_ANCOUNT(q_pkt))
- return 0;
- if(LDNS_NSCOUNT(p_pkt) != LDNS_NSCOUNT(q_pkt))
- return 0;
- if(LDNS_ARCOUNT(p_pkt) != LDNS_ARCOUNT(q_pkt))
- return 0;
- /* get a line from both; compare; at sections do section */
- get_line(&q, &nq);
- get_line(&p, &np);
- if(strcmp(q, p) != 0) {
- /* header line opcode, rcode, id */
- return 0;
- }
- get_line(&q, &nq);
- get_line(&p, &np);
- if(strcmp(q, p) != 0) {
- /* header flags, rr counts */
- return 0;
- }
- /* ;; QUESTION SECTION */
- get_line(&q, &nq);
- get_line(&p, &np);
- if(strcmp(q, p) != 0) return 0;
- if(!match_noloc_section(&q, &nq, &p, &np, LDNS_QDCOUNT(p_pkt)))
- return 0;
-
- /* empty line and ;; ANSWER SECTION */
- get_line(&q, &nq);
- get_line(&p, &np);
- if(strcmp(q, p) != 0) return 0;
- get_line(&q, &nq);
- get_line(&p, &np);
- if(strcmp(q, p) != 0) return 0;
- if(!match_noloc_section(&q, &nq, &p, &np, LDNS_ANCOUNT(p_pkt)))
- return 0;
-
- /* empty line and ;; AUTHORITY SECTION */
- get_line(&q, &nq);
- get_line(&p, &np);
- if(strcmp(q, p) != 0) return 0;
- get_line(&q, &nq);
- get_line(&p, &np);
- if(strcmp(q, p) != 0) return 0;
- if(!match_noloc_section(&q, &nq, &p, &np, LDNS_NSCOUNT(p_pkt)))
- return 0;
-
- /* empty line and ;; ADDITIONAL SECTION */
- get_line(&q, &nq);
- get_line(&p, &np);
- if(strcmp(q, p) != 0) return 0;
- get_line(&q, &nq);
- get_line(&p, &np);
- if(strcmp(q, p) != 0) return 0;
- if(!match_noloc_section(&q, &nq, &p, &np, LDNS_ARCOUNT(p_pkt)))
- return 0;
-
- return 1;
-}
-
-/** lowercase domain name - does not follow compression pointers */
-static void lowercase_dname(uint8_t** p, size_t* remain)
-{
- unsigned i, llen;
- if(*remain == 0) return;
- while(**p != 0) {
- /* compressed? */
- if((**p & 0xc0) == 0xc0) {
- *p += 2;
- *remain -= 2;
- return;
- }
- llen = (unsigned int)**p;
- *p += 1;
- *remain -= 1;
- if(*remain < llen)
- llen = (unsigned int)*remain;
- for(i=0; i<llen; i++) {
- (*p)[i] = (uint8_t)tolower((int)(*p)[i]);
- }
- *p += llen;
- *remain -= llen;
- if(*remain == 0) return;
- }
- /* skip root label */
- *p += 1;
- *remain -= 1;
-}
-
-/** lowercase rdata of type */
-static void lowercase_rdata(uint8_t** p, size_t* remain,
- uint16_t rdatalen, uint16_t t)
-{
- const sldns_rr_descriptor *desc = sldns_rr_descript(t);
- uint8_t dname_count = 0;
- size_t i = 0;
- size_t rdataremain = rdatalen;
- if(!desc) {
- /* unknown type */
- *p += rdatalen;
- *remain -= rdatalen;
- return;
- }
- while(dname_count < desc->_dname_count) {
- sldns_rdf_type f = sldns_rr_descriptor_field_type(desc, i++);
- if(f == LDNS_RDF_TYPE_DNAME) {
- lowercase_dname(p, &rdataremain);
- dname_count++;
- } else if(f == LDNS_RDF_TYPE_STR) {
- uint8_t len;
- if(rdataremain == 0) return;
- len = **p;
- *p += len+1;
- rdataremain -= len+1;
- } else {
- int len = 0;
- switch(f) {
- case LDNS_RDF_TYPE_CLASS:
- case LDNS_RDF_TYPE_ALG:
- case LDNS_RDF_TYPE_INT8:
- len = 1;
- break;
- case LDNS_RDF_TYPE_INT16:
- case LDNS_RDF_TYPE_TYPE:
- case LDNS_RDF_TYPE_CERT_ALG:
- len = 2;
- break;
- case LDNS_RDF_TYPE_INT32:
- case LDNS_RDF_TYPE_TIME:
- case LDNS_RDF_TYPE_A:
- case LDNS_RDF_TYPE_PERIOD:
- len = 4;
- break;
- case LDNS_RDF_TYPE_TSIGTIME:
- len = 6;
- break;
- case LDNS_RDF_TYPE_AAAA:
- len = 16;
- break;
- default: error("bad rdf type in lowercase %d", (int)f);
- }
- *p += len;
- rdataremain -= len;
- }
- }
- /* skip remainder of rdata */
- *p += rdataremain;
- *remain -= rdatalen;
-}
-
-/** lowercase all names in the message */
-static void lowercase_pkt(uint8_t* pkt, size_t pktlen)
-{
- uint16_t i;
- uint8_t* p = pkt;
- size_t remain = pktlen;
- uint16_t t, rdatalen;
- if(pktlen < LDNS_HEADER_SIZE)
- return;
- p += LDNS_HEADER_SIZE;
- remain -= LDNS_HEADER_SIZE;
- for(i=0; i<LDNS_QDCOUNT(pkt); i++) {
- lowercase_dname(&p, &remain);
- if(remain < 4) return;
- p += 4;
- remain -= 4;
- }
- for(i=0; i<LDNS_ANCOUNT(pkt)+LDNS_NSCOUNT(pkt)+LDNS_ARCOUNT(pkt); i++) {
- lowercase_dname(&p, &remain);
- if(remain < 10) return;
- t = sldns_read_uint16(p);
- rdatalen = sldns_read_uint16(p+8);
- p += 10;
- remain -= 10;
- if(remain < rdatalen) return;
- lowercase_rdata(&p, &remain, rdatalen, t);
- }
-}
-
-/** match question section of packet */
-static int
-match_question(uint8_t* q, size_t qlen, uint8_t* p, size_t plen, int mttl)
-{
- char* qstr, *pstr, *s, *qcmpstr, *pcmpstr;
- uint8_t* qb = q, *pb = p;
- int r;
- /* zero TTLs */
- qb = memdup(q, qlen);
- pb = memdup(p, plen);
- if(!qb || !pb) error("out of memory");
- if(!mttl) {
- zerottls(qb, qlen);
- zerottls(pb, plen);
- }
- lowercase_pkt(qb, qlen);
- lowercase_pkt(pb, plen);
- qstr = sldns_wire2str_pkt(qb, qlen);
- pstr = sldns_wire2str_pkt(pb, plen);
- if(!qstr || !pstr) error("cannot pkt2string");
-
- /* remove before ;; QUESTION */
- s = strstr(qstr, ";; QUESTION SECTION");
- qcmpstr = s;
- s = strstr(pstr, ";; QUESTION SECTION");
- pcmpstr = s;
- if(!qcmpstr && !pcmpstr) {
- free(qstr);
- free(pstr);
- free(qb);
- free(pb);
- return 1;
- }
- if(!qcmpstr || !pcmpstr) {
- free(qstr);
- free(pstr);
- free(qb);
- free(pb);
- return 0;
- }
-
- /* remove after answer section, (;; AUTH, ;; ADD, ;; MSG size ..) */
- s = strstr(qcmpstr, ";; ANSWER SECTION");
- if(!s) s = strstr(qcmpstr, ";; AUTHORITY SECTION");
- if(!s) s = strstr(qcmpstr, ";; ADDITIONAL SECTION");
- if(!s) s = strstr(qcmpstr, ";; MSG SIZE");
- if(s) *s = 0;
- s = strstr(pcmpstr, ";; ANSWER SECTION");
- if(!s) s = strstr(pcmpstr, ";; AUTHORITY SECTION");
- if(!s) s = strstr(pcmpstr, ";; ADDITIONAL SECTION");
- if(!s) s = strstr(pcmpstr, ";; MSG SIZE");
- if(s) *s = 0;
-
- r = (strcmp(qcmpstr, pcmpstr) == 0);
-
- if(!r) {
- verbose(3, "mismatch question section '%s' and '%s'",
- qcmpstr, pcmpstr);
- }
-
- free(qstr);
- free(pstr);
- free(qb);
- free(pb);
- return r;
-}
-
-/** match answer section of packet */
-static int
-match_answer(uint8_t* q, size_t qlen, uint8_t* p, size_t plen, int mttl)
-{
- char* qstr, *pstr, *s, *qcmpstr, *pcmpstr;
- uint8_t* qb = q, *pb = p;
- int r;
- /* zero TTLs */
- qb = memdup(q, qlen);
- pb = memdup(p, plen);
- if(!qb || !pb) error("out of memory");
- if(!mttl) {
- zerottls(qb, qlen);
- zerottls(pb, plen);
- }
- lowercase_pkt(qb, qlen);
- lowercase_pkt(pb, plen);
- qstr = sldns_wire2str_pkt(qb, qlen);
- pstr = sldns_wire2str_pkt(pb, plen);
- if(!qstr || !pstr) error("cannot pkt2string");
-
- /* remove before ;; ANSWER */
- s = strstr(qstr, ";; ANSWER SECTION");
- qcmpstr = s;
- s = strstr(pstr, ";; ANSWER SECTION");
- pcmpstr = s;
- if(!qcmpstr && !pcmpstr) {
- free(qstr);
- free(pstr);
- free(qb);
- free(pb);
- return 1;
- }
- if(!qcmpstr || !pcmpstr) {
- free(qstr);
- free(pstr);
- free(qb);
- free(pb);
- return 0;
- }
-
- /* remove after answer section, (;; AUTH, ;; ADD, ;; MSG size ..) */
- s = strstr(qcmpstr, ";; AUTHORITY SECTION");
- if(!s) s = strstr(qcmpstr, ";; ADDITIONAL SECTION");
- if(!s) s = strstr(qcmpstr, ";; MSG SIZE");
- if(s) *s = 0;
- s = strstr(pcmpstr, ";; AUTHORITY SECTION");
- if(!s) s = strstr(pcmpstr, ";; ADDITIONAL SECTION");
- if(!s) s = strstr(pcmpstr, ";; MSG SIZE");
- if(s) *s = 0;
-
- r = (strcmp(qcmpstr, pcmpstr) == 0);
-
- if(!r) {
- verbose(3, "mismatch answer section '%s' and '%s'",
- qcmpstr, pcmpstr);
- }
-
- free(qstr);
- free(pstr);
- free(qb);
- free(pb);
- return r;
-}
-
-/** match all of the packet */
-int
-match_all(uint8_t* q, size_t qlen, uint8_t* p, size_t plen, int mttl,
- int noloc)
-{
- char* qstr, *pstr;
- uint8_t* qb = q, *pb = p;
- int r;
- /* zero TTLs */
- qb = memdup(q, qlen);
- pb = memdup(p, plen);
- if(!qb || !pb) error("out of memory");
- if(!mttl) {
- zerottls(qb, qlen);
- zerottls(pb, plen);
- }
- lowercase_pkt(qb, qlen);
- lowercase_pkt(pb, plen);
- qstr = sldns_wire2str_pkt(qb, qlen);
- pstr = sldns_wire2str_pkt(pb, plen);
- if(!qstr || !pstr) error("cannot pkt2string");
- r = (strcmp(qstr, pstr) == 0);
- if(!r) {
- /* remove ;; MSG SIZE (at end of string) */
- char* s = strstr(qstr, ";; MSG SIZE");
- if(s) *s=0;
- s = strstr(pstr, ";; MSG SIZE");
- if(s) *s=0;
- r = (strcmp(qstr, pstr) == 0);
- if(!r && !noloc) {
- /* we are going to fail see if it is because of EDNS */
- char* a = strstr(qstr, "; EDNS");
- char* b = strstr(pstr, "; EDNS");
- if( (a&&!b) || (b&&!a) ) {
- verbose(3, "mismatch in EDNS\n");
- }
- }
- }
- if(!r && noloc) {
- /* check for reordered sections */
- r = match_noloc(qstr, pstr, q, qlen, p, plen);
- }
- if(!r) {
- verbose(3, "mismatch pkt '%s' and '%s'", qstr, pstr);
- }
- free(qstr);
- free(pstr);
- free(qb);
- free(pb);
- return r;
-}
-
-/** see if domain names are equal */
-static int equal_dname(uint8_t* q, size_t qlen, uint8_t* p, size_t plen)
-{
- uint8_t* qn = get_qname(q, qlen);
- uint8_t* pn = get_qname(p, plen);
- char qs[512], ps[512];
- size_t qslen = sizeof(qs), pslen = sizeof(ps);
- char* qss = qs, *pss = ps;
- if(!qn || !pn)
- return 0;
- (void)sldns_wire2str_dname_scan(&qn, &qlen, &qss, &qslen, q, qlen);
- (void)sldns_wire2str_dname_scan(&pn, &plen, &pss, &pslen, p, plen);
- return (strcmp(qs, ps) == 0);
-}
-
-/** see if domain names are subdomain q of p */
-static int subdomain_dname(uint8_t* q, size_t qlen, uint8_t* p, size_t plen)
-{
- /* we use the tostring routines so as to test unbound's routines
- * with something else */
- uint8_t* qn = get_qname(q, qlen);
- uint8_t* pn = get_qname(p, plen);
- char qs[5120], ps[5120];
- size_t qslen = sizeof(qs), pslen = sizeof(ps);
- char* qss = qs, *pss = ps;
- if(!qn || !pn)
- return 0;
- /* decompresses domain names */
- (void)sldns_wire2str_dname_scan(&qn, &qlen, &qss, &qslen, q, qlen);
- (void)sldns_wire2str_dname_scan(&pn, &plen, &pss, &pslen, p, plen);
- /* same: false, (strict subdomain check)??? */
- if(strcmp(qs, ps) == 0)
- return 1;
- /* qs must end in ps, at a dot, without \ in front */
- qslen = strlen(qs);
- pslen = strlen(ps);
- if(qslen > pslen && strcmp(qs + (qslen-pslen), ps) == 0 &&
- qslen + 2 >= pslen && /* space for label and dot */
- qs[qslen-pslen-1] == '.') {
- unsigned int slashcount = 0;
- size_t i = qslen-pslen-2;
- while(i>0 && qs[i]=='\\') {
- i++;
- slashcount++;
- }
- if(slashcount%1 == 1) return 0; /* . preceded by \ */
- return 1;
- }
- return 0;
-}
-
-/** Match OPT RDATA (not the EDNS payload size or flags) */
-static int
-match_ednsdata(uint8_t* q, size_t qlen, uint8_t* p, size_t plen)
-{
- uint8_t* walk_q = q;
- size_t walk_qlen = qlen;
- uint8_t* walk_p = p;
- size_t walk_plen = plen;
-
- if(!pkt_find_edns_opt(&walk_q, &walk_qlen))
- walk_qlen = 0;
- if(!pkt_find_edns_opt(&walk_p, &walk_plen))
- walk_plen = 0;
-
- /* class + ttl + rdlen = 8 */
- if(walk_qlen <= 8 && walk_plen <= 8) {
- verbose(3, "NO edns opt, move on");
- return 1;
- }
- if(walk_qlen != walk_plen)
- return 0;
-
- return (memcmp(walk_p+8, walk_q+8, walk_qlen-8) == 0);
-}
-
-/* finds entry in list, or returns NULL */
-struct entry*
-find_match(struct entry* entries, uint8_t* query_pkt, size_t len,
- enum transport_type transport)
-{
- struct entry* p = entries;
- uint8_t* reply;
- size_t rlen;
- for(p=entries; p; p=p->next) {
- verbose(3, "comparepkt: ");
- reply = p->reply_list->reply_pkt;
- rlen = p->reply_list->reply_len;
- if(p->match_opcode && get_opcode(query_pkt, len) !=
- get_opcode(reply, rlen)) {
- verbose(3, "bad opcode\n");
- continue;
- }
- if(p->match_qtype && get_qtype(query_pkt, len) !=
- get_qtype(reply, rlen)) {
- verbose(3, "bad qtype %d %d\n", get_qtype(query_pkt, len), get_qtype(reply, rlen));
- continue;
- }
- if(p->match_qname) {
- if(!equal_dname(query_pkt, len, reply, rlen)) {
- verbose(3, "bad qname\n");
- continue;
- }
- }
- if(p->match_rcode) {
- if(get_rcode(query_pkt, len) != get_rcode(reply, rlen)) {
- char *r1 = sldns_wire2str_rcode(get_rcode(query_pkt, len));
- char *r2 = sldns_wire2str_rcode(get_rcode(reply, rlen));
- verbose(3, "bad rcode %s instead of %s\n",
- r1, r2);
- free(r1);
- free(r2);
- continue;
- }
- }
- if(p->match_question) {
- if(!match_question(query_pkt, len, reply, rlen,
- (int)p->match_ttl)) {
- verbose(3, "bad question section\n");
- continue;
- }
- }
- if(p->match_answer) {
- if(!match_answer(query_pkt, len, reply, rlen,
- (int)p->match_ttl)) {
- verbose(3, "bad answer section\n");
- continue;
- }
- }
- if(p->match_subdomain) {
- if(!subdomain_dname(query_pkt, len, reply, rlen)) {
- verbose(3, "bad subdomain\n");
- continue;
- }
- }
- if(p->match_serial && get_serial(query_pkt, len) != p->ixfr_soa_serial) {
- verbose(3, "bad serial\n");
- continue;
- }
- if(p->match_do && !get_do_flag(query_pkt, len)) {
- verbose(3, "no DO bit set\n");
- continue;
- }
- if(p->match_noedns && get_has_edns(query_pkt, len)) {
- verbose(3, "bad; EDNS OPT present\n");
- continue;
- }
- if(p->match_ednsdata_raw &&
- !match_ednsdata(query_pkt, len, reply, rlen)) {
- verbose(3, "bad EDNS data match.\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, len, reply, rlen,
- (int)p->match_ttl, 0)) {
- verbose(3, "bad allmatch\n");
- continue;
- }
- verbose(3, "match!\n");
- return p;
- }
- return NULL;
-}
-
-void
-adjust_packet(struct entry* match, uint8_t** answer_pkt, size_t *answer_len,
- uint8_t* query_pkt, size_t query_len)
-{
- uint8_t* orig = *answer_pkt;
- size_t origlen = *answer_len;
- uint8_t* res;
- size_t reslen;
-
- /* perform the copy; if possible; must be uncompressed */
- if(match->copy_query && origlen >= LDNS_HEADER_SIZE &&
- query_len >= LDNS_HEADER_SIZE && LDNS_QDCOUNT(query_pkt)!=0
- && LDNS_QDCOUNT(orig)==0) {
- /* no qname in output packet, insert it */
- size_t dlen = get_qname_len(query_pkt, query_len);
- reslen = origlen + dlen + 4;
- res = (uint8_t*)malloc(reslen);
- if(!res) {
- verbose(1, "out of memory; send without adjust\n");
- return;
- }
- /* copy the header, query, remainder */
- memcpy(res, orig, LDNS_HEADER_SIZE);
- memmove(res+LDNS_HEADER_SIZE, query_pkt+LDNS_HEADER_SIZE,
- dlen+4);
- memmove(res+LDNS_HEADER_SIZE+dlen+4, orig+LDNS_HEADER_SIZE,
- reslen-(LDNS_HEADER_SIZE+dlen+4));
- /* set QDCOUNT */
- sldns_write_uint16(res+4, 1);
- } else if(match->copy_query && origlen >= LDNS_HEADER_SIZE &&
- query_len >= LDNS_HEADER_SIZE && LDNS_QDCOUNT(query_pkt)!=0
- && get_qname_len(orig, origlen) == 0) {
- /* QDCOUNT(orig)!=0 but qlen == 0, therefore, an error */
- verbose(1, "error: malformed qname; send without adjust\n");
- res = memdup(orig, origlen);
- reslen = origlen;
- } else if(match->copy_query && origlen >= LDNS_HEADER_SIZE &&
- query_len >= LDNS_HEADER_SIZE && LDNS_QDCOUNT(query_pkt)!=0
- && LDNS_QDCOUNT(orig)!=0) {
- /* in this case olen != 0 and QDCOUNT(orig)!=0 */
- /* copy query section */
- size_t dlen = get_qname_len(query_pkt, query_len);
- size_t olen = get_qname_len(orig, origlen);
- reslen = origlen + dlen - olen;
- res = (uint8_t*)malloc(reslen);
- if(!res) {
- verbose(1, "out of memory; send without adjust\n");
- return;
- }
- /* copy the header, query, remainder */
- memcpy(res, orig, LDNS_HEADER_SIZE);
- memmove(res+LDNS_HEADER_SIZE, query_pkt+LDNS_HEADER_SIZE,
- dlen+4);
- memmove(res+LDNS_HEADER_SIZE+dlen+4,
- orig+LDNS_HEADER_SIZE+olen+4,
- reslen-(LDNS_HEADER_SIZE+dlen+4));
- } else {
- res = memdup(orig, origlen);
- reslen = origlen;
- }
- if(!res) {
- verbose(1, "out of memory; send without adjust\n");
- return;
- }
- /* copy the ID */
- if(match->copy_id && reslen >= 2)
- res[1] = orig[1];
- if(match->copy_id && reslen >= 1)
- res[0] = orig[0];
-
- if(match->copy_ednsdata_assume_clientsubnet) {
- /** Assume there is only one EDNS option, which is ECS.
- * Copy source mask from query to scope mask in reply. Assume
- * rest of ECS data in response (eg address) matches the query.
- */
- uint8_t* walk_q = orig;
- size_t walk_qlen = origlen;
- uint8_t* walk_p = res;
- size_t walk_plen = reslen;
-
- if(!pkt_find_edns_opt(&walk_q, &walk_qlen)) {
- walk_qlen = 0;
- }
- if(!pkt_find_edns_opt(&walk_p, &walk_plen)) {
- walk_plen = 0;
- }
- /* class + ttl + rdlen + optcode + optlen + ecs fam + ecs source
- * + ecs scope = index 15 */
- if(walk_qlen >= 15 && walk_plen >= 15) {
- walk_p[15] = walk_q[14];
- }
- }
-
- if(match->sleeptime > 0) {
- verbose(3, "sleeping for %d seconds\n", match->sleeptime);
-#ifdef HAVE_SLEEP
- sleep(match->sleeptime);
-#else
- Sleep(match->sleeptime * 1000);
-#endif
- }
- *answer_pkt = res;
- *answer_len = reslen;
-}
-
-/*
- * Parses data buffer to a query, finds the correct answer
- * and calls the given function for every packet to send.
- */
-void
-handle_query(uint8_t* inbuf, ssize_t inlen, struct entry* entries, int* count,
- enum transport_type transport, void (*sendfunc)(uint8_t*, size_t, void*),
- void* userdata, FILE* verbose_out)
-{
- struct reply_packet *p;
- uint8_t *outbuf = NULL;
- size_t outlen = 0;
- struct entry* entry = NULL;
-
- verbose(1, "query %d: id %d: %s %d bytes: ", ++(*count),
- (int)(inlen>=2?LDNS_ID_WIRE(inbuf):0),
- (transport==transport_tcp)?"TCP":"UDP", (int)inlen);
- if(verbose_out) {
- char* out = sldns_wire2str_pkt(inbuf, (size_t)inlen);
- printf("%s\n", out);
- free(out);
- }
-
- /* fill up answer packet */
- entry = find_match(entries, inbuf, (size_t)inlen, transport);
- if(!entry || !entry->reply_list) {
- verbose(1, "no answer packet for this query, no reply.\n");
- return;
- }
- for(p = entry->reply_list; p; p = p->next)
- {
- verbose(3, "Answer pkt:\n");
- if (p->reply_from_hex) {
- /* try to adjust the hex packet, if it can be
- * parsed, we can use adjust rules. if not,
- * send packet literally */
- /* still try to adjust ID if others fail */
- outlen = sldns_buffer_limit(p->reply_from_hex);
- outbuf = sldns_buffer_begin(p->reply_from_hex);
- } else {
- outbuf = p->reply_pkt;
- outlen = p->reply_len;
- }
- if(!outbuf) {
- verbose(1, "out of memory\n");
- return;
- }
- /* copies outbuf in memory allocation */
- adjust_packet(entry, &outbuf, &outlen, inbuf, (size_t)inlen);
- verbose(1, "Answer packet size: %u bytes.\n", (unsigned int)outlen);
- if(verbose_out) {
- char* out = sldns_wire2str_pkt(outbuf, outlen);
- printf("%s\n", out);
- free(out);
- }
- if(p->packet_sleep) {
- verbose(3, "sleeping for next packet %d secs\n",
- p->packet_sleep);
-#ifdef HAVE_SLEEP
- sleep(p->packet_sleep);
-#else
- Sleep(p->packet_sleep * 1000);
-#endif
- verbose(3, "wakeup for next packet "
- "(slept %d secs)\n", p->packet_sleep);
- }
- sendfunc(outbuf, outlen, userdata);
- free(outbuf);
- outbuf = NULL;
- outlen = 0;
- }
-}
-
-/** delete the list of reply packets */
-void delete_replylist(struct reply_packet* replist)
-{
- struct reply_packet *p=replist, *np;
- while(p) {
- np = p->next;
- free(p->reply_pkt);
- sldns_buffer_free(p->reply_from_hex);
- sldns_buffer_free(p->raw_ednsdata);
- free(p);
- p=np;
- }
-}
-
-void delete_entry(struct entry* list)
-{
- struct entry *p=list, *np;
- while(p) {
- np = p->next;
- delete_replylist(p->reply_list);
- free(p);
- p = np;
- }
-}
diff --git a/external/unbound/testcode/testpkts.h b/external/unbound/testcode/testpkts.h
deleted file mode 100644
index b175cab06..000000000
--- a/external/unbound/testcode/testpkts.h
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- * testpkts. Data file parse for test packets, and query matching.
- *
- * Data storage for specially crafted replies for testing purposes.
- *
- * (c) NLnet Labs, 2005, 2006, 2007
- * See the file LICENSE for the license
- */
-
-#ifndef TESTPKTS_H
-#define TESTPKTS_H
-struct sldns_buffer;
-struct sldns_file_parse_state;
-
-/**
- * \file
- *
- * This is a debugging aid. It is not efficient, especially
- * with a long config file, but it can give any reply to any query.
- * This can help the developer pre-script replies for queries.
- *
- * You can specify a packet RR by RR with header flags to return.
- *
- * Missing features:
- * - matching content different from reply content.
- * - find way to adjust mangled packets?
- *
- */
-
- /*
- The data file format is as follows:
-
- ; comment.
- ; a number of entries, these are processed first to last.
- ; a line based format.
-
- $ORIGIN origin
- $TTL default_ttl
-
- ENTRY_BEGIN
- ; first give MATCH lines, that say what queries are matched
- ; by this entry.
- ; 'opcode' makes the query match the opcode from the reply
- ; if you leave it out, any opcode matches this entry.
- ; 'qtype' makes the query match the qtype from the reply
- ; 'qname' makes the query match the qname from the reply
- ; 'subdomain' makes the query match subdomains of 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.
- ; 'noedns' matches queries without EDNS OPT records.
- ; 'rcode' makes the query match the rcode from the reply
- ; 'question' makes the query match the question section
- ; 'answer' makes the query match the answer section
- ; 'ednsdata' matches queries to HEX_EDNS section.
- MATCH [opcode] [qtype] [qname] [serial=<value>] [all] [ttl]
- MATCH [UDP|TCP] DO
- MATCH ...
- ; Then the REPLY header is specified.
- REPLY opcode, rcode or flags.
- (opcode) QUERY IQUERY STATUS NOTIFY UPDATE
- (rcode) NOERROR FORMERR SERVFAIL NXDOMAIN NOTIMPL YXDOMAIN
- YXRRSET NXRRSET NOTAUTH NOTZONE
- (flags) QR AA TC RD CD RA AD DO
- REPLY ...
- ; any additional actions to do.
- ; 'copy_id' copies the ID from the query to the answer.
- ADJUST copy_id
- ; 'copy_query' copies the query name, type and class to the answer.
- ADJUST copy_query
- ; 'sleep=10' sleeps for 10 seconds before giving the answer (TCP is open)
- ADJUST [sleep=<num>] ; sleep before giving any reply
- ADJUST [packet_sleep=<num>] ; sleep before this packet in sequence
- SECTION QUESTION
- <RRs, one per line> ; the RRcount is determined automatically.
- SECTION ANSWER
- <RRs, one per line>
- SECTION AUTHORITY
- <RRs, one per line>
- SECTION ADDITIONAL
- <RRs, one per line>
- EXTRA_PACKET ; follow with SECTION, REPLY for more packets.
- HEX_ANSWER_BEGIN ; follow with hex data
- ; this replaces any answer packet constructed
- ; with the SECTION keywords (only SECTION QUERY
- ; is used to match queries). If the data cannot
- ; be parsed, ADJUST rules for the answer packet
- ; are ignored. Only copy_id is done.
- HEX_ANSWER_END
- HEX_EDNS_BEGIN ; follow with hex data.
- ; Raw EDNS data to match against. It must be an
- ; exact match (all options are matched) and will be
- ; evaluated only when 'MATCH ednsdata' given.
- HEX_EDNS_END
- ENTRY_END
-
-
- Example data file:
-$ORIGIN nlnetlabs.nl
-$TTL 3600
-
-ENTRY_BEGIN
-MATCH qname
-REPLY NOERROR
-ADJUST copy_id
-SECTION QUESTION
-www.nlnetlabs.nl. IN A
-SECTION ANSWER
-www.nlnetlabs.nl. IN A 195.169.215.155
-SECTION AUTHORITY
-nlnetlabs.nl. IN NS www.nlnetlabs.nl.
-ENTRY_END
-
-ENTRY_BEGIN
-MATCH qname
-REPLY NOERROR
-ADJUST copy_id
-SECTION QUESTION
-www2.nlnetlabs.nl. IN A
-HEX_ANSWER_BEGIN
-; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
-;-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
- 00 bf 81 80 00 01 00 01 00 02 00 02 03 77 77 77 0b 6b 61 6e ; 1- 20
- 61 72 69 65 70 69 65 74 03 63 6f 6d 00 00 01 00 01 03 77 77 ; 21- 40
- 77 0b 6b 61 6e 61 72 69 65 70 69 65 74 03 63 6f 6d 00 00 01 ; 41- 60
- 00 01 00 01 50 8b 00 04 52 5e ed 32 0b 6b 61 6e 61 72 69 65 ; 61- 80
- 70 69 65 74 03 63 6f 6d 00 00 02 00 01 00 01 50 8b 00 11 03 ; 81- 100
- 6e 73 31 08 68 65 78 6f 6e 2d 69 73 02 6e 6c 00 0b 6b 61 6e ; 101- 120
- 61 72 69 65 70 69 65 74 03 63 6f 6d 00 00 02 00 01 00 01 50 ; 121- 140
- 8b 00 11 03 6e 73 32 08 68 65 78 6f 6e 2d 69 73 02 6e 6c 00 ; 141- 160
- 03 6e 73 31 08 68 65 78 6f 6e 2d 69 73 02 6e 6c 00 00 01 00 ; 161- 180
- 01 00 00 46 53 00 04 52 5e ed 02 03 6e 73 32 08 68 65 78 6f ; 181- 200
- 6e 2d 69 73 02 6e 6c 00 00 01 00 01 00 00 46 53 00 04 d4 cc ; 201- 220
- db 5b
-HEX_ANSWER_END
-ENTRY_END
-
-
-
- note that this file will link with your
- void verbose(int level, char* format, ...); output function.
-*/
-
-/** Type of transport, since some entries match based on UDP or TCP of query */
-enum transport_type {transport_any = 0, transport_udp, transport_tcp };
-
-/** struct to keep a linked list of reply packets for a query */
-struct reply_packet {
- /** next in list of reply packets, for TCP multiple pkts on wire */
- struct reply_packet* next;
- /** the reply pkt */
- uint8_t* reply_pkt;
- /** length of reply pkt */
- size_t reply_len;
- /** Additional EDNS data for matching queries. */
- struct sldns_buffer* raw_ednsdata;
- /** or reply pkt in hex if not parsable */
- struct sldns_buffer* reply_from_hex;
- /** seconds to sleep before giving packet */
- unsigned int packet_sleep;
-};
-
-/** data structure to keep the canned queries in.
- format is the 'matching query' and the 'canned answer' */
-struct entry {
- /* match */
- /* How to match an incoming query with this canned reply */
- /** match query opcode with answer opcode */
- uint8_t match_opcode;
- /** match qtype with answer qtype */
- uint8_t match_qtype;
- /** match qname with answer qname */
- uint8_t match_qname;
- /** match rcode with answer rcode */
- uint8_t match_rcode;
- /** match question section */
- uint8_t match_question;
- /** match answer section */
- uint8_t match_answer;
- /** match qname as subdomain of answer qname */
- uint8_t match_subdomain;
- /** match SOA serial number, from auth section */
- uint8_t match_serial;
- /** match all of the packet */
- uint8_t match_all;
- /** match ttls in the packet */
- uint8_t match_ttl;
- /** match DO bit */
- uint8_t match_do;
- /** match absence of EDNS OPT record in query */
- uint8_t match_noedns;
- /** match edns data field given in hex */
- uint8_t match_ednsdata_raw;
- /** match query serial with this value. */
- uint32_t ixfr_soa_serial;
- /** match on UDP/TCP */
- enum transport_type match_transport;
-
- /** pre canned reply */
- struct reply_packet *reply_list;
-
- /** how to adjust the reply packet */
- /** copy over the ID from the query into the answer */
- uint8_t copy_id;
- /** copy the query nametypeclass from query into the answer */
- uint8_t copy_query;
- /** copy ednsdata to reply, assume it is clientsubnet and
- * adjust scopemask to match sourcemask */
- uint8_t copy_ednsdata_assume_clientsubnet;
- /** in seconds */
- unsigned int sleeptime;
-
- /** some number that names this entry, line number in file or so */
- int lineno;
-
- /** next in list */
- struct entry* next;
-};
-
-/**
- * reads the canned reply file and returns a list of structs
- * does an exit on error.
- * @param name: name of the file to read.
- * @param skip_whitespace: skip leftside whitespace.
- */
-struct entry* read_datafile(const char* name, int skip_whitespace);
-
-/**
- * Delete linked list of entries.
- */
-void delete_entry(struct entry* list);
-
-/**
- * Read one entry from the data file.
- * @param in: file to read from. Filepos must be at the start of a new line.
- * @param name: name of the file for prettier errors.
- * @param pstate: file parse state with lineno, default_ttl,
- * origin and prev_rr name.
- * @param skip_whitespace: skip leftside whitespace.
- * @return: The entry read (malloced) or NULL if no entry could be read.
- */
-struct entry* read_entry(FILE* in, const char* name,
- struct sldns_file_parse_state* pstate, int skip_whitespace);
-
-/**
- * finds entry in list, or returns NULL.
- */
-struct entry* find_match(struct entry* entries, uint8_t* query_pkt,
- size_t query_pkt_len, enum transport_type transport);
-
-/**
- * match two packets, all must match
- * @param q: packet 1
- * @param qlen: length of q.
- * @param p: packet 2
- * @param plen: length of p.
- * @param mttl: if true, ttls must match, if false, ttls do not need to match
- * @param noloc: if true, rrs may be reordered in their packet-section.
- * rrs are then matches without location of the rr being important.
- * @return true if matched.
- */
-int match_all(uint8_t* q, size_t qlen, uint8_t* p, size_t plen, int mttl,
- int noloc);
-
-/**
- * copy & adjust packet, mallocs a copy.
- */
-void adjust_packet(struct entry* match, uint8_t** answer_pkt,
- size_t* answer_pkt_len, uint8_t* query_pkt, size_t query_pkt_len);
-
-/**
- * Parses data buffer to a query, finds the correct answer
- * and calls the given function for every packet to send.
- * if verbose_out filename is given, packets are dumped there.
- * @param inbuf: the packet that came in
- * @param inlen: length of packet.
- * @param entries: entries read in from datafile.
- * @param count: is increased to count number of queries answered.
- * @param transport: set to UDP or TCP to match some types of entries.
- * @param sendfunc: called to send answer (buffer, size, userarg).
- * @param userdata: userarg to give to sendfunc.
- * @param verbose_out: if not NULL, verbose messages are printed there.
- */
-void handle_query(uint8_t* inbuf, ssize_t inlen, struct entry* entries,
- int* count, enum transport_type transport,
- void (*sendfunc)(uint8_t*, size_t, void*), void* userdata,
- FILE* verbose_out);
-
-#endif /* TESTPKTS_H */
diff --git a/external/unbound/testcode/unitanchor.c b/external/unbound/testcode/unitanchor.c
deleted file mode 100644
index 8819c5ab6..000000000
--- a/external/unbound/testcode/unitanchor.c
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * testcode/unitanchor.c - unit test for trust anchor 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 COPYRIGHT
- * HOLDER 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 trust anchor unit tests. Exits with code 1 on a failure.
- */
-
-#include "config.h"
-#include "util/log.h"
-#include "util/data/dname.h"
-#include "testcode/unitmain.h"
-#include "validator/val_anchor.h"
-#include "sldns/sbuffer.h"
-#include "sldns/rrdef.h"
-
-/** test empty set */
-static void
-test_anchor_empty(struct val_anchors* a)
-{
- uint16_t c = LDNS_RR_CLASS_IN;
- unit_assert(anchors_lookup(a, (uint8_t*)"\000", 1, c) == NULL);
- unit_assert(anchors_lookup(a, (uint8_t*)"\003com\000", 5, c) == NULL);
- unit_assert(anchors_lookup(a,
- (uint8_t*)"\007example\003com\000", 11, c) == NULL);
- unit_assert(anchors_lookup(a, (uint8_t*)"\002nl\000", 4, c) == NULL);
- unit_assert(anchors_lookup(a,
- (uint8_t*)"\004labs\002nl\000", 9, c) == NULL);
- unit_assert(anchors_lookup(a,
- (uint8_t*)"\004fabs\002nl\000", 9, c) == NULL);
-}
-
-/** test set of one anchor */
-static void
-test_anchor_one(sldns_buffer* buff, struct val_anchors* a)
-{
- struct trust_anchor* ta;
- uint16_t c = LDNS_RR_CLASS_IN;
- unit_assert(anchor_store_str(a, buff,
- "nl. DS 42860 5 1 14D739EB566D2B1A5E216A0BA4D17FA9B038BE4A"));
- unit_assert(anchors_lookup(a, (uint8_t*)"\000", 1, c) == NULL);
- unit_assert(anchors_lookup(a, (uint8_t*)"\003com\000", 5, c) == NULL);
- unit_assert(anchors_lookup(a,
- (uint8_t*)"\007example\003com\000", 11, c) == NULL);
-
- unit_assert((ta=anchors_lookup(a,
- (uint8_t*)"\002nl\000", 4, c)) != NULL);
- lock_basic_unlock(&ta->lock);
-
- unit_assert((ta=anchors_lookup(a,
- (uint8_t*)"\004labs\002nl\000", 9, c)) != NULL);
- lock_basic_unlock(&ta->lock);
-
- unit_assert((ta=anchors_lookup(a,
- (uint8_t*)"\004fabs\002nl\000", 9, c)) != NULL);
- lock_basic_unlock(&ta->lock);
-
- unit_assert(anchors_lookup(a, (uint8_t*)"\002oo\000", 4, c) == NULL);
-}
-
-/** test with several anchors */
-static void
-test_anchors(sldns_buffer* buff, struct val_anchors* a)
-{
- struct trust_anchor* ta;
- uint16_t c = LDNS_RR_CLASS_IN;
- unit_assert(anchor_store_str(a, buff,
- "labs.nl. DS 42860 5 1 14D739EB566D2B1A5E216A0BA4D17FA9B038BE4A"));
- unit_assert(anchors_lookup(a, (uint8_t*)"\000", 1, c) == NULL);
- unit_assert(anchors_lookup(a, (uint8_t*)"\003com\000", 5, c) == NULL);
- unit_assert(anchors_lookup(a,
- (uint8_t*)"\007example\003com\000", 11, c) == NULL);
-
- unit_assert(ta = anchors_lookup(a, (uint8_t*)"\002nl\000", 4, c));
- unit_assert(query_dname_compare(ta->name, (uint8_t*)"\002nl\000")==0);
- lock_basic_unlock(&ta->lock);
-
- unit_assert(ta = anchors_lookup(a,
- (uint8_t*)"\004labs\002nl\000", 9, c));
- unit_assert(query_dname_compare(ta->name,
- (uint8_t*)"\004labs\002nl\000") == 0);
- lock_basic_unlock(&ta->lock);
-
- unit_assert(ta = anchors_lookup(a,
- (uint8_t*)"\004fabs\002nl\000", 9, c));
- unit_assert(query_dname_compare(ta->name,
- (uint8_t*)"\002nl\000") == 0);
- lock_basic_unlock(&ta->lock);
-
- unit_assert(anchors_lookup(a, (uint8_t*)"\002oo\000", 4, c) == NULL);
-}
-
-void anchors_test(void)
-{
- sldns_buffer* buff = sldns_buffer_new(65800);
- struct val_anchors* a;
- unit_show_feature("trust anchor store");
- unit_assert(a = anchors_create());
- sldns_buffer_flip(buff);
- test_anchor_empty(a);
- test_anchor_one(buff, a);
- test_anchors(buff, a);
- anchors_delete(a);
- sldns_buffer_free(buff);
-}
diff --git a/external/unbound/testcode/unitdname.c b/external/unbound/testcode/unitdname.c
deleted file mode 100644
index 238c3edf7..000000000
--- a/external/unbound/testcode/unitdname.c
+++ /dev/null
@@ -1,861 +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 COPYRIGHT
- * HOLDER 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"
-#include "sldns/sbuffer.h"
-#include "sldns/str2wire.h"
-
-/** put dname into buffer */
-static sldns_buffer*
-dname_to_buf(sldns_buffer* b, const char* str)
-{
- int e;
- size_t len = sldns_buffer_capacity(b);
- sldns_buffer_clear(b);
- e = sldns_str2wire_dname_buf(str, sldns_buffer_begin(b), &len);
- if(e != 0)
- fatal_exit("%s ldns: %s", __func__,
- sldns_get_errorstr_parse(e));
- sldns_buffer_set_position(b, len);
- sldns_buffer_flip(b);
- return b;
-}
-
-/** test query_dname_len function */
-static void
-dname_test_qdl(sldns_buffer* buff)
-{
- unit_show_func("util/data/dname.c", "query_dname_len");
- 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(sldns_buffer* buff)
-{
- unit_show_func("util/data/dname.c", "query_dname_tolower");
- sldns_buffer_write_at(buff, 0, "\012abCDeaBCde\003cOm\000", 16);
- query_dname_tolower(sldns_buffer_begin(buff));
- unit_assert( memcmp(sldns_buffer_begin(buff),
- "\012abcdeabcde\003com\000", 16) == 0);
-
- sldns_buffer_write_at(buff, 0, "\001+\012abC{e-ZYXe\003NET\000", 18);
- query_dname_tolower(sldns_buffer_begin(buff));
- unit_assert( memcmp(sldns_buffer_begin(buff),
- "\001+\012abc{e-zyxe\003net\000", 18) == 0);
-
- sldns_buffer_write_at(buff, 0, "\000", 1);
- query_dname_tolower(sldns_buffer_begin(buff));
- unit_assert( memcmp(sldns_buffer_begin(buff), "\000", 1) == 0);
-
- sldns_buffer_write_at(buff, 0, "\002NL\000", 4);
- query_dname_tolower(sldns_buffer_begin(buff));
- unit_assert( memcmp(sldns_buffer_begin(buff), "\002nl\000", 4) == 0);
-}
-
-/** test query_dname_compare */
-static void
-dname_test_query_dname_compare(void)
-{
- unit_show_func("util/data/dname.c", "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(void)
-{
- unit_show_func("util/data/dname.c", "dname_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(void)
-{
- size_t sz = 0;
- unit_show_func("util/data/dname.c", "dname_count_size_labels");
- 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(sldns_buffer* buff)
-{
- unit_show_func("util/data/dname.c", "pkt_dname_len");
- sldns_buffer_clear(buff);
- sldns_buffer_write(buff, "\000", 1);
- sldns_buffer_flip(buff);
- unit_assert( pkt_dname_len(buff) == 1 );
- unit_assert( sldns_buffer_position(buff) == 1);
-
- sldns_buffer_clear(buff);
- sldns_buffer_write(buff, "\003org\000", 5);
- sldns_buffer_flip(buff);
- unit_assert( pkt_dname_len(buff) == 5 );
- unit_assert( sldns_buffer_position(buff) == 5);
-
- sldns_buffer_clear(buff);
- sldns_buffer_write(buff, "\002os\007example\003org\000", 16);
- sldns_buffer_flip(buff);
- unit_assert( pkt_dname_len(buff) == 16 );
- unit_assert( sldns_buffer_position(buff) == 16);
-
- /* invalid compression pointer: to self */
- sldns_buffer_clear(buff);
- sldns_buffer_write(buff, "\300\000os\007example\003org\000", 17);
- sldns_buffer_flip(buff);
- unit_assert( pkt_dname_len(buff) == 0 );
-
- /* valid compression pointer */
- sldns_buffer_clear(buff);
- sldns_buffer_write(buff, "\003com\000\040\300\000", 8);
- sldns_buffer_flip(buff);
- sldns_buffer_set_position(buff, 6);
- unit_assert( pkt_dname_len(buff) == 5 );
- unit_assert( sldns_buffer_position(buff) == 8);
-
- /* unknown label type */
- sldns_buffer_clear(buff);
- sldns_buffer_write(buff, "\002os\107example\003org\000", 16);
- sldns_buffer_flip(buff);
- unit_assert( pkt_dname_len(buff) == 0 );
-
- /* label too long */
- sldns_buffer_clear(buff);
- sldns_buffer_write(buff, "\002os\047example\003org\000", 16);
- sldns_buffer_flip(buff);
- unit_assert( pkt_dname_len(buff) == 0 );
-
- /* label exceeds packet */
- sldns_buffer_clear(buff);
- sldns_buffer_write(buff, "\002os\007example\007org\004", 16);
- sldns_buffer_flip(buff);
- unit_assert( pkt_dname_len(buff) == 0 );
-
- /* name very long */
- sldns_buffer_clear(buff);
- sldns_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);
- sldns_buffer_flip(buff);
- unit_assert( pkt_dname_len(buff) == 255 );
- unit_assert( sldns_buffer_position(buff) == 255);
-
- /* name too long */
- sldns_buffer_clear(buff);
- sldns_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);
- sldns_buffer_flip(buff);
- unit_assert( pkt_dname_len(buff) == 0 );
-}
-
-/** test dname_lab_cmp */
-static void
-dname_test_dname_lab_cmp(void)
-{
- int ml = 0; /* number of labels that matched exactly */
- unit_show_func("util/data/dname.c", "dname_lab_cmp");
-
- /* 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(void)
-{
- unit_show_func("util/data/dname.c", "dname_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(void)
-{
- unit_show_func("util/data/dname.c", "dname_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));
-}
-
-/** test dname_is_root */
-static void
-dname_test_isroot(void)
-{
- unit_show_func("util/data/dname.c", "dname_isroot");
- unit_assert(dname_is_root((uint8_t*)"\000"));
- unit_assert(!dname_is_root((uint8_t*)"\001a\000"));
- unit_assert(!dname_is_root((uint8_t*)"\005abvcd\003com\000"));
- /* malformed dname in this test, but should work */
- unit_assert(!dname_is_root((uint8_t*)"\077a\000"));
- unit_assert(dname_is_root((uint8_t*)"\000"));
-}
-
-/** test dname_remove_label */
-static void
-dname_test_removelabel(void)
-{
- uint8_t* orig = (uint8_t*)"\007example\003com\000";
- uint8_t* n = orig;
- size_t l = 13;
- unit_show_func("util/data/dname.c", "dname_remove_label");
- dname_remove_label(&n, &l);
- unit_assert( n == orig+8 );
- unit_assert( l == 5 );
- dname_remove_label(&n, &l);
- unit_assert( n == orig+12 );
- unit_assert( l == 1 );
- dname_remove_label(&n, &l);
- unit_assert( n == orig+12 );
- unit_assert( l == 1 );
-}
-
-/** test dname_signame_label_count */
-static void
-dname_test_sigcount(void)
-{
- unit_show_func("util/data/dname.c", "dname_signame_label_count");
- unit_assert(dname_signame_label_count((uint8_t*)"\000") == 0);
- unit_assert(dname_signame_label_count((uint8_t*)"\001*\000") == 0);
- unit_assert(dname_signame_label_count((uint8_t*)"\003xom\000") == 1);
- unit_assert(dname_signame_label_count(
- (uint8_t*)"\001*\003xom\000") == 1);
- unit_assert(dname_signame_label_count(
- (uint8_t*)"\007example\003xom\000") == 2);
- unit_assert(dname_signame_label_count(
- (uint8_t*)"\001*\007example\003xom\000") == 2);
- unit_assert(dname_signame_label_count(
- (uint8_t*)"\003www\007example\003xom\000") == 3);
- unit_assert(dname_signame_label_count(
- (uint8_t*)"\001*\003www\007example\003xom\000") == 3);
-}
-
-/** test dname_is_wild routine */
-static void
-dname_test_iswild(void)
-{
- unit_show_func("util/data/dname.c", "dname_iswild");
- unit_assert( !dname_is_wild((uint8_t*)"\000") );
- unit_assert( dname_is_wild((uint8_t*)"\001*\000") );
- unit_assert( !dname_is_wild((uint8_t*)"\003net\000") );
- unit_assert( dname_is_wild((uint8_t*)"\001*\003net\000") );
-}
-
-/** test dname_canonical_compare */
-static void
-dname_test_canoncmp(void)
-{
- unit_show_func("util/data/dname.c", "dname_canonical_compare");
- /* equality */
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\000",
- (uint8_t*)"\000"
- ) == 0);
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\003net\000",
- (uint8_t*)"\003net\000"
- ) == 0);
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\007example\003net\000",
- (uint8_t*)"\007example\003net\000"
- ) == 0);
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\004test\007example\003net\000",
- (uint8_t*)"\004test\007example\003net\000"
- ) == 0);
-
- /* subdomains */
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\003com",
- (uint8_t*)"\000"
- ) == 1);
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\000",
- (uint8_t*)"\003com"
- ) == -1);
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\007example\003com",
- (uint8_t*)"\003com"
- ) == 1);
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\003com",
- (uint8_t*)"\007example\003com"
- ) == -1);
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\007example\003com",
- (uint8_t*)"\000"
- ) == 1);
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\000",
- (uint8_t*)"\007example\003com"
- ) == -1);
-
- /* compare rightmost label */
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\003com",
- (uint8_t*)"\003net"
- ) == -1);
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\003net",
- (uint8_t*)"\003com"
- ) == 1);
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\003net",
- (uint8_t*)"\003org"
- ) == -1);
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\007example\003net",
- (uint8_t*)"\003org"
- ) == -1);
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\003org",
- (uint8_t*)"\007example\003net"
- ) == 1);
-
- /* label length makes a difference; but only if rest is equal */
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\004neta",
- (uint8_t*)"\003net"
- ) == 1);
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\002ne",
- (uint8_t*)"\004neta"
- ) == -1);
-
- /* label content */
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\003aag\007example\003net",
- (uint8_t*)"\003bla\007example\003net"
- ) == -1);
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\003bla\007example\003net",
- (uint8_t*)"\003aag\007example\003net"
- ) == 1);
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\003bla\003aag\007example\003net",
- (uint8_t*)"\003aag\003bla\007example\003net"
- ) == -1);
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\02sn\003opt\003aag\007example\003net",
- (uint8_t*)"\02sn\003opt\003bla\007example\003net"
- ) == -1);
-
- /* lowercase during compare */
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\003bLa\007examPLe\003net",
- (uint8_t*)"\003bla\007eXAmple\003nET"
- ) == 0);
-
- /* example from 4034 */
- /* example a.example yljkjljk.a.example Z.a.example zABC.a.EXAMPLE
- z.example \001.z.example *.z.example \200.z.example */
- unit_assert( dname_canonical_compare(
- (uint8_t*)"",
- (uint8_t*)"\007example"
- ) == -1);
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\007example",
- (uint8_t*)"\001a\007example"
- ) == -1);
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\001a\007example",
- (uint8_t*)"\010yljkjljk\001a\007example"
- ) == -1);
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\010yljkjljk\001a\007example",
- (uint8_t*)"\001Z\001a\007example"
- ) == -1);
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\001Z\001a\007example",
- (uint8_t*)"\004zABC\001a\007EXAMPLE"
- ) == -1);
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\004zABC\001a\007EXAMPLE",
- (uint8_t*)"\001z\007example"
- ) == -1);
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\001z\007example",
- (uint8_t*)"\001\001\001z\007example"
- ) == -1);
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\001\001\001z\007example",
- (uint8_t*)"\001*\001z\007example"
- ) == -1);
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\001*\001z\007example",
- (uint8_t*)"\001\200\001z\007example"
- ) == -1);
- /* same example in reverse */
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\007example",
- (uint8_t*)""
- ) == 1);
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\001a\007example",
- (uint8_t*)"\007example"
- ) == 1);
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\010yljkjljk\001a\007example",
- (uint8_t*)"\001a\007example"
- ) == 1);
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\001Z\001a\007example",
- (uint8_t*)"\010yljkjljk\001a\007example"
- ) == 1);
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\004zABC\001a\007EXAMPLE",
- (uint8_t*)"\001Z\001a\007example"
- ) == 1);
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\001z\007example",
- (uint8_t*)"\004zABC\001a\007EXAMPLE"
- ) == 1);
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\001\001\001z\007example",
- (uint8_t*)"\001z\007example"
- ) == 1);
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\001*\001z\007example",
- (uint8_t*)"\001\001\001z\007example"
- ) == 1);
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\001\200\001z\007example",
- (uint8_t*)"\001*\001z\007example"
- ) == 1);
- /* same example for equality */
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\007example",
- (uint8_t*)"\007example"
- ) == 0);
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\001a\007example",
- (uint8_t*)"\001a\007example"
- ) == 0);
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\010yljkjljk\001a\007example",
- (uint8_t*)"\010yljkjljk\001a\007example"
- ) == 0);
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\001Z\001a\007example",
- (uint8_t*)"\001Z\001a\007example"
- ) == 0);
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\004zABC\001a\007EXAMPLE",
- (uint8_t*)"\004zABC\001a\007EXAMPLE"
- ) == 0);
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\001z\007example",
- (uint8_t*)"\001z\007example"
- ) == 0);
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\001\001\001z\007example",
- (uint8_t*)"\001\001\001z\007example"
- ) == 0);
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\001*\001z\007example",
- (uint8_t*)"\001*\001z\007example"
- ) == 0);
- unit_assert( dname_canonical_compare(
- (uint8_t*)"\001\200\001z\007example",
- (uint8_t*)"\001\200\001z\007example"
- ) == 0);
-}
-
-/** Test dname_get_shared_topdomain */
-static void
-dname_test_topdomain(void)
-{
- unit_show_func("util/data/dname.c", "dname_get_shared_topdomain");
- unit_assert( query_dname_compare(
- dname_get_shared_topdomain(
- (uint8_t*)"",
- (uint8_t*)""),
- (uint8_t*)"") == 0);
- unit_assert( query_dname_compare(
- dname_get_shared_topdomain(
- (uint8_t*)"\003www\007example\003com",
- (uint8_t*)"\003www\007example\003com"),
- (uint8_t*)"\003www\007example\003com") == 0);
- unit_assert( query_dname_compare(
- dname_get_shared_topdomain(
- (uint8_t*)"\003www\007example\003com",
- (uint8_t*)"\003bla\007example\003com"),
- (uint8_t*)"\007example\003com") == 0);
-}
-
-/** Test dname_valid */
-static void
-dname_test_valid(void)
-{
- unit_show_func("util/data/dname.c", "dname_valid");
- unit_assert( dname_valid(
- (uint8_t*)"\003www\007example\003com", 255) == 17);
- unit_assert( dname_valid((uint8_t*)"", 255) == 1);
- unit_assert( dname_valid( (uint8_t*)
- "\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) == 255);
- unit_assert( dname_valid( (uint8_t*)
- "\020a1cdef5555544444"
- "\020a2cdef5555544444"
- "\020a3cdef5555544444"
- "\020a4cdef5555544444"
- "\020a5cdef5555544444"
- "\020a6cdef5555544444"
- "\020a7cdef5555544444"
- "\020a8cdef5555544444"
- "\020a9cdef5555544444"
- "\020aAcdef5555544444"
- "\020aBcdef5555544444"
- "\020aCcdef5555544444"
- "\020aDcdef5555544444"
- "\020aEcdef5555544444" /* 238 up to here */
- "\007aabbccd" /* 246 up to here */
- "\010exampleX\000" /* 256 to here */
- , 4096) == 0);
-}
-
-/** test pkt_dname_tolower */
-static void
-dname_test_pdtl(sldns_buffer* loopbuf, sldns_buffer* boundbuf)
-{
- unit_show_func("util/data/dname.c", "pkt_dname_tolower");
- pkt_dname_tolower(loopbuf, sldns_buffer_at(loopbuf, 12));
- pkt_dname_tolower(boundbuf, sldns_buffer_at(boundbuf, 12));
-}
-
-/** setup looped dname and out-of-bounds dname ptr */
-static void
-dname_setup_bufs(sldns_buffer* loopbuf, sldns_buffer* boundbuf)
-{
- sldns_buffer_write_u16(loopbuf, 0xd54d); /* id */
- sldns_buffer_write_u16(loopbuf, 0x12); /* flags */
- sldns_buffer_write_u16(loopbuf, 1); /* qdcount */
- sldns_buffer_write_u16(loopbuf, 0); /* ancount */
- sldns_buffer_write_u16(loopbuf, 0); /* nscount */
- sldns_buffer_write_u16(loopbuf, 0); /* arcount */
- sldns_buffer_write_u8(loopbuf, 0xc0); /* PTR back at itself */
- sldns_buffer_write_u8(loopbuf, 0x0c);
- sldns_buffer_flip(loopbuf);
-
- sldns_buffer_write_u16(boundbuf, 0xd54d); /* id */
- sldns_buffer_write_u16(boundbuf, 0x12); /* flags */
- sldns_buffer_write_u16(boundbuf, 1); /* qdcount */
- sldns_buffer_write_u16(boundbuf, 0); /* ancount */
- sldns_buffer_write_u16(boundbuf, 0); /* nscount */
- sldns_buffer_write_u16(boundbuf, 0); /* arcount */
- sldns_buffer_write_u8(boundbuf, 0x01); /* len=1 */
- sldns_buffer_write_u8(boundbuf, (uint8_t)'A'); /* A. label */
- sldns_buffer_write_u8(boundbuf, 0xc0); /* PTR out of bounds */
- sldns_buffer_write_u8(boundbuf, 0xcc);
- sldns_buffer_flip(boundbuf);
-}
-
-void dname_test(void)
-{
- sldns_buffer* loopbuf = sldns_buffer_new(14);
- sldns_buffer* boundbuf = sldns_buffer_new(16);
- sldns_buffer* buff = sldns_buffer_new(65800);
- unit_assert(loopbuf && boundbuf && buff);
- sldns_buffer_flip(buff);
- dname_setup_bufs(loopbuf, boundbuf);
- dname_test_qdl(buff);
- dname_test_qdtl(buff);
- dname_test_pdtl(loopbuf, boundbuf);
- 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();
- dname_test_isroot();
- dname_test_removelabel();
- dname_test_sigcount();
- dname_test_iswild();
- dname_test_canoncmp();
- dname_test_topdomain();
- dname_test_valid();
- sldns_buffer_free(buff);
- sldns_buffer_free(loopbuf);
- sldns_buffer_free(boundbuf);
-}
diff --git a/external/unbound/testcode/unitecs.c b/external/unbound/testcode/unitecs.c
deleted file mode 100644
index 3584b0f98..000000000
--- a/external/unbound/testcode/unitecs.c
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * testcode/unitecs.c - unit test for ecs routines.
- *
- * Copyright (c) 2013, 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 ecs related unit tests. Exits with code 1 on a failure.
- */
-
-#include "config.h"
-
-#ifdef CLIENT_SUBNET
-
-#include "util/log.h"
-#include "util/module.h"
-#include "testcode/unitmain.h"
-#include "edns-subnet/addrtree.h"
-#include "edns-subnet/subnetmod.h"
-
-/*
- void printkey(addrkey_t *k, addrlen_t bits)
- {
- int byte;
- int bytes = bits/8 + ((bits%8)>0);
- char msk = 0xFF;
- for (byte = 0; byte < bytes; byte++) {
- //~ if (byte+1 == bytes)
- //~ msk = 0xFF<<(8-bits%8);
- printf("%02x ", k[byte]&msk);
- }
- }
-
- void print_tree(struct addrnode* node, int indent, int maxdepth)
- {
- struct addredge* edge;
- int i, s, byte;
- if (indent == 0) printf("-----Tree-----\n");
- if (indent > maxdepth) {
- printf("\n");
- return;
- }
- printf("[node elem:%d] (%d)\n", node->elem != NULL, node);
- for (i = 0; i<2; i++) {
- if (node->edge[i]) {
- for (s = 0; s < indent; s++) printf(" ");
- printkey(node->edge[i]->str, node->edge[i]->len);
- printf("(len %d bits, %d bytes) ", node->edge[i]->len,
- node->edge[i]->len/8 + ((node->edge[i]->len%8)>0));
- print_tree(node->edge[i]->node, indent+1, maxdepth);
- }
- }
- if (indent == 0) printf("-----Tree-----");
- }
-*/
-
-/* what should we check?
- * X - is it balanced? (a node with 1 child shoudl not have
- * a node with 1 child MUST have elem
- * child must be sub of parent
- * edge must be longer than parent edge
- * */
-static int addrtree_inconsistent_subtree(struct addrtree* tree,
- struct addredge* parent_edge, addrlen_t depth)
-{
- struct addredge* edge;
- struct addrnode* node = parent_edge->node;
- int childcount, i, r;
- if (depth > tree->max_depth) return 15;
- childcount = (node->edge[0] != NULL) + (node->edge[1] != NULL);
- /* Only nodes with 2 children should possibly have no element. */
- if (childcount < 2 && !node->elem) return 10;
- for (i = 0; i<2; i++) {
- edge = node->edge[i];
- if (!edge) continue;
- if (!edge->node) return 11;
- if (!edge->str) return 12;
- if (edge->len <= parent_edge->len) return 13;
- if (!unittest_wrapper_addrtree_issub(parent_edge->str,
- parent_edge->len, edge->str, edge->len, 0))
- return 14;
- if ((r = addrtree_inconsistent_subtree(tree, edge, depth+1)) != 0)
- return 100+r;
- }
- return 0;
-}
-
-static int addrtree_inconsistent(struct addrtree* tree)
-{
- struct addredge* edge;
- int i, r;
-
- if (!tree) return 0;
- if (!tree->root) return 1;
-
- for (i = 0; i<2; i++) {
- edge = tree->root->edge[i];
- if (!edge) continue;
- if (!edge->node) return 3;
- if (!edge->str) return 4;
- if ((r = addrtree_inconsistent_subtree(tree, edge, 1)) != 0)
- return r;
- }
- return 0;
-}
-
-static addrlen_t randomkey(addrkey_t **k, int maxlen)
-{
- int byte;
- int bits = rand() % maxlen;
- int bytes = bits/8 + (bits%8>0); /*ceil*/
- *k = (addrkey_t *) malloc(bytes * sizeof(addrkey_t));
- for (byte = 0; byte < bytes; byte++) {
- (*k)[byte] = (addrkey_t)(rand() & 0xFF);
- }
- return (addrlen_t)bits;
-}
-
-static void elemfree(void *envptr, void *elemptr)
-{
- struct reply_info *elem = (struct reply_info *)elemptr;
- (void)envptr;
- free(elem);
-}
-
-static void consistency_test(void)
-{
- addrlen_t l;
- time_t i;
- unsigned int count;
- addrkey_t *k;
- struct addrtree* t;
- struct module_env env;
- struct reply_info *elem;
- time_t timenow = 0;
- unit_show_func("edns-subnet/addrtree.h", "Tree consistency check");
- srand(9195); /* just some value for reproducibility */
-
- t = addrtree_create(100, &elemfree, &unittest_wrapper_subnetmod_sizefunc, &env, 0);
- count = t->node_count;
- unit_assert(count == 0);
- for (i = 0; i < 1000; i++) {
- l = randomkey(&k, 128);
- elem = (struct reply_info *) calloc(1, sizeof(struct reply_info));
- addrtree_insert(t, k, l, 64, elem, timenow + 10, timenow);
- /* This should always hold because no items ever expire. They
- * could be overwritten, though. */
- unit_assert( count <= t->node_count );
- count = t->node_count;
- free(k);
- unit_assert( !addrtree_inconsistent(t) );
- }
- addrtree_delete(t);
-
- unit_show_func("edns-subnet/addrtree.h", "Tree consistency with purge");
- t = addrtree_create(8, &elemfree, &unittest_wrapper_subnetmod_sizefunc, &env, 0);
- unit_assert(t->node_count == 0);
- for (i = 0; i < 1000; i++) {
- l = randomkey(&k, 128);
- elem = (struct reply_info *) calloc(1, sizeof(struct reply_info));
- addrtree_insert(t, k, l, 64, elem, i + 10, i);
- free(k);
- unit_assert( !addrtree_inconsistent(t) );
- }
- addrtree_delete(t);
-
- unit_show_func("edns-subnet/addrtree.h", "Tree consistency with limit");
- t = addrtree_create(8, &elemfree, &unittest_wrapper_subnetmod_sizefunc, &env, 27);
- unit_assert(t->node_count == 0);
- for (i = 0; i < 1000; i++) {
- l = randomkey(&k, 128);
- elem = (struct reply_info *) calloc(1, sizeof(struct reply_info));
- addrtree_insert(t, k, l, 64, elem, i + 10, i);
- unit_assert( t->node_count <= 27);
- free(k);
- unit_assert( !addrtree_inconsistent(t) );
- }
- addrtree_delete(t);
-}
-
-static void issub_test(void)
-{
- addrkey_t k1[] = {0x55, 0x55, 0x5A};
- addrkey_t k2[] = {0x55, 0x5D, 0x5A};
- unit_show_func("edns-subnet/addrtree.h", "issub");
- unit_assert( !unittest_wrapper_addrtree_issub(k1, 24, k2, 24, 0) );
- unit_assert( unittest_wrapper_addrtree_issub(k1, 8, k2, 16, 0) );
- unit_assert( unittest_wrapper_addrtree_issub(k2, 12, k1, 13, 0) );
- unit_assert( !unittest_wrapper_addrtree_issub(k1, 16, k2, 12, 0) );
- unit_assert( unittest_wrapper_addrtree_issub(k1, 12, k2, 12, 0) );
- unit_assert( !unittest_wrapper_addrtree_issub(k1, 13, k2, 13, 0) );
- unit_assert( unittest_wrapper_addrtree_issub(k1, 24, k2, 24, 13) );
- unit_assert( !unittest_wrapper_addrtree_issub(k1, 24, k2, 20, 13) );
- unit_assert( unittest_wrapper_addrtree_issub(k1, 20, k2, 24, 13) );
-}
-
-static void getbit_test(void)
-{
- addrkey_t k1[] = {0x55, 0x55, 0x5A};
- int i;
- unit_show_func("edns-subnet/addrtree.h", "getbit");
- for(i = 0; i<20; i++) {
- unit_assert( unittest_wrapper_addrtree_getbit(k1, 20, (addrlen_t)i) == (i&1) );
- }
-}
-
-static void bits_common_test(void)
-{
- addrkey_t k1[] = {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0};
- addrkey_t k2[] = {0,0,0,0,0,0,0,0};
- addrlen_t i;
-
- unit_show_func("edns-subnet/addrtree.h", "bits_common");
- for(i = 0; i<64; i++) {
- unit_assert( unittest_wrapper_addrtree_bits_common(k1, 64, k1, 64, i) == 64 );
- }
- for(i = 0; i<8; i++) {
- k2[i] = k1[i]^(1<<i);
- }
- unit_assert( unittest_wrapper_addrtree_bits_common(k1, 64, k2, 64, 0) == 0*8+7 );
- unit_assert( unittest_wrapper_addrtree_bits_common(k1, 64, k2, 64, 8) == 1*8+6 );
- unit_assert( unittest_wrapper_addrtree_bits_common(k1, 64, k2, 64, 16) == 2*8+5 );
- unit_assert( unittest_wrapper_addrtree_bits_common(k1, 64, k2, 64, 24) == 3*8+4 );
- unit_assert( unittest_wrapper_addrtree_bits_common(k1, 64, k2, 64, 32) == 4*8+3 );
- unit_assert( unittest_wrapper_addrtree_bits_common(k1, 64, k2, 64, 40) == 5*8+2 );
- unit_assert( unittest_wrapper_addrtree_bits_common(k1, 64, k2, 64, 48) == 6*8+1 );
- unit_assert( unittest_wrapper_addrtree_bits_common(k1, 64, k2, 64, 56) == 7*8+0 );
-}
-
-static void cmpbit_test(void)
-{
- addrkey_t k1[] = {0xA5, 0x0F};
- addrkey_t k2[] = {0x5A, 0xF0};
- addrlen_t i;
-
- unit_show_func("edns-subnet/addrtree.h", "cmpbit");
- for(i = 0; i<16; i++) {
- unit_assert( !unittest_wrapper_addrtree_cmpbit(k1,k1,i) );
- unit_assert( unittest_wrapper_addrtree_cmpbit(k1,k2,i) );
- }
-}
-
-void ecs_test(void)
-{
- unit_show_feature("ecs");
- cmpbit_test();
- bits_common_test();
- getbit_test();
- issub_test();
- consistency_test();
-}
-#endif /* CLIENT_SUBNET */
-
diff --git a/external/unbound/testcode/unitldns.c b/external/unbound/testcode/unitldns.c
deleted file mode 100644
index e27e46eaa..000000000
--- a/external/unbound/testcode/unitldns.c
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * testcode/unitldns.c - unit test for ldns routines.
- *
- * Copyright (c) 2014, 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 COPYRIGHT
- * HOLDER 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 ldns unit tests. Exits with code 1 on a failure.
- */
-
-#include "config.h"
-#include "util/log.h"
-#include "testcode/unitmain.h"
-#include "sldns/sbuffer.h"
-#include "sldns/str2wire.h"
-#include "sldns/wire2str.h"
-
-/** verbose this unit test */
-static int vbmp = 0;
-
-/** print buffer to hex into string */
-static void
-buf_to_hex(uint8_t* b, size_t blen, char* s, size_t slen)
-{
- const char* h = "0123456789ABCDEF";
- size_t i;
- if(slen < blen*2+2 && vbmp) printf("hexstring buffer too small\n");
- unit_assert(slen >= blen*2+2);
- for(i=0; i<blen; i++) {
- s[i*2] = h[(b[i]&0xf0)>>4];
- s[i*2+1] = h[b[i]&0x0f];
- }
- s[blen*2] = '\n';
- s[blen*2+1] = 0;
-}
-
-/** Transform input.
- * @param txt_in: input text format.
- * @param wire1: output wireformat in hex (txt_in converted to wire).
- * @param txt_out: output text format (converted from wire_out).
- * @param wire2: output wireformat in hex, txt_out converted back to wireformat.
- * @param bufs: size of the text buffers.
- */
-static void
-rr_transform(char* txt_in, char* wire1, char* txt_out, char* wire2,
- size_t bufs)
-{
- uint8_t b[65536];
- size_t len;
- int err;
-
- len = sizeof(b);
- err = sldns_str2wire_rr_buf(txt_in, b, &len, NULL, 3600,
- NULL, 0, NULL, 0);
- if(err != 0) {
- if(vbmp) printf("sldns_str2wire_rr_buf, pos %d: %s\n",
- LDNS_WIREPARSE_OFFSET(err),
- sldns_get_errorstr_parse(err));
- }
- unit_assert(err == 0);
- buf_to_hex(b, len, wire1, bufs);
- if(vbmp) printf("wire1: %s", wire1);
-
- err = sldns_wire2str_rr_buf(b, len, txt_out, bufs);
- unit_assert(err < (int)bufs && err > 0);
- if(vbmp) printf("txt: %s", txt_out);
-
- len = sizeof(b);
- err = sldns_str2wire_rr_buf(txt_out, b, &len, NULL, 3600,
- NULL, 0, NULL, 0);
- if(err != 0) {
- if(vbmp) printf("sldns_str2wire_rr_buf-2, pos %d: %s\n",
- LDNS_WIREPARSE_OFFSET(err),
- sldns_get_errorstr_parse(err));
- }
- unit_assert(err == 0);
- buf_to_hex(b, len, wire2, bufs);
- if(vbmp) printf("wire2: %s", wire2);
-}
-
-/** Check if results are correct */
-static void
-rr_checks(char* wire_chk, char* txt_chk, char* txt_out, char* wire_out,
- char* back)
-{
-#ifdef __APPLE__
- /* the wiretostr on ipv6 is weird on apple, we cannot check it.
- * skip AAAA on OSX */
- if(strstr(txt_out, "IN AAAA"))
- txt_out = txt_chk; /* skip this test, but test wirefmt */
- /* so we know that txt_out back to wire is the same */
-#endif
-
- if(strcmp(txt_chk, txt_out) != 0 && vbmp)
- printf("txt different\n");
- if(strcmp(wire_chk, wire_out) != 0 && vbmp)
- printf("wire1 different\n");
- if(strcmp(wire_chk, back) != 0 && vbmp)
- printf("wire2 different\n");
-
- unit_assert(strcmp(txt_chk, txt_out) == 0);
- unit_assert(strcmp(wire_chk, wire_out) == 0);
- unit_assert(strcmp(wire_chk, back) == 0);
-}
-
-/** read rrs to and from string, and wireformat
- * Skips empty lines and comments.
- * @param input: input file with text format.
- * @param check: check file with hex and then textformat
- */
-static void
-rr_test_file(const char* input, const char* check)
-{
- size_t bufs = 131072;
- FILE* inf, *chf, *of;
- int lineno = 0, chlineno = 0;
- char* txt_in = (char*)malloc(bufs);
- char* txt_out = (char*)malloc(bufs);
- char* txt_chk = (char*)malloc(bufs);
- char* wire_out = (char*)malloc(bufs);
- char* wire_chk = (char*)malloc(bufs);
- char* back = (char*)malloc(bufs);
- if(!txt_in || !txt_out || !txt_chk || !wire_out || !wire_chk || !back)
- fatal_exit("malloc failure");
- inf = fopen(input, "r");
- if(!inf) fatal_exit("cannot open %s: %s", input, strerror(errno));
- chf = fopen(check, "r");
- if(!chf) fatal_exit("cannot open %s: %s", check, strerror(errno));
-
- of = NULL;
- if(0) {
- /* debug: create check file */
- of = fopen("outputfile", "w");
- if(!of) fatal_exit("cannot write output: %s", strerror(errno));
- }
-
- while(fgets(txt_in, (int)bufs, inf)) {
- lineno++;
- if(vbmp) printf("\n%s:%d %s", input, lineno, txt_in);
- /* skip empty lines and comments */
- if(txt_in[0] == 0 || txt_in[0] == '\n' || txt_in[0] == ';')
- continue;
- /* read check lines */
- if(!fgets(wire_chk, (int)bufs, chf))
- printf("%s too short\n", check);
- if(!fgets(txt_chk, (int)bufs, chf))
- printf("%s too short\n", check);
- chlineno += 2;
- if(vbmp) printf("%s:%d %s", check, chlineno-1, wire_chk);
- if(vbmp) printf("%s:%d %s", check, chlineno, txt_chk);
- /* generate results */
- rr_transform(txt_in, wire_out, txt_out, back, bufs);
- /* checks */
- if(of) {
- fprintf(of, "%s%s", wire_out, txt_out);
- } else {
- rr_checks(wire_chk, txt_chk, txt_out, wire_out, back);
- }
- }
-
- if(of) fclose(of);
- fclose(inf);
- fclose(chf);
- free(txt_in);
- free(txt_out);
- free(txt_chk);
- free(wire_out);
- free(wire_chk);
- free(back);
-}
-
-/** read rrs to and from string, to and from wireformat */
-static void
-rr_tests(void)
-{
- rr_test_file("testdata/test_ldnsrr.1", "testdata/test_ldnsrr.c1");
- rr_test_file("testdata/test_ldnsrr.2", "testdata/test_ldnsrr.c2");
- rr_test_file("testdata/test_ldnsrr.3", "testdata/test_ldnsrr.c3");
- rr_test_file("testdata/test_ldnsrr.4", "testdata/test_ldnsrr.c4");
- rr_test_file("testdata/test_ldnsrr.5", "testdata/test_ldnsrr.c5");
-}
-
-void
-ldns_test(void)
-{
- unit_show_feature("sldns");
- rr_tests();
-}
diff --git a/external/unbound/testcode/unitlruhash.c b/external/unbound/testcode/unitlruhash.c
deleted file mode 100644
index e196f0b63..000000000
--- a/external/unbound/testcode/unitlruhash.c
+++ /dev/null
@@ -1,499 +0,0 @@
-/*
- * testcode/unitlruhash.c - unit test for lruhash table.
- *
- * 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 COPYRIGHT
- * HOLDER 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
- * Tests the locking LRU keeping hash table implementation.
- */
-
-#include "config.h"
-#include "testcode/unitmain.h"
-#include "util/log.h"
-#include "util/storage/lruhash.h"
-#include "util/storage/slabhash.h" /* for the test structures */
-
-/** use this type for the lruhash test key */
-typedef struct slabhash_testkey testkey_type;
-/** use this type for the lruhash test data */
-typedef struct slabhash_testdata testdata_type;
-
-/** delete key */
-static void delkey(struct slabhash_testkey* k) {
- lock_rw_destroy(&k->entry.lock); free(k);}
-/** delete data */
-static void deldata(struct slabhash_testdata* d) {free(d);}
-
-/** hash func, very bad to improve collisions */
-static hashvalue_type myhash(int id) {return (hashvalue_type)id & 0x0f;}
-/** allocate new key, fill in hash */
-static testkey_type* newkey(int id) {
- testkey_type* k = (testkey_type*)calloc(1, sizeof(testkey_type));
- if(!k) fatal_exit("out of memory");
- k->id = id;
- k->entry.hash = myhash(id);
- k->entry.key = k;
- lock_rw_init(&k->entry.lock);
- return k;
-}
-/** new data el */
-static testdata_type* newdata(int val) {
- testdata_type* d = (testdata_type*)calloc(1,
- sizeof(testdata_type));
- if(!d) fatal_exit("out of memory");
- d->data = val;
- return d;
-}
-
-/** test bin_find_entry function and bin_overflow_remove */
-static void
-test_bin_find_entry(struct lruhash* table)
-{
- testkey_type* k = newkey(12);
- testdata_type* d = newdata(128);
- testkey_type* k2 = newkey(12 + 1024);
- testkey_type* k3 = newkey(14);
- testkey_type* k4 = newkey(12 + 1024*2);
- hashvalue_type h = myhash(12);
- struct lruhash_bin bin;
- memset(&bin, 0, sizeof(bin));
- bin_init(&bin, 1);
-
- /* remove from empty list */
- bin_overflow_remove(&bin, &k->entry);
-
- /* find in empty list */
- unit_assert( bin_find_entry(table, &bin, h, k) == NULL );
-
- /* insert */
- lock_quick_lock(&bin.lock);
- bin.overflow_list = &k->entry;
- lock_quick_unlock(&bin.lock);
-
- /* find, hash not OK. */
- unit_assert( bin_find_entry(table, &bin, myhash(13), k) == NULL );
-
- /* find, hash OK, but cmp not */
- unit_assert( k->entry.hash == k2->entry.hash );
- unit_assert( bin_find_entry(table, &bin, h, k2) == NULL );
-
- /* find, hash OK, and cmp too */
- unit_assert( bin_find_entry(table, &bin, h, k) == &k->entry );
-
- /* remove the element */
- lock_quick_lock(&bin.lock);
- bin_overflow_remove(&bin, &k->entry);
- lock_quick_unlock(&bin.lock);
- unit_assert( bin_find_entry(table, &bin, h, k) == NULL );
-
- /* prepend two different elements; so the list is long */
- /* one has the same hash, but different cmp */
- lock_quick_lock(&bin.lock);
- unit_assert( k->entry.hash == k4->entry.hash );
- k4->entry.overflow_next = &k->entry;
- k3->entry.overflow_next = &k4->entry;
- bin.overflow_list = &k3->entry;
- lock_quick_unlock(&bin.lock);
-
- /* find, hash not OK. */
- unit_assert( bin_find_entry(table, &bin, myhash(13), k) == NULL );
-
- /* find, hash OK, but cmp not */
- unit_assert( k->entry.hash == k2->entry.hash );
- unit_assert( bin_find_entry(table, &bin, h, k2) == NULL );
-
- /* find, hash OK, and cmp too */
- unit_assert( bin_find_entry(table, &bin, h, k) == &k->entry );
-
- /* remove middle element */
- unit_assert( bin_find_entry(table, &bin, k4->entry.hash, k4)
- == &k4->entry );
- lock_quick_lock(&bin.lock);
- bin_overflow_remove(&bin, &k4->entry);
- lock_quick_unlock(&bin.lock);
- unit_assert( bin_find_entry(table, &bin, k4->entry.hash, k4) == NULL);
-
- /* remove last element */
- lock_quick_lock(&bin.lock);
- bin_overflow_remove(&bin, &k->entry);
- lock_quick_unlock(&bin.lock);
- unit_assert( bin_find_entry(table, &bin, h, k) == NULL );
-
- lock_quick_destroy(&bin.lock);
- delkey(k);
- delkey(k2);
- delkey(k3);
- delkey(k4);
- deldata(d);
-}
-
-/** test lru_front lru_remove */
-static void test_lru(struct lruhash* table)
-{
- testkey_type* k = newkey(12);
- testkey_type* k2 = newkey(14);
- lock_quick_lock(&table->lock);
-
- unit_assert( table->lru_start == NULL && table->lru_end == NULL);
- lru_remove(table, &k->entry);
- unit_assert( table->lru_start == NULL && table->lru_end == NULL);
-
- /* add one */
- lru_front(table, &k->entry);
- unit_assert( table->lru_start == &k->entry &&
- table->lru_end == &k->entry);
- /* remove it */
- lru_remove(table, &k->entry);
- unit_assert( table->lru_start == NULL && table->lru_end == NULL);
-
- /* add two */
- lru_front(table, &k->entry);
- unit_assert( table->lru_start == &k->entry &&
- table->lru_end == &k->entry);
- lru_front(table, &k2->entry);
- unit_assert( table->lru_start == &k2->entry &&
- table->lru_end == &k->entry);
- /* remove first in list */
- lru_remove(table, &k2->entry);
- unit_assert( table->lru_start == &k->entry &&
- table->lru_end == &k->entry);
- lru_front(table, &k2->entry);
- unit_assert( table->lru_start == &k2->entry &&
- table->lru_end == &k->entry);
- /* remove last in list */
- lru_remove(table, &k->entry);
- unit_assert( table->lru_start == &k2->entry &&
- table->lru_end == &k2->entry);
-
- /* empty the list */
- lru_remove(table, &k2->entry);
- unit_assert( table->lru_start == NULL && table->lru_end == NULL);
- lock_quick_unlock(&table->lock);
- delkey(k);
- delkey(k2);
-}
-
-/** test hashtable using short sequence */
-static void
-test_short_table(struct lruhash* table)
-{
- testkey_type* k = newkey(12);
- testkey_type* k2 = newkey(14);
- testdata_type* d = newdata(128);
- testdata_type* d2 = newdata(129);
-
- 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);
-
- unit_assert( lruhash_lookup(table, myhash(12), k, 0) == &k->entry);
- lock_rw_unlock( &k->entry.lock );
- unit_assert( lruhash_lookup(table, myhash(14), k2, 0) == &k2->entry);
- lock_rw_unlock( &k2->entry.lock );
- lruhash_remove(table, myhash(12), k);
- lruhash_remove(table, myhash(14), k2);
-}
-
-/** number of hash test max */
-#define HASHTESTMAX 25
-
-/** test adding a random element */
-static void
-testadd(struct lruhash* table, testdata_type* ref[])
-{
- int numtoadd = random() % HASHTESTMAX;
- testdata_type* data = newdata(numtoadd);
- testkey_type* key = newkey(numtoadd);
- key->entry.data = data;
- lruhash_insert(table, myhash(numtoadd), &key->entry, data, NULL);
- ref[numtoadd] = data;
-}
-
-/** test adding a random element */
-static void
-testremove(struct lruhash* table, testdata_type* ref[])
-{
- int num = random() % HASHTESTMAX;
- testkey_type* key = newkey(num);
- lruhash_remove(table, myhash(num), key);
- ref[num] = NULL;
- delkey(key);
-}
-
-/** test adding a random element */
-static void
-testlookup(struct lruhash* table, testdata_type* ref[])
-{
- int num = random() % HASHTESTMAX;
- testkey_type* key = newkey(num);
- struct lruhash_entry* en = lruhash_lookup(table, myhash(num), key, 0);
- testdata_type* data = en? (testdata_type*)en->data : NULL;
- if(en) {
- unit_assert(en->key);
- unit_assert(en->data);
- }
- if(0) log_info("lookup %d got %d, expect %d", num, en? data->data :-1,
- ref[num]? ref[num]->data : -1);
- unit_assert( data == ref[num] );
- if(en) { lock_rw_unlock(&en->lock); }
- delkey(key);
-}
-
-/** check integrity of hash table */
-static void
-check_table(struct lruhash* table)
-{
- struct lruhash_entry* p;
- size_t c = 0;
- lock_quick_lock(&table->lock);
- unit_assert( table->num <= table->size);
- unit_assert( table->size_mask == (int)table->size-1 );
- unit_assert( (table->lru_start && table->lru_end) ||
- (!table->lru_start && !table->lru_end) );
- unit_assert( table->space_used <= table->space_max );
- /* check lru list integrity */
- if(table->lru_start)
- unit_assert(table->lru_start->lru_prev == NULL);
- if(table->lru_end)
- unit_assert(table->lru_end->lru_next == NULL);
- p = table->lru_start;
- while(p) {
- if(p->lru_prev) {
- unit_assert(p->lru_prev->lru_next == p);
- }
- if(p->lru_next) {
- unit_assert(p->lru_next->lru_prev == p);
- }
- c++;
- p = p->lru_next;
- }
- unit_assert(c == table->num);
-
- /* this assertion is specific to the unit test */
- unit_assert( table->space_used ==
- table->num * test_slabhash_sizefunc(NULL, NULL) );
- lock_quick_unlock(&table->lock);
-}
-
-/** test adding a random element (unlimited range) */
-static void
-testadd_unlim(struct lruhash* table, testdata_type** ref)
-{
- int numtoadd = random() % (HASHTESTMAX * 10);
- testdata_type* data = newdata(numtoadd);
- testkey_type* key = newkey(numtoadd);
- key->entry.data = data;
- lruhash_insert(table, myhash(numtoadd), &key->entry, data, NULL);
- if(ref)
- ref[numtoadd] = data;
-}
-
-/** test adding a random element (unlimited range) */
-static void
-testremove_unlim(struct lruhash* table, testdata_type** ref)
-{
- int num = random() % (HASHTESTMAX*10);
- testkey_type* key = newkey(num);
- lruhash_remove(table, myhash(num), key);
- if(ref)
- ref[num] = NULL;
- delkey(key);
-}
-
-/** test adding a random element (unlimited range) */
-static void
-testlookup_unlim(struct lruhash* table, testdata_type** ref)
-{
- int num = random() % (HASHTESTMAX*10);
- testkey_type* key = newkey(num);
- struct lruhash_entry* en = lruhash_lookup(table, myhash(num), key, 0);
- testdata_type* data = en? (testdata_type*)en->data : NULL;
- if(en) {
- unit_assert(en->key);
- unit_assert(en->data);
- }
- if(0 && ref) log_info("lookup unlim %d got %d, expect %d", num, en ?
- data->data :-1, ref[num] ? ref[num]->data : -1);
- if(data && ref) {
- /* its okay for !data, it fell off the lru */
- unit_assert( data == ref[num] );
- }
- if(en) { lock_rw_unlock(&en->lock); }
- delkey(key);
-}
-
-/** test with long sequence of adds, removes and updates, and lookups */
-static void
-test_long_table(struct lruhash* table)
-{
- /* assuming it all fits in the hashtable, this check will work */
- testdata_type* ref[HASHTESTMAX * 100];
- size_t i;
- memset(ref, 0, sizeof(ref));
- /* test assumption */
- if(0) log_info(" size %d x %d < %d", (int)test_slabhash_sizefunc(NULL, NULL),
- (int)HASHTESTMAX, (int)table->space_max);
- unit_assert( test_slabhash_sizefunc(NULL, NULL)*HASHTESTMAX < table->space_max);
- if(0) lruhash_status(table, "unit test", 1);
- srandom(48);
- for(i=0; i<1000; i++) {
- /* what to do? */
- if(i == 500) {
- lruhash_clear(table);
- memset(ref, 0, sizeof(ref));
- continue;
- }
- switch(random() % 4) {
- case 0:
- case 3:
- testadd(table, ref);
- break;
- case 1:
- testremove(table, ref);
- break;
- case 2:
- testlookup(table, ref);
- break;
- default:
- unit_assert(0);
- }
- if(0) lruhash_status(table, "unit test", 1);
- check_table(table);
- unit_assert( table->num <= HASHTESTMAX );
- }
-
- /* test more, but 'ref' assumption does not hold anymore */
- for(i=0; i<1000; i++) {
- /* what to do? */
- switch(random() % 4) {
- case 0:
- case 3:
- testadd_unlim(table, ref);
- break;
- case 1:
- testremove_unlim(table, ref);
- break;
- case 2:
- testlookup_unlim(table, ref);
- break;
- default:
- unit_assert(0);
- }
- if(0) lruhash_status(table, "unlim", 1);
- check_table(table);
- }
-}
-
-/** structure to threaded test the lru hash table */
-struct test_thr {
- /** thread num, first entry. */
- int num;
- /** id */
- ub_thread_type id;
- /** hash table */
- struct lruhash* table;
-};
-
-/** main routine for threaded hash table test */
-static void*
-test_thr_main(void* arg)
-{
- struct test_thr* t = (struct test_thr*)arg;
- int i;
- log_thread_set(&t->num);
- for(i=0; i<1000; i++) {
- switch(random() % 4) {
- case 0:
- case 3:
- testadd_unlim(t->table, NULL);
- break;
- case 1:
- testremove_unlim(t->table, NULL);
- break;
- case 2:
- testlookup_unlim(t->table, NULL);
- break;
- default:
- unit_assert(0);
- }
- if(0) lruhash_status(t->table, "hashtest", 1);
- if(i % 100 == 0) /* because of locking, not all the time */
- check_table(t->table);
- }
- check_table(t->table);
- return NULL;
-}
-
-/** test hash table access by multiple threads */
-static void
-test_threaded_table(struct lruhash* table)
-{
- int numth = 10;
- struct test_thr t[100];
- int i;
-
- for(i=1; i<numth; i++) {
- t[i].num = i;
- t[i].table = table;
- ub_thread_create(&t[i].id, test_thr_main, &t[i]);
- }
-
- for(i=1; i<numth; i++) {
- ub_thread_join(t[i].id);
- }
- if(0) lruhash_status(table, "hashtest", 1);
-}
-
-void lruhash_test(void)
-{
- /* start very very small array, so it can do lots of table_grow() */
- /* also small in size so that reclaim has to be done quickly. */
- struct lruhash* table ;
- unit_show_feature("lruhash");
- table = lruhash_create(2, 8192,
- test_slabhash_sizefunc, test_slabhash_compfunc,
- test_slabhash_delkey, test_slabhash_deldata, NULL);
- test_bin_find_entry(table);
- test_lru(table);
- test_short_table(table);
- test_long_table(table);
- lruhash_delete(table);
- table = lruhash_create(2, 8192,
- test_slabhash_sizefunc, test_slabhash_compfunc,
- test_slabhash_delkey, test_slabhash_deldata, NULL);
- test_threaded_table(table);
- lruhash_delete(table);
-}
diff --git a/external/unbound/testcode/unitmain.c b/external/unbound/testcode/unitmain.c
deleted file mode 100644
index fd56e64d3..000000000
--- a/external/unbound/testcode/unitmain.c
+++ /dev/null
@@ -1,919 +0,0 @@
-/*
- * testcode/unitmain.c - unit test main program for unbound.
- *
- * 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 COPYRIGHT
- * HOLDER 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
- * Unit test main program. Calls all the other unit tests.
- * Exits with code 1 on a failure. 0 if all unit tests are successful.
- */
-
-#include "config.h"
-#ifdef HAVE_OPENSSL_ERR_H
-#include <openssl/err.h>
-#endif
-
-#ifdef HAVE_OPENSSL_RAND_H
-#include <openssl/rand.h>
-#endif
-
-#ifdef HAVE_OPENSSL_CONF_H
-#include <openssl/conf.h>
-#endif
-
-#ifdef HAVE_OPENSSL_ENGINE_H
-#include <openssl/engine.h>
-#endif
-
-#ifdef HAVE_NSS
-/* nss3 */
-#include "nss.h"
-#endif
-
-#include "sldns/rrdef.h"
-#include "sldns/keyraw.h"
-#include "util/log.h"
-#include "testcode/unitmain.h"
-
-/** number of tests done */
-int testcount = 0;
-
-#include "util/alloc.h"
-/** test alloc code */
-static void
-alloc_test(void) {
- alloc_special_type *t1, *t2;
- struct alloc_cache major, minor1, minor2;
- int i;
-
- unit_show_feature("alloc_special_obtain");
- alloc_init(&major, NULL, 0);
- alloc_init(&minor1, &major, 0);
- alloc_init(&minor2, &major, 1);
-
- t1 = alloc_special_obtain(&minor1);
- alloc_clear(&minor1);
-
- alloc_special_release(&minor2, t1);
- t2 = alloc_special_obtain(&minor2);
- unit_assert( t1 == t2 ); /* reused */
- alloc_special_release(&minor2, t1);
-
- for(i=0; i<100; i++) {
- t1 = alloc_special_obtain(&minor1);
- alloc_special_release(&minor2, t1);
- }
- if(0) {
- alloc_stats(&minor1);
- alloc_stats(&minor2);
- alloc_stats(&major);
- }
- /* reuse happened */
- unit_assert(minor1.num_quar + minor2.num_quar + major.num_quar == 11);
-
- alloc_clear(&minor1);
- alloc_clear(&minor2);
- unit_assert(major.num_quar == 11);
- alloc_clear(&major);
-}
-
-#include "util/net_help.h"
-/** test net code */
-static void
-net_test(void)
-{
- const char* t4[] = {"\000\000\000\000",
- "\200\000\000\000",
- "\300\000\000\000",
- "\340\000\000\000",
- "\360\000\000\000",
- "\370\000\000\000",
- "\374\000\000\000",
- "\376\000\000\000",
- "\377\000\000\000",
- "\377\200\000\000",
- "\377\300\000\000",
- "\377\340\000\000",
- "\377\360\000\000",
- "\377\370\000\000",
- "\377\374\000\000",
- "\377\376\000\000",
- "\377\377\000\000",
- "\377\377\200\000",
- "\377\377\300\000",
- "\377\377\340\000",
- "\377\377\360\000",
- "\377\377\370\000",
- "\377\377\374\000",
- "\377\377\376\000",
- "\377\377\377\000",
- "\377\377\377\200",
- "\377\377\377\300",
- "\377\377\377\340",
- "\377\377\377\360",
- "\377\377\377\370",
- "\377\377\377\374",
- "\377\377\377\376",
- "\377\377\377\377",
- "\377\377\377\377",
- "\377\377\377\377",
- };
- unit_show_func("util/net_help.c", "str_is_ip6");
- unit_assert( str_is_ip6("::") );
- unit_assert( str_is_ip6("::1") );
- unit_assert( str_is_ip6("2001:7b8:206:1:240:f4ff:fe37:8810") );
- unit_assert( str_is_ip6("fe80::240:f4ff:fe37:8810") );
- unit_assert( !str_is_ip6("0.0.0.0") );
- unit_assert( !str_is_ip6("213.154.224.12") );
- unit_assert( !str_is_ip6("213.154.224.255") );
- unit_assert( !str_is_ip6("255.255.255.0") );
- unit_show_func("util/net_help.c", "is_pow2");
- unit_assert( is_pow2(0) );
- unit_assert( is_pow2(1) );
- unit_assert( is_pow2(2) );
- unit_assert( is_pow2(4) );
- unit_assert( is_pow2(8) );
- unit_assert( is_pow2(16) );
- unit_assert( is_pow2(1024) );
- unit_assert( is_pow2(1024*1024) );
- unit_assert( is_pow2(1024*1024*1024) );
- unit_assert( !is_pow2(3) );
- unit_assert( !is_pow2(5) );
- unit_assert( !is_pow2(6) );
- unit_assert( !is_pow2(7) );
- unit_assert( !is_pow2(9) );
- unit_assert( !is_pow2(10) );
- unit_assert( !is_pow2(11) );
- unit_assert( !is_pow2(17) );
- unit_assert( !is_pow2(23) );
- unit_assert( !is_pow2(257) );
- unit_assert( !is_pow2(259) );
-
- /* test addr_mask */
- unit_show_func("util/net_help.c", "addr_mask");
- if(1) {
- struct sockaddr_in a4;
- struct sockaddr_in6 a6;
- socklen_t l4 = (socklen_t)sizeof(a4);
- socklen_t l6 = (socklen_t)sizeof(a6);
- int i;
- a4.sin_family = AF_INET;
- a6.sin6_family = AF_INET6;
- for(i=0; i<35; i++) {
- /* address 255.255.255.255 */
- memcpy(&a4.sin_addr, "\377\377\377\377", 4);
- addr_mask((struct sockaddr_storage*)&a4, l4, i);
- unit_assert(memcmp(&a4.sin_addr, t4[i], 4) == 0);
- }
- memcpy(&a6.sin6_addr, "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377", 16);
- addr_mask((struct sockaddr_storage*)&a6, l6, 128);
- unit_assert(memcmp(&a6.sin6_addr, "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377", 16) == 0);
- addr_mask((struct sockaddr_storage*)&a6, l6, 122);
- unit_assert(memcmp(&a6.sin6_addr, "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\300", 16) == 0);
- addr_mask((struct sockaddr_storage*)&a6, l6, 120);
- unit_assert(memcmp(&a6.sin6_addr, "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\000", 16) == 0);
- addr_mask((struct sockaddr_storage*)&a6, l6, 64);
- unit_assert(memcmp(&a6.sin6_addr, "\377\377\377\377\377\377\377\377\000\000\000\000\000\000\000\000", 16) == 0);
- addr_mask((struct sockaddr_storage*)&a6, l6, 0);
- unit_assert(memcmp(&a6.sin6_addr, "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000", 16) == 0);
- }
-
- /* test addr_in_common */
- unit_show_func("util/net_help.c", "addr_in_common");
- if(1) {
- struct sockaddr_in a4, b4;
- struct sockaddr_in6 a6, b6;
- socklen_t l4 = (socklen_t)sizeof(a4);
- socklen_t l6 = (socklen_t)sizeof(a6);
- int i;
- a4.sin_family = AF_INET;
- b4.sin_family = AF_INET;
- a6.sin6_family = AF_INET6;
- b6.sin6_family = AF_INET6;
- memcpy(&a4.sin_addr, "abcd", 4);
- memcpy(&b4.sin_addr, "abcd", 4);
- unit_assert(addr_in_common((struct sockaddr_storage*)&a4, 32,
- (struct sockaddr_storage*)&b4, 32, l4) == 32);
- unit_assert(addr_in_common((struct sockaddr_storage*)&a4, 34,
- (struct sockaddr_storage*)&b4, 32, l4) == 32);
- for(i=0; i<=32; i++) {
- unit_assert(addr_in_common(
- (struct sockaddr_storage*)&a4, 32,
- (struct sockaddr_storage*)&b4, i, l4) == i);
- unit_assert(addr_in_common(
- (struct sockaddr_storage*)&a4, i,
- (struct sockaddr_storage*)&b4, 32, l4) == i);
- unit_assert(addr_in_common(
- (struct sockaddr_storage*)&a4, i,
- (struct sockaddr_storage*)&b4, i, l4) == i);
- }
- for(i=0; i<=32; i++) {
- memcpy(&a4.sin_addr, "\377\377\377\377", 4);
- memcpy(&b4.sin_addr, t4[i], 4);
- unit_assert(addr_in_common(
- (struct sockaddr_storage*)&a4, 32,
- (struct sockaddr_storage*)&b4, 32, l4) == i);
- unit_assert(addr_in_common(
- (struct sockaddr_storage*)&b4, 32,
- (struct sockaddr_storage*)&a4, 32, l4) == i);
- }
- memcpy(&a6.sin6_addr, "abcdefghabcdefgh", 16);
- memcpy(&b6.sin6_addr, "abcdefghabcdefgh", 16);
- unit_assert(addr_in_common((struct sockaddr_storage*)&a6, 128,
- (struct sockaddr_storage*)&b6, 128, l6) == 128);
- unit_assert(addr_in_common((struct sockaddr_storage*)&a6, 129,
- (struct sockaddr_storage*)&b6, 128, l6) == 128);
- for(i=0; i<=128; i++) {
- unit_assert(addr_in_common(
- (struct sockaddr_storage*)&a6, 128,
- (struct sockaddr_storage*)&b6, i, l6) == i);
- unit_assert(addr_in_common(
- (struct sockaddr_storage*)&a6, i,
- (struct sockaddr_storage*)&b6, 128, l6) == i);
- unit_assert(addr_in_common(
- (struct sockaddr_storage*)&a6, i,
- (struct sockaddr_storage*)&b6, i, l6) == i);
- }
- }
- /* test sockaddr_cmp_addr */
- unit_show_func("util/net_help.c", "sockaddr_cmp_addr");
- if(1) {
- struct sockaddr_storage a, b;
- socklen_t alen = (socklen_t)sizeof(a);
- socklen_t blen = (socklen_t)sizeof(b);
- unit_assert(ipstrtoaddr("127.0.0.0", 53, &a, &alen));
- unit_assert(ipstrtoaddr("127.255.255.255", 53, &b, &blen));
- unit_assert(sockaddr_cmp_addr(&a, alen, &b, blen) < 0);
- unit_assert(sockaddr_cmp_addr(&b, blen, &a, alen) > 0);
- unit_assert(sockaddr_cmp_addr(&a, alen, &a, alen) == 0);
- unit_assert(sockaddr_cmp_addr(&b, blen, &b, blen) == 0);
- unit_assert(ipstrtoaddr("192.168.121.5", 53, &a, &alen));
- unit_assert(sockaddr_cmp_addr(&a, alen, &b, blen) > 0);
- unit_assert(sockaddr_cmp_addr(&b, blen, &a, alen) < 0);
- unit_assert(sockaddr_cmp_addr(&a, alen, &a, alen) == 0);
- unit_assert(ipstrtoaddr("2001:3578:ffeb::99", 53, &b, &blen));
- unit_assert(sockaddr_cmp_addr(&b, blen, &b, blen) == 0);
- unit_assert(sockaddr_cmp_addr(&a, alen, &b, blen) < 0);
- unit_assert(sockaddr_cmp_addr(&b, blen, &a, alen) > 0);
- }
- /* test addr_is_ip4mapped */
- unit_show_func("util/net_help.c", "addr_is_ip4mapped");
- if(1) {
- struct sockaddr_storage a;
- socklen_t l = (socklen_t)sizeof(a);
- unit_assert(ipstrtoaddr("12.13.14.15", 53, &a, &l));
- unit_assert(!addr_is_ip4mapped(&a, l));
- unit_assert(ipstrtoaddr("fe80::217:31ff:fe91:df", 53, &a, &l));
- unit_assert(!addr_is_ip4mapped(&a, l));
- unit_assert(ipstrtoaddr("ffff::217:31ff:fe91:df", 53, &a, &l));
- unit_assert(!addr_is_ip4mapped(&a, l));
- unit_assert(ipstrtoaddr("::ffff:31ff:fe91:df", 53, &a, &l));
- unit_assert(!addr_is_ip4mapped(&a, l));
- unit_assert(ipstrtoaddr("::fffe:fe91:df", 53, &a, &l));
- unit_assert(!addr_is_ip4mapped(&a, l));
- unit_assert(ipstrtoaddr("::ffff:127.0.0.1", 53, &a, &l));
- unit_assert(addr_is_ip4mapped(&a, l));
- unit_assert(ipstrtoaddr("::ffff:127.0.0.2", 53, &a, &l));
- unit_assert(addr_is_ip4mapped(&a, l));
- unit_assert(ipstrtoaddr("::ffff:192.168.0.2", 53, &a, &l));
- unit_assert(addr_is_ip4mapped(&a, l));
- unit_assert(ipstrtoaddr("2::ffff:192.168.0.2", 53, &a, &l));
- unit_assert(!addr_is_ip4mapped(&a, l));
- }
- /* test addr_is_any */
- unit_show_func("util/net_help.c", "addr_is_any");
- if(1) {
- struct sockaddr_storage a;
- socklen_t l = (socklen_t)sizeof(a);
- unit_assert(ipstrtoaddr("0.0.0.0", 53, &a, &l));
- unit_assert(addr_is_any(&a, l));
- unit_assert(ipstrtoaddr("0.0.0.0", 10053, &a, &l));
- unit_assert(addr_is_any(&a, l));
- unit_assert(ipstrtoaddr("0.0.0.0", 0, &a, &l));
- unit_assert(addr_is_any(&a, l));
- unit_assert(ipstrtoaddr("::0", 0, &a, &l));
- unit_assert(addr_is_any(&a, l));
- unit_assert(ipstrtoaddr("::0", 53, &a, &l));
- unit_assert(addr_is_any(&a, l));
- unit_assert(ipstrtoaddr("::1", 53, &a, &l));
- unit_assert(!addr_is_any(&a, l));
- unit_assert(ipstrtoaddr("2001:1667::1", 0, &a, &l));
- unit_assert(!addr_is_any(&a, l));
- unit_assert(ipstrtoaddr("2001::0", 0, &a, &l));
- unit_assert(!addr_is_any(&a, l));
- unit_assert(ipstrtoaddr("10.0.0.0", 0, &a, &l));
- unit_assert(!addr_is_any(&a, l));
- unit_assert(ipstrtoaddr("0.0.0.10", 0, &a, &l));
- unit_assert(!addr_is_any(&a, l));
- unit_assert(ipstrtoaddr("192.0.2.1", 0, &a, &l));
- unit_assert(!addr_is_any(&a, l));
- }
-}
-
-#include "util/config_file.h"
-/** test config_file: cfg_parse_memsize */
-static void
-config_memsize_test(void)
-{
- size_t v = 0;
- unit_show_func("util/config_file.c", "cfg_parse_memsize");
- if(0) {
- /* these emit errors */
- unit_assert( cfg_parse_memsize("", &v) == 0);
- unit_assert( cfg_parse_memsize("bla", &v) == 0);
- unit_assert( cfg_parse_memsize("nop", &v) == 0);
- unit_assert( cfg_parse_memsize("n0b", &v) == 0);
- unit_assert( cfg_parse_memsize("gb", &v) == 0);
- unit_assert( cfg_parse_memsize("b", &v) == 0);
- unit_assert( cfg_parse_memsize("kb", &v) == 0);
- unit_assert( cfg_parse_memsize("kk kb", &v) == 0);
- }
- unit_assert( cfg_parse_memsize("0", &v) && v==0);
- unit_assert( cfg_parse_memsize("1", &v) && v==1);
- unit_assert( cfg_parse_memsize("10", &v) && v==10);
- unit_assert( cfg_parse_memsize("10b", &v) && v==10);
- unit_assert( cfg_parse_memsize("5b", &v) && v==5);
- unit_assert( cfg_parse_memsize("1024", &v) && v==1024);
- unit_assert( cfg_parse_memsize("1k", &v) && v==1024);
- unit_assert( cfg_parse_memsize("1K", &v) && v==1024);
- unit_assert( cfg_parse_memsize("1Kb", &v) && v==1024);
- unit_assert( cfg_parse_memsize("1kb", &v) && v==1024);
- unit_assert( cfg_parse_memsize("1 kb", &v) && v==1024);
- unit_assert( cfg_parse_memsize("10 kb", &v) && v==10240);
- unit_assert( cfg_parse_memsize("2k", &v) && v==2048);
- unit_assert( cfg_parse_memsize("2m", &v) && v==2048*1024);
- unit_assert( cfg_parse_memsize("3M", &v) && v==3072*1024);
- unit_assert( cfg_parse_memsize("40m", &v) && v==40960*1024);
- unit_assert( cfg_parse_memsize("1G", &v) && v==1024*1024*1024);
- unit_assert( cfg_parse_memsize("1 Gb", &v) && v==1024*1024*1024);
- unit_assert( cfg_parse_memsize("0 Gb", &v) && v==0*1024*1024);
-}
-
-/** test config_file: test tag code */
-static void
-config_tag_test(void)
-{
- unit_show_func("util/config_file.c", "taglist_intersect");
- unit_assert( taglist_intersect(
- (uint8_t*)"\000\000\000", 3, (uint8_t*)"\001\000\001", 3
- ) == 0);
- unit_assert( taglist_intersect(
- (uint8_t*)"\000\000\001", 3, (uint8_t*)"\001\000\001", 3
- ) == 1);
- unit_assert( taglist_intersect(
- (uint8_t*)"\001\000\000", 3, (uint8_t*)"\001\000\001", 3
- ) == 1);
- unit_assert( taglist_intersect(
- (uint8_t*)"\001", 1, (uint8_t*)"\001\000\001", 3
- ) == 1);
- unit_assert( taglist_intersect(
- (uint8_t*)"\001\000\001", 3, (uint8_t*)"\001", 1
- ) == 1);
-}
-
-#include "util/rtt.h"
-/** test RTT code */
-static void
-rtt_test(void)
-{
- int init = 376;
- int i;
- struct rtt_info r;
- unit_show_func("util/rtt.c", "rtt_timeout");
- rtt_init(&r);
- /* initial value sensible */
- unit_assert( rtt_timeout(&r) == init );
- rtt_lost(&r, init);
- unit_assert( rtt_timeout(&r) == init*2 );
- rtt_lost(&r, init*2);
- unit_assert( rtt_timeout(&r) == init*4 );
- rtt_update(&r, 4000);
- unit_assert( rtt_timeout(&r) >= 2000 );
- rtt_lost(&r, rtt_timeout(&r) );
- for(i=0; i<100; i++) {
- rtt_lost(&r, rtt_timeout(&r) );
- unit_assert( rtt_timeout(&r) > RTT_MIN_TIMEOUT-1);
- unit_assert( rtt_timeout(&r) < RTT_MAX_TIMEOUT+1);
- }
-}
-
-#include "services/cache/infra.h"
-#include "util/config_file.h"
-
-/* lookup and get key and data structs easily */
-static struct infra_data* infra_lookup_host(struct infra_cache* infra,
- struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
- size_t zonelen, int wr, time_t now, struct infra_key** k)
-{
- struct infra_data* d;
- struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
- zone, zonelen, wr);
- if(!e) return NULL;
- d = (struct infra_data*)e->data;
- if(d->ttl < now) {
- lock_rw_unlock(&e->lock);
- return NULL;
- }
- *k = (struct infra_key*)e->key;
- return d;
-}
-
-/** test host cache */
-static void
-infra_test(void)
-{
- struct sockaddr_storage one;
- socklen_t onelen;
- 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;
- uint8_t edns_lame;
- int vs, to;
- struct infra_key* k;
- struct infra_data* d;
- int init = 376;
-
- unit_show_feature("infra cache");
- unit_assert(ipstrtoaddr("127.0.0.1", 53, &one, &onelen));
-
- slab = infra_create(cfg);
- unit_assert( infra_host(slab, &one, onelen, zone, zonelen, now,
- &vs, &edns_lame, &to) );
- unit_assert( vs == 0 && to == init && edns_lame == 0 );
-
- unit_assert( infra_rtt_update(slab, &one, onelen, zone, zonelen, LDNS_RR_TYPE_A, -1, init, now) );
- unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
- now, &vs, &edns_lame, &to) );
- unit_assert( vs == 0 && to == init*2 && edns_lame == 0 );
-
- unit_assert( infra_edns_update(slab, &one, onelen, zone, zonelen, -1, now) );
- unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
- now, &vs, &edns_lame, &to) );
- unit_assert( vs == -1 && to == init*2 && edns_lame == 1);
-
- now += cfg->host_ttl + 10;
- unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
- now, &vs, &edns_lame, &to) );
- unit_assert( vs == 0 && to == init && edns_lame == 0 );
-
- unit_assert( infra_set_lame(slab, &one, onelen,
- zone, zonelen, now, 0, 0, LDNS_RR_TYPE_A) );
- unit_assert( (d=infra_lookup_host(slab, &one, onelen, zone, zonelen, 0, now, &k)) );
- unit_assert( d->ttl == now+cfg->host_ttl );
- unit_assert( d->edns_version == 0 );
- unit_assert(!d->isdnsseclame && !d->rec_lame && d->lame_type_A &&
- !d->lame_other);
- lock_rw_unlock(&k->entry.lock);
-
- /* test merge of data */
- unit_assert( infra_set_lame(slab, &one, onelen,
- zone, zonelen, now, 0, 0, LDNS_RR_TYPE_AAAA) );
- unit_assert( (d=infra_lookup_host(slab, &one, onelen, zone, zonelen, 0, now, &k)) );
- unit_assert(!d->isdnsseclame && !d->rec_lame && d->lame_type_A &&
- d->lame_other);
- lock_rw_unlock(&k->entry.lock);
-
- /* test that noEDNS cannot overwrite known-yesEDNS */
- now += cfg->host_ttl + 10;
- unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
- now, &vs, &edns_lame, &to) );
- unit_assert( vs == 0 && to == init && edns_lame == 0 );
-
- unit_assert( infra_edns_update(slab, &one, onelen, zone, zonelen, 0, now) );
- unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
- now, &vs, &edns_lame, &to) );
- unit_assert( vs == 0 && to == init && edns_lame == 1 );
-
- unit_assert( infra_edns_update(slab, &one, onelen, zone, zonelen, -1, now) );
- unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
- now, &vs, &edns_lame, &to) );
- unit_assert( vs == 0 && to == init && edns_lame == 1 );
-
- infra_delete(slab);
- config_delete(cfg);
-}
-
-#include "util/random.h"
-/** test randomness */
-static void
-rnd_test(void)
-{
- struct ub_randstate* r;
- int num = 1000, i;
- long int a[1000];
- unsigned int seed = (unsigned)time(NULL);
- unit_show_feature("ub_random");
- printf("ub_random seed is %u\n", seed);
- unit_assert( (r = ub_initstate(seed, NULL)) );
- for(i=0; i<num; i++) {
- a[i] = ub_random(r);
- unit_assert(a[i] >= 0);
- unit_assert((size_t)a[i] <= (size_t)0x7fffffff);
- if(i > 5)
- unit_assert(a[i] != a[i-1] || a[i] != a[i-2] ||
- a[i] != a[i-3] || a[i] != a[i-4] ||
- a[i] != a[i-5] || a[i] != a[i-6]);
- }
- a[0] = ub_random_max(r, 1);
- unit_assert(a[0] >= 0 && a[0] < 1);
- a[0] = ub_random_max(r, 10000);
- unit_assert(a[0] >= 0 && a[0] < 10000);
- for(i=0; i<num; i++) {
- a[i] = ub_random_max(r, 10);
- unit_assert(a[i] >= 0 && a[i] < 10);
- }
- ub_randfree(r);
-}
-
-#include "respip/respip.h"
-#include "services/localzone.h"
-#include "util/data/packed_rrset.h"
-typedef struct addr_action {char* ip; char* sact; enum respip_action act;}
- addr_action_t;
-
-/** Utility function that verifies that the respip set has actions as expected */
-static void
-verify_respip_set_actions(struct respip_set* set, addr_action_t actions[],
- int actions_len)
-{
- int i = 0;
- struct rbtree_type* tree = respip_set_get_tree(set);
- for (i=0; i<actions_len; i++) {
- struct sockaddr_storage addr;
- int net;
- socklen_t addrlen;
- struct resp_addr* node;
- netblockstrtoaddr(actions[i].ip, UNBOUND_DNS_PORT, &addr,
- &addrlen, &net);
- node = (struct resp_addr*)addr_tree_find(tree, &addr, addrlen, net);
-
- /** we have the node and the node has the correct action
- * and has no data */
- unit_assert(node);
- unit_assert(actions[i].act ==
- resp_addr_get_action(node));
- unit_assert(resp_addr_get_rrset(node) == NULL);
- }
- unit_assert(actions_len && i == actions_len);
- unit_assert(actions_len == (int)tree->count);
-}
-
-/** Global respip actions test; apply raw config data and verify that
- * all the nodes in the respip set, looked up by address, have expected
- * actions */
-static void
-respip_conf_actions_test(void)
-{
- addr_action_t config_response_ip[] = {
- {"192.0.1.0/24", "deny", respip_deny},
- {"192.0.2.0/24", "redirect", respip_redirect},
- {"192.0.3.0/26", "inform", respip_inform},
- {"192.0.4.0/27", "inform_deny", respip_inform_deny},
- {"2001:db8:1::/48", "always_transparent", respip_always_transparent},
- {"2001:db8:2::/49", "always_refuse", respip_always_refuse},
- {"2001:db8:3::/50", "always_nxdomain", respip_always_nxdomain},
- };
- int i;
- struct respip_set* set = respip_set_create();
- struct config_file cfg;
- int clen = (int)(sizeof(config_response_ip) / sizeof(addr_action_t));
-
- unit_assert(set);
- unit_show_feature("global respip config actions apply");
- memset(&cfg, 0, sizeof(cfg));
- for(i=0; i<clen; i++) {
- char* ip = strdup(config_response_ip[i].ip);
- char* sact = strdup(config_response_ip[i].sact);
- unit_assert(ip && sact);
- if(!cfg_str2list_insert(&cfg.respip_actions, ip, sact))
- unit_assert(0);
- }
- unit_assert(respip_global_apply_cfg(set, &cfg));
- verify_respip_set_actions(set, config_response_ip, clen);
-}
-
-/** Per-view respip actions test; apply raw configuration with two views
- * and verify that actions are as expected in respip sets of both views */
-static void
-respip_view_conf_actions_test(void)
-{
- addr_action_t config_response_ip_view1[] = {
- {"192.0.1.0/24", "deny", respip_deny},
- {"192.0.2.0/24", "redirect", respip_redirect},
- {"192.0.3.0/26", "inform", respip_inform},
- {"192.0.4.0/27", "inform_deny", respip_inform_deny},
- };
- addr_action_t config_response_ip_view2[] = {
- {"2001:db8:1::/48", "always_transparent", respip_always_transparent},
- {"2001:db8:2::/49", "always_refuse", respip_always_refuse},
- {"2001:db8:3::/50", "always_nxdomain", respip_always_nxdomain},
- };
- int i;
- struct config_file cfg;
- int clen1 = (int)(sizeof(config_response_ip_view1) / sizeof(addr_action_t));
- int clen2 = (int)(sizeof(config_response_ip_view2) / sizeof(addr_action_t));
- struct config_view* cv1;
- struct config_view* cv2;
- int have_respip_cfg = 0;
- struct views* views = NULL;
- struct view* v = NULL;
-
- unit_show_feature("per-view respip config actions apply");
- memset(&cfg, 0, sizeof(cfg));
- cv1 = (struct config_view*)calloc(1, sizeof(struct config_view));
- cv2 = (struct config_view*)calloc(1, sizeof(struct config_view));
- unit_assert(cv1 && cv2);
- cv1->name = strdup("view1");
- cv2->name = strdup("view2");
- unit_assert(cv1->name && cv2->name);
- cv1->next = cv2;
- cfg.views = cv1;
-
- for(i=0; i<clen1; i++) {
- char* ip = strdup(config_response_ip_view1[i].ip);
- char* sact = strdup(config_response_ip_view1[i].sact);
- unit_assert(ip && sact);
- if(!cfg_str2list_insert(&cv1->respip_actions, ip, sact))
- unit_assert(0);
- }
- for(i=0; i<clen2; i++) {
- char* ip = strdup(config_response_ip_view2[i].ip);
- char* sact = strdup(config_response_ip_view2[i].sact);
- unit_assert(ip && sact);
- if(!cfg_str2list_insert(&cv2->respip_actions, ip, sact))
- unit_assert(0);
- }
- views = views_create();
- unit_assert(views);
- unit_assert(views_apply_cfg(views, &cfg));
- unit_assert(respip_views_apply_cfg(views, &cfg, &have_respip_cfg));
-
- /* now verify the respip sets in each view */
- v = views_find_view(views, "view1", 0);
- unit_assert(v);
- verify_respip_set_actions(v->respip_set, config_response_ip_view1, clen1);
- lock_rw_unlock(&v->lock);
- v = views_find_view(views, "view2", 0);
- unit_assert(v);
- verify_respip_set_actions(v->respip_set, config_response_ip_view2, clen2);
- lock_rw_unlock(&v->lock);
-}
-
-typedef struct addr_data {char* ip; char* data;} addr_data_t;
-
-/** find the respip address node in the specified tree (by address lookup)
- * and verify type and address of the specified rdata (by index) in this
- * node's rrset */
-static void
-verify_rrset(struct respip_set* set, const char* ipstr,
- const char* rdatastr, size_t rdi, uint16_t type)
-{
- struct sockaddr_storage addr;
- int net;
- char buf[65536];
- socklen_t addrlen;
- struct rbtree_type* tree;
- struct resp_addr* node;
- const struct ub_packed_rrset_key* rrs;
-
- netblockstrtoaddr(ipstr, UNBOUND_DNS_PORT, &addr, &addrlen, &net);
- tree = respip_set_get_tree(set);
- node = (struct resp_addr*)addr_tree_find(tree, &addr, addrlen, net);
- unit_assert(node);
- unit_assert((rrs = resp_addr_get_rrset(node)));
- unit_assert(ntohs(rrs->rk.type) == type);
- packed_rr_to_string((struct ub_packed_rrset_key*)rrs,
- rdi, 0, buf, sizeof(buf));
- unit_assert(strstr(buf, rdatastr));
-}
-
-/** Dataset used to test redirect rrset initialization for both
- * global and per-view respip redirect configuration */
-static addr_data_t config_response_ip_data[] = {
- {"192.0.1.0/24", "A 1.2.3.4"},
- {"192.0.1.0/24", "A 11.12.13.14"},
- {"192.0.2.0/24", "CNAME www.example.com."},
- {"2001:db8:1::/48", "AAAA 2001:db8:1::2:1"},
-};
-
-/** Populate raw respip redirect config data, used for both global and
- * view-based respip redirect test case */
-static void
-cfg_insert_respip_data(struct config_str2list** respip_actions,
- struct config_str2list** respip_data)
-{
- int clen = (int)(sizeof(config_response_ip_data) / sizeof(addr_data_t));
- int i = 0;
-
- /* insert actions (duplicate netblocks don't matter) */
- for(i=0; i<clen; i++) {
- char* ip = strdup(config_response_ip_data[i].ip);
- char* sact = strdup("redirect");
- unit_assert(ip && sact);
- if(!cfg_str2list_insert(respip_actions, ip, sact))
- unit_assert(0);
- }
- /* insert data */
- for(i=0; i<clen; i++) {
- char* ip = strdup(config_response_ip_data[i].ip);
- char* data = strdup(config_response_ip_data[i].data);
- unit_assert(ip && data);
- if(!cfg_str2list_insert(respip_data, ip, data))
- unit_assert(0);
- }
-}
-
-/** Test global respip redirect w/ data directives */
-static void
-respip_conf_data_test(void)
-{
- struct respip_set* set = respip_set_create();
- struct config_file cfg;
-
- unit_show_feature("global respip config data apply");
- memset(&cfg, 0, sizeof(cfg));
-
- cfg_insert_respip_data(&cfg.respip_actions, &cfg.respip_data);
-
- /* apply configuration and verify rrsets */
- unit_assert(respip_global_apply_cfg(set, &cfg));
- verify_rrset(set, "192.0.1.0/24", "1.2.3.4", 0, LDNS_RR_TYPE_A);
- verify_rrset(set, "192.0.1.0/24", "11.12.13.14", 1, LDNS_RR_TYPE_A);
- verify_rrset(set, "192.0.2.0/24", "www.example.com", 0, LDNS_RR_TYPE_CNAME);
- verify_rrset(set, "2001:db8:1::/48", "2001:db8:1::2:1", 0, LDNS_RR_TYPE_AAAA);
-}
-
-/** Test per-view respip redirect w/ data directives */
-static void
-respip_view_conf_data_test(void)
-{
- struct config_file cfg;
- struct config_view* cv;
- int have_respip_cfg = 0;
- struct views* views = NULL;
- struct view* v = NULL;
-
- unit_show_feature("per-view respip config data apply");
- memset(&cfg, 0, sizeof(cfg));
- cv = (struct config_view*)calloc(1, sizeof(struct config_view));
- unit_assert(cv);
- cv->name = strdup("view1");
- unit_assert(cv->name);
- cfg.views = cv;
- cfg_insert_respip_data(&cv->respip_actions, &cv->respip_data);
- views = views_create();
- unit_assert(views);
- unit_assert(views_apply_cfg(views, &cfg));
-
- /* apply configuration and verify rrsets */
- unit_assert(respip_views_apply_cfg(views, &cfg, &have_respip_cfg));
- v = views_find_view(views, "view1", 0);
- unit_assert(v);
- verify_rrset(v->respip_set, "192.0.1.0/24", "1.2.3.4",
- 0, LDNS_RR_TYPE_A);
- verify_rrset(v->respip_set, "192.0.1.0/24", "11.12.13.14",
- 1, LDNS_RR_TYPE_A);
- verify_rrset(v->respip_set, "192.0.2.0/24", "www.example.com",
- 0, LDNS_RR_TYPE_CNAME);
- verify_rrset(v->respip_set, "2001:db8:1::/48", "2001:db8:1::2:1",
- 0, LDNS_RR_TYPE_AAAA);
-}
-
-/** respip unit tests */
-static void respip_test(void)
-{
- respip_view_conf_data_test();
- respip_conf_data_test();
- respip_view_conf_actions_test();
- respip_conf_actions_test();
-}
-
-void unit_show_func(const char* file, const char* func)
-{
- printf("test %s:%s\n", file, func);
-}
-
-void unit_show_feature(const char* feature)
-{
- printf("test %s functions\n", feature);
-}
-
-#ifdef USE_ECDSA_EVP_WORKAROUND
-void ecdsa_evp_workaround_init(void);
-#endif
-/**
- * Main unit test program. Setup, teardown and report errors.
- * @param argc: arg count.
- * @param argv: array of commandline arguments.
- * @return program failure if test fails.
- */
-int
-main(int argc, char* argv[])
-{
- log_init(NULL, 0, NULL);
- if(argc != 1) {
- printf("usage: %s\n", argv[0]);
- printf("\tperforms unit tests.\n");
- return 1;
- }
- printf("Start of %s unit test.\n", PACKAGE_STRING);
-#ifdef HAVE_SSL
-# ifdef HAVE_ERR_LOAD_CRYPTO_STRINGS
- ERR_load_crypto_strings();
-# endif
-# ifdef USE_GOST
- (void)sldns_key_EVP_load_gost_id();
-# endif
-# ifdef USE_ECDSA_EVP_WORKAROUND
- ecdsa_evp_workaround_init();
-# endif
-#elif defined(HAVE_NSS)
- if(NSS_NoDB_Init(".") != SECSuccess)
- fatal_exit("could not init NSS");
-#endif /* HAVE_SSL or HAVE_NSS*/
- checklock_start();
- neg_test();
- rnd_test();
- respip_test();
- verify_test();
- net_test();
- config_memsize_test();
- config_tag_test();
- dname_test();
- rtt_test();
- anchors_test();
- alloc_test();
- regional_test();
- lruhash_test();
- slabhash_test();
- infra_test();
- ldns_test();
- msgparse_test();
-#ifdef CLIENT_SUBNET
- ecs_test();
-#endif /* CLIENT_SUBNET */
- checklock_stop();
- printf("%d checks ok.\n", testcount);
-#ifdef HAVE_SSL
-# if defined(USE_GOST) && defined(HAVE_LDNS_KEY_EVP_UNLOAD_GOST)
- sldns_key_EVP_unload_gost();
-# endif
-# ifdef HAVE_OPENSSL_CONFIG
-# ifdef HAVE_EVP_CLEANUP
- EVP_cleanup();
-# endif
- ENGINE_cleanup();
- CONF_modules_free();
-# endif
-# ifdef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA
- CRYPTO_cleanup_all_ex_data();
-# endif
-# ifdef HAVE_ERR_FREE_STRINGS
- ERR_free_strings();
-# endif
-# ifdef HAVE_RAND_CLEANUP
- RAND_cleanup();
-# endif
-#elif defined(HAVE_NSS)
- if(NSS_Shutdown() != SECSuccess)
- fatal_exit("could not shutdown NSS");
-#endif /* HAVE_SSL or HAVE_NSS */
-#ifdef HAVE_PTHREAD
- /* dlopen frees its thread specific state */
- pthread_exit(NULL);
-#endif
- return 0;
-}
diff --git a/external/unbound/testcode/unitmain.h b/external/unbound/testcode/unitmain.h
deleted file mode 100644
index d81b603b2..000000000
--- a/external/unbound/testcode/unitmain.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * testcode/unitmain.h - unit test main program for unbound.
- *
- * 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 COPYRIGHT
- * HOLDER 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_UNITMAIN_H
-#define TESTCODE_UNITMAIN_H
-#include "util/log.h"
-
-/** number of tests done */
-extern int testcount;
-/** test bool x, exits on failure, increases testcount. */
-#ifdef DEBUG_UNBOUND
-#define unit_assert(x) do {testcount++; log_assert(x);} while(0)
-#else
-#define unit_assert(x) do {testcount++; if(!(x)) { fprintf(stderr, "assertion failure %s:%d\n", __FILE__, __LINE__); exit(1);}} while(0)
-#endif
-
-/** we are now testing this function */
-void unit_show_func(const char* file, const char* func);
-/** we are testing this functionality */
-void unit_show_feature(const char* feature);
-
-/** unit test lruhashtable implementation */
-void lruhash_test(void);
-/** unit test slabhashtable implementation */
-void slabhash_test(void);
-/** unit test for msgreply and msgparse */
-void msgparse_test(void);
-/** unit test dname handling functions */
-void dname_test(void);
-/** unit test trust anchor storage functions */
-void anchors_test(void);
-/** unit test for verification functions */
-void verify_test(void);
-/** unit test for negative cache functions */
-void neg_test(void);
-/** unit test for regional allocator functions */
-void regional_test(void);
-#ifdef CLIENT_SUBNET
-/** Unit test for ECS functions */
-void ecs_test(void);
-#endif /* CLIENT_SUBNET */
-/** unit test for ldns functions */
-void ldns_test(void);
-
-#endif /* TESTCODE_UNITMAIN_H */
diff --git a/external/unbound/testcode/unitmsgparse.c b/external/unbound/testcode/unitmsgparse.c
deleted file mode 100644
index 627d10b78..000000000
--- a/external/unbound/testcode/unitmsgparse.c
+++ /dev/null
@@ -1,542 +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 COPYRIGHT
- * HOLDER 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 <sys/time.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/data/dname.h"
-#include "util/alloc.h"
-#include "util/regional.h"
-#include "util/net_help.h"
-#include "testcode/readhex.h"
-#include "testcode/testpkts.h"
-#include "sldns/sbuffer.h"
-#include "sldns/str2wire.h"
-#include "sldns/wire2str.h"
-
-/** verbose message parse unit test */
-static int vbmp = 0;
-/** do not accept formerr */
-static int check_formerr_gone = 0;
-/** if matching within a section should disregard the order of RRs. */
-static int matches_nolocation = 0;
-/** see if RRSIGs are properly matched to RRsets. */
-static int check_rrsigs = 0;
-/** do not check buffer sameness */
-static int check_nosameness = 0;
-
-/** see if buffers contain the same packet */
-static int
-test_buffers(sldns_buffer* pkt, sldns_buffer* out)
-{
- /* check binary same */
- if(sldns_buffer_limit(pkt) == sldns_buffer_limit(out) &&
- memcmp(sldns_buffer_begin(pkt), sldns_buffer_begin(out),
- sldns_buffer_limit(pkt)) == 0) {
- if(vbmp) printf("binary the same (length=%u)\n",
- (unsigned)sldns_buffer_limit(pkt));
- return 1;
- }
-
- if(vbmp) {
- size_t sz = 16;
- size_t count;
- size_t lim = sldns_buffer_limit(out);
- if(sldns_buffer_limit(pkt) < lim)
- lim = sldns_buffer_limit(pkt);
- for(count=0; count<lim; count+=sz) {
- size_t rem = sz;
- if(lim-count < sz) rem = lim-count;
- if(memcmp(sldns_buffer_at(pkt, count),
- sldns_buffer_at(out, count), rem) == 0) {
- log_info("same %d %d", (int)count, (int)rem);
- log_hex("same: ", sldns_buffer_at(pkt, count),
- rem);
- } else {
- log_info("diff %d %d", (int)count, (int)rem);
- log_hex("difp: ", sldns_buffer_at(pkt, count),
- rem);
- log_hex("difo: ", sldns_buffer_at(out, count),
- rem);
- }
- }
- }
-
- /* check if it 'means the same' */
- if(vbmp) {
- char* s1, *s2;
- log_buf(0, "orig in hex", pkt);
- log_buf(0, "unbound out in hex", out);
- printf("\npacket from unbound (%d):\n",
- (int)sldns_buffer_limit(out));
- s1 = sldns_wire2str_pkt(sldns_buffer_begin(out),
- sldns_buffer_limit(out));
- printf("%s\n", s1?s1:"null");
- free(s1);
-
- printf("\npacket original (%d):\n",
- (int)sldns_buffer_limit(pkt));
- s2 = sldns_wire2str_pkt(sldns_buffer_begin(pkt),
- sldns_buffer_limit(pkt));
- printf("%s\n", s2?s2:"null");
- free(s2);
- printf("\n");
- }
- /* if it had two EDNS sections, skip comparison */
- if(1) {
- char* s = sldns_wire2str_pkt(sldns_buffer_begin(pkt),
- sldns_buffer_limit(pkt));
- char* e1 = strstr(s, "; EDNS:");
- if(e1 && strstr(e1+4, "; EDNS:")) {
- free(s);
- return 0;
- }
- free(s);
- }
- /* compare packets */
- unit_assert(match_all(sldns_buffer_begin(pkt), sldns_buffer_limit(pkt),
- sldns_buffer_begin(out), sldns_buffer_limit(out), 1,
- matches_nolocation));
- return 0;
-}
-
-/** check if unbound formerr equals ldns formerr */
-static void
-checkformerr(sldns_buffer* pkt)
-{
- int status = 0;
- char* s = sldns_wire2str_pkt(sldns_buffer_begin(pkt),
- sldns_buffer_limit(pkt));
- if(!s) fatal_exit("out of memory");
- if(strstr(s, "Error")) status = 1;
- if(strstr(s, "error")) status = 1;
- if(status == 0) {
- printf("Formerr, but ldns gives packet:\n");
- printf("%s\n", s);
- free(s);
- exit(1);
- }
- free(s);
- unit_assert(status != 0);
-}
-
-/** performance test message encoding */
-static void
-perf_encode(struct query_info* qi, struct reply_info* rep, uint16_t id,
- uint16_t flags, sldns_buffer* out, time_t timenow,
- struct edns_data* edns)
-{
- static int num = 0;
- int ret;
- size_t max = 10000;
- size_t i;
- struct timeval start, end;
- double dt;
- struct regional* r2 = regional_create();
- if(gettimeofday(&start, NULL) < 0)
- fatal_exit("gettimeofday: %s", strerror(errno));
- /* encode a couple times */
- for(i=0; i<max; i++) {
- ret = reply_info_encode(qi, rep, id, flags, out, timenow,
- r2, 65535, (int)(edns->bits & EDNS_DO) );
- unit_assert(ret != 0); /* udp packets should fit */
- attach_edns_record(out, edns);
- regional_free_all(r2);
- }
- if(gettimeofday(&end, NULL) < 0)
- fatal_exit("gettimeofday: %s", strerror(errno));
- /* time in millisec */
- dt = (double)(end.tv_sec - start.tv_sec)*1000. +
- ((double)end.tv_usec - (double)start.tv_usec)/1000.;
- printf("[%d] did %u in %g msec for %f encode/sec size %d\n", num++,
- (unsigned)max, dt, (double)max / (dt/1000.),
- (int)sldns_buffer_limit(out));
- regional_destroy(r2);
-}
-
-/** perf test a packet */
-static void
-perftestpkt(sldns_buffer* pkt, struct alloc_cache* alloc, sldns_buffer* out,
- const char* hex)
-{
- struct query_info qi;
- struct reply_info* rep = 0;
- int ret;
- uint16_t id;
- uint16_t flags;
- time_t timenow = 0;
- struct regional* region = regional_create();
- struct edns_data edns;
-
- hex_to_buf(pkt, hex);
- memmove(&id, sldns_buffer_begin(pkt), sizeof(id));
- if(sldns_buffer_limit(pkt) < 2)
- flags = 0;
- else memmove(&flags, sldns_buffer_at(pkt, 2), sizeof(flags));
- flags = ntohs(flags);
- ret = reply_info_parse(pkt, alloc, &qi, &rep, region, &edns);
- if(ret != 0) {
- char rbuf[16];
- sldns_wire2str_rcode_buf(ret, rbuf, sizeof(rbuf));
- if(vbmp) printf("parse code %d: %s\n", ret, rbuf);
- if(ret == LDNS_RCODE_FORMERR)
- checkformerr(pkt);
- unit_assert(ret != LDNS_RCODE_SERVFAIL);
- } else {
- perf_encode(&qi, rep, id, flags, out, timenow, &edns);
- }
-
- query_info_clear(&qi);
- reply_info_parsedelete(rep, alloc);
- regional_destroy(region);
-}
-
-/** print packed rrset */
-static void
-print_rrset(struct ub_packed_rrset_key* rrset)
-{
- struct packed_rrset_data* d = (struct packed_rrset_data*)rrset->
- entry.data;
- char buf[65535];
- size_t i;
- for(i=0; i<d->count+d->rrsig_count; i++) {
- if(!packed_rr_to_string(rrset, i, 0, buf, sizeof(buf)))
- printf("failedtoconvert %d\n", (int)i);
- else
- printf("%s\n", buf);
- }
-}
-
-/** debug print a packet that failed */
-static void
-print_packet_rrsets(struct query_info* qinfo, struct reply_info* rep)
-{
- size_t i;
- log_query_info(0, "failed query", qinfo);
- printf(";; ANSWER SECTION (%d rrsets)\n", (int)rep->an_numrrsets);
- for(i=0; i<rep->an_numrrsets; i++) {
- printf("; rrset %d\n", (int)i);
- print_rrset(rep->rrsets[i]);
- }
- printf(";; AUTHORITY SECTION (%d rrsets)\n", (int)rep->ns_numrrsets);
- for(i=rep->an_numrrsets; i<rep->an_numrrsets+rep->ns_numrrsets; i++) {
- printf("; rrset %d\n", (int)i);
- print_rrset(rep->rrsets[i]);
- }
- printf(";; ADDITIONAL SECTION (%d rrsets)\n", (int)rep->ar_numrrsets);
- for(i=rep->an_numrrsets+rep->ns_numrrsets; i<rep->rrset_count; i++) {
- printf("; rrset %d\n", (int)i);
- print_rrset(rep->rrsets[i]);
- }
- printf(";; packet end\n");
-}
-
-/** check that there is no data element that matches the RRSIG */
-static int
-no_data_for_rrsig(struct reply_info* rep, struct ub_packed_rrset_key* rrsig)
-{
- size_t i;
- for(i=0; i<rep->rrset_count; i++) {
- if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_RRSIG)
- continue;
- if(query_dname_compare(rep->rrsets[i]->rk.dname,
- rrsig->rk.dname) == 0)
- /* only name is compared right now */
- return 0;
- }
- return 1;
-}
-
-/** check RRSIGs in packet */
-static void
-check_the_rrsigs(struct query_info* qinfo, struct reply_info* rep)
-{
- /* every RRSIG must be matched to an RRset */
- size_t i;
- for(i=0; i<rep->rrset_count; i++) {
- struct ub_packed_rrset_key* s = rep->rrsets[i];
- if(ntohs(s->rk.type) == LDNS_RR_TYPE_RRSIG) {
- /* see if really a problem, i.e. is there a data
- * element. */
- if(no_data_for_rrsig(rep, rep->rrsets[i]))
- continue;
- log_dns_msg("rrsig failed for packet", qinfo, rep);
- print_packet_rrsets(qinfo, rep);
- printf("failed rrset is nr %d\n", (int)i);
- unit_assert(0);
- }
- }
-}
-
-/** test a packet */
-static void
-testpkt(sldns_buffer* pkt, struct alloc_cache* alloc, sldns_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;
- struct regional* region = regional_create();
- struct edns_data edns;
-
- hex_to_buf(pkt, hex);
- memmove(&id, sldns_buffer_begin(pkt), sizeof(id));
- if(sldns_buffer_limit(pkt) < 2)
- flags = 0;
- else memmove(&flags, sldns_buffer_at(pkt, 2), sizeof(flags));
- flags = ntohs(flags);
- ret = reply_info_parse(pkt, alloc, &qi, &rep, region, &edns);
- if(ret != 0) {
- char rbuf[16];
- sldns_wire2str_rcode_buf(ret, rbuf, sizeof(rbuf));
- if(vbmp) printf("parse code %d: %s\n", ret, rbuf);
- if(ret == LDNS_RCODE_FORMERR) {
- unit_assert(!check_formerr_gone);
- checkformerr(pkt);
- }
- unit_assert(ret != LDNS_RCODE_SERVFAIL);
- } else if(!check_formerr_gone) {
- 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)sldns_buffer_limit(pkt),
- (unsigned)sldns_buffer_limit(out));
- if(!check_nosameness)
- test_buffers(pkt, out);
- if(check_rrsigs)
- check_the_rrsigs(&qi, rep);
-
- if(sldns_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(sldns_buffer_begin(out)) !=
- LDNS_QDCOUNT(sldns_buffer_begin(pkt)) ||
- LDNS_ANCOUNT(sldns_buffer_begin(out)) !=
- LDNS_ANCOUNT(sldns_buffer_begin(pkt)) ||
- LDNS_NSCOUNT(sldns_buffer_begin(out)) !=
- LDNS_NSCOUNT(sldns_buffer_begin(pkt)))
- unit_assert(
- LDNS_TC_WIRE(sldns_buffer_begin(out)));
- /* must set TC bit if shortened */
- unit_assert(sldns_buffer_limit(out) <= lim);
- }
- }
-
- query_info_clear(&qi);
- reply_info_parsedelete(rep, alloc);
- regional_destroy(region);
-}
-
-/** simple test of parsing */
-static void
-simpletest(sldns_buffer* pkt, struct alloc_cache* alloc, sldns_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 ");
-
- /* root delegation from unbound trace with new AAAA glue */
- perftestpkt(pkt, alloc, out,
- "55BC84000001000D00000014000002000100000200010007E900001401610C726F6F742D73657276657273036E65740000000200010007E90000040162C01E00000200010007E90000040163C01E00000200010007E90000040164C01E00000200010007E90000040165C01E00000200010007E90000040166C01E00000200010007E90000040167C01E00000200010007E90000040168C01E00000200010007E90000040169C01E00000200010007E9000004016AC01E00000200010007E9000004016BC01E00000200010007E9000004016CC01E00000200010007E9000004016DC01EC01C000100010007E9000004C6290004C03B000100010007E9000004C0E44FC9C04A000100010007E9000004C021040CC059000100010007E900000480080A5AC068000100010007E9000004C0CBE60AC077000100010007E9000004C00505F1C086000100010007E9000004C0702404C095000100010007E9000004803F0235C0A4000100010007E9000004C0249411C0B3000100010007E9000004C03A801EC0C2000100010007E9000004C1000E81C0D1000100010007E9000004C707532AC0E0000100010007E9000004CA0C1B21C01C001C00010007E900001020010503BA3E00000000000000020030C077001C00010007E900001020010500002F0000000000000000000FC095001C00010007E90000102001050000010000"
- "00000000803F0235C0B3001C00010007E9000010200105030C2700000000000000020030C0C2001C00010007E9000010200107FD000000000000000000000001C0E0001C00010007E900001020010DC30000000000000000000000350000291000000000000000"
- );
-}
-
-/** simple test of parsing, pcat file */
-static void
-testfromfile(sldns_buffer* pkt, struct alloc_cache* alloc, sldns_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(sldns_buffer* pkt, struct alloc_cache* alloc,
- sldns_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(void)
-{
- time_t origttl = MAX_NEG_TTL;
- sldns_buffer* pkt = sldns_buffer_new(65553);
- sldns_buffer* out = sldns_buffer_new(65553);
- struct alloc_cache super_a, alloc;
- MAX_NEG_TTL = 86400;
- /* init */
- alloc_init(&super_a, NULL, 0);
- alloc_init(&alloc, &super_a, 2);
-
- unit_show_feature("message parse");
- 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");
-
- matches_nolocation = 1; /* RR order not important for the next test */
- testfromdrillfile(pkt, &alloc, out, "testdata/test_packets.6");
- check_rrsigs = 1;
- testfromdrillfile(pkt, &alloc, out, "testdata/test_packets.7");
- check_rrsigs = 0;
- matches_nolocation = 0;
-
- check_formerr_gone = 1;
- testfromdrillfile(pkt, &alloc, out, "testdata/test_packets.8");
- check_formerr_gone = 0;
-
- check_rrsigs = 1;
- check_nosameness = 1;
- testfromdrillfile(pkt, &alloc, out, "testdata/test_packets.9");
- check_nosameness = 0;
- check_rrsigs = 0;
-
- /* cleanup */
- alloc_clear(&alloc);
- alloc_clear(&super_a);
- sldns_buffer_free(pkt);
- sldns_buffer_free(out);
- MAX_NEG_TTL = origttl;
-}
diff --git a/external/unbound/testcode/unitneg.c b/external/unbound/testcode/unitneg.c
deleted file mode 100644
index 2b67df182..000000000
--- a/external/unbound/testcode/unitneg.c
+++ /dev/null
@@ -1,543 +0,0 @@
-/*
- * testcode/unitneg.c - unit test for negative cache routines.
- *
- * Copyright (c) 2008, 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 COPYRIGHT
- * HOLDER 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 negative cache unit tests. Exits with code 1 on a failure.
- */
-
-#include "config.h"
-#include "util/log.h"
-#include "util/net_help.h"
-#include "util/data/packed_rrset.h"
-#include "util/data/dname.h"
-#include "testcode/unitmain.h"
-#include "validator/val_neg.h"
-#include "sldns/rrdef.h"
-
-/** verbose unit test for negative cache */
-static int negverbose = 0;
-
-/** debug printout of neg cache */
-static void print_neg_cache(struct val_neg_cache* neg)
-{
- char buf[1024];
- struct val_neg_zone* z;
- struct val_neg_data* d;
- printf("neg_cache print\n");
- printf("memuse %d of %d\n", (int)neg->use, (int)neg->max);
- printf("maxiter %d\n", (int)neg->nsec3_max_iter);
- printf("%d zones\n", (int)neg->tree.count);
- RBTREE_FOR(z, struct val_neg_zone*, &neg->tree) {
- dname_str(z->name, buf);
- printf("%24s", buf);
- printf(" len=%2.2d labs=%d inuse=%d count=%d tree.count=%d\n",
- (int)z->len, z->labs, (int)z->in_use, z->count,
- (int)z->tree.count);
- }
- RBTREE_FOR(z, struct val_neg_zone*, &neg->tree) {
- printf("\n");
- dname_print(stdout, NULL, z->name);
- printf(" zone details\n");
- printf("len=%2.2d labs=%d inuse=%d count=%d tree.count=%d\n",
- (int)z->len, z->labs, (int)z->in_use, z->count,
- (int)z->tree.count);
- if(z->parent) {
- printf("parent=");
- dname_print(stdout, NULL, z->parent->name);
- printf("\n");
- } else {
- printf("parent=NULL\n");
- }
-
- RBTREE_FOR(d, struct val_neg_data*, &z->tree) {
- dname_str(d->name, buf);
- printf("%24s", buf);
- printf(" len=%2.2d labs=%d inuse=%d count=%d\n",
- (int)d->len, d->labs, (int)d->in_use, d->count);
- }
- }
-}
-
-/** get static pointer to random zone name */
-static char* get_random_zone(void)
-{
- static char zname[256];
- int labels = random() % 3;
- int i;
- char* p = zname;
- int labnum;
-
- for(i=0; i<labels; i++) {
- labnum = random()%10;
- snprintf(p, 256-(p-zname), "\003%3.3d", labnum);
- p+=4;
- }
- snprintf(p, 256-(p-zname), "\007example\003com");
- return zname;
-}
-
-/** get static pointer to random data names from and to */
-static void get_random_data(char** fromp, char** top, char* zname)
-{
- static char buf1[256], buf2[256];
- int type;
- int lab1, lab2;
- int labnum1[10], labnum2[10];
- int i;
- char* p;
-
- *fromp = buf1;
- *top = buf2;
- type = random()%10;
-
- if(type == 0) {
- /* ENT */
- lab1 = random() %3 + 1;
- lab2 = lab1 + random()%3 + 1;
- for(i=0; i<lab1; i++) {
- labnum1[i] = random()%100;
- labnum2[i] = labnum1[i];
- }
- for(i=lab1; i<lab2; i++) {
- labnum2[i] = random()%100;
- }
- } else if(type == 1) {
- /* end of zone */
- lab2 = 0;
- lab1 = random()%3 + 1;
- for(i=0; i<lab1; i++) {
- labnum1[i] = random()%100;
- }
- } else if(type == 2) {
- /* start of zone */
- lab1 = 0;
- lab2 = random()%3 + 1;
- for(i=0; i<lab2; i++) {
- labnum2[i] = random()%100;
- }
- } else {
- /* normal item */
- int common = random()%3;
- lab1 = random() %3 + 1;
- lab2 = random() %3 + 1;
- for(i=0; i<common; i++) {
- labnum1[i] = random()%100;
- labnum2[i] = labnum1[i];
- }
- labnum1[common] = random()%100;
- labnum2[common] = labnum1[common] + random()%20;
- for(i=common; i<lab1; i++)
- labnum1[i] = random()%100;
- for(i=common; i<lab2; i++)
- labnum2[i] = random()%100;
- }
-
- /* construct first */
- p = buf1;
- for(i=0; i<lab1; i++) {
- snprintf(p, 256-(p-buf1), "\003%3.3d", labnum1[i]);
- p+=4;
- }
- snprintf(p, 256-(p-buf1), "%s", zname);
-
- /* construct 2nd */
- p = buf2+2;
- for(i=0; i<lab2; i++) {
- snprintf(p, 256-(p-buf2)-3, "\003%3.3d", labnum2[i]);
- p+=4;
- }
- snprintf(p, 256-(p-buf2)-3, "%s", zname);
- buf2[0] = (char)(strlen(buf2+2)+1);
- buf2[1] = 0;
-
- if(negverbose) {
- log_nametypeclass(0, "add from", (uint8_t*)buf1, 0, 0);
- log_nametypeclass(0, "add to ", (uint8_t*)buf2+2, 0, 0);
- }
-}
-
-/** add a random item */
-static void add_item(struct val_neg_cache* neg)
-{
- struct val_neg_zone* z;
- struct packed_rrset_data rd;
- struct ub_packed_rrset_key nsec;
- size_t rr_len;
- time_t rr_ttl;
- uint8_t* rr_data;
- char* zname = get_random_zone();
- char* from, *to;
-
- lock_basic_lock(&neg->lock);
- if(negverbose)
- log_nametypeclass(0, "add to zone", (uint8_t*)zname, 0, 0);
- z = neg_find_zone(neg, (uint8_t*)zname, strlen(zname)+1,
- LDNS_RR_CLASS_IN);
- if(!z) {
- z = neg_create_zone(neg, (uint8_t*)zname, strlen(zname)+1,
- LDNS_RR_CLASS_IN);
- }
- unit_assert(z);
- val_neg_zone_take_inuse(z);
-
- /* construct random NSEC item */
- get_random_data(&from, &to, zname);
-
- /* create nsec and insert it */
- memset(&rd, 0, sizeof(rd));
- memset(&nsec, 0, sizeof(nsec));
- nsec.rk.dname = (uint8_t*)from;
- nsec.rk.dname_len = strlen(from)+1;
- nsec.rk.type = htons(LDNS_RR_TYPE_NSEC);
- nsec.rk.rrset_class = htons(LDNS_RR_CLASS_IN);
- nsec.entry.data = &rd;
- rd.security = sec_status_secure;
- rd.count = 1;
- rd.rr_len = &rr_len;
- rr_len = 19;
- rd.rr_ttl = &rr_ttl;
- rr_ttl = 0;
- rd.rr_data = &rr_data;
- rr_data = (uint8_t*)to;
-
- neg_insert_data(neg, z, &nsec);
- lock_basic_unlock(&neg->lock);
-}
-
-/** remove a random item */
-static void remove_item(struct val_neg_cache* neg)
-{
- int n, i;
- struct val_neg_data* d;
- rbnode_type* walk;
- struct val_neg_zone* z;
-
- lock_basic_lock(&neg->lock);
- if(neg->tree.count == 0) {
- lock_basic_unlock(&neg->lock);
- return; /* nothing to delete */
- }
-
- /* pick a random zone */
- walk = rbtree_first(&neg->tree); /* first highest parent, big count */
- z = (struct val_neg_zone*)walk;
- n = random() % (int)(z->count);
- if(negverbose)
- printf("neg stress delete zone %d\n", n);
- i=0;
- walk = rbtree_first(&neg->tree);
- z = (struct val_neg_zone*)walk;
- while(i!=n+1 && walk && walk != RBTREE_NULL && !z->in_use) {
- walk = rbtree_next(walk);
- z = (struct val_neg_zone*)walk;
- if(z->in_use)
- i++;
- }
- if(!walk || walk == RBTREE_NULL) {
- lock_basic_unlock(&neg->lock);
- return;
- }
- if(!z->in_use) {
- lock_basic_unlock(&neg->lock);
- return;
- }
- if(negverbose)
- log_nametypeclass(0, "delete zone", z->name, 0, 0);
-
- /* pick a random nsec item. - that is in use */
- walk = rbtree_first(&z->tree); /* first is highest parent */
- d = (struct val_neg_data*)walk;
- n = random() % (int)(d->count);
- if(negverbose)
- printf("neg stress delete item %d\n", n);
- i=0;
- walk = rbtree_first(&z->tree);
- d = (struct val_neg_data*)walk;
- while(i!=n+1 && walk && walk != RBTREE_NULL && !d->in_use) {
- walk = rbtree_next(walk);
- d = (struct val_neg_data*)walk;
- if(d->in_use)
- i++;
- }
- if(!walk || walk == RBTREE_NULL) {
- lock_basic_unlock(&neg->lock);
- return;
- }
- if(d->in_use) {
- if(negverbose)
- log_nametypeclass(0, "neg delete item:", d->name, 0, 0);
- neg_delete_data(neg, d);
- }
- lock_basic_unlock(&neg->lock);
-}
-
-/** sum up the zone trees */
-static size_t sumtrees_all(struct val_neg_cache* neg)
-{
- size_t res = 0;
- struct val_neg_zone* z;
- RBTREE_FOR(z, struct val_neg_zone*, &neg->tree) {
- res += z->tree.count;
- }
- return res;
-}
-
-/** sum up the zone trees, in_use only */
-static size_t sumtrees_inuse(struct val_neg_cache* neg)
-{
- size_t res = 0;
- struct val_neg_zone* z;
- struct val_neg_data* d;
- RBTREE_FOR(z, struct val_neg_zone*, &neg->tree) {
- /* get count of highest parent for num in use */
- d = (struct val_neg_data*)rbtree_first(&z->tree);
- if(d && (rbnode_type*)d!=RBTREE_NULL)
- res += d->count;
- }
- return res;
-}
-
-/** check if lru is still valid */
-static void check_lru(struct val_neg_cache* neg)
-{
- struct val_neg_data* p, *np;
- size_t num = 0;
- size_t inuse;
- p = neg->first;
- while(p) {
- if(!p->prev) {
- unit_assert(neg->first == p);
- }
- np = p->next;
- if(np) {
- unit_assert(np->prev == p);
- } else {
- unit_assert(neg->last == p);
- }
- num++;
- p = np;
- }
- inuse = sumtrees_inuse(neg);
- if(negverbose)
- printf("num lru %d, inuse %d, all %d\n",
- (int)num, (int)sumtrees_inuse(neg),
- (int)sumtrees_all(neg));
- unit_assert( num == inuse);
- unit_assert( inuse <= sumtrees_all(neg));
-}
-
-/** sum up number of items inuse in subtree */
-static int sum_subtree_inuse(struct val_neg_zone* zone,
- struct val_neg_data* data)
-{
- struct val_neg_data* d;
- int num = 0;
- RBTREE_FOR(d, struct val_neg_data*, &zone->tree) {
- if(dname_subdomain_c(d->name, data->name)) {
- if(d->in_use)
- num++;
- }
- }
- return num;
-}
-
-/** sum up number of items inuse in subtree */
-static int sum_zone_subtree_inuse(struct val_neg_cache* neg,
- struct val_neg_zone* zone)
-{
- struct val_neg_zone* z;
- int num = 0;
- RBTREE_FOR(z, struct val_neg_zone*, &neg->tree) {
- if(dname_subdomain_c(z->name, zone->name)) {
- if(z->in_use)
- num++;
- }
- }
- return num;
-}
-
-/** check point in data tree */
-static void check_data(struct val_neg_zone* zone, struct val_neg_data* data)
-{
- unit_assert(data->count > 0);
- if(data->parent) {
- unit_assert(data->parent->count >= data->count);
- if(data->parent->in_use) {
- unit_assert(data->parent->count > data->count);
- }
- unit_assert(data->parent->labs == data->labs-1);
- /* and parent must be one label shorter */
- unit_assert(data->name[0] == (data->len-data->parent->len-1));
- unit_assert(query_dname_compare(data->name + data->name[0]+1,
- data->parent->name) == 0);
- } else {
- /* must be apex */
- unit_assert(dname_is_root(data->name));
- }
- /* tree property: */
- unit_assert(data->count == sum_subtree_inuse(zone, data));
-}
-
-/** check if tree of data in zone is valid */
-static void checkzonetree(struct val_neg_zone* zone)
-{
- struct val_neg_data* d;
-
- /* check all data in tree */
- RBTREE_FOR(d, struct val_neg_data*, &zone->tree) {
- check_data(zone, d);
- }
-}
-
-/** check if negative cache is still valid */
-static void check_zone_invariants(struct val_neg_cache* neg,
- struct val_neg_zone* zone)
-{
- unit_assert(zone->nsec3_hash == 0);
- unit_assert(zone->tree.cmp == &val_neg_data_compare);
- unit_assert(zone->count != 0);
-
- if(zone->tree.count == 0)
- unit_assert(!zone->in_use);
- else {
- if(!zone->in_use) {
- /* details on error */
- log_nametypeclass(0, "zone", zone->name, 0, 0);
- log_err("inuse %d count=%d tree.count=%d",
- zone->in_use, zone->count,
- (int)zone->tree.count);
- if(negverbose)
- print_neg_cache(neg);
- }
- unit_assert(zone->in_use);
- }
-
- if(zone->parent) {
- unit_assert(zone->parent->count >= zone->count);
- if(zone->parent->in_use) {
- unit_assert(zone->parent->count > zone->count);
- }
- unit_assert(zone->parent->labs == zone->labs-1);
- /* and parent must be one label shorter */
- unit_assert(zone->name[0] == (zone->len-zone->parent->len-1));
- unit_assert(query_dname_compare(zone->name + zone->name[0]+1,
- zone->parent->name) == 0);
- } else {
- /* must be apex */
- unit_assert(dname_is_root(zone->name));
- }
- /* tree property: */
- unit_assert(zone->count == sum_zone_subtree_inuse(neg, zone));
-
- /* check structure of zone data tree */
- checkzonetree(zone);
-}
-
-/** check if negative cache is still valid */
-static void check_neg_invariants(struct val_neg_cache* neg)
-{
- struct val_neg_zone* z;
- /* check structure of LRU list */
- lock_basic_lock(&neg->lock);
- check_lru(neg);
- unit_assert(neg->max == 1024*1024);
- unit_assert(neg->nsec3_max_iter == 1500);
- unit_assert(neg->tree.cmp == &val_neg_zone_compare);
-
- if(neg->tree.count == 0) {
- /* empty */
- unit_assert(neg->tree.count == 0);
- unit_assert(neg->first == NULL);
- unit_assert(neg->last == NULL);
- unit_assert(neg->use == 0);
- lock_basic_unlock(&neg->lock);
- return;
- }
-
- unit_assert(neg->first != NULL);
- unit_assert(neg->last != NULL);
-
- RBTREE_FOR(z, struct val_neg_zone*, &neg->tree) {
- check_zone_invariants(neg, z);
- }
- lock_basic_unlock(&neg->lock);
-}
-
-/** perform stress test on insert and delete in neg cache */
-static void stress_test(struct val_neg_cache* neg)
-{
- int i;
- if(negverbose)
- printf("negcache test\n");
- for(i=0; i<100; i++) {
- if(random() % 10 < 8)
- add_item(neg);
- else remove_item(neg);
- check_neg_invariants(neg);
- }
- /* empty it */
- if(negverbose)
- printf("neg stress empty\n");
- while(neg->first) {
- remove_item(neg);
- check_neg_invariants(neg);
- }
- if(negverbose)
- printf("neg stress emptied\n");
- unit_assert(neg->first == NULL);
- /* insert again */
- for(i=0; i<100; i++) {
- if(random() % 10 < 8)
- add_item(neg);
- else remove_item(neg);
- check_neg_invariants(neg);
- }
-}
-
-void neg_test(void)
-{
- struct val_neg_cache* neg;
- srandom(48);
- unit_show_feature("negative cache");
-
- /* create with defaults */
- neg = val_neg_create(NULL, 1500);
- unit_assert(neg);
-
- stress_test(neg);
-
- neg_cache_delete(neg);
-}
diff --git a/external/unbound/testcode/unitregional.c b/external/unbound/testcode/unitregional.c
deleted file mode 100644
index 49c8147c9..000000000
--- a/external/unbound/testcode/unitregional.c
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * testcode/unitregional.c - unit test for regional allocator.
- *
- * Copyright (c) 2010, 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 COPYRIGHT
- * HOLDER 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
- * Tests the regional special purpose allocator.
- */
-
-#include "config.h"
-#include "testcode/unitmain.h"
-#include "util/log.h"
-#include "util/regional.h"
-
-/** test regional corner cases, zero, one, end of structure */
-static void
-corner_cases(struct regional* r)
-{
- size_t s; /* shadow count of allocated memory */
- void* a;
- size_t minsize = sizeof(uint64_t);
- size_t mysize;
- char* str;
- unit_assert(r);
- /* alloc cases:
- * 0, 1, 2.
- * smaller than LARGE_OBJECT_SIZE.
- * smaller but does not fit in remainder in regional.
- * smaller but exactly fits in remainder of regional.
- * size is remainder of regional - 8.
- * size is remainder of regional + 8.
- * larger than LARGE_OBJECT_SIZE.
- */
- s = sizeof(struct regional);
- unit_assert((s % minsize) == 0);
- unit_assert(r->available == r->first_size - s);
- unit_assert(r->large_list == NULL);
- unit_assert(r->next == NULL);
-
- /* Note an alloc of 0 gets a pointer to current last
- * position (where you should then use 0 bytes) */
- a = regional_alloc(r, 0);
- unit_assert(a);
- s+=0;
- unit_assert(r->available == r->first_size - s);
-
- a = regional_alloc(r, 1);
- unit_assert(a);
- memset(a, 0x42, 1);
- s+=minsize;
- unit_assert(r->available == r->first_size - s);
-
- a = regional_alloc(r, 2);
- unit_assert(a);
- memset(a, 0x42, 2);
- s+=minsize;
- unit_assert(r->available == r->first_size - s);
-
- a = regional_alloc(r, 128);
- unit_assert(a);
- memset(a, 0x42, 128);
- s+=128;
- unit_assert(r->available == r->first_size - s);
-
- unit_assert(r->large_list == NULL);
- a = regional_alloc(r, 10240);
- unit_assert(a);
- unit_assert(r->large_list != NULL);
- memset(a, 0x42, 10240);
- /* s does not change */
- unit_assert(r->available == r->first_size - s);
- unit_assert(r->total_large == 10240+minsize);
-
- /* go towards the end of the current chunk */
- while(r->available > 1024) {
- a = regional_alloc(r, 1024);
- unit_assert(a);
- memset(a, 0x42, 1024);
- s += 1024;
- unit_assert(r->available == r->first_size - s);
- }
-
- unit_assert(r->next == NULL);
- mysize = 1280; /* does not fit in current chunk */
- a = regional_alloc(r, mysize);
- memset(a, 0x42, mysize);
- unit_assert(r->next != NULL);
- unit_assert(a);
-
- /* go towards the end of the current chunk */
- while(r->available > 864) {
- a = regional_alloc(r, 864);
- unit_assert(a);
- memset(a, 0x42, 864);
- s += 864;
- }
-
- mysize = r->available; /* exactly fits */
- a = regional_alloc(r, mysize);
- memset(a, 0x42, mysize);
- unit_assert(a);
- unit_assert(r->available == 0); /* implementation does not go ahead*/
-
- a = regional_alloc(r, 8192); /* another large allocation */
- unit_assert(a);
- memset(a, 0x42, 8192);
- unit_assert(r->available == 0);
- unit_assert(r->total_large == 10240 + 8192 + 2*minsize);
-
- a = regional_alloc(r, 32); /* make new chunk */
- unit_assert(a);
- memset(a, 0x42, 32);
- unit_assert(r->available > 0);
- unit_assert(r->total_large == 10240 + 8192 + 2*minsize);
-
- /* go towards the end of the current chunk */
- while(r->available > 1320) {
- a = regional_alloc(r, 1320);
- unit_assert(a);
- memset(a, 0x42, 1320);
- s += 1320;
- }
-
- mysize = r->available + 8; /* exact + 8 ; does not fit */
- a = regional_alloc(r, mysize);
- memset(a, 0x42, mysize);
- unit_assert(a);
- unit_assert(r->available > 0); /* new chunk */
-
- /* go towards the end of the current chunk */
- while(r->available > 1480) {
- a = regional_alloc(r, 1480);
- unit_assert(a);
- memset(a, 0x42, 1480);
- s += 1480;
- }
-
- mysize = r->available - 8; /* exact - 8 ; fits. */
- a = regional_alloc(r, mysize);
- memset(a, 0x42, mysize);
- unit_assert(a);
- unit_assert(r->available == 8);
-
- /* test if really copied over */
- str = "test12345";
- a = regional_alloc_init(r, str, 8);
- unit_assert(a);
- unit_assert(memcmp(a, str, 8) == 0);
-
- /* test if really zeroed */
- a = regional_alloc_zero(r, 32);
- str="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
- unit_assert(a);
- unit_assert(memcmp(a, str, 32) == 0);
-
- /* test if copied over (and null byte) */
- str = "an interesting string";
- a = regional_strdup(r, str);
- unit_assert(a);
- unit_assert(memcmp(a, str, strlen(str)+1) == 0);
-
- regional_free_all(r);
-}
-
-/** test specific cases */
-static void
-specific_cases(void)
-{
- struct regional* r = regional_create();
- corner_cases(r);
- regional_destroy(r);
- r = regional_create_custom(2048); /* a small regional */
- unit_assert(r->first_size == 2048);
- unit_assert(regional_get_mem(r) == 2048);
- corner_cases(r);
- unit_assert(regional_get_mem(r) == 2048);
- regional_destroy(r);
-}
-
-/** put random stuff in a region and free it */
-static void
-burden_test(size_t max)
-{
- size_t get;
- void* a;
- int i;
- struct regional* r = regional_create_custom(2048);
- for(i=0; i<1000; i++) {
- get = random() % max;
- a = regional_alloc(r, get);
- unit_assert(a);
- memset(a, 0x54, get);
- }
- regional_free_all(r);
- regional_destroy(r);
-}
-
-/** randomly allocate stuff */
-static void
-random_burden(void)
-{
- size_t max_alloc = 2048 + 128; /* small chance of LARGE */
- int i;
- for(i=0; i<100; i++)
- burden_test(max_alloc);
-}
-
-void regional_test(void)
-{
- unit_show_feature("regional");
- specific_cases();
- random_burden();
-}
diff --git a/external/unbound/testcode/unitslabhash.c b/external/unbound/testcode/unitslabhash.c
deleted file mode 100644
index 565d36139..000000000
--- a/external/unbound/testcode/unitslabhash.c
+++ /dev/null
@@ -1,376 +0,0 @@
-/*
- * testcode/unitslabhash.c - unit test for slabhash table.
- *
- * 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 COPYRIGHT
- * HOLDER 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
- * Tests the locking LRU keeping hash table implementation.
- */
-
-#include "config.h"
-#include "testcode/unitmain.h"
-#include "util/log.h"
-#include "util/storage/slabhash.h"
-
-/** use this type for the slabhash test key */
-typedef struct slabhash_testkey testkey_type;
-/** use this type for the slabhash test data */
-typedef struct slabhash_testdata testdata_type;
-
-/** delete key */
-static void delkey(struct slabhash_testkey* k) {
- lock_rw_destroy(&k->entry.lock); free(k);}
-
-/** hash func, very bad to improve collisions, both high and low bits */
-static hashvalue_type myhash(int id) {
- hashvalue_type h = (hashvalue_type)id & 0x0f;
- h |= (h << 28);
- return h;
-}
-
-/** allocate new key, fill in hash */
-static testkey_type* newkey(int id) {
- testkey_type* k = (testkey_type*)calloc(1, sizeof(testkey_type));
- if(!k) fatal_exit("out of memory");
- k->id = id;
- k->entry.hash = myhash(id);
- k->entry.key = k;
- lock_rw_init(&k->entry.lock);
- return k;
-}
-/** new data el */
-static testdata_type* newdata(int val) {
- testdata_type* d = (testdata_type*)calloc(1,
- sizeof(testdata_type));
- if(!d) fatal_exit("out of memory");
- d->data = val;
- return d;
-}
-
-/** test hashtable using short sequence */
-static void
-test_short_table(struct slabhash* table)
-{
- testkey_type* k = newkey(12);
- testkey_type* k2 = newkey(14);
- testdata_type* d = newdata(128);
- testdata_type* d2 = newdata(129);
-
- 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);
-
- unit_assert( slabhash_lookup(table, myhash(12), k, 0) == &k->entry);
- lock_rw_unlock( &k->entry.lock );
- unit_assert( slabhash_lookup(table, myhash(14), k2, 0) == &k2->entry);
- lock_rw_unlock( &k2->entry.lock );
- slabhash_remove(table, myhash(12), k);
- slabhash_remove(table, myhash(14), k2);
-}
-
-/** number of hash test max */
-#define HASHTESTMAX 32
-
-/** test adding a random element */
-static void
-testadd(struct slabhash* table, testdata_type* ref[])
-{
- int numtoadd = random() % HASHTESTMAX;
- testdata_type* data = newdata(numtoadd);
- testkey_type* key = newkey(numtoadd);
- key->entry.data = data;
- slabhash_insert(table, myhash(numtoadd), &key->entry, data, NULL);
- ref[numtoadd] = data;
-}
-
-/** test adding a random element */
-static void
-testremove(struct slabhash* table, testdata_type* ref[])
-{
- int num = random() % HASHTESTMAX;
- testkey_type* key = newkey(num);
- slabhash_remove(table, myhash(num), key);
- ref[num] = NULL;
- delkey(key);
-}
-
-/** test adding a random element */
-static void
-testlookup(struct slabhash* table, testdata_type* ref[])
-{
- int num = random() % HASHTESTMAX;
- testkey_type* key = newkey(num);
- struct lruhash_entry* en = slabhash_lookup(table, myhash(num), key, 0);
- testdata_type* data = en? (testdata_type*)en->data : NULL;
- if(en) {
- unit_assert(en->key);
- unit_assert(en->data);
- }
- if(0) log_info("lookup %d got %d, expect %d", num, en? data->data :-1,
- ref[num]? ref[num]->data : -1);
- unit_assert( data == ref[num] );
- if(en) { lock_rw_unlock(&en->lock); }
- delkey(key);
-}
-
-/** check integrity of hash table */
-static void
-check_lru_table(struct lruhash* table)
-{
- struct lruhash_entry* p;
- size_t c = 0;
- lock_quick_lock(&table->lock);
- unit_assert( table->num <= table->size);
- unit_assert( table->size_mask == (int)table->size-1 );
- unit_assert( (table->lru_start && table->lru_end) ||
- (!table->lru_start && !table->lru_end) );
- unit_assert( table->space_used <= table->space_max );
- /* check lru list integrity */
- if(table->lru_start)
- unit_assert(table->lru_start->lru_prev == NULL);
- if(table->lru_end)
- unit_assert(table->lru_end->lru_next == NULL);
- p = table->lru_start;
- while(p) {
- if(p->lru_prev) {
- unit_assert(p->lru_prev->lru_next == p);
- }
- if(p->lru_next) {
- unit_assert(p->lru_next->lru_prev == p);
- }
- c++;
- p = p->lru_next;
- }
- unit_assert(c == table->num);
-
- /* this assertion is specific to the unit test */
- unit_assert( table->space_used ==
- table->num * test_slabhash_sizefunc(NULL, NULL) );
- lock_quick_unlock(&table->lock);
-}
-
-/** check integrity of hash table */
-static void
-check_table(struct slabhash* table)
-{
- size_t i;
- for(i=0; i<table->size; i++)
- check_lru_table(table->array[i]);
-}
-
-/** test adding a random element (unlimited range) */
-static void
-testadd_unlim(struct slabhash* table, testdata_type** ref)
-{
- int numtoadd = random() % (HASHTESTMAX * 10);
- testdata_type* data = newdata(numtoadd);
- testkey_type* key = newkey(numtoadd);
- key->entry.data = data;
- slabhash_insert(table, myhash(numtoadd), &key->entry, data, NULL);
- if(ref)
- ref[numtoadd] = data;
-}
-
-/** test adding a random element (unlimited range) */
-static void
-testremove_unlim(struct slabhash* table, testdata_type** ref)
-{
- int num = random() % (HASHTESTMAX*10);
- testkey_type* key = newkey(num);
- slabhash_remove(table, myhash(num), key);
- if(ref)
- ref[num] = NULL;
- delkey(key);
-}
-
-/** test adding a random element (unlimited range) */
-static void
-testlookup_unlim(struct slabhash* table, testdata_type** ref)
-{
- int num = random() % (HASHTESTMAX*10);
- testkey_type* key = newkey(num);
- struct lruhash_entry* en = slabhash_lookup(table, myhash(num), key, 0);
- testdata_type* data = en? (testdata_type*)en->data : NULL;
- if(en) {
- unit_assert(en->key);
- unit_assert(en->data);
- }
- if(0 && ref) log_info("lookup unlim %d got %d, expect %d", num, en ?
- data->data :-1, ref[num] ? ref[num]->data : -1);
- if(data && ref) {
- /* its okay for !data, it fell off the lru */
- unit_assert( data == ref[num] );
- }
- if(en) { lock_rw_unlock(&en->lock); }
- delkey(key);
-}
-
-/** test with long sequence of adds, removes and updates, and lookups */
-static void
-test_long_table(struct slabhash* table)
-{
- /* assuming it all fits in the hashtable, this check will work */
- testdata_type* ref[HASHTESTMAX * 100];
- size_t i;
- memset(ref, 0, sizeof(ref));
- /* test assumption */
- if(0) slabhash_status(table, "unit test", 1);
- srandom(48);
- for(i=0; i<1000; i++) {
- /* what to do? */
- if(i == 500) {
- slabhash_clear(table);
- memset(ref, 0, sizeof(ref));
- continue;
- }
- switch(random() % 4) {
- case 0:
- case 3:
- testadd(table, ref);
- break;
- case 1:
- testremove(table, ref);
- break;
- case 2:
- testlookup(table, ref);
- break;
- default:
- unit_assert(0);
- }
- if(0) slabhash_status(table, "unit test", 1);
- check_table(table);
- }
-
- /* test more, but 'ref' assumption does not hold anymore */
- for(i=0; i<1000; i++) {
- /* what to do? */
- switch(random() % 4) {
- case 0:
- case 3:
- testadd_unlim(table, ref);
- break;
- case 1:
- testremove_unlim(table, ref);
- break;
- case 2:
- testlookup_unlim(table, ref);
- break;
- default:
- unit_assert(0);
- }
- if(0) slabhash_status(table, "unlim", 1);
- check_table(table);
- }
-}
-
-/** structure to threaded test the lru hash table */
-struct slab_test_thr {
- /** thread num, first entry. */
- int num;
- /** id */
- ub_thread_type id;
- /** hash table */
- struct slabhash* table;
-};
-
-/** main routine for threaded hash table test */
-static void*
-test_thr_main(void* arg)
-{
- struct slab_test_thr* t = (struct slab_test_thr*)arg;
- int i;
- log_thread_set(&t->num);
- for(i=0; i<1000; i++) {
- switch(random() % 4) {
- case 0:
- case 3:
- testadd_unlim(t->table, NULL);
- break;
- case 1:
- testremove_unlim(t->table, NULL);
- break;
- case 2:
- testlookup_unlim(t->table, NULL);
- break;
- default:
- unit_assert(0);
- }
- if(0) slabhash_status(t->table, "hashtest", 1);
- if(i % 100 == 0) /* because of locking, not all the time */
- check_table(t->table);
- }
- check_table(t->table);
- return NULL;
-}
-
-/** test hash table access by multiple threads */
-static void
-test_threaded_table(struct slabhash* table)
-{
- int numth = 10;
- struct slab_test_thr t[100];
- int i;
-
- for(i=1; i<numth; i++) {
- t[i].num = i;
- t[i].table = table;
- ub_thread_create(&t[i].id, test_thr_main, &t[i]);
- }
-
- for(i=1; i<numth; i++) {
- ub_thread_join(t[i].id);
- }
- if(0) slabhash_status(table, "hashtest", 1);
-}
-
-void slabhash_test(void)
-{
- /* start very very small array, so it can do lots of table_grow() */
- /* also small in size so that reclaim has to be done quickly. */
- struct slabhash* table;
- unit_show_feature("slabhash");
- table = slabhash_create(4, 2, 10400,
- test_slabhash_sizefunc, test_slabhash_compfunc,
- test_slabhash_delkey, test_slabhash_deldata, NULL);
- test_short_table(table);
- test_long_table(table);
- slabhash_delete(table);
- table = slabhash_create(4, 2, 10400,
- test_slabhash_sizefunc, test_slabhash_compfunc,
- test_slabhash_delkey, test_slabhash_deldata, NULL);
- test_threaded_table(table);
- slabhash_delete(table);
-}
diff --git a/external/unbound/testcode/unitverify.c b/external/unbound/testcode/unitverify.c
deleted file mode 100644
index 37994a377..000000000
--- a/external/unbound/testcode/unitverify.c
+++ /dev/null
@@ -1,545 +0,0 @@
-/*
- * testcode/unitverify.c - unit test for signature verification 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 COPYRIGHT
- * HOLDER 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 verification unit tests. Exits with code 1 on a failure.
- */
-
-#include "config.h"
-#include "util/log.h"
-#include "testcode/unitmain.h"
-#include "validator/val_sigcrypt.h"
-#include "validator/val_secalgo.h"
-#include "validator/val_nsec.h"
-#include "validator/val_nsec3.h"
-#include "validator/validator.h"
-#include "testcode/testpkts.h"
-#include "util/data/msgreply.h"
-#include "util/data/msgparse.h"
-#include "util/data/dname.h"
-#include "util/regional.h"
-#include "util/alloc.h"
-#include "util/rbtree.h"
-#include "util/net_help.h"
-#include "util/module.h"
-#include "util/config_file.h"
-#include "sldns/sbuffer.h"
-#include "sldns/keyraw.h"
-#include "sldns/str2wire.h"
-#include "sldns/wire2str.h"
-
-/** verbose signature test */
-static int vsig = 0;
-
-/** entry to packet buffer with wireformat */
-static void
-entry_to_buf(struct entry* e, sldns_buffer* pkt)
-{
- unit_assert(e->reply_list);
- if(e->reply_list->reply_from_hex) {
- sldns_buffer_copy(pkt, e->reply_list->reply_from_hex);
- } else {
- sldns_buffer_clear(pkt);
- sldns_buffer_write(pkt, e->reply_list->reply_pkt,
- e->reply_list->reply_len);
- sldns_buffer_flip(pkt);
- }
-}
-
-/** entry to reply info conversion */
-static void
-entry_to_repinfo(struct entry* e, struct alloc_cache* alloc,
- struct regional* region, sldns_buffer* pkt, struct query_info* qi,
- struct reply_info** rep)
-{
- int ret;
- struct edns_data edns;
- entry_to_buf(e, pkt);
- /* lock alloc lock to please lock checking software.
- * alloc_special_obtain assumes it is talking to a ub-alloc,
- * and does not need to perform locking. Here the alloc is
- * the only one, so we lock it here */
- lock_quick_lock(&alloc->lock);
- ret = reply_info_parse(pkt, alloc, qi, rep, region, &edns);
- lock_quick_unlock(&alloc->lock);
- if(ret != 0) {
- char rcode[16];
- sldns_wire2str_rcode_buf(ret, rcode, sizeof(rcode));
- printf("parse code %d: %s\n", ret, rcode);
- unit_assert(ret != 0);
- }
-}
-
-/** extract DNSKEY rrset from answer and convert it */
-static struct ub_packed_rrset_key*
-extract_keys(struct entry* e, struct alloc_cache* alloc,
- struct regional* region, sldns_buffer* pkt)
-{
- struct ub_packed_rrset_key* dnskey = NULL;
- struct query_info qinfo;
- struct reply_info* rep = NULL;
- size_t i;
-
- entry_to_repinfo(e, alloc, region, pkt, &qinfo, &rep);
- for(i=0; i<rep->an_numrrsets; i++) {
- if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_DNSKEY) {
- dnskey = rep->rrsets[i];
- rep->rrsets[i] = NULL;
- break;
- }
- }
- unit_assert(dnskey);
-
- reply_info_parsedelete(rep, alloc);
- query_info_clear(&qinfo);
- return dnskey;
-}
-
-/** return true if answer should be bogus */
-static int
-should_be_bogus(struct ub_packed_rrset_key* rrset, struct query_info* qinfo)
-{
- struct packed_rrset_data* d = (struct packed_rrset_data*)rrset->
- entry.data;
- if(d->rrsig_count == 0)
- return 1;
- /* name 'bogus' as first label signals bogus */
- if(rrset->rk.dname_len > 6 && memcmp(rrset->rk.dname+1, "bogus", 5)==0)
- return 1;
- if(qinfo->qname_len > 6 && memcmp(qinfo->qname+1, "bogus", 5)==0)
- return 1;
- return 0;
-}
-
-/** return number of rrs in an rrset */
-static size_t
-rrset_get_count(struct ub_packed_rrset_key* rrset)
-{
- struct packed_rrset_data* d = (struct packed_rrset_data*)
- rrset->entry.data;
- if(!d) return 0;
- return d->count;
-}
-
-/** setup sig alg list from dnskey */
-static void
-setup_sigalg(struct ub_packed_rrset_key* dnskey, uint8_t* sigalg)
-{
- uint8_t a[ALGO_NEEDS_MAX];
- size_t i, n = 0;
- memset(a, 0, sizeof(a));
- for(i=0; i<rrset_get_count(dnskey); i++) {
- uint8_t algo = (uint8_t)dnskey_get_algo(dnskey, i);
- if(a[algo] == 0) {
- a[algo] = 1;
- sigalg[n++] = algo;
- }
- }
- sigalg[n] = 0;
-}
-
-/** verify and test one rrset against the key rrset */
-static void
-verifytest_rrset(struct module_env* env, struct val_env* ve,
- struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey,
- struct query_info* qinfo)
-{
- enum sec_status sec;
- char* reason = NULL;
- uint8_t sigalg[ALGO_NEEDS_MAX+1];
- if(vsig) {
- log_nametypeclass(VERB_QUERY, "verify of rrset",
- rrset->rk.dname, ntohs(rrset->rk.type),
- ntohs(rrset->rk.rrset_class));
- }
- setup_sigalg(dnskey, sigalg); /* check all algorithms in the dnskey */
- sec = dnskeyset_verify_rrset(env, ve, rrset, dnskey, sigalg, &reason);
- if(vsig) {
- printf("verify outcome is: %s %s\n", sec_status_to_string(sec),
- reason?reason:"");
- }
- if(should_be_bogus(rrset, qinfo)) {
- unit_assert(sec == sec_status_bogus);
- } else {
- unit_assert(sec == sec_status_secure);
- }
-}
-
-/** verify and test an entry - every rr in the message */
-static void
-verifytest_entry(struct entry* e, struct alloc_cache* alloc,
- struct regional* region, sldns_buffer* pkt,
- struct ub_packed_rrset_key* dnskey, struct module_env* env,
- struct val_env* ve)
-{
- struct query_info qinfo;
- struct reply_info* rep = NULL;
- size_t i;
-
- regional_free_all(region);
- if(vsig) {
- char* s = sldns_wire2str_pkt(e->reply_list->reply_pkt,
- e->reply_list->reply_len);
- printf("verifying pkt:\n%s\n", s?s:"outofmemory");
- free(s);
- }
- entry_to_repinfo(e, alloc, region, pkt, &qinfo, &rep);
-
- for(i=0; i<rep->rrset_count; i++) {
- verifytest_rrset(env, ve, rep->rrsets[i], dnskey, &qinfo);
- }
-
- reply_info_parsedelete(rep, alloc);
- query_info_clear(&qinfo);
-}
-
-/** find RRset in reply by type */
-static struct ub_packed_rrset_key*
-find_rrset_type(struct reply_info* rep, uint16_t type)
-{
- size_t i;
- for(i=0; i<rep->rrset_count; i++) {
- if(ntohs(rep->rrsets[i]->rk.type) == type)
- return rep->rrsets[i];
- }
- return NULL;
-}
-
-/** DS sig test an entry - get DNSKEY and DS in entry and verify */
-static void
-dstest_entry(struct entry* e, struct alloc_cache* alloc,
- struct regional* region, sldns_buffer* pkt, struct module_env* env)
-{
- struct query_info qinfo;
- struct reply_info* rep = NULL;
- struct ub_packed_rrset_key* ds, *dnskey;
- int ret;
-
- regional_free_all(region);
- if(vsig) {
- char* s = sldns_wire2str_pkt(e->reply_list->reply_pkt,
- e->reply_list->reply_len);
- printf("verifying DS-DNSKEY match:\n%s\n", s?s:"outofmemory");
- free(s);
- }
- entry_to_repinfo(e, alloc, region, pkt, &qinfo, &rep);
- ds = find_rrset_type(rep, LDNS_RR_TYPE_DS);
- dnskey = find_rrset_type(rep, LDNS_RR_TYPE_DNSKEY);
- /* check test is OK */
- unit_assert(ds && dnskey);
-
- ret = ds_digest_match_dnskey(env, dnskey, 0, ds, 0);
- if(strncmp((char*)qinfo.qname, "\003yes", 4) == 0) {
- if(vsig) {
- printf("result(yes)= %s\n", ret?"yes":"no");
- }
- unit_assert(ret);
- } else if (strncmp((char*)qinfo.qname, "\002no", 3) == 0) {
- if(vsig) {
- printf("result(no)= %s\n", ret?"yes":"no");
- }
- unit_assert(!ret);
- verbose(VERB_QUERY, "DS fail: OK; matched unit test");
- } else {
- fatal_exit("Bad qname in DS unit test, yes or no");
- }
-
- reply_info_parsedelete(rep, alloc);
- query_info_clear(&qinfo);
-}
-
-/** verify from a file */
-static void
-verifytest_file(const char* fname, const char* at_date)
-{
- /*
- * The file contains a list of ldns-testpkts entries.
- * The first entry must be a query for DNSKEY.
- * The answer rrset is the keyset that will be used for verification
- */
- struct ub_packed_rrset_key* dnskey;
- struct regional* region = regional_create();
- struct alloc_cache alloc;
- sldns_buffer* buf = sldns_buffer_new(65535);
- struct entry* e;
- struct entry* list = read_datafile(fname, 1);
- struct module_env env;
- struct val_env ve;
- time_t now = time(NULL);
-
- if(!list)
- fatal_exit("could not read %s: %s", fname, strerror(errno));
- alloc_init(&alloc, NULL, 1);
- memset(&env, 0, sizeof(env));
- memset(&ve, 0, sizeof(ve));
- env.scratch = region;
- env.scratch_buffer = buf;
- env.now = &now;
- ve.date_override = cfg_convert_timeval(at_date);
- unit_assert(region && buf);
- dnskey = extract_keys(list, &alloc, region, buf);
- if(vsig) log_nametypeclass(VERB_QUERY, "test dnskey",
- dnskey->rk.dname, ntohs(dnskey->rk.type),
- ntohs(dnskey->rk.rrset_class));
- /* ready to go! */
- for(e = list->next; e; e = e->next) {
- verifytest_entry(e, &alloc, region, buf, dnskey, &env, &ve);
- }
-
- ub_packed_rrset_parsedelete(dnskey, &alloc);
- delete_entry(list);
- regional_destroy(region);
- alloc_clear(&alloc);
- sldns_buffer_free(buf);
-}
-
-/** verify DS matches DNSKEY from a file */
-static void
-dstest_file(const char* fname)
-{
- /*
- * The file contains a list of ldns-testpkts entries.
- * The first entry must be a query for DNSKEY.
- * The answer rrset is the keyset that will be used for verification
- */
- struct regional* region = regional_create();
- struct alloc_cache alloc;
- sldns_buffer* buf = sldns_buffer_new(65535);
- struct entry* e;
- struct entry* list = read_datafile(fname, 1);
- struct module_env env;
-
- if(!list)
- fatal_exit("could not read %s: %s", fname, strerror(errno));
- alloc_init(&alloc, NULL, 1);
- memset(&env, 0, sizeof(env));
- env.scratch = region;
- env.scratch_buffer = buf;
- unit_assert(region && buf);
-
- /* ready to go! */
- for(e = list; e; e = e->next) {
- dstest_entry(e, &alloc, region, buf, &env);
- }
-
- delete_entry(list);
- regional_destroy(region);
- alloc_clear(&alloc);
- sldns_buffer_free(buf);
-}
-
-/** helper for unittest of NSEC routines */
-static int
-unitest_nsec_has_type_rdata(char* bitmap, size_t len, uint16_t type)
-{
- return nsecbitmap_has_type_rdata((uint8_t*)bitmap, len, type);
-}
-
-/** Test NSEC type bitmap routine */
-static void
-nsectest(void)
-{
- /* bitmap starts at type bitmap rdata field */
- /* from rfc 4034 example */
- char* bitmap = "\000\006\100\001\000\000\000\003"
- "\004\033\000\000\000\000\000\000"
- "\000\000\000\000\000\000\000\000"
- "\000\000\000\000\000\000\000\000"
- "\000\000\000\000\040";
- size_t len = 37;
-
- unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 0));
- unit_assert(unitest_nsec_has_type_rdata(bitmap, len, LDNS_RR_TYPE_A));
- unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 2));
- unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 3));
- unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 4));
- unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 5));
- unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 6));
- unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 7));
- unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 8));
- unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 9));
- unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 10));
- unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 11));
- unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 12));
- unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 13));
- unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 14));
- unit_assert(unitest_nsec_has_type_rdata(bitmap, len, LDNS_RR_TYPE_MX));
- unit_assert(unitest_nsec_has_type_rdata(bitmap, len, LDNS_RR_TYPE_RRSIG));
- unit_assert(unitest_nsec_has_type_rdata(bitmap, len, LDNS_RR_TYPE_NSEC));
- unit_assert(unitest_nsec_has_type_rdata(bitmap, len, 1234));
- unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1233));
- unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1235));
- unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1236));
- unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1237));
- unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1238));
- unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1239));
- unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1240));
- unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 2230));
-}
-
-/** Test hash algo - NSEC3 hash it and compare result */
-static void
-nsec3_hash_test_entry(struct entry* e, rbtree_type* ct,
- struct alloc_cache* alloc, struct regional* region,
- sldns_buffer* buf)
-{
- struct query_info qinfo;
- struct reply_info* rep = NULL;
- struct ub_packed_rrset_key* answer, *nsec3;
- struct nsec3_cached_hash* hash = NULL;
- int ret;
- uint8_t* qname;
-
- if(vsig) {
- char* s = sldns_wire2str_pkt(e->reply_list->reply_pkt,
- e->reply_list->reply_len);
- printf("verifying NSEC3 hash:\n%s\n", s?s:"outofmemory");
- free(s);
- }
- entry_to_repinfo(e, alloc, region, buf, &qinfo, &rep);
- nsec3 = find_rrset_type(rep, LDNS_RR_TYPE_NSEC3);
- answer = find_rrset_type(rep, LDNS_RR_TYPE_AAAA);
- qname = regional_alloc_init(region, qinfo.qname, qinfo.qname_len);
- /* check test is OK */
- unit_assert(nsec3 && answer && qname);
-
- ret = nsec3_hash_name(ct, region, buf, nsec3, 0, qname,
- qinfo.qname_len, &hash);
- if(ret != 1) {
- printf("Bad nsec3_hash_name retcode %d\n", ret);
- unit_assert(ret == 1);
- }
- unit_assert(hash->dname && hash->hash && hash->hash_len &&
- hash->b32 && hash->b32_len);
- unit_assert(hash->b32_len == (size_t)answer->rk.dname[0]);
- /* does not do lowercasing. */
- unit_assert(memcmp(hash->b32, answer->rk.dname+1, hash->b32_len)
- == 0);
-
- reply_info_parsedelete(rep, alloc);
- query_info_clear(&qinfo);
-}
-
-
-/** Read file to test NSEC3 hash algo */
-static void
-nsec3_hash_test(const char* fname)
-{
- /*
- * The list contains a list of ldns-testpkts entries.
- * Every entry is a test.
- * The qname is hashed.
- * The answer section AAAA RR name is the required result.
- * The auth section NSEC3 is used to get hash parameters.
- * The hash cache is maintained per file.
- *
- * The test does not perform canonicalization during the compare.
- */
- rbtree_type ct;
- struct regional* region = regional_create();
- struct alloc_cache alloc;
- sldns_buffer* buf = sldns_buffer_new(65535);
- struct entry* e;
- struct entry* list = read_datafile(fname, 1);
-
- if(!list)
- fatal_exit("could not read %s: %s", fname, strerror(errno));
- rbtree_init(&ct, &nsec3_hash_cmp);
- alloc_init(&alloc, NULL, 1);
- unit_assert(region && buf);
-
- /* ready to go! */
- for(e = list; e; e = e->next) {
- nsec3_hash_test_entry(e, &ct, &alloc, region, buf);
- }
-
- delete_entry(list);
- regional_destroy(region);
- alloc_clear(&alloc);
- sldns_buffer_free(buf);
-}
-
-void
-verify_test(void)
-{
- unit_show_feature("signature verify");
-#ifdef USE_SHA1
- verifytest_file("testdata/test_signatures.1", "20070818005004");
-#endif
-#if defined(USE_DSA) && defined(USE_SHA1)
- verifytest_file("testdata/test_signatures.2", "20080414005004");
- verifytest_file("testdata/test_signatures.3", "20080416005004");
- verifytest_file("testdata/test_signatures.4", "20080416005004");
- verifytest_file("testdata/test_signatures.5", "20080416005004");
- verifytest_file("testdata/test_signatures.6", "20080416005004");
- verifytest_file("testdata/test_signatures.7", "20070829144150");
-#endif /* USE_DSA */
-#ifdef USE_SHA1
- verifytest_file("testdata/test_signatures.8", "20070829144150");
-#endif
-#if (defined(HAVE_EVP_SHA256) || defined(HAVE_NSS) || defined(HAVE_NETTLE)) && defined(USE_SHA2)
- verifytest_file("testdata/test_sigs.rsasha256", "20070829144150");
-# ifdef USE_SHA1
- verifytest_file("testdata/test_sigs.sha1_and_256", "20070829144150");
-# endif
- verifytest_file("testdata/test_sigs.rsasha256_draft", "20090101000000");
-#endif
-#if (defined(HAVE_EVP_SHA512) || defined(HAVE_NSS) || defined(HAVE_NETTLE)) && defined(USE_SHA2)
- verifytest_file("testdata/test_sigs.rsasha512_draft", "20070829144150");
-#endif
-#ifdef USE_SHA1
- verifytest_file("testdata/test_sigs.hinfo", "20090107100022");
- verifytest_file("testdata/test_sigs.revoked", "20080414005004");
-#endif
-#ifdef USE_GOST
- if(sldns_key_EVP_load_gost_id())
- verifytest_file("testdata/test_sigs.gost", "20090807060504");
- else printf("Warning: skipped GOST, openssl does not provide gost.\n");
-#endif
-#ifdef USE_ECDSA
- /* test for support in case we use libNSS and ECC is removed */
- if(dnskey_algo_id_is_supported(LDNS_ECDSAP256SHA256)) {
- verifytest_file("testdata/test_sigs.ecdsa_p256", "20100908100439");
- verifytest_file("testdata/test_sigs.ecdsa_p384", "20100908100439");
- }
- dstest_file("testdata/test_ds.sha384");
-#endif
-#ifdef USE_SHA1
- dstest_file("testdata/test_ds.sha1");
-#endif
- nsectest();
- nsec3_hash_test("testdata/test_nsec3_hash.1");
-}