Example #1
0
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);
}
Example #2
0
/**
 * 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_t* 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);
}
Example #3
0
/**
 * 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_t* 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);
}
Example #4
0
/** 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);
}
Example #5
0
void 
outside_network_delete(struct outside_network* outnet)
{
	if(!outnet)
		return;
	sldns_buffer_free(outnet->udp_buff);
	free(outnet);
}
Example #6
0
void 
listen_delete(struct listen_dnsport* listen)
{
	if(!listen)
		return;
	sldns_buffer_free(listen->udp_buff);
	free(listen);
}
Example #7
0
void 
listen_delete(struct listen_dnsport* front)
{
	if(!front) 
		return;
	listen_list_delete(front->cps);
	sldns_buffer_free(front->udp_buff);
	free(front);
}
Example #8
0
/** 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");
}
Example #9
0
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);
	}
}
Example #10
0
/** 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);
}
Example #11
0
void msgparse_test(void)
{
	sldns_buffer* pkt = sldns_buffer_new(65553);
	sldns_buffer* out = sldns_buffer_new(65553);
	struct alloc_cache super_a, alloc;
	/* 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);
}
Example #12
0
/** 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);
}
Example #13
0
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);
}
Example #14
0
/** 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;
}
Example #15
0
/** 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);
}
Example #16
0
/** delete libworker env */
static void
libworker_delete_env(struct libworker* w)
{
	if(w->env) {
		outside_network_quit_prepare(w->back);
		mesh_delete(w->env->mesh);
		context_release_alloc(w->ctx, w->env->alloc, 
			!w->is_bg || w->is_bg_thread);
		sldns_buffer_free(w->env->scratch_buffer);
		regional_destroy(w->env->scratch);
		forwards_delete(w->env->fwds);
		hints_delete(w->env->hints);
		ub_randfree(w->env->rnd);
		free(w->env);
	}
#ifdef HAVE_SSL
	SSL_CTX_free(w->sslctx);
#endif
	outside_network_delete(w->back);
}
Example #17
0
void 
log_dns_msg(const char* str, struct query_info* qinfo, struct reply_info* rep)
{
	/* not particularly fast but flexible, make wireformat and print */
	sldns_buffer* buf = sldns_buffer_new(65535);
	struct regional* region = regional_create();
	if(!reply_info_encode(qinfo, rep, 0, rep->flags, buf, 0, 
		region, 65535, 1)) {
		log_info("%s: log_dns_msg: out of memory", str);
	} else {
		char* s = sldns_wire2str_pkt(sldns_buffer_begin(buf),
			sldns_buffer_limit(buf));
		if(!s) {
			log_info("%s: log_dns_msg: ldns tostr failed", str);
		} else {
			log_info("%s %s", str, s);
		}
		free(s);
	}
	sldns_buffer_free(buf);
	regional_destroy(region);
}
Example #18
0
/** 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);
}
Example #19
0
void outnet_serviced_query_stop(struct serviced_query* sq, void* cb_arg)
{
	struct fake_pending* pend = (struct fake_pending*)sq;
	struct replay_runtime* runtime = pend->runtime;
	/* delete from the list */
	struct fake_pending* p = runtime->pending_list, *prev=NULL;
	while(p) {
		if(p == pend) {
			log_assert(p->cb_arg == cb_arg);
			log_info("serviced pending delete");
			if(prev)
				prev->next = p->next;
			else 	runtime->pending_list = p->next;
			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");
}
Example #20
0
/** process answer from bg worker */
static int
process_answer_detail(struct ub_ctx* ctx, uint8_t* msg, uint32_t len,
	ub_callback_t* cb, void** cbarg, int* err,
	struct ub_result** res)
{
	struct ctx_query* q;
	if(context_serial_getcmd(msg, len) != UB_LIBCMD_ANSWER) {
		log_err("error: bad data from bg worker %d",
			(int)context_serial_getcmd(msg, len));
		return 0;
	}

	lock_basic_lock(&ctx->cfglock);
	q = context_deserialize_answer(ctx, msg, len, err);
	if(!q) {
		lock_basic_unlock(&ctx->cfglock);
		/* probably simply the lookup that failed, i.e.
		 * response returned before cancel was sent out, so noerror */
		return 1;
	}
	log_assert(q->async);

	/* grab cb while locked */
	if(q->cancelled) {
		*cb = NULL;
		*cbarg = NULL;
	} else {
		*cb = q->cb;
		*cbarg = q->cb_arg;
	}
	if(*err) {
		*res = NULL;
		ub_resolve_free(q->res);
	} else {
		/* parse the message, extract rcode, fill result */
		sldns_buffer* buf = sldns_buffer_new(q->msg_len);
		struct regional* region = regional_create();
		*res = q->res;
		(*res)->rcode = LDNS_RCODE_SERVFAIL;
		if(region && buf) {
			sldns_buffer_clear(buf);
			sldns_buffer_write(buf, q->msg, q->msg_len);
			sldns_buffer_flip(buf);
			libworker_enter_result(*res, buf, region,
				q->msg_security);
		}
		(*res)->answer_packet = q->msg;
		(*res)->answer_len = (int)q->msg_len;
		q->msg = NULL;
		sldns_buffer_free(buf);
		regional_destroy(region);
	}
	q->res = NULL;
	/* delete the q from list */
	(void)rbtree_delete(&ctx->queries, q->node.key);
	ctx->num_async--;
	context_query_delete(q);
	lock_basic_unlock(&ctx->cfglock);

	if(*cb) return 2;
	ub_resolve_free(*res);
	return 1;
}
Example #21
0
/** 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;
}
Example #22
0
/** 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 + random()%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 + random()%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);
}
Example #23
0
int 
anchors_apply_cfg(struct val_anchors* anchors, struct config_file* cfg)
{
	struct config_strlist* f;
	char* nm;
	sldns_buffer* parsebuf = sldns_buffer_new(65535);
	for(f = cfg->domain_insecure; f; f = f->next) {
		if(!f->str || f->str[0] == 0) /* empty "" */
			continue;
		if(!anchor_insert_insecure(anchors, f->str)) {
			log_err("error in domain-insecure: %s", f->str);
			sldns_buffer_free(parsebuf);
			return 0;
		}
	}
	for(f = cfg->trust_anchor_file_list; f; f = f->next) {
		if(!f->str || f->str[0] == 0) /* empty "" */
			continue;
		nm = f->str;
		if(cfg->chrootdir && cfg->chrootdir[0] && strncmp(nm,
			cfg->chrootdir, strlen(cfg->chrootdir)) == 0)
			nm += strlen(cfg->chrootdir);
		if(!anchor_read_file(anchors, parsebuf, nm, 0)) {
			log_err("error reading trust-anchor-file: %s", f->str);
			sldns_buffer_free(parsebuf);
			return 0;
		}
	}
	for(f = cfg->trusted_keys_file_list; f; f = f->next) {
		if(!f->str || f->str[0] == 0) /* empty "" */
			continue;
		nm = f->str;
		if(cfg->chrootdir && cfg->chrootdir[0] && strncmp(nm,
			cfg->chrootdir, strlen(cfg->chrootdir)) == 0)
			nm += strlen(cfg->chrootdir);
		if(!anchor_read_bind_file_wild(anchors, parsebuf, nm)) {
			log_err("error reading trusted-keys-file: %s", f->str);
			sldns_buffer_free(parsebuf);
			return 0;
		}
	}
	for(f = cfg->trust_anchor_list; f; f = f->next) {
		if(!f->str || f->str[0] == 0) /* empty "" */
			continue;
		if(!anchor_store_str(anchors, parsebuf, f->str)) {
			log_err("error in trust-anchor: \"%s\"", f->str);
			sldns_buffer_free(parsebuf);
			return 0;
		}
	}
	if(cfg->dlv_anchor_file && cfg->dlv_anchor_file[0] != 0) {
		struct trust_anchor* dlva;
		nm = cfg->dlv_anchor_file;
		if(cfg->chrootdir && cfg->chrootdir[0] && strncmp(nm,
			cfg->chrootdir, strlen(cfg->chrootdir)) == 0)
			nm += strlen(cfg->chrootdir);
		if(!(dlva = anchor_read_file(anchors, parsebuf,
			nm, 1))) {
			log_err("error reading dlv-anchor-file: %s", 
				cfg->dlv_anchor_file);
			sldns_buffer_free(parsebuf);
			return 0;
		}
		lock_basic_lock(&anchors->lock);
		anchors->dlv_anchor = dlva;
		lock_basic_unlock(&anchors->lock);
	}
	for(f = cfg->dlv_anchor_list; f; f = f->next) {
		struct trust_anchor* dlva;
		if(!f->str || f->str[0] == 0) /* empty "" */
			continue;
		if(!(dlva = anchor_store_str(
			anchors, parsebuf, f->str))) {
			log_err("error in dlv-anchor: \"%s\"", f->str);
			sldns_buffer_free(parsebuf);
			return 0;
		}
		lock_basic_lock(&anchors->lock);
		anchors->dlv_anchor = dlva;
		lock_basic_unlock(&anchors->lock);
	}
	/* do autr last, so that it sees what anchors are filled by other
	 * means can can print errors about double config for the name */
	for(f = cfg->auto_trust_anchor_file_list; f; f = f->next) {
		if(!f->str || f->str[0] == 0) /* empty "" */
			continue;
		nm = f->str;
		if(cfg->chrootdir && cfg->chrootdir[0] && strncmp(nm,
			cfg->chrootdir, strlen(cfg->chrootdir)) == 0)
			nm += strlen(cfg->chrootdir);
		if(!autr_read_file(anchors, nm)) {
			log_err("error reading auto-trust-anchor-file: %s", 
				f->str);
			sldns_buffer_free(parsebuf);
			return 0;
		}
	}
	/* first assemble, since it may delete useless anchors */
	anchors_assemble_rrsets(anchors);
	init_parents(anchors);
	sldns_buffer_free(parsebuf);
	if(verbosity >= VERB_ALGO) autr_debug_print(anchors);
	return 1;
}