diff options
Diffstat (limited to 'external/unbound/testcode/asynclook.c')
-rw-r--r-- | external/unbound/testcode/asynclook.c | 528 |
1 files changed, 0 insertions, 528 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; -} |