Пример #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);
}
Пример #2
0
/**
 * 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));
}
Пример #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);
}
Пример #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);
}
Пример #5
0
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),
	void (*unwanted_action)(void*), void* ATTR_UNUSED(unwanted_param),
	int ATTR_UNUSED(do_udp), void* ATTR_UNUSED(sslctx),
	int ATTR_UNUSED(delayclose))
{
	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;
}
Пример #6
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);
}
Пример #7
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");
}
Пример #8
0
struct listen_dnsport* 
listen_create(struct comm_base* base, struct listen_port* ports,
	size_t bufsize, int tcp_accept_count, void* sslctx,
	struct dt_env* dtenv, comm_point_callback_t* cb, void *cb_arg)
{
	struct listen_dnsport* front = (struct listen_dnsport*)
		malloc(sizeof(struct listen_dnsport));
	if(!front)
		return NULL;
	front->cps = NULL;
	front->udp_buff = sldns_buffer_new(bufsize);
	if(!front->udp_buff) {
		free(front);
		return NULL;
	}

	/* create comm points as needed */
	while(ports) {
		struct comm_point* cp = NULL;
		if(ports->ftype == listen_type_udp) 
			cp = comm_point_create_udp(base, ports->fd, 
				front->udp_buff, cb, cb_arg);
		else if(ports->ftype == listen_type_tcp)
			cp = comm_point_create_tcp(base, ports->fd, 
				tcp_accept_count, bufsize, cb, cb_arg);
		else if(ports->ftype == listen_type_ssl) {
			cp = comm_point_create_tcp(base, ports->fd, 
				tcp_accept_count, bufsize, cb, cb_arg);
			cp->ssl = sslctx;
		} else if(ports->ftype == listen_type_udpancil) 
			cp = comm_point_create_udp_ancil(base, ports->fd, 
				front->udp_buff, cb, cb_arg);
		if(!cp) {
			log_err("can't create commpoint");	
			listen_delete(front);
			return NULL;
		}
		cp->dtenv = dtenv;
		cp->do_not_close = 1;
		if(!listen_cp_insert(cp, front)) {
			log_err("malloc failed");
			comm_point_delete(cp);
			listen_delete(front);
			return NULL;
		}
		ports = ports->next;
	}
	if(!front->cps) {
		log_err("Could not open sockets to accept queries.");
		listen_delete(front);
		return NULL;
	}

	return front;
}
Пример #9
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);
}
Пример #10
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);
}
Пример #11
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;
}
Пример #12
0
struct waiting_tcp* 
pending_tcp_query(struct outside_network* outnet, sldns_buffer* packet,
	struct sockaddr_storage* addr, socklen_t addrlen, int timeout,
	comm_point_callback_t* callback, void* callback_arg,
	int ATTR_UNUSED(ssl_upstream))
{
	struct replay_runtime* runtime = (struct replay_runtime*)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, addr, addrlen);
	pend->addrlen = 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;
}
Пример #13
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);
}
Пример #14
0
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), comm_point_callback_t* 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;
}
Пример #15
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);
}
Пример #16
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);
}
Пример #17
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;
}
Пример #18
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);
}
Пример #19
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;
}
Пример #20
0
/** setup fresh libworker struct */
static struct libworker*
libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb)
{
	unsigned int seed;
	struct libworker* w = (struct libworker*)calloc(1, sizeof(*w));
	struct config_file* cfg = ctx->env->cfg;
	int* ports;
	int numports;
	if(!w) return NULL;
	w->is_bg = is_bg;
	w->ctx = ctx;
	w->env = (struct module_env*)malloc(sizeof(*w->env));
	if(!w->env) {
		free(w);
		return NULL;
	}
	*w->env = *ctx->env;
	w->env->alloc = context_obtain_alloc(ctx, !w->is_bg || w->is_bg_thread);
	if(!w->env->alloc) {
		libworker_delete(w);
		return NULL;
	}
	w->thread_num = w->env->alloc->thread_num;
	alloc_set_id_cleanup(w->env->alloc, &libworker_alloc_cleanup, w);
	if(!w->is_bg || w->is_bg_thread) {
		lock_basic_lock(&ctx->cfglock);
	}
	w->env->scratch = regional_create_custom(cfg->msg_buffer_size);
	w->env->scratch_buffer = sldns_buffer_new(cfg->msg_buffer_size);
	w->env->fwds = forwards_create();
	if(w->env->fwds && !forwards_apply_cfg(w->env->fwds, cfg)) { 
		forwards_delete(w->env->fwds);
		w->env->fwds = NULL;
	}
	w->env->hints = hints_create();
	if(w->env->hints && !hints_apply_cfg(w->env->hints, cfg)) { 
		hints_delete(w->env->hints);
		w->env->hints = NULL;
	}
	if(cfg->ssl_upstream) {
		w->sslctx = connect_sslctx_create(NULL, NULL,
			cfg->tls_cert_bundle);
		if(!w->sslctx) {
			/* to make the setup fail after unlock */
			hints_delete(w->env->hints);
			w->env->hints = NULL;
		}
	}
	if(!w->is_bg || w->is_bg_thread) {
		lock_basic_unlock(&ctx->cfglock);
	}
	if(!w->env->scratch || !w->env->scratch_buffer || !w->env->fwds ||
		!w->env->hints) {
		libworker_delete(w);
		return NULL;
	}
	w->env->worker = (struct worker*)w;
	w->env->probe_timer = NULL;
	seed = (unsigned int)time(NULL) ^ (unsigned int)getpid() ^
		(((unsigned int)w->thread_num)<<17);
	seed ^= (unsigned int)w->env->alloc->next_id;
	if(!w->is_bg || w->is_bg_thread) {
		lock_basic_lock(&ctx->cfglock);
	}
	if(!(w->env->rnd = ub_initstate(seed, ctx->seed_rnd))) {
		if(!w->is_bg || w->is_bg_thread) {
			lock_basic_unlock(&ctx->cfglock);
		}
		seed = 0;
		libworker_delete(w);
		return NULL;
	}
	if(!w->is_bg || w->is_bg_thread) {
		lock_basic_unlock(&ctx->cfglock);
	}
	if(1) {
		/* primitive lockout for threading: if it overwrites another
		 * thread it is like wiping the cache (which is likely empty
		 * at the start) */
		/* note we are holding the ctx lock in normal threaded
		 * cases so that is solved properly, it is only for many ctx
		 * in different threads that this may clash */
		static int done_raninit = 0;
		if(!done_raninit) {
			done_raninit = 1;
			hash_set_raninit((uint32_t)ub_random(w->env->rnd));
		}
	}
	seed = 0;

	if(eb)
		w->base = comm_base_create_event(eb);
	else	w->base = comm_base_create(0);
	if(!w->base) {
		libworker_delete(w);
		return NULL;
	}
	w->env->worker_base = w->base;
	if(!w->is_bg || w->is_bg_thread) {
		lock_basic_lock(&ctx->cfglock);
	}
	numports = cfg_condense_ports(cfg, &ports);
	if(numports == 0) {
		int locked = !w->is_bg || w->is_bg_thread;
		libworker_delete(w);
		if(locked) {
			lock_basic_unlock(&ctx->cfglock);
		}
		return NULL;
	}
	w->back = outside_network_create(w->base, cfg->msg_buffer_size,
		(size_t)cfg->outgoing_num_ports, cfg->out_ifs,
		cfg->num_out_ifs, cfg->do_ip4, cfg->do_ip6, 
		cfg->do_tcp?cfg->outgoing_num_tcp:0,
		w->env->infra_cache, w->env->rnd, cfg->use_caps_bits_for_id,
		ports, numports, cfg->unwanted_threshold,
		cfg->outgoing_tcp_mss, &libworker_alloc_cleanup, w,
		cfg->do_udp || cfg->udp_upstream_without_downstream, w->sslctx,
		cfg->delay_close, NULL);
	w->env->outnet = w->back;
	if(!w->is_bg || w->is_bg_thread) {
		lock_basic_unlock(&ctx->cfglock);
	}
	free(ports);
	if(!w->back) {
		libworker_delete(w);
		return NULL;
	}
	w->env->mesh = mesh_create(&ctx->mods, w->env);
	if(!w->env->mesh) {
		libworker_delete(w);
		return NULL;
	}
	w->env->send_query = &libworker_send_query;
	w->env->detach_subs = &mesh_detach_subs;
	w->env->attach_sub = &mesh_attach_sub;
	w->env->add_sub = &mesh_add_sub;
	w->env->kill_sub = &mesh_state_delete;
	w->env->detect_cycle = &mesh_detect_cycle;
	comm_base_timept(w->base, &w->env->now, &w->env->now_tv);
	return w;
}
Пример #21
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;
}
Пример #22
0
struct serviced_query* outnet_serviced_query(struct outside_network* outnet,
        uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
	uint16_t flags, int dnssec, int ATTR_UNUSED(want_dnssec),
	int ATTR_UNUSED(tcp_upstream), int ATTR_UNUSED(ssl_upstream),
	struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
	size_t zonelen, comm_point_callback_t* callback, void* callback_arg,
	sldns_buffer* ATTR_UNUSED(buff))
{
	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", 
		qname, qtype, 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, qname, qnamelen);
	sldns_buffer_write_u16(pend->buffer, qtype);
	sldns_buffer_write_u16(pend->buffer, qclass);
	sldns_buffer_flip(pend->buffer);
	if(1) {
		/* add edns */
		struct edns_data edns;
		edns.edns_present = 1;
		edns.ext_rcode = 0;
		edns.edns_version = EDNS_ADVERTISED_VERSION;
		edns.udp_size = EDNS_ADVERTISED_SIZE;
		edns.bits = 0;
		if(dnssec)
			edns.bits = EDNS_DO;
		attach_edns_record(pend->buffer, &edns);
	}
	memcpy(&pend->addr, addr, addrlen);
	pend->addrlen = addrlen;
	pend->zone = memdup(zone, zonelen);
	pend->zonelen = zonelen;
	pend->qtype = (int)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;
}