1/*
2 * Copyright (c) 2003-2007 Niels Provos <provos@citi.umich.edu>
3 * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 *    derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27#include "../util-internal.h"
28
29#ifdef _WIN32
30#include <winsock2.h>
31#include <windows.h>
32#include <ws2tcpip.h>
33#endif
34
35#include "event2/event-config.h"
36
37#include <sys/types.h>
38#include <sys/stat.h>
39#ifdef EVENT__HAVE_SYS_TIME_H
40#include <sys/time.h>
41#endif
42#include <sys/queue.h>
43#ifndef _WIN32
44#include <sys/socket.h>
45#include <signal.h>
46#include <netinet/in.h>
47#include <arpa/inet.h>
48#include <unistd.h>
49#endif
50#ifdef EVENT__HAVE_NETINET_IN6_H
51#include <netinet/in6.h>
52#endif
53#ifdef HAVE_NETDB_H
54#include <netdb.h>
55#endif
56#include <fcntl.h>
57#include <stdlib.h>
58#include <stdio.h>
59#include <string.h>
60#include <errno.h>
61
62#ifdef EVENT__HAVE_SYS_RESOURCE_H
63#include <sys/resource.h>
64#endif
65
66#include "event2/dns.h"
67#include "event2/dns_compat.h"
68#include "event2/dns_struct.h"
69#include "event2/event.h"
70#include "event2/event_compat.h"
71#include "event2/event_struct.h"
72#include "event2/util.h"
73#include "event2/listener.h"
74#include "event2/bufferevent.h"
75#include <event2/thread.h>
76#include "log-internal.h"
77#include "evthread-internal.h"
78#include "regress.h"
79#include "regress_testutils.h"
80#include "regress_thread.h"
81
82#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
83
84static int dns_ok = 0;
85static int dns_got_cancel = 0;
86static int dns_err = 0;
87
88
89static void
90dns_gethostbyname_cb(int result, char type, int count, int ttl,
91    void *addresses, void *arg)
92{
93	dns_ok = dns_err = 0;
94
95	if (result == DNS_ERR_TIMEOUT) {
96		printf("[Timed out] ");
97		dns_err = result;
98		goto out;
99	}
100
101	if (result != DNS_ERR_NONE) {
102		printf("[Error code %d] ", result);
103		goto out;
104	}
105
106	TT_BLATHER(("type: %d, count: %d, ttl: %d: ", type, count, ttl));
107
108	switch (type) {
109	case DNS_IPv6_AAAA: {
110#if defined(EVENT__HAVE_STRUCT_IN6_ADDR) && defined(EVENT__HAVE_INET_NTOP) && defined(INET6_ADDRSTRLEN)
111		struct in6_addr *in6_addrs = addresses;
112		char buf[INET6_ADDRSTRLEN+1];
113		int i;
114		/* a resolution that's not valid does not help */
115		if (ttl < 0)
116			goto out;
117		for (i = 0; i < count; ++i) {
118			const char *b = evutil_inet_ntop(AF_INET6, &in6_addrs[i], buf,sizeof(buf));
119			if (b)
120				TT_BLATHER(("%s ", b));
121			else
122				TT_BLATHER(("%s ", strerror(errno)));
123		}
124#endif
125		break;
126	}
127	case DNS_IPv4_A: {
128		struct in_addr *in_addrs = addresses;
129		int i;
130		/* a resolution that's not valid does not help */
131		if (ttl < 0)
132			goto out;
133		for (i = 0; i < count; ++i)
134			TT_BLATHER(("%s ", inet_ntoa(in_addrs[i])));
135		break;
136	}
137	case DNS_PTR:
138		/* may get at most one PTR */
139		if (count != 1)
140			goto out;
141
142		TT_BLATHER(("%s ", *(char **)addresses));
143		break;
144	default:
145		goto out;
146	}
147
148	dns_ok = type;
149
150out:
151	if (arg == NULL)
152		event_loopexit(NULL);
153	else
154		event_base_loopexit((struct event_base *)arg, NULL);
155}
156
157static void
158dns_gethostbyname(void)
159{
160	dns_ok = 0;
161	evdns_resolve_ipv4("www.monkey.org", 0, dns_gethostbyname_cb, NULL);
162	event_dispatch();
163
164	tt_int_op(dns_ok, ==, DNS_IPv4_A);
165	test_ok = dns_ok;
166end:
167	;
168}
169
170static void
171dns_gethostbyname6(void)
172{
173	dns_ok = 0;
174	evdns_resolve_ipv6("www.ietf.org", 0, dns_gethostbyname_cb, NULL);
175	event_dispatch();
176
177	if (!dns_ok && dns_err == DNS_ERR_TIMEOUT) {
178		tt_skip();
179	}
180
181	tt_int_op(dns_ok, ==, DNS_IPv6_AAAA);
182	test_ok = 1;
183end:
184	;
185}
186
187static void
188dns_gethostbyaddr(void)
189{
190	struct in_addr in;
191	in.s_addr = htonl(0x7f000001ul); /* 127.0.0.1 */
192	dns_ok = 0;
193	evdns_resolve_reverse(&in, 0, dns_gethostbyname_cb, NULL);
194	event_dispatch();
195
196	tt_int_op(dns_ok, ==, DNS_PTR);
197	test_ok = dns_ok;
198end:
199	;
200}
201
202static void
203dns_resolve_reverse(void *ptr)
204{
205	struct in_addr in;
206	struct event_base *base = event_base_new();
207	struct evdns_base *dns = evdns_base_new(base, EVDNS_BASE_INITIALIZE_NAMESERVERS);
208	struct evdns_request *req = NULL;
209
210	tt_assert(base);
211	tt_assert(dns);
212	in.s_addr = htonl(0x7f000001ul); /* 127.0.0.1 */
213	dns_ok = 0;
214
215	req = evdns_base_resolve_reverse(
216		dns, &in, 0, dns_gethostbyname_cb, base);
217	tt_assert(req);
218
219	event_base_dispatch(base);
220
221	tt_int_op(dns_ok, ==, DNS_PTR);
222
223end:
224	if (dns)
225		evdns_base_free(dns, 0);
226	if (base)
227		event_base_free(base);
228}
229
230static int n_server_responses = 0;
231
232static void
233dns_server_request_cb(struct evdns_server_request *req, void *data)
234{
235	int i, r;
236	const char TEST_ARPA[] = "11.11.168.192.in-addr.arpa";
237	const char TEST_IN6[] =
238	    "f.e.f.e." "0.0.0.0." "0.0.0.0." "1.1.1.1."
239	    "a.a.a.a." "0.0.0.0." "0.0.0.0." "0.f.f.f.ip6.arpa";
240
241	for (i = 0; i < req->nquestions; ++i) {
242		const int qtype = req->questions[i]->type;
243		const int qclass = req->questions[i]->dns_question_class;
244		const char *qname = req->questions[i]->name;
245
246		struct in_addr ans;
247		ans.s_addr = htonl(0xc0a80b0bUL); /* 192.168.11.11 */
248		if (qtype == EVDNS_TYPE_A &&
249		    qclass == EVDNS_CLASS_INET &&
250		    !evutil_ascii_strcasecmp(qname, "zz.example.com")) {
251			r = evdns_server_request_add_a_reply(req, qname,
252			    1, &ans.s_addr, 12345);
253			if (r<0)
254				dns_ok = 0;
255		} else if (qtype == EVDNS_TYPE_AAAA &&
256		    qclass == EVDNS_CLASS_INET &&
257		    !evutil_ascii_strcasecmp(qname, "zz.example.com")) {
258			char addr6[17] = "abcdefghijklmnop";
259			r = evdns_server_request_add_aaaa_reply(req,
260			    qname, 1, addr6, 123);
261			if (r<0)
262				dns_ok = 0;
263		} else if (qtype == EVDNS_TYPE_PTR &&
264		    qclass == EVDNS_CLASS_INET &&
265		    !evutil_ascii_strcasecmp(qname, TEST_ARPA)) {
266			r = evdns_server_request_add_ptr_reply(req, NULL,
267			    qname, "ZZ.EXAMPLE.COM", 54321);
268			if (r<0)
269				dns_ok = 0;
270		} else if (qtype == EVDNS_TYPE_PTR &&
271		    qclass == EVDNS_CLASS_INET &&
272		    !evutil_ascii_strcasecmp(qname, TEST_IN6)){
273			r = evdns_server_request_add_ptr_reply(req, NULL,
274			    qname,
275			    "ZZ-INET6.EXAMPLE.COM", 54322);
276			if (r<0)
277				dns_ok = 0;
278		} else if (qtype == EVDNS_TYPE_A &&
279		    qclass == EVDNS_CLASS_INET &&
280		    !evutil_ascii_strcasecmp(qname, "drop.example.com")) {
281			if (evdns_server_request_drop(req)<0)
282				dns_ok = 0;
283			return;
284		} else {
285			printf("Unexpected question %d %d \"%s\" ",
286			    qtype, qclass, qname);
287			dns_ok = 0;
288		}
289	}
290	r = evdns_server_request_respond(req, 0);
291	if (r<0) {
292		printf("Couldn't send reply. ");
293		dns_ok = 0;
294	}
295}
296
297static void
298dns_server_gethostbyname_cb(int result, char type, int count, int ttl,
299    void *addresses, void *arg)
300{
301	if (result == DNS_ERR_CANCEL) {
302		if (arg != (void*)(char*)90909) {
303			printf("Unexpected cancelation");
304			dns_ok = 0;
305		}
306		dns_got_cancel = 1;
307		goto out;
308	}
309	if (result != DNS_ERR_NONE) {
310		printf("Unexpected result %d. ", result);
311		dns_ok = 0;
312		goto out;
313	}
314	if (count != 1) {
315		printf("Unexpected answer count %d. ", count);
316		dns_ok = 0;
317		goto out;
318	}
319	switch (type) {
320	case DNS_IPv4_A: {
321		struct in_addr *in_addrs = addresses;
322		if (in_addrs[0].s_addr != htonl(0xc0a80b0bUL) || ttl != 12345) {
323			printf("Bad IPv4 response \"%s\" %d. ",
324					inet_ntoa(in_addrs[0]), ttl);
325			dns_ok = 0;
326			goto out;
327		}
328		break;
329	}
330	case DNS_IPv6_AAAA: {
331#if defined (EVENT__HAVE_STRUCT_IN6_ADDR) && defined(EVENT__HAVE_INET_NTOP) && defined(INET6_ADDRSTRLEN)
332		struct in6_addr *in6_addrs = addresses;
333		char buf[INET6_ADDRSTRLEN+1];
334		if (memcmp(&in6_addrs[0].s6_addr, "abcdefghijklmnop", 16)
335		    || ttl != 123) {
336			const char *b = evutil_inet_ntop(AF_INET6, &in6_addrs[0],buf,sizeof(buf));
337			printf("Bad IPv6 response \"%s\" %d. ", b, ttl);
338			dns_ok = 0;
339			goto out;
340		}
341#endif
342		break;
343	}
344	case DNS_PTR: {
345		char **addrs = addresses;
346		if (arg != (void*)6) {
347			if (strcmp(addrs[0], "ZZ.EXAMPLE.COM") ||
348			    ttl != 54321) {
349				printf("Bad PTR response \"%s\" %d. ",
350				    addrs[0], ttl);
351				dns_ok = 0;
352				goto out;
353			}
354		} else {
355			if (strcmp(addrs[0], "ZZ-INET6.EXAMPLE.COM") ||
356			    ttl != 54322) {
357				printf("Bad ipv6 PTR response \"%s\" %d. ",
358				    addrs[0], ttl);
359				dns_ok = 0;
360				goto out;
361			}
362		}
363		break;
364	}
365	default:
366		printf("Bad response type %d. ", type);
367		dns_ok = 0;
368	}
369 out:
370	if (++n_server_responses == 3) {
371		event_loopexit(NULL);
372	}
373}
374
375static void
376dns_server(void)
377{
378	evutil_socket_t sock=-1;
379	struct sockaddr_in my_addr;
380	struct sockaddr_storage ss;
381	ev_socklen_t slen;
382	struct evdns_server_port *port=NULL;
383	struct in_addr resolve_addr;
384	struct in6_addr resolve_addr6;
385	struct evdns_base *base=NULL;
386	struct evdns_request *req=NULL;
387
388	dns_ok = 1;
389
390	base = evdns_base_new(NULL, 0);
391
392	/* Now configure a nameserver port. */
393	sock = socket(AF_INET, SOCK_DGRAM, 0);
394	if (sock<0) {
395		tt_abort_perror("socket");
396	}
397
398	evutil_make_socket_nonblocking(sock);
399
400	memset(&my_addr, 0, sizeof(my_addr));
401	my_addr.sin_family = AF_INET;
402	my_addr.sin_port = 0; /* kernel picks */
403	my_addr.sin_addr.s_addr = htonl(0x7f000001UL);
404	if (bind(sock, (struct sockaddr*)&my_addr, sizeof(my_addr)) < 0) {
405		tt_abort_perror("bind");
406	}
407	slen = sizeof(ss);
408	if (getsockname(sock, (struct sockaddr*)&ss, &slen) < 0) {
409		tt_abort_perror("getsockname");
410	}
411
412	port = evdns_add_server_port(sock, 0, dns_server_request_cb, NULL);
413
414	/* Add ourself as the only nameserver, and make sure we really are
415	 * the only nameserver. */
416	evdns_base_nameserver_sockaddr_add(base, (struct sockaddr*)&ss, slen, 0);
417	tt_int_op(evdns_base_count_nameservers(base), ==, 1);
418	{
419		struct sockaddr_storage ss2;
420		int slen2;
421
422		memset(&ss2, 0, sizeof(ss2));
423
424		slen2 = evdns_base_get_nameserver_addr(base, 0, (struct sockaddr *)&ss2, 3);
425		tt_int_op(slen2, ==, slen);
426		tt_int_op(ss2.ss_family, ==, 0);
427		slen2 = evdns_base_get_nameserver_addr(base, 0, (struct sockaddr *)&ss2, sizeof(ss2));
428		tt_int_op(slen2, ==, slen);
429		tt_mem_op(&ss2, ==, &ss, slen);
430
431		slen2 = evdns_base_get_nameserver_addr(base, 1, (struct sockaddr *)&ss2, sizeof(ss2));
432		tt_int_op(-1, ==, slen2);
433	}
434
435	/* Send some queries. */
436	evdns_base_resolve_ipv4(base, "zz.example.com", DNS_QUERY_NO_SEARCH,
437					   dns_server_gethostbyname_cb, NULL);
438	evdns_base_resolve_ipv6(base, "zz.example.com", DNS_QUERY_NO_SEARCH,
439					   dns_server_gethostbyname_cb, NULL);
440	resolve_addr.s_addr = htonl(0xc0a80b0bUL); /* 192.168.11.11 */
441	evdns_base_resolve_reverse(base, &resolve_addr, 0,
442	    dns_server_gethostbyname_cb, NULL);
443	memcpy(resolve_addr6.s6_addr,
444	    "\xff\xf0\x00\x00\x00\x00\xaa\xaa"
445	    "\x11\x11\x00\x00\x00\x00\xef\xef", 16);
446	evdns_base_resolve_reverse_ipv6(base, &resolve_addr6, 0,
447	    dns_server_gethostbyname_cb, (void*)6);
448
449	req = evdns_base_resolve_ipv4(base,
450	    "drop.example.com", DNS_QUERY_NO_SEARCH,
451	    dns_server_gethostbyname_cb, (void*)(char*)90909);
452
453	evdns_cancel_request(base, req);
454
455	event_dispatch();
456
457	tt_assert(dns_got_cancel);
458	test_ok = dns_ok;
459
460end:
461	if (port)
462		evdns_close_server_port(port);
463	if (sock >= 0)
464		evutil_closesocket(sock);
465	if (base)
466		evdns_base_free(base, 0);
467}
468
469static int n_replies_left;
470static struct event_base *exit_base;
471static struct evdns_server_port *exit_port;
472
473struct generic_dns_callback_result {
474	int result;
475	char type;
476	int count;
477	int ttl;
478	size_t addrs_len;
479	void *addrs;
480	char addrs_buf[256];
481};
482
483static void
484generic_dns_callback(int result, char type, int count, int ttl, void *addresses,
485    void *arg)
486{
487	size_t len;
488	struct generic_dns_callback_result *res = arg;
489	res->result = result;
490	res->type = type;
491	res->count = count;
492	res->ttl = ttl;
493
494	if (type == DNS_IPv4_A)
495		len = count * 4;
496	else if (type == DNS_IPv6_AAAA)
497		len = count * 16;
498	else if (type == DNS_PTR)
499		len = strlen(addresses)+1;
500	else {
501		res->addrs_len = len = 0;
502		res->addrs = NULL;
503	}
504	if (len) {
505		res->addrs_len = len;
506		if (len > 256)
507			len = 256;
508		memcpy(res->addrs_buf, addresses, len);
509		res->addrs = res->addrs_buf;
510	}
511
512	--n_replies_left;
513	if (n_replies_left == 0) {
514		if (exit_port) {
515			evdns_close_server_port(exit_port);
516			exit_port = NULL;
517		} else
518			event_base_loopexit(exit_base, NULL);
519	}
520}
521
522static struct regress_dns_server_table search_table[] = {
523	{ "host.a.example.com", "err", "3", 0, 0 },
524	{ "host.b.example.com", "err", "3", 0, 0 },
525	{ "host.c.example.com", "A", "11.22.33.44", 0, 0 },
526	{ "host2.a.example.com", "err", "3", 0, 0 },
527	{ "host2.b.example.com", "A", "200.100.0.100", 0, 0 },
528	{ "host2.c.example.com", "err", "3", 0, 0 },
529	{ "hostn.a.example.com", "errsoa", "0", 0, 0 },
530	{ "hostn.b.example.com", "errsoa", "3", 0, 0 },
531	{ "hostn.c.example.com", "err", "0", 0, 0 },
532
533	{ "host", "err", "3", 0, 0 },
534	{ "host2", "err", "3", 0, 0 },
535	{ "*", "err", "3", 0, 0 },
536	{ NULL, NULL, NULL, 0, 0 }
537};
538static void
539dns_search_test_impl(void *arg, int lower)
540{
541	struct regress_dns_server_table table[ARRAY_SIZE(search_table)];
542	struct basic_test_data *data = arg;
543	struct event_base *base = data->base;
544	struct evdns_base *dns = NULL;
545	ev_uint16_t portnum = 0;
546	char buf[64];
547
548	struct generic_dns_callback_result r[8];
549	size_t i;
550
551	for (i = 0; i < ARRAY_SIZE(table); ++i) {
552		table[i] = search_table[i];
553		table[i].lower = lower;
554	}
555
556	tt_assert(regress_dnsserver(base, &portnum, table));
557	evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum);
558
559	dns = evdns_base_new(base, 0);
560	tt_assert(!evdns_base_nameserver_ip_add(dns, buf));
561
562	evdns_base_search_add(dns, "a.example.com");
563	evdns_base_search_add(dns, "b.example.com");
564	evdns_base_search_add(dns, "c.example.com");
565
566	n_replies_left = ARRAY_SIZE(r);
567	exit_base = base;
568
569	evdns_base_resolve_ipv4(dns, "host", 0, generic_dns_callback, &r[0]);
570	evdns_base_resolve_ipv4(dns, "host2", 0, generic_dns_callback, &r[1]);
571	evdns_base_resolve_ipv4(dns, "host", DNS_NO_SEARCH, generic_dns_callback, &r[2]);
572	evdns_base_resolve_ipv4(dns, "host2", DNS_NO_SEARCH, generic_dns_callback, &r[3]);
573	evdns_base_resolve_ipv4(dns, "host3", 0, generic_dns_callback, &r[4]);
574	evdns_base_resolve_ipv4(dns, "hostn.a.example.com", DNS_NO_SEARCH, generic_dns_callback, &r[5]);
575	evdns_base_resolve_ipv4(dns, "hostn.b.example.com", DNS_NO_SEARCH, generic_dns_callback, &r[6]);
576	evdns_base_resolve_ipv4(dns, "hostn.c.example.com", DNS_NO_SEARCH, generic_dns_callback, &r[7]);
577
578	event_base_dispatch(base);
579
580	tt_int_op(r[0].type, ==, DNS_IPv4_A);
581	tt_int_op(r[0].count, ==, 1);
582	tt_int_op(((ev_uint32_t*)r[0].addrs)[0], ==, htonl(0x0b16212c));
583	tt_int_op(r[1].type, ==, DNS_IPv4_A);
584	tt_int_op(r[1].count, ==, 1);
585	tt_int_op(((ev_uint32_t*)r[1].addrs)[0], ==, htonl(0xc8640064));
586	tt_int_op(r[2].result, ==, DNS_ERR_NOTEXIST);
587	tt_int_op(r[3].result, ==, DNS_ERR_NOTEXIST);
588	tt_int_op(r[4].result, ==, DNS_ERR_NOTEXIST);
589	tt_int_op(r[5].result, ==, DNS_ERR_NODATA);
590	tt_int_op(r[5].ttl, ==, 42);
591	tt_int_op(r[6].result, ==, DNS_ERR_NOTEXIST);
592	tt_int_op(r[6].ttl, ==, 42);
593	tt_int_op(r[7].result, ==, DNS_ERR_NODATA);
594	tt_int_op(r[7].ttl, ==, 0);
595
596end:
597	if (dns)
598		evdns_base_free(dns, 0);
599
600	regress_clean_dnsserver();
601}
602static void
603dns_search_empty_test(void *arg)
604{
605	struct basic_test_data *data = arg;
606	struct event_base *base = data->base;
607	struct evdns_base *dns = NULL;
608
609	dns = evdns_base_new(base, 0);
610
611	evdns_base_search_add(dns, "whatever.example.com");
612
613	n_replies_left = 1;
614	exit_base = base;
615
616	tt_ptr_op(evdns_base_resolve_ipv4(dns, "", 0, generic_dns_callback, NULL), ==, NULL);
617
618end:
619	if (dns)
620		evdns_base_free(dns, 0);
621}
622static void dns_search_test(void *arg) { dns_search_test_impl(arg, 0); }
623static void dns_search_lower_test(void *arg) { dns_search_test_impl(arg, 1); }
624
625static int request_count = 0;
626static struct evdns_request *current_req = NULL;
627
628static void
629search_cancel_server_cb(struct evdns_server_request *req, void *data)
630{
631	const char *question;
632
633	if (req->nquestions != 1)
634		TT_DIE(("Only handling one question at a time; got %d",
635			req->nquestions));
636
637	question = req->questions[0]->name;
638
639	TT_BLATHER(("got question, %s", question));
640
641	tt_assert(request_count > 0);
642	tt_assert(!evdns_server_request_respond(req, 3));
643
644	if (!--request_count)
645		evdns_cancel_request(NULL, current_req);
646
647end:
648	;
649}
650
651static void
652dns_search_cancel_test(void *arg)
653{
654	struct basic_test_data *data = arg;
655	struct event_base *base = data->base;
656	struct evdns_base *dns = NULL;
657	struct evdns_server_port *port = NULL;
658	ev_uint16_t portnum = 0;
659	struct generic_dns_callback_result r1;
660	char buf[64];
661
662	port = regress_get_dnsserver(base, &portnum, NULL,
663	    search_cancel_server_cb, NULL);
664	tt_assert(port);
665	evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum);
666
667	dns = evdns_base_new(base, 0);
668	tt_assert(!evdns_base_nameserver_ip_add(dns, buf));
669
670	evdns_base_search_add(dns, "a.example.com");
671	evdns_base_search_add(dns, "b.example.com");
672	evdns_base_search_add(dns, "c.example.com");
673	evdns_base_search_add(dns, "d.example.com");
674
675	exit_base = base;
676	request_count = 3;
677	n_replies_left = 1;
678
679	current_req = evdns_base_resolve_ipv4(dns, "host", 0,
680					generic_dns_callback, &r1);
681	event_base_dispatch(base);
682
683	tt_int_op(r1.result, ==, DNS_ERR_CANCEL);
684
685end:
686	if (port)
687		evdns_close_server_port(port);
688	if (dns)
689		evdns_base_free(dns, 0);
690}
691
692static void
693fail_server_cb(struct evdns_server_request *req, void *data)
694{
695	const char *question;
696	int *count = data;
697	struct in_addr in;
698
699	/* Drop the first N requests that we get. */
700	if (*count > 0) {
701		--*count;
702		tt_want(! evdns_server_request_drop(req));
703		return;
704	}
705
706	if (req->nquestions != 1)
707		TT_DIE(("Only handling one question at a time; got %d",
708			req->nquestions));
709
710	question = req->questions[0]->name;
711
712	if (!evutil_ascii_strcasecmp(question, "google.com")) {
713		/* Detect a probe, and get out of the loop. */
714		event_base_loopexit(exit_base, NULL);
715	}
716
717	tt_assert(evutil_inet_pton(AF_INET, "16.32.64.128", &in));
718	evdns_server_request_add_a_reply(req, question, 1, &in.s_addr,
719	    100);
720	tt_assert(! evdns_server_request_respond(req, 0))
721	return;
722end:
723	tt_want(! evdns_server_request_drop(req));
724}
725
726static void
727dns_retry_test_impl(void *arg, int flags)
728{
729	struct basic_test_data *data = arg;
730	struct event_base *base = data->base;
731	struct evdns_server_port *port = NULL;
732	struct evdns_base *dns = NULL;
733	int drop_count = 2;
734	ev_uint16_t portnum = 0;
735	char buf[64];
736
737	struct generic_dns_callback_result r1;
738
739	port = regress_get_dnsserver(base, &portnum, NULL,
740	    fail_server_cb, &drop_count);
741	tt_assert(port);
742	evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum);
743
744	dns = evdns_base_new(base, flags);
745	tt_assert(!evdns_base_nameserver_ip_add(dns, buf));
746	tt_assert(! evdns_base_set_option(dns, "timeout", "0.2"));
747	tt_assert(! evdns_base_set_option(dns, "max-timeouts:", "10"));
748	tt_assert(! evdns_base_set_option(dns, "initial-probe-timeout", "0.1"));
749
750	evdns_base_resolve_ipv4(dns, "host.example.com", 0,
751	    generic_dns_callback, &r1);
752
753	n_replies_left = 1;
754	exit_base = base;
755
756	event_base_dispatch(base);
757
758	tt_int_op(drop_count, ==, 0);
759
760	tt_int_op(r1.type, ==, DNS_IPv4_A);
761	tt_int_op(r1.count, ==, 1);
762	tt_int_op(((ev_uint32_t*)r1.addrs)[0], ==, htonl(0x10204080));
763
764	/* Now try again, but this time have the server get treated as
765	 * failed, so we can send it a test probe. */
766	drop_count = 4;
767	tt_assert(! evdns_base_set_option(dns, "max-timeouts:", "2"));
768	tt_assert(! evdns_base_set_option(dns, "attempts:", "3"));
769	memset(&r1, 0, sizeof(r1));
770
771	evdns_base_resolve_ipv4(dns, "host.example.com", 0,
772	    generic_dns_callback, &r1);
773
774	n_replies_left = 2;
775
776	/* This will run until it answers the "google.com" probe request. */
777	event_base_dispatch(base);
778
779	/* We'll treat the server as failed here. */
780	tt_int_op(r1.result, ==, DNS_ERR_TIMEOUT);
781
782	/* It should work this time. */
783	tt_int_op(drop_count, ==, 0);
784	evdns_base_resolve_ipv4(dns, "host.example.com", 0,
785	    generic_dns_callback, &r1);
786
787	event_base_dispatch(base);
788	tt_int_op(r1.result, ==, DNS_ERR_NONE);
789	tt_int_op(r1.type, ==, DNS_IPv4_A);
790	tt_int_op(r1.count, ==, 1);
791	tt_int_op(((ev_uint32_t*)r1.addrs)[0], ==, htonl(0x10204080));
792
793end:
794	if (dns)
795		evdns_base_free(dns, 0);
796	if (port)
797		evdns_close_server_port(port);
798}
799static void
800dns_retry_test(void *arg)
801{
802	dns_retry_test_impl(arg, 0);
803}
804static void
805dns_retry_disable_when_inactive_test(void *arg)
806{
807	dns_retry_test_impl(arg, EVDNS_BASE_DISABLE_WHEN_INACTIVE);
808}
809
810static struct regress_dns_server_table internal_error_table[] = {
811	/* Error 4 (NOTIMPL) makes us reissue the request to another server
812	   if we can.
813
814	   XXXX we should reissue under a much wider set of circumstances!
815	 */
816	{ "foof.example.com", "err", "4", 0, 0 },
817	{ NULL, NULL, NULL, 0, 0 }
818};
819
820static struct regress_dns_server_table reissue_table[] = {
821	{ "foof.example.com", "A", "240.15.240.15", 0, 0 },
822	{ NULL, NULL, NULL, 0, 0 }
823};
824
825static void
826dns_reissue_test_impl(void *arg, int flags)
827{
828	struct basic_test_data *data = arg;
829	struct event_base *base = data->base;
830	struct evdns_server_port *port1 = NULL, *port2 = NULL;
831	struct evdns_base *dns = NULL;
832	struct generic_dns_callback_result r1;
833	ev_uint16_t portnum1 = 0, portnum2=0;
834	char buf1[64], buf2[64];
835
836	port1 = regress_get_dnsserver(base, &portnum1, NULL,
837	    regress_dns_server_cb, internal_error_table);
838	tt_assert(port1);
839	port2 = regress_get_dnsserver(base, &portnum2, NULL,
840	    regress_dns_server_cb, reissue_table);
841	tt_assert(port2);
842	evutil_snprintf(buf1, sizeof(buf1), "127.0.0.1:%d", (int)portnum1);
843	evutil_snprintf(buf2, sizeof(buf2), "127.0.0.1:%d", (int)portnum2);
844
845	dns = evdns_base_new(base, flags);
846	tt_assert(!evdns_base_nameserver_ip_add(dns, buf1));
847	tt_assert(! evdns_base_set_option(dns, "timeout:", "0.3"));
848	tt_assert(! evdns_base_set_option(dns, "max-timeouts:", "2"));
849	tt_assert(! evdns_base_set_option(dns, "attempts:", "5"));
850
851	memset(&r1, 0, sizeof(r1));
852	evdns_base_resolve_ipv4(dns, "foof.example.com", 0,
853	    generic_dns_callback, &r1);
854
855	/* Add this after, so that we are sure to get a reissue. */
856	tt_assert(!evdns_base_nameserver_ip_add(dns, buf2));
857
858	n_replies_left = 1;
859	exit_base = base;
860
861	event_base_dispatch(base);
862	tt_int_op(r1.result, ==, DNS_ERR_NONE);
863	tt_int_op(r1.type, ==, DNS_IPv4_A);
864	tt_int_op(r1.count, ==, 1);
865	tt_int_op(((ev_uint32_t*)r1.addrs)[0], ==, htonl(0xf00ff00f));
866
867	/* Make sure we dropped at least once. */
868	tt_int_op(internal_error_table[0].seen, >, 0);
869
870end:
871	if (dns)
872		evdns_base_free(dns, 0);
873	if (port1)
874		evdns_close_server_port(port1);
875	if (port2)
876		evdns_close_server_port(port2);
877}
878static void
879dns_reissue_test(void *arg)
880{
881	dns_reissue_test_impl(arg, 0);
882}
883static void
884dns_reissue_disable_when_inactive_test(void *arg)
885{
886	dns_reissue_test_impl(arg, EVDNS_BASE_DISABLE_WHEN_INACTIVE);
887}
888
889#if 0
890static void
891dumb_bytes_fn(char *p, size_t n)
892{
893	unsigned i;
894	/* This gets us 6 bits of entropy per transaction ID, which means we
895	 * will have probably have collisions and need to pick again. */
896	for (i=0;i<n;++i)
897		p[i] = (char)(rand() & 7);
898}
899#endif
900
901static void
902dns_inflight_test_impl(void *arg, int flags)
903{
904	struct basic_test_data *data = arg;
905	struct event_base *base = data->base;
906	struct evdns_base *dns = NULL;
907	struct evdns_server_port *dns_port = NULL;
908	ev_uint16_t portnum = 0;
909	char buf[64];
910	int disable_when_inactive = flags & EVDNS_BASE_DISABLE_WHEN_INACTIVE;
911
912	struct generic_dns_callback_result r[20];
913	int i;
914
915	dns_port = regress_get_dnsserver(base, &portnum, NULL,
916		regress_dns_server_cb, reissue_table);
917	tt_assert(dns_port);
918	if (disable_when_inactive) {
919		exit_port = dns_port;
920	}
921
922	evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum);
923
924	dns = evdns_base_new(base, flags);
925	tt_assert(!evdns_base_nameserver_ip_add(dns, buf));
926	tt_assert(! evdns_base_set_option(dns, "max-inflight:", "3"));
927	tt_assert(! evdns_base_set_option(dns, "randomize-case:", "0"));
928
929	for (i=0;i<20;++i)
930		evdns_base_resolve_ipv4(dns, "foof.example.com", 0, generic_dns_callback, &r[i]);
931
932	n_replies_left = 20;
933	exit_base = base;
934
935	event_base_dispatch(base);
936
937	for (i=0;i<20;++i) {
938		tt_int_op(r[i].type, ==, DNS_IPv4_A);
939		tt_int_op(r[i].count, ==, 1);
940		tt_int_op(((ev_uint32_t*)r[i].addrs)[0], ==, htonl(0xf00ff00f));
941	}
942
943end:
944	if (dns)
945		evdns_base_free(dns, 0);
946	if (exit_port) {
947		evdns_close_server_port(exit_port);
948		exit_port = NULL;
949	} else if (! disable_when_inactive) {
950		evdns_close_server_port(dns_port);
951	}
952}
953
954static void
955dns_inflight_test(void *arg)
956{
957	dns_inflight_test_impl(arg, 0);
958}
959
960static void
961dns_disable_when_inactive_test(void *arg)
962{
963	dns_inflight_test_impl(arg, EVDNS_BASE_DISABLE_WHEN_INACTIVE);
964}
965
966static void
967dns_disable_when_inactive_no_ns_test(void *arg)
968{
969	struct basic_test_data *data = arg;
970	struct event_base *base = data->base, *inactive_base;
971	struct evdns_base *dns = NULL;
972	ev_uint16_t portnum = 0;
973	char buf[64];
974	struct generic_dns_callback_result r;
975
976	inactive_base = event_base_new();
977	tt_assert(inactive_base);
978
979	/** Create dns server with inactive base, to avoid replying to clients */
980	tt_assert(regress_dnsserver(inactive_base, &portnum, search_table));
981	evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum);
982
983	dns = evdns_base_new(base, EVDNS_BASE_DISABLE_WHEN_INACTIVE);
984	tt_assert(!evdns_base_nameserver_ip_add(dns, buf));
985	tt_assert(! evdns_base_set_option(dns, "timeout:", "0.1"));
986
987	evdns_base_resolve_ipv4(dns, "foof.example.com", 0, generic_dns_callback, &r);
988	n_replies_left = 1;
989	exit_base = base;
990
991	event_base_dispatch(base);
992
993	tt_int_op(n_replies_left, ==, 0);
994
995	tt_int_op(r.result, ==, DNS_ERR_TIMEOUT);
996	tt_int_op(r.count, ==, 0);
997	tt_ptr_op(r.addrs, ==, NULL);
998
999end:
1000	if (dns)
1001		evdns_base_free(dns, 0);
1002	regress_clean_dnsserver();
1003	if (inactive_base)
1004		event_base_free(inactive_base);
1005}
1006
1007static void
1008dns_initialize_nameservers_test(void *arg)
1009{
1010	struct basic_test_data *data = arg;
1011	struct event_base *base = data->base;
1012	struct evdns_base *dns = NULL;
1013
1014	dns = evdns_base_new(base, 0);
1015	tt_assert(dns);
1016	tt_int_op(evdns_base_get_nameserver_addr(dns, 0, NULL, 0), ==, -1);
1017	evdns_base_free(dns, 0);
1018
1019	dns = evdns_base_new(base, EVDNS_BASE_INITIALIZE_NAMESERVERS);
1020	tt_assert(dns);
1021	tt_int_op(evdns_base_get_nameserver_addr(dns, 0, NULL, 0), ==, sizeof(struct sockaddr));
1022
1023end:
1024	if (dns)
1025		evdns_base_free(dns, 0);
1026}
1027#ifndef _WIN32
1028#define RESOLV_FILE "empty-resolv.conf"
1029static void
1030dns_nameservers_no_default_test(void *arg)
1031{
1032	struct basic_test_data *data = arg;
1033	struct event_base *base = data->base;
1034	struct evdns_base *dns = NULL;
1035	int ok = access(RESOLV_FILE, R_OK);
1036
1037	tt_assert(ok);
1038
1039	dns = evdns_base_new(base, 0);
1040	tt_assert(dns);
1041	tt_int_op(evdns_base_get_nameserver_addr(dns, 0, NULL, 0), ==, -1);
1042
1043	/* We cannot test
1044	 * EVDNS_BASE_INITIALIZE_NAMESERVERS|EVDNS_BASE_NAMESERVERS_NO_DEFAULT
1045	 * because we cannot mock "/etc/resolv.conf" (yet). */
1046
1047	evdns_base_resolv_conf_parse(dns,
1048		DNS_OPTIONS_ALL|DNS_OPTION_NAMESERVERS_NO_DEFAULT, RESOLV_FILE);
1049	tt_int_op(evdns_base_get_nameserver_addr(dns, 0, NULL, 0), ==, -1);
1050
1051	evdns_base_resolv_conf_parse(dns, DNS_OPTIONS_ALL, RESOLV_FILE);
1052	tt_int_op(evdns_base_get_nameserver_addr(dns, 0, NULL, 0), ==, sizeof(struct sockaddr));
1053
1054end:
1055	if (dns)
1056		evdns_base_free(dns, 0);
1057}
1058#endif
1059
1060/* === Test for bufferevent_socket_connect_hostname */
1061
1062static int total_connected_or_failed = 0;
1063static int total_n_accepted = 0;
1064static struct event_base *be_connect_hostname_base = NULL;
1065
1066/* Implements a DNS server for the connect_hostname test and the
1067 * getaddrinfo_async test */
1068static void
1069be_getaddrinfo_server_cb(struct evdns_server_request *req, void *data)
1070{
1071	int i;
1072	int *n_got_p=data;
1073	int added_any=0;
1074	++*n_got_p;
1075
1076	for (i = 0; i < req->nquestions; ++i) {
1077		const int qtype = req->questions[i]->type;
1078		const int qclass = req->questions[i]->dns_question_class;
1079		const char *qname = req->questions[i]->name;
1080		struct in_addr ans;
1081		struct in6_addr ans6;
1082		memset(&ans6, 0, sizeof(ans6));
1083
1084		TT_BLATHER(("Got question about %s, type=%d", qname, qtype));
1085
1086		if (qtype == EVDNS_TYPE_A &&
1087		    qclass == EVDNS_CLASS_INET &&
1088		    !evutil_ascii_strcasecmp(qname, "nobodaddy.example.com")) {
1089			ans.s_addr = htonl(0x7f000001);
1090			evdns_server_request_add_a_reply(req, qname,
1091			    1, &ans.s_addr, 2000);
1092			added_any = 1;
1093		} else if (!evutil_ascii_strcasecmp(qname,
1094			"nosuchplace.example.com")) {
1095			/* ok, just say notfound. */
1096		} else if (!evutil_ascii_strcasecmp(qname,
1097			"both.example.com")) {
1098			if (qtype == EVDNS_TYPE_A) {
1099				ans.s_addr = htonl(0x50502020);
1100				evdns_server_request_add_a_reply(req, qname,
1101				    1, &ans.s_addr, 2000);
1102				added_any = 1;
1103			} else if (qtype == EVDNS_TYPE_AAAA) {
1104				ans6.s6_addr[0] = 0x80;
1105				ans6.s6_addr[1] = 0xff;
1106				ans6.s6_addr[14] = 0xbb;
1107				ans6.s6_addr[15] = 0xbb;
1108				evdns_server_request_add_aaaa_reply(req, qname,
1109				    1, &ans6.s6_addr, 2000);
1110				added_any = 1;
1111			}
1112			evdns_server_request_add_cname_reply(req, qname,
1113			    "both-canonical.example.com", 1000);
1114		} else if (!evutil_ascii_strcasecmp(qname,
1115			"v4only.example.com") ||
1116		    !evutil_ascii_strcasecmp(qname, "v4assert.example.com")) {
1117			if (qtype == EVDNS_TYPE_A) {
1118				ans.s_addr = htonl(0x12345678);
1119				evdns_server_request_add_a_reply(req, qname,
1120				    1, &ans.s_addr, 2000);
1121				added_any = 1;
1122			} else if (!evutil_ascii_strcasecmp(qname,
1123				"v4assert.example.com")) {
1124				TT_FAIL(("Got an AAAA request for v4assert"));
1125			}
1126		} else if (!evutil_ascii_strcasecmp(qname,
1127			"v6only.example.com") ||
1128		    !evutil_ascii_strcasecmp(qname, "v6assert.example.com")) {
1129			if (qtype == EVDNS_TYPE_AAAA) {
1130				ans6.s6_addr[0] = 0x0b;
1131				ans6.s6_addr[1] = 0x0b;
1132				ans6.s6_addr[14] = 0xf0;
1133				ans6.s6_addr[15] = 0x0d;
1134				evdns_server_request_add_aaaa_reply(req, qname,
1135				    1, &ans6.s6_addr, 2000);
1136				added_any = 1;
1137			}  else if (!evutil_ascii_strcasecmp(qname,
1138				"v6assert.example.com")) {
1139				TT_FAIL(("Got a A request for v6assert"));
1140			}
1141		} else if (!evutil_ascii_strcasecmp(qname,
1142			"v6timeout.example.com")) {
1143			if (qtype == EVDNS_TYPE_A) {
1144				ans.s_addr = htonl(0xabcdef01);
1145				evdns_server_request_add_a_reply(req, qname,
1146				    1, &ans.s_addr, 2000);
1147				added_any = 1;
1148			} else if (qtype == EVDNS_TYPE_AAAA) {
1149				/* Let the v6 request time out.*/
1150				evdns_server_request_drop(req);
1151				return;
1152			}
1153		} else if (!evutil_ascii_strcasecmp(qname,
1154			"v4timeout.example.com")) {
1155			if (qtype == EVDNS_TYPE_AAAA) {
1156				ans6.s6_addr[0] = 0x0a;
1157				ans6.s6_addr[1] = 0x0a;
1158				ans6.s6_addr[14] = 0xff;
1159				ans6.s6_addr[15] = 0x01;
1160				evdns_server_request_add_aaaa_reply(req, qname,
1161				    1, &ans6.s6_addr, 2000);
1162				added_any = 1;
1163			} else if (qtype == EVDNS_TYPE_A) {
1164				/* Let the v4 request time out.*/
1165				evdns_server_request_drop(req);
1166				return;
1167			}
1168		} else if (!evutil_ascii_strcasecmp(qname,
1169			"v6timeout-nonexist.example.com")) {
1170			if (qtype == EVDNS_TYPE_A) {
1171				/* Fall through, give an nexist. */
1172			} else if (qtype == EVDNS_TYPE_AAAA) {
1173				/* Let the v6 request time out.*/
1174				evdns_server_request_drop(req);
1175				return;
1176			}
1177		} else if (!evutil_ascii_strcasecmp(qname,
1178			"all-timeout.example.com")) {
1179			/* drop all requests */
1180			evdns_server_request_drop(req);
1181			return;
1182		} else {
1183			TT_GRIPE(("Got weird request for %s",qname));
1184		}
1185	}
1186	if (added_any) {
1187		TT_BLATHER(("answering"));
1188		evdns_server_request_respond(req, 0);
1189	} else {
1190		TT_BLATHER(("saying nexist."));
1191		evdns_server_request_respond(req, 3);
1192	}
1193}
1194
1195/* Implements a listener for connect_hostname test. */
1196static void
1197nil_accept_cb(struct evconnlistener *l, evutil_socket_t fd, struct sockaddr *s,
1198    int socklen, void *arg)
1199{
1200	int *p = arg;
1201	(*p)++;
1202	++total_n_accepted;
1203	/* don't do anything with the socket; let it close when we exit() */
1204	if (total_n_accepted >= 3 && total_connected_or_failed >= 5)
1205		event_base_loopexit(be_connect_hostname_base,
1206		    NULL);
1207}
1208
1209struct be_conn_hostname_result {
1210	int dnserr;
1211	int what;
1212};
1213
1214/* Bufferevent event callback for the connect_hostname test: remembers what
1215 * event we got. */
1216static void
1217be_connect_hostname_event_cb(struct bufferevent *bev, short what, void *ctx)
1218{
1219	struct be_conn_hostname_result *got = ctx;
1220
1221	if (got->what) {
1222		TT_FAIL(("Two events on one bufferevent. %d,%d",
1223			got->what, (int)what));
1224	}
1225
1226	TT_BLATHER(("Got a bufferevent event %d", what));
1227	got->what = what;
1228
1229	if ((what & BEV_EVENT_CONNECTED) || (what & BEV_EVENT_ERROR)) {
1230		int expected = 3;
1231		int r = bufferevent_socket_get_dns_error(bev);
1232
1233		if (r) {
1234			got->dnserr = r;
1235			TT_BLATHER(("DNS error %d: %s", r,
1236				   evutil_gai_strerror(r)));
1237		}
1238		++total_connected_or_failed;
1239		TT_BLATHER(("Got %d connections or errors.", total_connected_or_failed));
1240
1241		/** emfile test */
1242		if (errno == EMFILE) {
1243			expected = 0;
1244		}
1245
1246		if (total_n_accepted >= expected && total_connected_or_failed >= 5)
1247			event_base_loopexit(be_connect_hostname_base,
1248			    NULL);
1249	}
1250}
1251
1252static void
1253test_bufferevent_connect_hostname(void *arg)
1254{
1255	struct basic_test_data *data = arg;
1256	struct evconnlistener *listener = NULL;
1257	struct bufferevent *be[5];
1258	struct be_conn_hostname_result be_outcome[ARRAY_SIZE(be)];
1259	int expect_err;
1260	struct evdns_base *dns=NULL;
1261	struct evdns_server_port *port=NULL;
1262	struct sockaddr_in sin;
1263	int listener_port=-1;
1264	ev_uint16_t dns_port=0;
1265	int n_accept=0, n_dns=0;
1266	char buf[128];
1267	int emfile = data->setup_data && !strcmp(data->setup_data, "emfile");
1268	unsigned i;
1269	int ret;
1270
1271	be_connect_hostname_base = data->base;
1272
1273	/* Bind an address and figure out what port it's on. */
1274	memset(&sin, 0, sizeof(sin));
1275	sin.sin_family = AF_INET;
1276	sin.sin_addr.s_addr = htonl(0x7f000001); /* 127.0.0.1 */
1277	sin.sin_port = 0;
1278	listener = evconnlistener_new_bind(data->base, nil_accept_cb,
1279	    &n_accept,
1280	    LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_EXEC,
1281	    -1, (struct sockaddr *)&sin, sizeof(sin));
1282	tt_assert(listener);
1283	listener_port = regress_get_socket_port(
1284		evconnlistener_get_fd(listener));
1285
1286	port = regress_get_dnsserver(data->base, &dns_port, NULL,
1287	    be_getaddrinfo_server_cb, &n_dns);
1288	tt_assert(port);
1289	tt_int_op(dns_port, >=, 0);
1290
1291	/* Start an evdns_base that uses the server as its resolver. */
1292	dns = evdns_base_new(data->base, 0);
1293	evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)dns_port);
1294	evdns_base_nameserver_ip_add(dns, buf);
1295
1296#ifdef EVENT__HAVE_SETRLIMIT
1297	if (emfile) {
1298		int fd = socket(AF_INET, SOCK_STREAM, 0);
1299		struct rlimit file = { fd, fd };
1300
1301		tt_int_op(fd, >=, 0);
1302		tt_assert(!close(fd));
1303
1304		tt_assert(!setrlimit(RLIMIT_NOFILE, &file));
1305	}
1306#endif
1307
1308	/* Now, finally, at long last, launch the bufferevents.	 One should do
1309	 * a failing lookup IP, one should do a successful lookup by IP,
1310	 * and one should do a successful lookup by hostname. */
1311	for (i = 0; i < ARRAY_SIZE(be); ++i) {
1312		memset(&be_outcome[i], 0, sizeof(be_outcome[i]));
1313		be[i] = bufferevent_socket_new(data->base, -1, BEV_OPT_CLOSE_ON_FREE);
1314		bufferevent_setcb(be[i], NULL, NULL, be_connect_hostname_event_cb,
1315			&be_outcome[i]);
1316	}
1317
1318	/* Use the blocking resolver.  This one will fail if your resolver
1319	 * can't resolve localhost to 127.0.0.1 */
1320	tt_assert(!bufferevent_socket_connect_hostname(be[3], NULL, AF_INET,
1321		"localhost", listener_port));
1322	/* Use the blocking resolver with a nonexistent hostname. */
1323	tt_assert(!bufferevent_socket_connect_hostname(be[4], NULL, AF_INET,
1324		"nonesuch.nowhere.example.com", 80));
1325	{
1326		/* The blocking resolver will use the system nameserver, which
1327		 * might tell us anything.  (Yes, some twits even pretend that
1328		 * example.com is real.) Let's see what answer to expect. */
1329		struct evutil_addrinfo hints, *ai = NULL;
1330		memset(&hints, 0, sizeof(hints));
1331		hints.ai_family = AF_INET;
1332		hints.ai_socktype = SOCK_STREAM;
1333		hints.ai_protocol = IPPROTO_TCP;
1334		expect_err = evutil_getaddrinfo(
1335			"nonesuch.nowhere.example.com", "80", &hints, &ai);
1336	}
1337	/* Launch an async resolve that will fail. */
1338	tt_assert(!bufferevent_socket_connect_hostname(be[0], dns, AF_INET,
1339		"nosuchplace.example.com", listener_port));
1340	/* Connect to the IP without resolving. */
1341	tt_assert(!bufferevent_socket_connect_hostname(be[1], dns, AF_INET,
1342		"127.0.0.1", listener_port));
1343	/* Launch an async resolve that will succeed. */
1344	tt_assert(!bufferevent_socket_connect_hostname(be[2], dns, AF_INET,
1345		"nobodaddy.example.com", listener_port));
1346
1347	ret = event_base_dispatch(data->base);
1348#ifdef __sun__
1349	if (emfile && !strcmp(event_base_get_method(data->base), "devpoll")) {
1350		tt_int_op(ret, ==, -1);
1351		/** DP_POLL failed */
1352		tt_skip();
1353	} else
1354#endif
1355	{
1356		tt_int_op(ret, ==, 0);
1357	}
1358
1359	tt_int_op(be_outcome[0].what, ==, BEV_EVENT_ERROR);
1360	tt_int_op(be_outcome[0].dnserr, ==, EVUTIL_EAI_NONAME);
1361	tt_int_op(be_outcome[1].what, ==, !emfile ? BEV_EVENT_CONNECTED : BEV_EVENT_ERROR);
1362	tt_int_op(be_outcome[1].dnserr, ==, 0);
1363	tt_int_op(be_outcome[2].what, ==, !emfile ? BEV_EVENT_CONNECTED : BEV_EVENT_ERROR);
1364	tt_int_op(be_outcome[2].dnserr, ==, 0);
1365	tt_int_op(be_outcome[3].what, ==, !emfile ? BEV_EVENT_CONNECTED : BEV_EVENT_ERROR);
1366	if (!emfile) {
1367		tt_int_op(be_outcome[3].dnserr, ==, 0);
1368	} else {
1369		tt_int_op(be_outcome[3].dnserr, !=, 0);
1370	}
1371	if (expect_err) {
1372		tt_int_op(be_outcome[4].what, ==, BEV_EVENT_ERROR);
1373		tt_int_op(be_outcome[4].dnserr, ==, expect_err);
1374	}
1375
1376	if (emfile) {
1377		tt_int_op(n_accept, ==, 0);
1378	} else {
1379		tt_int_op(n_accept, ==, 3);
1380	}
1381	tt_int_op(n_dns, ==, 2);
1382
1383end:
1384	if (listener)
1385		evconnlistener_free(listener);
1386	if (port)
1387		evdns_close_server_port(port);
1388	if (dns)
1389		evdns_base_free(dns, 0);
1390	for (i = 0; i < ARRAY_SIZE(be); ++i) {
1391		if (be[i])
1392			bufferevent_free(be[i]);
1393	}
1394}
1395
1396
1397struct gai_outcome {
1398	int err;
1399	struct evutil_addrinfo *ai;
1400};
1401
1402static int n_gai_results_pending = 0;
1403static struct event_base *exit_base_on_no_pending_results = NULL;
1404
1405static void
1406gai_cb(int err, struct evutil_addrinfo *res, void *ptr)
1407{
1408	struct gai_outcome *go = ptr;
1409	go->err = err;
1410	go->ai = res;
1411	if (--n_gai_results_pending <= 0 && exit_base_on_no_pending_results)
1412		event_base_loopexit(exit_base_on_no_pending_results, NULL);
1413	if (n_gai_results_pending < 900)
1414		TT_BLATHER(("Got an answer; expecting %d more.",
1415			n_gai_results_pending));
1416}
1417
1418static void
1419cancel_gai_cb(evutil_socket_t fd, short what, void *ptr)
1420{
1421	struct evdns_getaddrinfo_request *r = ptr;
1422	evdns_getaddrinfo_cancel(r);
1423}
1424
1425static void
1426test_getaddrinfo_async(void *arg)
1427{
1428	struct basic_test_data *data = arg;
1429	struct evutil_addrinfo hints, *a;
1430	struct gai_outcome local_outcome;
1431	struct gai_outcome a_out[12];
1432	unsigned i;
1433	struct evdns_getaddrinfo_request *r;
1434	char buf[128];
1435	struct evdns_server_port *port = NULL;
1436	ev_uint16_t dns_port = 0;
1437	int n_dns_questions = 0;
1438	struct evdns_base *dns_base;
1439
1440	memset(a_out, 0, sizeof(a_out));
1441	memset(&local_outcome, 0, sizeof(local_outcome));
1442
1443	dns_base = evdns_base_new(data->base, 0);
1444	tt_assert(dns_base);
1445
1446	/* for localhost */
1447	evdns_base_load_hosts(dns_base, NULL);
1448
1449	tt_assert(! evdns_base_set_option(dns_base, "timeout", "0.3"));
1450	tt_assert(! evdns_base_set_option(dns_base, "getaddrinfo-allow-skew", "0.2"));
1451
1452	n_gai_results_pending = 10000; /* don't think about exiting yet. */
1453
1454	/* 1. Try some cases that will never hit the asynchronous resolver. */
1455	/* 1a. Simple case with a symbolic service name */
1456	memset(&hints, 0, sizeof(hints));
1457	hints.ai_family = PF_UNSPEC;
1458	hints.ai_socktype = SOCK_STREAM;
1459	memset(&local_outcome, 0, sizeof(local_outcome));
1460	r = evdns_getaddrinfo(dns_base, "1.2.3.4", "http",
1461	    &hints, gai_cb, &local_outcome);
1462	tt_assert(! r);
1463	if (!local_outcome.err) {
1464		tt_ptr_op(local_outcome.ai,!=,NULL);
1465		test_ai_eq(local_outcome.ai, "1.2.3.4:80", SOCK_STREAM, IPPROTO_TCP);
1466		evutil_freeaddrinfo(local_outcome.ai);
1467		local_outcome.ai = NULL;
1468	} else {
1469		TT_BLATHER(("Apparently we have no getservbyname."));
1470	}
1471
1472	/* 1b. EVUTIL_AI_NUMERICHOST is set */
1473	memset(&hints, 0, sizeof(hints));
1474	hints.ai_family = PF_UNSPEC;
1475	hints.ai_flags = EVUTIL_AI_NUMERICHOST;
1476	memset(&local_outcome, 0, sizeof(local_outcome));
1477	r = evdns_getaddrinfo(dns_base, "www.google.com", "80",
1478	    &hints, gai_cb, &local_outcome);
1479	tt_ptr_op(r,==,NULL);
1480	tt_int_op(local_outcome.err,==,EVUTIL_EAI_NONAME);
1481	tt_ptr_op(local_outcome.ai,==,NULL);
1482
1483	/* 1c. We give a numeric address (ipv6) */
1484	memset(&hints, 0, sizeof(hints));
1485	memset(&local_outcome, 0, sizeof(local_outcome));
1486	hints.ai_family = PF_UNSPEC;
1487	hints.ai_protocol = IPPROTO_TCP;
1488	r = evdns_getaddrinfo(dns_base, "f::f", "8008",
1489	    &hints, gai_cb, &local_outcome);
1490	tt_assert(!r);
1491	tt_int_op(local_outcome.err,==,0);
1492	tt_assert(local_outcome.ai);
1493	tt_ptr_op(local_outcome.ai->ai_next,==,NULL);
1494	test_ai_eq(local_outcome.ai, "[f::f]:8008", SOCK_STREAM, IPPROTO_TCP);
1495	evutil_freeaddrinfo(local_outcome.ai);
1496	local_outcome.ai = NULL;
1497
1498	/* 1d. We give a numeric address (ipv4) */
1499	memset(&hints, 0, sizeof(hints));
1500	memset(&local_outcome, 0, sizeof(local_outcome));
1501	hints.ai_family = PF_UNSPEC;
1502	r = evdns_getaddrinfo(dns_base, "5.6.7.8", NULL,
1503	    &hints, gai_cb, &local_outcome);
1504	tt_assert(!r);
1505	tt_int_op(local_outcome.err,==,0);
1506	tt_assert(local_outcome.ai);
1507	a = ai_find_by_protocol(local_outcome.ai, IPPROTO_TCP);
1508	tt_assert(a);
1509	test_ai_eq(a, "5.6.7.8", SOCK_STREAM, IPPROTO_TCP);
1510	a = ai_find_by_protocol(local_outcome.ai, IPPROTO_UDP);
1511	tt_assert(a);
1512	test_ai_eq(a, "5.6.7.8", SOCK_DGRAM, IPPROTO_UDP);
1513	evutil_freeaddrinfo(local_outcome.ai);
1514	local_outcome.ai = NULL;
1515
1516	/* 1e. nodename is NULL (bind) */
1517	memset(&hints, 0, sizeof(hints));
1518	memset(&local_outcome, 0, sizeof(local_outcome));
1519	hints.ai_family = PF_UNSPEC;
1520	hints.ai_socktype = SOCK_DGRAM;
1521	hints.ai_flags = EVUTIL_AI_PASSIVE;
1522	r = evdns_getaddrinfo(dns_base, NULL, "9090",
1523	    &hints, gai_cb, &local_outcome);
1524	tt_assert(!r);
1525	tt_int_op(local_outcome.err,==,0);
1526	tt_assert(local_outcome.ai);
1527	/* we should get a v4 address of 0.0.0.0... */
1528	a = ai_find_by_family(local_outcome.ai, PF_INET);
1529	tt_assert(a);
1530	test_ai_eq(a, "0.0.0.0:9090", SOCK_DGRAM, IPPROTO_UDP);
1531	/* ... and a v6 address of ::0 */
1532	a = ai_find_by_family(local_outcome.ai, PF_INET6);
1533	tt_assert(a);
1534	test_ai_eq(a, "[::]:9090", SOCK_DGRAM, IPPROTO_UDP);
1535	evutil_freeaddrinfo(local_outcome.ai);
1536	local_outcome.ai = NULL;
1537
1538	/* 1f. nodename is NULL (connect) */
1539	memset(&hints, 0, sizeof(hints));
1540	memset(&local_outcome, 0, sizeof(local_outcome));
1541	hints.ai_family = PF_UNSPEC;
1542	hints.ai_socktype = SOCK_STREAM;
1543	r = evdns_getaddrinfo(dns_base, NULL, "2",
1544	    &hints, gai_cb, &local_outcome);
1545	tt_assert(!r);
1546	tt_int_op(local_outcome.err,==,0);
1547	tt_assert(local_outcome.ai);
1548	/* we should get a v4 address of 127.0.0.1 .... */
1549	a = ai_find_by_family(local_outcome.ai, PF_INET);
1550	tt_assert(a);
1551	test_ai_eq(a, "127.0.0.1:2", SOCK_STREAM, IPPROTO_TCP);
1552	/* ... and a v6 address of ::1 */
1553	a = ai_find_by_family(local_outcome.ai, PF_INET6);
1554	tt_assert(a);
1555	test_ai_eq(a, "[::1]:2", SOCK_STREAM, IPPROTO_TCP);
1556	evutil_freeaddrinfo(local_outcome.ai);
1557	local_outcome.ai = NULL;
1558
1559	/* 1g. We find localhost immediately. (pf_unspec) */
1560	memset(&hints, 0, sizeof(hints));
1561	memset(&local_outcome, 0, sizeof(local_outcome));
1562	hints.ai_family = PF_UNSPEC;
1563	hints.ai_socktype = SOCK_STREAM;
1564	r = evdns_getaddrinfo(dns_base, "LOCALHOST", "80",
1565	    &hints, gai_cb, &local_outcome);
1566	tt_assert(!r);
1567	tt_int_op(local_outcome.err,==,0);
1568	tt_assert(local_outcome.ai);
1569	/* we should get a v4 address of 127.0.0.1 .... */
1570	a = ai_find_by_family(local_outcome.ai, PF_INET);
1571	tt_assert(a);
1572	test_ai_eq(a, "127.0.0.1:80", SOCK_STREAM, IPPROTO_TCP);
1573	/* ... and a v6 address of ::1 */
1574	a = ai_find_by_family(local_outcome.ai, PF_INET6);
1575	tt_assert(a);
1576	test_ai_eq(a, "[::1]:80", SOCK_STREAM, IPPROTO_TCP);
1577	evutil_freeaddrinfo(local_outcome.ai);
1578	local_outcome.ai = NULL;
1579
1580	/* 1g. We find localhost immediately. (pf_inet6) */
1581	memset(&hints, 0, sizeof(hints));
1582	memset(&local_outcome, 0, sizeof(local_outcome));
1583	hints.ai_family = PF_INET6;
1584	hints.ai_socktype = SOCK_STREAM;
1585	r = evdns_getaddrinfo(dns_base, "LOCALHOST", "9999",
1586	    &hints, gai_cb, &local_outcome);
1587	tt_assert(! r);
1588	tt_int_op(local_outcome.err,==,0);
1589	tt_assert(local_outcome.ai);
1590	a = local_outcome.ai;
1591	test_ai_eq(a, "[::1]:9999", SOCK_STREAM, IPPROTO_TCP);
1592	tt_ptr_op(a->ai_next, ==, NULL);
1593	evutil_freeaddrinfo(local_outcome.ai);
1594	local_outcome.ai = NULL;
1595
1596	/* 2. Okay, now we can actually test the asynchronous resolver. */
1597	/* Start a dummy local dns server... */
1598	port = regress_get_dnsserver(data->base, &dns_port, NULL,
1599	    be_getaddrinfo_server_cb, &n_dns_questions);
1600	tt_assert(port);
1601	tt_int_op(dns_port, >=, 0);
1602	/* ... and tell the evdns_base about it. */
1603	evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", dns_port);
1604	evdns_base_nameserver_ip_add(dns_base, buf);
1605
1606	memset(&hints, 0, sizeof(hints));
1607	hints.ai_family = PF_UNSPEC;
1608	hints.ai_socktype = SOCK_STREAM;
1609	hints.ai_flags = EVUTIL_AI_CANONNAME;
1610	/* 0: Request for both.example.com should return both addresses. */
1611	r = evdns_getaddrinfo(dns_base, "both.example.com", "8000",
1612	    &hints, gai_cb, &a_out[0]);
1613	tt_assert(r);
1614
1615	/* 1: Request for v4only.example.com should return one address. */
1616	r = evdns_getaddrinfo(dns_base, "v4only.example.com", "8001",
1617	    &hints, gai_cb, &a_out[1]);
1618	tt_assert(r);
1619
1620	/* 2: Request for v6only.example.com should return one address. */
1621	hints.ai_flags = 0;
1622	r = evdns_getaddrinfo(dns_base, "v6only.example.com", "8002",
1623	    &hints, gai_cb, &a_out[2]);
1624	tt_assert(r);
1625
1626	/* 3: PF_INET request for v4assert.example.com should not generate a
1627	 * v6 request.	The server will fail the test if it does. */
1628	hints.ai_family = PF_INET;
1629	r = evdns_getaddrinfo(dns_base, "v4assert.example.com", "8003",
1630	    &hints, gai_cb, &a_out[3]);
1631	tt_assert(r);
1632
1633	/* 4: PF_INET6 request for v6assert.example.com should not generate a
1634	 * v4 request.	The server will fail the test if it does. */
1635	hints.ai_family = PF_INET6;
1636	r = evdns_getaddrinfo(dns_base, "v6assert.example.com", "8004",
1637	    &hints, gai_cb, &a_out[4]);
1638	tt_assert(r);
1639
1640	/* 5: PF_INET request for nosuchplace.example.com should give NEXIST. */
1641	hints.ai_family = PF_INET;
1642	r = evdns_getaddrinfo(dns_base, "nosuchplace.example.com", "8005",
1643	    &hints, gai_cb, &a_out[5]);
1644	tt_assert(r);
1645
1646	/* 6: PF_UNSPEC request for nosuchplace.example.com should give NEXIST.
1647	 */
1648	hints.ai_family = PF_UNSPEC;
1649	r = evdns_getaddrinfo(dns_base, "nosuchplace.example.com", "8006",
1650	    &hints, gai_cb, &a_out[6]);
1651	tt_assert(r);
1652
1653	/* 7: PF_UNSPEC request for v6timeout.example.com should give an ipv4
1654	 * address only. */
1655	hints.ai_family = PF_UNSPEC;
1656	r = evdns_getaddrinfo(dns_base, "v6timeout.example.com", "8007",
1657	    &hints, gai_cb, &a_out[7]);
1658	tt_assert(r);
1659
1660	/* 8: PF_UNSPEC request for v6timeout-nonexist.example.com should give
1661	 * a NEXIST */
1662	hints.ai_family = PF_UNSPEC;
1663	r = evdns_getaddrinfo(dns_base, "v6timeout-nonexist.example.com",
1664	    "8008", &hints, gai_cb, &a_out[8]);
1665	tt_assert(r);
1666
1667	/* 9: AI_ADDRCONFIG should at least not crash.	Can't test it more
1668	 * without knowing what kind of internet we have. */
1669	hints.ai_flags |= EVUTIL_AI_ADDRCONFIG;
1670	r = evdns_getaddrinfo(dns_base, "both.example.com",
1671	    "8009", &hints, gai_cb, &a_out[9]);
1672	tt_assert(r);
1673
1674	/* 10: PF_UNSPEC for v4timeout.example.com should give an ipv6 address
1675	 * only. */
1676	hints.ai_family = PF_UNSPEC;
1677	hints.ai_flags = 0;
1678	r = evdns_getaddrinfo(dns_base, "v4timeout.example.com", "8010",
1679	    &hints, gai_cb, &a_out[10]);
1680	tt_assert(r);
1681
1682	/* 11: timeout.example.com: cancel it after 100 msec. */
1683	r = evdns_getaddrinfo(dns_base, "all-timeout.example.com", "8011",
1684	    &hints, gai_cb, &a_out[11]);
1685	tt_assert(r);
1686	{
1687		struct timeval tv;
1688		tv.tv_sec = 0;
1689		tv.tv_usec = 100*1000; /* 100 msec */
1690		event_base_once(data->base, -1, EV_TIMEOUT, cancel_gai_cb,
1691		    r, &tv);
1692	}
1693
1694	/* XXXXX There are more tests we could do, including:
1695
1696	   - A test to elicit NODATA.
1697
1698	 */
1699
1700	n_gai_results_pending = 12;
1701	exit_base_on_no_pending_results = data->base;
1702
1703	event_base_dispatch(data->base);
1704
1705	/* 0: both.example.com */
1706	tt_int_op(a_out[0].err, ==, 0);
1707	tt_assert(a_out[0].ai);
1708	tt_assert(a_out[0].ai->ai_next);
1709	tt_assert(!a_out[0].ai->ai_next->ai_next);
1710	a = ai_find_by_family(a_out[0].ai, PF_INET);
1711	tt_assert(a);
1712	test_ai_eq(a, "80.80.32.32:8000", SOCK_STREAM, IPPROTO_TCP);
1713	a = ai_find_by_family(a_out[0].ai, PF_INET6);
1714	tt_assert(a);
1715	test_ai_eq(a, "[80ff::bbbb]:8000", SOCK_STREAM, IPPROTO_TCP);
1716	tt_assert(a_out[0].ai->ai_canonname);
1717	tt_str_op(a_out[0].ai->ai_canonname, ==, "both-canonical.example.com");
1718
1719	/* 1: v4only.example.com */
1720	tt_int_op(a_out[1].err, ==, 0);
1721	tt_assert(a_out[1].ai);
1722	tt_assert(! a_out[1].ai->ai_next);
1723	test_ai_eq(a_out[1].ai, "18.52.86.120:8001", SOCK_STREAM, IPPROTO_TCP);
1724	tt_assert(a_out[1].ai->ai_canonname == NULL);
1725
1726
1727	/* 2: v6only.example.com */
1728	tt_int_op(a_out[2].err, ==, 0);
1729	tt_assert(a_out[2].ai);
1730	tt_assert(! a_out[2].ai->ai_next);
1731	test_ai_eq(a_out[2].ai, "[b0b::f00d]:8002", SOCK_STREAM, IPPROTO_TCP);
1732
1733	/* 3: v4assert.example.com */
1734	tt_int_op(a_out[3].err, ==, 0);
1735	tt_assert(a_out[3].ai);
1736	tt_assert(! a_out[3].ai->ai_next);
1737	test_ai_eq(a_out[3].ai, "18.52.86.120:8003", SOCK_STREAM, IPPROTO_TCP);
1738
1739	/* 4: v6assert.example.com */
1740	tt_int_op(a_out[4].err, ==, 0);
1741	tt_assert(a_out[4].ai);
1742	tt_assert(! a_out[4].ai->ai_next);
1743	test_ai_eq(a_out[4].ai, "[b0b::f00d]:8004", SOCK_STREAM, IPPROTO_TCP);
1744
1745	/* 5: nosuchplace.example.com (inet) */
1746	tt_int_op(a_out[5].err, ==, EVUTIL_EAI_NONAME);
1747	tt_assert(! a_out[5].ai);
1748
1749	/* 6: nosuchplace.example.com (unspec) */
1750	tt_int_op(a_out[6].err, ==, EVUTIL_EAI_NONAME);
1751	tt_assert(! a_out[6].ai);
1752
1753	/* 7: v6timeout.example.com */
1754	tt_int_op(a_out[7].err, ==, 0);
1755	tt_assert(a_out[7].ai);
1756	tt_assert(! a_out[7].ai->ai_next);
1757	test_ai_eq(a_out[7].ai, "171.205.239.1:8007", SOCK_STREAM, IPPROTO_TCP);
1758
1759	/* 8: v6timeout-nonexist.example.com */
1760	tt_int_op(a_out[8].err, ==, EVUTIL_EAI_NONAME);
1761	tt_assert(! a_out[8].ai);
1762
1763	/* 9: both (ADDRCONFIG) */
1764	tt_int_op(a_out[9].err, ==, 0);
1765	tt_assert(a_out[9].ai);
1766	a = ai_find_by_family(a_out[9].ai, PF_INET);
1767	if (a)
1768		test_ai_eq(a, "80.80.32.32:8009", SOCK_STREAM, IPPROTO_TCP);
1769	else
1770		tt_assert(ai_find_by_family(a_out[9].ai, PF_INET6));
1771	a = ai_find_by_family(a_out[9].ai, PF_INET6);
1772	if (a)
1773		test_ai_eq(a, "[80ff::bbbb]:8009", SOCK_STREAM, IPPROTO_TCP);
1774	else
1775		tt_assert(ai_find_by_family(a_out[9].ai, PF_INET));
1776
1777	/* 10: v4timeout.example.com */
1778	tt_int_op(a_out[10].err, ==, 0);
1779	tt_assert(a_out[10].ai);
1780	tt_assert(! a_out[10].ai->ai_next);
1781	test_ai_eq(a_out[10].ai, "[a0a::ff01]:8010", SOCK_STREAM, IPPROTO_TCP);
1782
1783	/* 11: cancelled request. */
1784	tt_int_op(a_out[11].err, ==, EVUTIL_EAI_CANCEL);
1785	tt_assert(a_out[11].ai == NULL);
1786
1787end:
1788	if (local_outcome.ai)
1789		evutil_freeaddrinfo(local_outcome.ai);
1790	for (i = 0; i < ARRAY_SIZE(a_out); ++i) {
1791		if (a_out[i].ai)
1792			evutil_freeaddrinfo(a_out[i].ai);
1793	}
1794	if (port)
1795		evdns_close_server_port(port);
1796	if (dns_base)
1797		evdns_base_free(dns_base, 0);
1798}
1799
1800struct gaic_request_status {
1801	int magic;
1802	struct event_base *base;
1803	struct evdns_base *dns_base;
1804	struct evdns_getaddrinfo_request *request;
1805	struct event cancel_event;
1806	int canceled;
1807};
1808
1809#define GAIC_MAGIC 0x1234abcd
1810
1811static int gaic_pending = 0;
1812static int gaic_freed = 0;
1813
1814static void
1815gaic_cancel_request_cb(evutil_socket_t fd, short what, void *arg)
1816{
1817	struct gaic_request_status *status = arg;
1818
1819	tt_assert(status->magic == GAIC_MAGIC);
1820	status->canceled = 1;
1821	evdns_getaddrinfo_cancel(status->request);
1822	return;
1823end:
1824	event_base_loopexit(status->base, NULL);
1825}
1826
1827static void
1828gaic_server_cb(struct evdns_server_request *req, void *arg)
1829{
1830	ev_uint32_t answer = 0x7f000001;
1831	tt_assert(req->nquestions);
1832	evdns_server_request_add_a_reply(req, req->questions[0]->name, 1,
1833	    &answer, 100);
1834	evdns_server_request_respond(req, 0);
1835	return;
1836end:
1837	evdns_server_request_respond(req, DNS_ERR_REFUSED);
1838}
1839
1840
1841static void
1842gaic_getaddrinfo_cb(int result, struct evutil_addrinfo *res, void *arg)
1843{
1844	struct gaic_request_status *status = arg;
1845	struct event_base *base = status->base;
1846	tt_assert(status->magic == GAIC_MAGIC);
1847
1848	if (result == EVUTIL_EAI_CANCEL) {
1849		tt_assert(status->canceled);
1850	}
1851	event_del(&status->cancel_event);
1852
1853	memset(status, 0xf0, sizeof(*status));
1854	free(status);
1855
1856end:
1857	if (res)
1858	{
1859		TT_BLATHER(("evutil_freeaddrinfo(%p)", res));
1860		evutil_freeaddrinfo(res);
1861		++gaic_freed;
1862	}
1863	if (--gaic_pending <= 0)
1864		event_base_loopexit(base, NULL);
1865}
1866
1867static void
1868gaic_launch(struct event_base *base, struct evdns_base *dns_base)
1869{
1870	struct gaic_request_status *status = calloc(1,sizeof(*status));
1871	struct timeval tv = { 0, 10000 };
1872	status->magic = GAIC_MAGIC;
1873	status->base = base;
1874	status->dns_base = dns_base;
1875	event_assign(&status->cancel_event, base, -1, 0, gaic_cancel_request_cb,
1876	    status);
1877	status->request = evdns_getaddrinfo(dns_base,
1878	    "foobar.bazquux.example.com", "80", NULL, gaic_getaddrinfo_cb,
1879	    status);
1880	event_add(&status->cancel_event, &tv);
1881	++gaic_pending;
1882}
1883
1884#ifdef EVENT_SET_MEM_FUNCTIONS_IMPLEMENTED
1885/* FIXME: We should move this to regress_main.c if anything else needs it.*/
1886
1887/* Trivial replacements for malloc/free/realloc to check for memory leaks.
1888 * Not threadsafe. */
1889static int allocated_chunks = 0;
1890
1891static void *
1892cnt_malloc(size_t sz)
1893{
1894	allocated_chunks += 1;
1895	return malloc(sz);
1896}
1897
1898static void *
1899cnt_realloc(void *old, size_t sz)
1900{
1901	if (!old)
1902		allocated_chunks += 1;
1903	if (!sz)
1904		allocated_chunks -= 1;
1905	return realloc(old, sz);
1906}
1907
1908static void
1909cnt_free(void *ptr)
1910{
1911	allocated_chunks -= 1;
1912	free(ptr);
1913}
1914
1915struct testleak_env_t {
1916	struct event_base *base;
1917	struct evdns_base *dns_base;
1918	struct evdns_request *req;
1919	struct generic_dns_callback_result r;
1920};
1921
1922static void *
1923testleak_setup(const struct testcase_t *testcase)
1924{
1925	struct testleak_env_t *env;
1926
1927	allocated_chunks = 0;
1928
1929	/* Reset allocation counter, to start allocations from the very beginning.
1930	 * (this will avoid false-positive negative numbers for allocated_chunks)
1931	 */
1932	libevent_global_shutdown();
1933
1934	event_set_mem_functions(cnt_malloc, cnt_realloc, cnt_free);
1935
1936	event_enable_debug_mode();
1937
1938	/* not mm_calloc: we don't want to mess with the count. */
1939	env = calloc(1, sizeof(struct testleak_env_t));
1940	env->base = event_base_new();
1941	env->dns_base = evdns_base_new(env->base, 0);
1942	env->req = evdns_base_resolve_ipv4(
1943		env->dns_base, "example.com", DNS_QUERY_NO_SEARCH,
1944		generic_dns_callback, &env->r);
1945	return env;
1946}
1947
1948static int
1949testleak_cleanup(const struct testcase_t *testcase, void *env_)
1950{
1951	int ok = 0;
1952	struct testleak_env_t *env = env_;
1953	tt_assert(env);
1954#ifdef EVENT__DISABLE_DEBUG_MODE
1955	tt_int_op(allocated_chunks, ==, 0);
1956#else
1957	libevent_global_shutdown();
1958	tt_int_op(allocated_chunks, ==, 0);
1959#endif
1960	ok = 1;
1961end:
1962	if (env) {
1963		if (env->dns_base)
1964			evdns_base_free(env->dns_base, 0);
1965		if (env->base)
1966			event_base_free(env->base);
1967		free(env);
1968	}
1969	return ok;
1970}
1971
1972static struct testcase_setup_t testleak_funcs = {
1973	testleak_setup, testleak_cleanup
1974};
1975
1976static void
1977test_dbg_leak_cancel(void *env_)
1978{
1979	/* cancel, loop, free/dns, free/base */
1980	struct testleak_env_t *env = env_;
1981	int send_err_shutdown = 1;
1982	evdns_cancel_request(env->dns_base, env->req);
1983	env->req = 0;
1984
1985	/* `req` is freed in callback, that's why one loop is required. */
1986	event_base_loop(env->base, EVLOOP_NONBLOCK);
1987
1988	/* send_err_shutdown means nothing as soon as our request is
1989	 * already canceled */
1990	evdns_base_free(env->dns_base, send_err_shutdown);
1991	env->dns_base = 0;
1992	event_base_free(env->base);
1993	env->base = 0;
1994}
1995
1996static void
1997dbg_leak_resume(void *env_, int cancel, int send_err_shutdown)
1998{
1999	/* cancel, loop, free/dns, free/base */
2000	struct testleak_env_t *env = env_;
2001	if (cancel) {
2002		evdns_cancel_request(env->dns_base, env->req);
2003		tt_assert(!evdns_base_resume(env->dns_base));
2004	} else {
2005		/* TODO: No nameservers, request can't be processed, must be errored */
2006		tt_assert(!evdns_base_resume(env->dns_base));
2007	}
2008
2009	event_base_loop(env->base, EVLOOP_NONBLOCK);
2010	/**
2011	 * Because we don't cancel request, and want our callback to recieve
2012	 * DNS_ERR_SHUTDOWN, we use deferred callback, and there was:
2013	 * - one extra malloc(),
2014	 *   @see reply_schedule_callback()
2015	 * - and one missing free
2016	 *   @see request_finished() (req->handle->pending_cb = 1)
2017	 * than we don't need to count in testleak_cleanup(), but we can clean them
2018	 * if we will run loop once again, but *after* evdns base freed.
2019	 */
2020	evdns_base_free(env->dns_base, send_err_shutdown);
2021	env->dns_base = 0;
2022	event_base_loop(env->base, EVLOOP_NONBLOCK);
2023
2024end:
2025	event_base_free(env->base);
2026	env->base = 0;
2027}
2028
2029#define IMPL_DBG_LEAK_RESUME(name, cancel, send_err_shutdown)      \
2030	static void                                                    \
2031	test_dbg_leak_##name##_(void *env_)                            \
2032	{                                                              \
2033		dbg_leak_resume(env_, cancel, send_err_shutdown);          \
2034	}
2035IMPL_DBG_LEAK_RESUME(resume, 0, 0)
2036IMPL_DBG_LEAK_RESUME(cancel_and_resume, 1, 0)
2037IMPL_DBG_LEAK_RESUME(resume_send_err, 0, 1)
2038IMPL_DBG_LEAK_RESUME(cancel_and_resume_send_err, 1, 1)
2039
2040static void
2041test_dbg_leak_shutdown(void *env_)
2042{
2043	/* free/dns, loop, free/base */
2044	struct testleak_env_t *env = env_;
2045	int send_err_shutdown = 1;
2046
2047	/* `req` is freed both with `send_err_shutdown` and without it,
2048	 * the only difference is `evdns_callback` call */
2049	env->req = 0;
2050
2051	evdns_base_free(env->dns_base, send_err_shutdown);
2052	env->dns_base = 0;
2053
2054	/* `req` is freed in callback, that's why one loop is required */
2055	event_base_loop(env->base, EVLOOP_NONBLOCK);
2056	event_base_free(env->base);
2057	env->base = 0;
2058}
2059#endif
2060
2061static void
2062test_getaddrinfo_async_cancel_stress(void *ptr)
2063{
2064	struct event_base *base;
2065	struct evdns_base *dns_base = NULL;
2066	struct evdns_server_port *server = NULL;
2067	evutil_socket_t fd = -1;
2068	struct sockaddr_in sin;
2069	struct sockaddr_storage ss;
2070	ev_socklen_t slen;
2071	unsigned i;
2072
2073	base = event_base_new();
2074	dns_base = evdns_base_new(base, 0);
2075
2076	memset(&sin, 0, sizeof(sin));
2077	sin.sin_family = AF_INET;
2078	sin.sin_port = 0;
2079	sin.sin_addr.s_addr = htonl(0x7f000001);
2080	if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
2081		tt_abort_perror("socket");
2082	}
2083	evutil_make_socket_nonblocking(fd);
2084	if (bind(fd, (struct sockaddr*)&sin, sizeof(sin))<0) {
2085		tt_abort_perror("bind");
2086	}
2087	server = evdns_add_server_port_with_base(base, fd, 0, gaic_server_cb,
2088	    base);
2089
2090	memset(&ss, 0, sizeof(ss));
2091	slen = sizeof(ss);
2092	if (getsockname(fd, (struct sockaddr*)&ss, &slen)<0) {
2093		tt_abort_perror("getsockname");
2094	}
2095	evdns_base_nameserver_sockaddr_add(dns_base,
2096	    (struct sockaddr*)&ss, slen, 0);
2097
2098	for (i = 0; i < 1000; ++i) {
2099		gaic_launch(base, dns_base);
2100	}
2101
2102	event_base_dispatch(base);
2103
2104	// at least some was canceled via external event
2105	tt_int_op(gaic_freed, !=, 1000);
2106
2107end:
2108	if (dns_base)
2109		evdns_base_free(dns_base, 1);
2110	if (server)
2111		evdns_close_server_port(server);
2112	if (base)
2113		event_base_free(base);
2114	if (fd >= 0)
2115		evutil_closesocket(fd);
2116}
2117
2118static void
2119dns_client_fail_requests_test(void *arg)
2120{
2121	struct basic_test_data *data = arg;
2122	struct event_base *base = data->base;
2123	int limit_inflight = data->setup_data && !strcmp(data->setup_data, "limit-inflight");
2124	struct evdns_base *dns = NULL;
2125	struct evdns_server_port *dns_port = NULL;
2126	ev_uint16_t portnum = 0;
2127	char buf[64];
2128
2129	struct generic_dns_callback_result r[20];
2130	unsigned i;
2131
2132	dns_port = regress_get_dnsserver(base, &portnum, NULL,
2133		regress_dns_server_cb, reissue_table);
2134	tt_assert(dns_port);
2135
2136	evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum);
2137
2138	dns = evdns_base_new(base, EVDNS_BASE_DISABLE_WHEN_INACTIVE);
2139	tt_assert(!evdns_base_nameserver_ip_add(dns, buf));
2140
2141	if (limit_inflight)
2142		tt_assert(!evdns_base_set_option(dns, "max-inflight:", "11"));
2143
2144	for (i = 0; i < 20; ++i)
2145		evdns_base_resolve_ipv4(dns, "foof.example.com", 0, generic_dns_callback, &r[i]);
2146
2147	n_replies_left = 20;
2148	exit_base = base;
2149
2150	evdns_base_free(dns, 1 /** fail requests */);
2151	/** run defered callbacks, to trigger UAF */
2152	event_base_dispatch(base);
2153
2154	tt_int_op(n_replies_left, ==, 0);
2155	for (i = 0; i < 20; ++i)
2156		tt_int_op(r[i].result, ==, DNS_ERR_SHUTDOWN);
2157
2158end:
2159	evdns_close_server_port(dns_port);
2160}
2161
2162static void
2163getaddrinfo_cb(int err, struct evutil_addrinfo *res, void *ptr)
2164{
2165	generic_dns_callback(err, 0, 0, 0, NULL, ptr);
2166}
2167static void
2168dns_client_fail_requests_getaddrinfo_test(void *arg)
2169{
2170	struct basic_test_data *data = arg;
2171	struct event_base *base = data->base;
2172	struct evdns_base *dns = NULL;
2173	struct evdns_server_port *dns_port = NULL;
2174	ev_uint16_t portnum = 0;
2175	char buf[64];
2176
2177	struct generic_dns_callback_result r[20];
2178	int i;
2179
2180	dns_port = regress_get_dnsserver(base, &portnum, NULL,
2181		regress_dns_server_cb, reissue_table);
2182	tt_assert(dns_port);
2183
2184	evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum);
2185
2186	dns = evdns_base_new(base, EVDNS_BASE_DISABLE_WHEN_INACTIVE);
2187	tt_assert(!evdns_base_nameserver_ip_add(dns, buf));
2188
2189	for (i = 0; i < 20; ++i)
2190		tt_assert(evdns_getaddrinfo(dns, "foof.example.com", "80", NULL, getaddrinfo_cb, &r[i]));
2191
2192	n_replies_left = 20;
2193	exit_base = base;
2194
2195	evdns_base_free(dns, 1 /** fail requests */);
2196	/** run defered callbacks, to trigger UAF */
2197	event_base_dispatch(base);
2198
2199	tt_int_op(n_replies_left, ==, 0);
2200	for (i = 0; i < 20; ++i)
2201		tt_int_op(r[i].result, ==, EVUTIL_EAI_FAIL);
2202
2203end:
2204	evdns_close_server_port(dns_port);
2205}
2206
2207#ifdef EVTHREAD_USE_PTHREADS_IMPLEMENTED
2208struct race_param
2209{
2210	void *lock;
2211	void *reqs_cmpl_cond;
2212	int bw_threads;
2213	void *bw_threads_exited_cond;
2214	volatile int stopping;
2215	void *base;
2216	void *dns;
2217
2218	int locked;
2219};
2220static void *
2221race_base_run(void *arg)
2222{
2223	struct race_param *rp = (struct race_param *)arg;
2224	event_base_loop(rp->base, EVLOOP_NO_EXIT_ON_EMPTY);
2225	THREAD_RETURN();
2226}
2227static void *
2228race_busywait_run(void *arg)
2229{
2230	struct race_param *rp = (struct race_param *)arg;
2231	struct sockaddr_storage ss;
2232	while (!rp->stopping)
2233		evdns_base_get_nameserver_addr(rp->dns, 0, (struct sockaddr *)&ss, sizeof(ss));
2234	EVLOCK_LOCK(rp->lock, 0);
2235	if (--rp->bw_threads == 0)
2236		EVTHREAD_COND_SIGNAL(rp->bw_threads_exited_cond);
2237	EVLOCK_UNLOCK(rp->lock, 0);
2238	THREAD_RETURN();
2239}
2240static void
2241race_gai_cb(int result, struct evutil_addrinfo *res, void *arg)
2242{
2243	struct race_param *rp = arg;
2244	(void)result;
2245	(void)res;
2246
2247	--n_replies_left;
2248	if (n_replies_left == 0) {
2249		EVLOCK_LOCK(rp->lock, 0);
2250		EVTHREAD_COND_SIGNAL(rp->reqs_cmpl_cond);
2251		EVLOCK_UNLOCK(rp->lock, 0);
2252	}
2253}
2254static void
2255getaddrinfo_race_gotresolve_test(void *arg)
2256{
2257	struct race_param rp;
2258	struct evdns_server_port *dns_port = NULL;
2259	ev_uint16_t portnum = 0;
2260	char buf[64];
2261	int i;
2262
2263	// Some stress is needed to yield inside getaddrinfo between resolve_ipv4 and resolve_ipv6
2264	int n_reqs = 16384;
2265#ifdef _SC_NPROCESSORS_ONLN
2266	int n_threads = sysconf(_SC_NPROCESSORS_ONLN) + 1;
2267#else
2268	int n_threads = 17;
2269#endif
2270	THREAD_T thread[n_threads];
2271	struct timeval tv;
2272
2273	(void)arg;
2274
2275	evthread_use_pthreads();
2276
2277	rp.base = event_base_new();
2278	tt_assert(rp.base);
2279	if (evthread_make_base_notifiable(rp.base) < 0)
2280		tt_abort_msg("Couldn't make base notifiable!");
2281
2282	dns_port = regress_get_dnsserver(rp.base, &portnum, NULL,
2283									 regress_dns_server_cb, reissue_table);
2284	tt_assert(dns_port);
2285
2286	evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum);
2287
2288	rp.dns = evdns_base_new(rp.base, 0);
2289	tt_assert(!evdns_base_nameserver_ip_add(rp.dns, buf));
2290
2291	n_replies_left = n_reqs;
2292
2293	EVTHREAD_ALLOC_LOCK(rp.lock, 0);
2294	EVTHREAD_ALLOC_COND(rp.reqs_cmpl_cond);
2295	EVTHREAD_ALLOC_COND(rp.bw_threads_exited_cond);
2296	tt_assert(rp.lock);
2297	tt_assert(rp.reqs_cmpl_cond);
2298	tt_assert(rp.bw_threads_exited_cond);
2299	rp.bw_threads = 0;
2300	rp.stopping = 0;
2301
2302	// Run resolver thread
2303	THREAD_START(thread[0], race_base_run, &rp);
2304	// Run busy-wait threads used to force yield this thread
2305	for (i = 1; i < n_threads; i++) {
2306		rp.bw_threads++;
2307		THREAD_START(thread[i], race_busywait_run, &rp);
2308	}
2309
2310	EVLOCK_LOCK(rp.lock, 0);
2311	rp.locked = 1;
2312
2313	for (i = 0; i < n_reqs; ++i) {
2314		tt_assert(evdns_getaddrinfo(rp.dns, "foof.example.com", "80", NULL, race_gai_cb, &rp));
2315		// This magic along with busy-wait threads make this thread yield frequently
2316		if (i % 100 == 0) {
2317			tv.tv_sec = 0;
2318			tv.tv_usec = 10000;
2319			evutil_usleep_(&tv);
2320		}
2321	}
2322
2323	exit_base = rp.base;
2324
2325	// Wait for some time
2326	tv.tv_sec = 5;
2327	tv.tv_usec = 0;
2328	EVTHREAD_COND_WAIT_TIMED(rp.reqs_cmpl_cond, rp.lock, &tv);
2329
2330	// Stop busy-wait threads
2331	tv.tv_sec = 1;
2332	tv.tv_usec = 0;
2333	rp.stopping = 1;
2334	tt_assert(EVTHREAD_COND_WAIT_TIMED(rp.bw_threads_exited_cond, rp.lock, &tv) == 0);
2335
2336	EVLOCK_UNLOCK(rp.lock, 0);
2337	rp.locked = 0;
2338
2339	evdns_base_free(rp.dns, 1 /** fail requests */);
2340
2341	tt_int_op(n_replies_left, ==, 0);
2342
2343end:
2344	if (rp.locked)
2345		EVLOCK_UNLOCK(rp.lock, 0);
2346	EVTHREAD_FREE_LOCK(rp.lock, 0);
2347	EVTHREAD_FREE_COND(rp.reqs_cmpl_cond);
2348	EVTHREAD_FREE_COND(rp.bw_threads_exited_cond);
2349	evdns_close_server_port(dns_port);
2350	event_base_loopbreak(rp.base);
2351	event_base_free(rp.base);
2352}
2353#endif
2354
2355static void
2356test_set_so_rcvbuf_so_sndbuf(void *arg)
2357{
2358	struct basic_test_data *data = arg;
2359	struct evdns_base *dns_base;
2360
2361	dns_base = evdns_base_new(data->base, 0);
2362	tt_assert(dns_base);
2363
2364	tt_assert(!evdns_base_set_option(dns_base, "so-rcvbuf", "10240"));
2365	tt_assert(!evdns_base_set_option(dns_base, "so-sndbuf", "10240"));
2366
2367	/* actually check SO_RCVBUF/SO_SNDBUF not fails */
2368	tt_assert(!evdns_base_nameserver_ip_add(dns_base, "127.0.0.1"));
2369
2370end:
2371	if (dns_base)
2372		evdns_base_free(dns_base, 0);
2373}
2374
2375static void
2376test_set_option(void *arg)
2377{
2378#define SUCCESS 0
2379#define FAIL -1
2380	struct basic_test_data *data = arg;
2381	struct evdns_base *dns_base;
2382	size_t i;
2383	/* Option names are allowed to have ':' at the end.
2384	 * So all test option names come in pairs.
2385	 */
2386	const char *int_options[] = {
2387		"ndots", "ndots:",
2388		"max-timeouts", "max-timeouts:",
2389		"max-inflight", "max-inflight:",
2390		"attempts", "attempts:",
2391		"randomize-case", "randomize-case:",
2392		"so-rcvbuf", "so-rcvbuf:",
2393		"so-sndbuf", "so-sndbuf:",
2394	};
2395	const char *timeval_options[] = {
2396		"timeout", "timeout:",
2397		"getaddrinfo-allow-skew", "getaddrinfo-allow-skew:",
2398		"initial-probe-timeout", "initial-probe-timeout:",
2399	};
2400	const char *addr_port_options[] = {
2401		"bind-to", "bind-to:",
2402	};
2403
2404	dns_base = evdns_base_new(data->base, 0);
2405	tt_assert(dns_base);
2406
2407	for (i = 0; i < ARRAY_SIZE(int_options); ++i) {
2408		tt_assert(SUCCESS == evdns_base_set_option(dns_base, int_options[i], "0"));
2409		tt_assert(SUCCESS == evdns_base_set_option(dns_base, int_options[i], "1"));
2410		tt_assert(SUCCESS == evdns_base_set_option(dns_base, int_options[i], "10000"));
2411		tt_assert(FAIL == evdns_base_set_option(dns_base, int_options[i], "foo"));
2412		tt_assert(FAIL == evdns_base_set_option(dns_base, int_options[i], "3.14"));
2413	}
2414
2415	for (i = 0; i < ARRAY_SIZE(timeval_options); ++i) {
2416		tt_assert(SUCCESS == evdns_base_set_option(dns_base, timeval_options[i], "1"));
2417		tt_assert(SUCCESS == evdns_base_set_option(dns_base, timeval_options[i], "0.001"));
2418		tt_assert(SUCCESS == evdns_base_set_option(dns_base, timeval_options[i], "3.14"));
2419		tt_assert(SUCCESS == evdns_base_set_option(dns_base, timeval_options[i], "10000"));
2420		tt_assert(FAIL == evdns_base_set_option(dns_base, timeval_options[i], "0"));
2421		tt_assert(FAIL == evdns_base_set_option(dns_base, timeval_options[i], "foo"));
2422	}
2423
2424	for (i = 0; i < ARRAY_SIZE(addr_port_options); ++i) {
2425		tt_assert(SUCCESS == evdns_base_set_option(dns_base, addr_port_options[i], "8.8.8.8:80"));
2426		tt_assert(SUCCESS == evdns_base_set_option(dns_base, addr_port_options[i], "1.2.3.4"));
2427		tt_assert(SUCCESS == evdns_base_set_option(dns_base, addr_port_options[i], "::1:82"));
2428		tt_assert(SUCCESS == evdns_base_set_option(dns_base, addr_port_options[i], "3::4"));
2429		tt_assert(FAIL == evdns_base_set_option(dns_base, addr_port_options[i], "3.14"));
2430		tt_assert(FAIL == evdns_base_set_option(dns_base, addr_port_options[i], "foo"));
2431	}
2432
2433#undef SUCCESS
2434#undef FAIL
2435end:
2436	if (dns_base)
2437		evdns_base_free(dns_base, 0);
2438}
2439
2440#define DNS_LEGACY(name, flags)					       \
2441	{ #name, run_legacy_test_fn, flags|TT_LEGACY, &legacy_setup,   \
2442		    dns_##name }
2443
2444struct testcase_t dns_testcases[] = {
2445	DNS_LEGACY(server, TT_FORK|TT_NEED_BASE),
2446	DNS_LEGACY(gethostbyname, TT_FORK|TT_NEED_BASE|TT_NEED_DNS|TT_OFF_BY_DEFAULT),
2447	DNS_LEGACY(gethostbyname6, TT_FORK|TT_NEED_BASE|TT_NEED_DNS|TT_OFF_BY_DEFAULT),
2448	DNS_LEGACY(gethostbyaddr, TT_FORK|TT_NEED_BASE|TT_NEED_DNS|TT_OFF_BY_DEFAULT),
2449	{ "resolve_reverse", dns_resolve_reverse, TT_FORK|TT_OFF_BY_DEFAULT, NULL, NULL },
2450	{ "search_empty", dns_search_empty_test, TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
2451	{ "search", dns_search_test, TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
2452	{ "search_lower", dns_search_lower_test, TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
2453	{ "search_cancel", dns_search_cancel_test,
2454	  TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
2455	{ "retry", dns_retry_test, TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, NULL },
2456	{ "retry_disable_when_inactive", dns_retry_disable_when_inactive_test,
2457	  TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, NULL },
2458	{ "reissue", dns_reissue_test, TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, NULL },
2459	{ "reissue_disable_when_inactive", dns_reissue_disable_when_inactive_test,
2460	  TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, NULL },
2461	{ "inflight", dns_inflight_test, TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
2462	{ "bufferevent_connect_hostname", test_bufferevent_connect_hostname,
2463	  TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
2464#ifdef EVENT__HAVE_SETRLIMIT
2465	{ "bufferevent_connect_hostname_emfile", test_bufferevent_connect_hostname,
2466	  TT_FORK|TT_NEED_BASE, &basic_setup, (char*)"emfile" },
2467#endif
2468	{ "disable_when_inactive", dns_disable_when_inactive_test,
2469	  TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
2470	{ "disable_when_inactive_no_ns", dns_disable_when_inactive_no_ns_test,
2471	  TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, NULL },
2472
2473	{ "initialize_nameservers", dns_initialize_nameservers_test,
2474	  TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
2475#ifndef _WIN32
2476	{ "nameservers_no_default", dns_nameservers_no_default_test,
2477	  TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
2478#endif
2479
2480	{ "getaddrinfo_async", test_getaddrinfo_async,
2481	  TT_FORK|TT_NEED_BASE, &basic_setup, (char*)"" },
2482	{ "getaddrinfo_cancel_stress", test_getaddrinfo_async_cancel_stress,
2483	  TT_FORK, NULL, NULL },
2484
2485#ifdef EVENT_SET_MEM_FUNCTIONS_IMPLEMENTED
2486	{ "leak_shutdown", test_dbg_leak_shutdown, TT_FORK, &testleak_funcs, NULL },
2487	{ "leak_cancel", test_dbg_leak_cancel, TT_FORK, &testleak_funcs, NULL },
2488
2489	{ "leak_resume", test_dbg_leak_resume_, TT_FORK, &testleak_funcs, NULL },
2490	{ "leak_cancel_and_resume", test_dbg_leak_cancel_and_resume_,
2491	  TT_FORK, &testleak_funcs, NULL },
2492	{ "leak_resume_send_err", test_dbg_leak_resume_send_err_,
2493	  TT_FORK, &testleak_funcs, NULL },
2494	{ "leak_cancel_and_resume_send_err", test_dbg_leak_cancel_and_resume_send_err_,
2495	  TT_FORK, &testleak_funcs, NULL },
2496#endif
2497
2498	{ "client_fail_requests", dns_client_fail_requests_test,
2499	  TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, NULL },
2500	{ "client_fail_waiting_requests", dns_client_fail_requests_test,
2501	  TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, (char*)"limit-inflight" },
2502	{ "client_fail_requests_getaddrinfo",
2503	  dns_client_fail_requests_getaddrinfo_test,
2504	  TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, NULL },
2505#ifdef EVTHREAD_USE_PTHREADS_IMPLEMENTED
2506	{ "getaddrinfo_race_gotresolve",
2507	  getaddrinfo_race_gotresolve_test,
2508	  TT_FORK|TT_OFF_BY_DEFAULT, NULL, NULL },
2509#endif
2510
2511	{ "set_SO_RCVBUF_SO_SNDBUF", test_set_so_rcvbuf_so_sndbuf,
2512	  TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
2513	{ "set_options", test_set_option,
2514	  TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
2515
2516	END_OF_TESTCASES
2517};
2518
2519