xref: /freebsd/contrib/ntp/sntp/libevent/test/regress_dns.c (revision 2b15cb3d0922bd70ea592f0da9b4a5b167f4d53f)
1*2b15cb3dSCy Schubert /*
2*2b15cb3dSCy Schubert  * Copyright (c) 2003-2007 Niels Provos <provos@citi.umich.edu>
3*2b15cb3dSCy Schubert  * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
4*2b15cb3dSCy Schubert  *
5*2b15cb3dSCy Schubert  * Redistribution and use in source and binary forms, with or without
6*2b15cb3dSCy Schubert  * modification, are permitted provided that the following conditions
7*2b15cb3dSCy Schubert  * are met:
8*2b15cb3dSCy Schubert  * 1. Redistributions of source code must retain the above copyright
9*2b15cb3dSCy Schubert  *    notice, this list of conditions and the following disclaimer.
10*2b15cb3dSCy Schubert  * 2. Redistributions in binary form must reproduce the above copyright
11*2b15cb3dSCy Schubert  *    notice, this list of conditions and the following disclaimer in the
12*2b15cb3dSCy Schubert  *    documentation and/or other materials provided with the distribution.
13*2b15cb3dSCy Schubert  * 3. The name of the author may not be used to endorse or promote products
14*2b15cb3dSCy Schubert  *    derived from this software without specific prior written permission.
15*2b15cb3dSCy Schubert  *
16*2b15cb3dSCy Schubert  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17*2b15cb3dSCy Schubert  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18*2b15cb3dSCy Schubert  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19*2b15cb3dSCy Schubert  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20*2b15cb3dSCy Schubert  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21*2b15cb3dSCy Schubert  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22*2b15cb3dSCy Schubert  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23*2b15cb3dSCy Schubert  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24*2b15cb3dSCy Schubert  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25*2b15cb3dSCy Schubert  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*2b15cb3dSCy Schubert  */
27*2b15cb3dSCy Schubert #include "../util-internal.h"
28*2b15cb3dSCy Schubert 
29*2b15cb3dSCy Schubert #ifdef _WIN32
30*2b15cb3dSCy Schubert #include <winsock2.h>
31*2b15cb3dSCy Schubert #include <windows.h>
32*2b15cb3dSCy Schubert #include <ws2tcpip.h>
33*2b15cb3dSCy Schubert #endif
34*2b15cb3dSCy Schubert 
35*2b15cb3dSCy Schubert #include "event2/event-config.h"
36*2b15cb3dSCy Schubert 
37*2b15cb3dSCy Schubert #include <sys/types.h>
38*2b15cb3dSCy Schubert #include <sys/stat.h>
39*2b15cb3dSCy Schubert #ifdef EVENT__HAVE_SYS_TIME_H
40*2b15cb3dSCy Schubert #include <sys/time.h>
41*2b15cb3dSCy Schubert #endif
42*2b15cb3dSCy Schubert #include <sys/queue.h>
43*2b15cb3dSCy Schubert #ifndef _WIN32
44*2b15cb3dSCy Schubert #include <sys/socket.h>
45*2b15cb3dSCy Schubert #include <signal.h>
46*2b15cb3dSCy Schubert #include <netinet/in.h>
47*2b15cb3dSCy Schubert #include <arpa/inet.h>
48*2b15cb3dSCy Schubert #include <unistd.h>
49*2b15cb3dSCy Schubert #endif
50*2b15cb3dSCy Schubert #ifdef EVENT__HAVE_NETINET_IN6_H
51*2b15cb3dSCy Schubert #include <netinet/in6.h>
52*2b15cb3dSCy Schubert #endif
53*2b15cb3dSCy Schubert #ifdef HAVE_NETDB_H
54*2b15cb3dSCy Schubert #include <netdb.h>
55*2b15cb3dSCy Schubert #endif
56*2b15cb3dSCy Schubert #include <fcntl.h>
57*2b15cb3dSCy Schubert #include <stdlib.h>
58*2b15cb3dSCy Schubert #include <stdio.h>
59*2b15cb3dSCy Schubert #include <string.h>
60*2b15cb3dSCy Schubert #include <errno.h>
61*2b15cb3dSCy Schubert 
62*2b15cb3dSCy Schubert #include "event2/dns.h"
63*2b15cb3dSCy Schubert #include "event2/dns_compat.h"
64*2b15cb3dSCy Schubert #include "event2/dns_struct.h"
65*2b15cb3dSCy Schubert #include "event2/event.h"
66*2b15cb3dSCy Schubert #include "event2/event_compat.h"
67*2b15cb3dSCy Schubert #include "event2/event_struct.h"
68*2b15cb3dSCy Schubert #include "event2/util.h"
69*2b15cb3dSCy Schubert #include "event2/listener.h"
70*2b15cb3dSCy Schubert #include "event2/bufferevent.h"
71*2b15cb3dSCy Schubert #include "log-internal.h"
72*2b15cb3dSCy Schubert #include "regress.h"
73*2b15cb3dSCy Schubert #include "regress_testutils.h"
74*2b15cb3dSCy Schubert 
75*2b15cb3dSCy Schubert static int dns_ok = 0;
76*2b15cb3dSCy Schubert static int dns_got_cancel = 0;
77*2b15cb3dSCy Schubert static int dns_err = 0;
78*2b15cb3dSCy Schubert 
79*2b15cb3dSCy Schubert 
80*2b15cb3dSCy Schubert static void
81*2b15cb3dSCy Schubert dns_gethostbyname_cb(int result, char type, int count, int ttl,
82*2b15cb3dSCy Schubert     void *addresses, void *arg)
83*2b15cb3dSCy Schubert {
84*2b15cb3dSCy Schubert 	dns_ok = dns_err = 0;
85*2b15cb3dSCy Schubert 
86*2b15cb3dSCy Schubert 	if (result == DNS_ERR_TIMEOUT) {
87*2b15cb3dSCy Schubert 		printf("[Timed out] ");
88*2b15cb3dSCy Schubert 		dns_err = result;
89*2b15cb3dSCy Schubert 		goto out;
90*2b15cb3dSCy Schubert 	}
91*2b15cb3dSCy Schubert 
92*2b15cb3dSCy Schubert 	if (result != DNS_ERR_NONE) {
93*2b15cb3dSCy Schubert 		printf("[Error code %d] ", result);
94*2b15cb3dSCy Schubert 		goto out;
95*2b15cb3dSCy Schubert 	}
96*2b15cb3dSCy Schubert 
97*2b15cb3dSCy Schubert 	TT_BLATHER(("type: %d, count: %d, ttl: %d: ", type, count, ttl));
98*2b15cb3dSCy Schubert 
99*2b15cb3dSCy Schubert 	switch (type) {
100*2b15cb3dSCy Schubert 	case DNS_IPv6_AAAA: {
101*2b15cb3dSCy Schubert #if defined(EVENT__HAVE_STRUCT_IN6_ADDR) && defined(EVENT__HAVE_INET_NTOP) && defined(INET6_ADDRSTRLEN)
102*2b15cb3dSCy Schubert 		struct in6_addr *in6_addrs = addresses;
103*2b15cb3dSCy Schubert 		char buf[INET6_ADDRSTRLEN+1];
104*2b15cb3dSCy Schubert 		int i;
105*2b15cb3dSCy Schubert 		/* a resolution that's not valid does not help */
106*2b15cb3dSCy Schubert 		if (ttl < 0)
107*2b15cb3dSCy Schubert 			goto out;
108*2b15cb3dSCy Schubert 		for (i = 0; i < count; ++i) {
109*2b15cb3dSCy Schubert 			const char *b = evutil_inet_ntop(AF_INET6, &in6_addrs[i], buf,sizeof(buf));
110*2b15cb3dSCy Schubert 			if (b)
111*2b15cb3dSCy Schubert 				TT_BLATHER(("%s ", b));
112*2b15cb3dSCy Schubert 			else
113*2b15cb3dSCy Schubert 				TT_BLATHER(("%s ", strerror(errno)));
114*2b15cb3dSCy Schubert 		}
115*2b15cb3dSCy Schubert #endif
116*2b15cb3dSCy Schubert 		break;
117*2b15cb3dSCy Schubert 	}
118*2b15cb3dSCy Schubert 	case DNS_IPv4_A: {
119*2b15cb3dSCy Schubert 		struct in_addr *in_addrs = addresses;
120*2b15cb3dSCy Schubert 		int i;
121*2b15cb3dSCy Schubert 		/* a resolution that's not valid does not help */
122*2b15cb3dSCy Schubert 		if (ttl < 0)
123*2b15cb3dSCy Schubert 			goto out;
124*2b15cb3dSCy Schubert 		for (i = 0; i < count; ++i)
125*2b15cb3dSCy Schubert 			TT_BLATHER(("%s ", inet_ntoa(in_addrs[i])));
126*2b15cb3dSCy Schubert 		break;
127*2b15cb3dSCy Schubert 	}
128*2b15cb3dSCy Schubert 	case DNS_PTR:
129*2b15cb3dSCy Schubert 		/* may get at most one PTR */
130*2b15cb3dSCy Schubert 		if (count != 1)
131*2b15cb3dSCy Schubert 			goto out;
132*2b15cb3dSCy Schubert 
133*2b15cb3dSCy Schubert 		TT_BLATHER(("%s ", *(char **)addresses));
134*2b15cb3dSCy Schubert 		break;
135*2b15cb3dSCy Schubert 	default:
136*2b15cb3dSCy Schubert 		goto out;
137*2b15cb3dSCy Schubert 	}
138*2b15cb3dSCy Schubert 
139*2b15cb3dSCy Schubert 	dns_ok = type;
140*2b15cb3dSCy Schubert 
141*2b15cb3dSCy Schubert out:
142*2b15cb3dSCy Schubert 	if (arg == NULL)
143*2b15cb3dSCy Schubert 		event_loopexit(NULL);
144*2b15cb3dSCy Schubert 	else
145*2b15cb3dSCy Schubert 		event_base_loopexit((struct event_base *)arg, NULL);
146*2b15cb3dSCy Schubert }
147*2b15cb3dSCy Schubert 
148*2b15cb3dSCy Schubert static void
149*2b15cb3dSCy Schubert dns_gethostbyname(void)
150*2b15cb3dSCy Schubert {
151*2b15cb3dSCy Schubert 	dns_ok = 0;
152*2b15cb3dSCy Schubert 	evdns_resolve_ipv4("www.monkey.org", 0, dns_gethostbyname_cb, NULL);
153*2b15cb3dSCy Schubert 	event_dispatch();
154*2b15cb3dSCy Schubert 
155*2b15cb3dSCy Schubert 	tt_int_op(dns_ok, ==, DNS_IPv4_A);
156*2b15cb3dSCy Schubert 	test_ok = dns_ok;
157*2b15cb3dSCy Schubert end:
158*2b15cb3dSCy Schubert 	;
159*2b15cb3dSCy Schubert }
160*2b15cb3dSCy Schubert 
161*2b15cb3dSCy Schubert static void
162*2b15cb3dSCy Schubert dns_gethostbyname6(void)
163*2b15cb3dSCy Schubert {
164*2b15cb3dSCy Schubert 	dns_ok = 0;
165*2b15cb3dSCy Schubert 	evdns_resolve_ipv6("www.ietf.org", 0, dns_gethostbyname_cb, NULL);
166*2b15cb3dSCy Schubert 	event_dispatch();
167*2b15cb3dSCy Schubert 
168*2b15cb3dSCy Schubert 	if (!dns_ok && dns_err == DNS_ERR_TIMEOUT) {
169*2b15cb3dSCy Schubert 		tt_skip();
170*2b15cb3dSCy Schubert 	}
171*2b15cb3dSCy Schubert 
172*2b15cb3dSCy Schubert 	tt_int_op(dns_ok, ==, DNS_IPv6_AAAA);
173*2b15cb3dSCy Schubert 	test_ok = 1;
174*2b15cb3dSCy Schubert end:
175*2b15cb3dSCy Schubert 	;
176*2b15cb3dSCy Schubert }
177*2b15cb3dSCy Schubert 
178*2b15cb3dSCy Schubert static void
179*2b15cb3dSCy Schubert dns_gethostbyaddr(void)
180*2b15cb3dSCy Schubert {
181*2b15cb3dSCy Schubert 	struct in_addr in;
182*2b15cb3dSCy Schubert 	in.s_addr = htonl(0x7f000001ul); /* 127.0.0.1 */
183*2b15cb3dSCy Schubert 	dns_ok = 0;
184*2b15cb3dSCy Schubert 	evdns_resolve_reverse(&in, 0, dns_gethostbyname_cb, NULL);
185*2b15cb3dSCy Schubert 	event_dispatch();
186*2b15cb3dSCy Schubert 
187*2b15cb3dSCy Schubert 	tt_int_op(dns_ok, ==, DNS_PTR);
188*2b15cb3dSCy Schubert 	test_ok = dns_ok;
189*2b15cb3dSCy Schubert end:
190*2b15cb3dSCy Schubert 	;
191*2b15cb3dSCy Schubert }
192*2b15cb3dSCy Schubert 
193*2b15cb3dSCy Schubert static void
194*2b15cb3dSCy Schubert dns_resolve_reverse(void *ptr)
195*2b15cb3dSCy Schubert {
196*2b15cb3dSCy Schubert 	struct in_addr in;
197*2b15cb3dSCy Schubert 	struct event_base *base = event_base_new();
198*2b15cb3dSCy Schubert 	struct evdns_base *dns = evdns_base_new(base, 1/* init name servers */);
199*2b15cb3dSCy Schubert 	struct evdns_request *req = NULL;
200*2b15cb3dSCy Schubert 
201*2b15cb3dSCy Schubert 	tt_assert(base);
202*2b15cb3dSCy Schubert 	tt_assert(dns);
203*2b15cb3dSCy Schubert 	in.s_addr = htonl(0x7f000001ul); /* 127.0.0.1 */
204*2b15cb3dSCy Schubert 	dns_ok = 0;
205*2b15cb3dSCy Schubert 
206*2b15cb3dSCy Schubert 	req = evdns_base_resolve_reverse(
207*2b15cb3dSCy Schubert 		dns, &in, 0, dns_gethostbyname_cb, base);
208*2b15cb3dSCy Schubert 	tt_assert(req);
209*2b15cb3dSCy Schubert 
210*2b15cb3dSCy Schubert 	event_base_dispatch(base);
211*2b15cb3dSCy Schubert 
212*2b15cb3dSCy Schubert 	tt_int_op(dns_ok, ==, DNS_PTR);
213*2b15cb3dSCy Schubert 
214*2b15cb3dSCy Schubert end:
215*2b15cb3dSCy Schubert 	if (dns)
216*2b15cb3dSCy Schubert 		evdns_base_free(dns, 0);
217*2b15cb3dSCy Schubert 	if (base)
218*2b15cb3dSCy Schubert 		event_base_free(base);
219*2b15cb3dSCy Schubert }
220*2b15cb3dSCy Schubert 
221*2b15cb3dSCy Schubert static int n_server_responses = 0;
222*2b15cb3dSCy Schubert 
223*2b15cb3dSCy Schubert static void
224*2b15cb3dSCy Schubert dns_server_request_cb(struct evdns_server_request *req, void *data)
225*2b15cb3dSCy Schubert {
226*2b15cb3dSCy Schubert 	int i, r;
227*2b15cb3dSCy Schubert 	const char TEST_ARPA[] = "11.11.168.192.in-addr.arpa";
228*2b15cb3dSCy Schubert 	const char TEST_IN6[] =
229*2b15cb3dSCy Schubert 	    "f.e.f.e." "0.0.0.0." "0.0.0.0." "1.1.1.1."
230*2b15cb3dSCy Schubert 	    "a.a.a.a." "0.0.0.0." "0.0.0.0." "0.f.f.f.ip6.arpa";
231*2b15cb3dSCy Schubert 
232*2b15cb3dSCy Schubert 	for (i = 0; i < req->nquestions; ++i) {
233*2b15cb3dSCy Schubert 		const int qtype = req->questions[i]->type;
234*2b15cb3dSCy Schubert 		const int qclass = req->questions[i]->dns_question_class;
235*2b15cb3dSCy Schubert 		const char *qname = req->questions[i]->name;
236*2b15cb3dSCy Schubert 
237*2b15cb3dSCy Schubert 		struct in_addr ans;
238*2b15cb3dSCy Schubert 		ans.s_addr = htonl(0xc0a80b0bUL); /* 192.168.11.11 */
239*2b15cb3dSCy Schubert 		if (qtype == EVDNS_TYPE_A &&
240*2b15cb3dSCy Schubert 		    qclass == EVDNS_CLASS_INET &&
241*2b15cb3dSCy Schubert 		    !evutil_ascii_strcasecmp(qname, "zz.example.com")) {
242*2b15cb3dSCy Schubert 			r = evdns_server_request_add_a_reply(req, qname,
243*2b15cb3dSCy Schubert 			    1, &ans.s_addr, 12345);
244*2b15cb3dSCy Schubert 			if (r<0)
245*2b15cb3dSCy Schubert 				dns_ok = 0;
246*2b15cb3dSCy Schubert 		} else if (qtype == EVDNS_TYPE_AAAA &&
247*2b15cb3dSCy Schubert 		    qclass == EVDNS_CLASS_INET &&
248*2b15cb3dSCy Schubert 		    !evutil_ascii_strcasecmp(qname, "zz.example.com")) {
249*2b15cb3dSCy Schubert 			char addr6[17] = "abcdefghijklmnop";
250*2b15cb3dSCy Schubert 			r = evdns_server_request_add_aaaa_reply(req,
251*2b15cb3dSCy Schubert 			    qname, 1, addr6, 123);
252*2b15cb3dSCy Schubert 			if (r<0)
253*2b15cb3dSCy Schubert 				dns_ok = 0;
254*2b15cb3dSCy Schubert 		} else if (qtype == EVDNS_TYPE_PTR &&
255*2b15cb3dSCy Schubert 		    qclass == EVDNS_CLASS_INET &&
256*2b15cb3dSCy Schubert 		    !evutil_ascii_strcasecmp(qname, TEST_ARPA)) {
257*2b15cb3dSCy Schubert 			r = evdns_server_request_add_ptr_reply(req, NULL,
258*2b15cb3dSCy Schubert 			    qname, "ZZ.EXAMPLE.COM", 54321);
259*2b15cb3dSCy Schubert 			if (r<0)
260*2b15cb3dSCy Schubert 				dns_ok = 0;
261*2b15cb3dSCy Schubert 		} else if (qtype == EVDNS_TYPE_PTR &&
262*2b15cb3dSCy Schubert 		    qclass == EVDNS_CLASS_INET &&
263*2b15cb3dSCy Schubert 		    !evutil_ascii_strcasecmp(qname, TEST_IN6)){
264*2b15cb3dSCy Schubert 			r = evdns_server_request_add_ptr_reply(req, NULL,
265*2b15cb3dSCy Schubert 			    qname,
266*2b15cb3dSCy Schubert 			    "ZZ-INET6.EXAMPLE.COM", 54322);
267*2b15cb3dSCy Schubert 			if (r<0)
268*2b15cb3dSCy Schubert 				dns_ok = 0;
269*2b15cb3dSCy Schubert 		} else if (qtype == EVDNS_TYPE_A &&
270*2b15cb3dSCy Schubert 		    qclass == EVDNS_CLASS_INET &&
271*2b15cb3dSCy Schubert 		    !evutil_ascii_strcasecmp(qname, "drop.example.com")) {
272*2b15cb3dSCy Schubert 			if (evdns_server_request_drop(req)<0)
273*2b15cb3dSCy Schubert 				dns_ok = 0;
274*2b15cb3dSCy Schubert 			return;
275*2b15cb3dSCy Schubert 		} else {
276*2b15cb3dSCy Schubert 			printf("Unexpected question %d %d \"%s\" ",
277*2b15cb3dSCy Schubert 			    qtype, qclass, qname);
278*2b15cb3dSCy Schubert 			dns_ok = 0;
279*2b15cb3dSCy Schubert 		}
280*2b15cb3dSCy Schubert 	}
281*2b15cb3dSCy Schubert 	r = evdns_server_request_respond(req, 0);
282*2b15cb3dSCy Schubert 	if (r<0) {
283*2b15cb3dSCy Schubert 		printf("Couldn't send reply. ");
284*2b15cb3dSCy Schubert 		dns_ok = 0;
285*2b15cb3dSCy Schubert 	}
286*2b15cb3dSCy Schubert }
287*2b15cb3dSCy Schubert 
288*2b15cb3dSCy Schubert static void
289*2b15cb3dSCy Schubert dns_server_gethostbyname_cb(int result, char type, int count, int ttl,
290*2b15cb3dSCy Schubert     void *addresses, void *arg)
291*2b15cb3dSCy Schubert {
292*2b15cb3dSCy Schubert 	if (result == DNS_ERR_CANCEL) {
293*2b15cb3dSCy Schubert 		if (arg != (void*)(char*)90909) {
294*2b15cb3dSCy Schubert 			printf("Unexpected cancelation");
295*2b15cb3dSCy Schubert 			dns_ok = 0;
296*2b15cb3dSCy Schubert 		}
297*2b15cb3dSCy Schubert 		dns_got_cancel = 1;
298*2b15cb3dSCy Schubert 		goto out;
299*2b15cb3dSCy Schubert 	}
300*2b15cb3dSCy Schubert 	if (result != DNS_ERR_NONE) {
301*2b15cb3dSCy Schubert 		printf("Unexpected result %d. ", result);
302*2b15cb3dSCy Schubert 		dns_ok = 0;
303*2b15cb3dSCy Schubert 		goto out;
304*2b15cb3dSCy Schubert 	}
305*2b15cb3dSCy Schubert 	if (count != 1) {
306*2b15cb3dSCy Schubert 		printf("Unexpected answer count %d. ", count);
307*2b15cb3dSCy Schubert 		dns_ok = 0;
308*2b15cb3dSCy Schubert 		goto out;
309*2b15cb3dSCy Schubert 	}
310*2b15cb3dSCy Schubert 	switch (type) {
311*2b15cb3dSCy Schubert 	case DNS_IPv4_A: {
312*2b15cb3dSCy Schubert 		struct in_addr *in_addrs = addresses;
313*2b15cb3dSCy Schubert 		if (in_addrs[0].s_addr != htonl(0xc0a80b0bUL) || ttl != 12345) {
314*2b15cb3dSCy Schubert 			printf("Bad IPv4 response \"%s\" %d. ",
315*2b15cb3dSCy Schubert 					inet_ntoa(in_addrs[0]), ttl);
316*2b15cb3dSCy Schubert 			dns_ok = 0;
317*2b15cb3dSCy Schubert 			goto out;
318*2b15cb3dSCy Schubert 		}
319*2b15cb3dSCy Schubert 		break;
320*2b15cb3dSCy Schubert 	}
321*2b15cb3dSCy Schubert 	case DNS_IPv6_AAAA: {
322*2b15cb3dSCy Schubert #if defined (EVENT__HAVE_STRUCT_IN6_ADDR) && defined(EVENT__HAVE_INET_NTOP) && defined(INET6_ADDRSTRLEN)
323*2b15cb3dSCy Schubert 		struct in6_addr *in6_addrs = addresses;
324*2b15cb3dSCy Schubert 		char buf[INET6_ADDRSTRLEN+1];
325*2b15cb3dSCy Schubert 		if (memcmp(&in6_addrs[0].s6_addr, "abcdefghijklmnop", 16)
326*2b15cb3dSCy Schubert 		    || ttl != 123) {
327*2b15cb3dSCy Schubert 			const char *b = evutil_inet_ntop(AF_INET6, &in6_addrs[0],buf,sizeof(buf));
328*2b15cb3dSCy Schubert 			printf("Bad IPv6 response \"%s\" %d. ", b, ttl);
329*2b15cb3dSCy Schubert 			dns_ok = 0;
330*2b15cb3dSCy Schubert 			goto out;
331*2b15cb3dSCy Schubert 		}
332*2b15cb3dSCy Schubert #endif
333*2b15cb3dSCy Schubert 		break;
334*2b15cb3dSCy Schubert 	}
335*2b15cb3dSCy Schubert 	case DNS_PTR: {
336*2b15cb3dSCy Schubert 		char **addrs = addresses;
337*2b15cb3dSCy Schubert 		if (arg != (void*)6) {
338*2b15cb3dSCy Schubert 			if (strcmp(addrs[0], "ZZ.EXAMPLE.COM") ||
339*2b15cb3dSCy Schubert 			    ttl != 54321) {
340*2b15cb3dSCy Schubert 				printf("Bad PTR response \"%s\" %d. ",
341*2b15cb3dSCy Schubert 				    addrs[0], ttl);
342*2b15cb3dSCy Schubert 				dns_ok = 0;
343*2b15cb3dSCy Schubert 				goto out;
344*2b15cb3dSCy Schubert 			}
345*2b15cb3dSCy Schubert 		} else {
346*2b15cb3dSCy Schubert 			if (strcmp(addrs[0], "ZZ-INET6.EXAMPLE.COM") ||
347*2b15cb3dSCy Schubert 			    ttl != 54322) {
348*2b15cb3dSCy Schubert 				printf("Bad ipv6 PTR response \"%s\" %d. ",
349*2b15cb3dSCy Schubert 				    addrs[0], ttl);
350*2b15cb3dSCy Schubert 				dns_ok = 0;
351*2b15cb3dSCy Schubert 				goto out;
352*2b15cb3dSCy Schubert 			}
353*2b15cb3dSCy Schubert 		}
354*2b15cb3dSCy Schubert 		break;
355*2b15cb3dSCy Schubert 	}
356*2b15cb3dSCy Schubert 	default:
357*2b15cb3dSCy Schubert 		printf("Bad response type %d. ", type);
358*2b15cb3dSCy Schubert 		dns_ok = 0;
359*2b15cb3dSCy Schubert 	}
360*2b15cb3dSCy Schubert  out:
361*2b15cb3dSCy Schubert 	if (++n_server_responses == 3) {
362*2b15cb3dSCy Schubert 		event_loopexit(NULL);
363*2b15cb3dSCy Schubert 	}
364*2b15cb3dSCy Schubert }
365*2b15cb3dSCy Schubert 
366*2b15cb3dSCy Schubert static void
367*2b15cb3dSCy Schubert dns_server(void)
368*2b15cb3dSCy Schubert {
369*2b15cb3dSCy Schubert 	evutil_socket_t sock=-1;
370*2b15cb3dSCy Schubert 	struct sockaddr_in my_addr;
371*2b15cb3dSCy Schubert 	struct sockaddr_storage ss;
372*2b15cb3dSCy Schubert 	ev_socklen_t slen;
373*2b15cb3dSCy Schubert 	struct evdns_server_port *port=NULL;
374*2b15cb3dSCy Schubert 	struct in_addr resolve_addr;
375*2b15cb3dSCy Schubert 	struct in6_addr resolve_addr6;
376*2b15cb3dSCy Schubert 	struct evdns_base *base=NULL;
377*2b15cb3dSCy Schubert 	struct evdns_request *req=NULL;
378*2b15cb3dSCy Schubert 
379*2b15cb3dSCy Schubert 	dns_ok = 1;
380*2b15cb3dSCy Schubert 
381*2b15cb3dSCy Schubert 	base = evdns_base_new(NULL, 0);
382*2b15cb3dSCy Schubert 
383*2b15cb3dSCy Schubert 	/* Now configure a nameserver port. */
384*2b15cb3dSCy Schubert 	sock = socket(AF_INET, SOCK_DGRAM, 0);
385*2b15cb3dSCy Schubert 	if (sock<0) {
386*2b15cb3dSCy Schubert 		tt_abort_perror("socket");
387*2b15cb3dSCy Schubert 	}
388*2b15cb3dSCy Schubert 
389*2b15cb3dSCy Schubert 	evutil_make_socket_nonblocking(sock);
390*2b15cb3dSCy Schubert 
391*2b15cb3dSCy Schubert 	memset(&my_addr, 0, sizeof(my_addr));
392*2b15cb3dSCy Schubert 	my_addr.sin_family = AF_INET;
393*2b15cb3dSCy Schubert 	my_addr.sin_port = 0; /* kernel picks */
394*2b15cb3dSCy Schubert 	my_addr.sin_addr.s_addr = htonl(0x7f000001UL);
395*2b15cb3dSCy Schubert 	if (bind(sock, (struct sockaddr*)&my_addr, sizeof(my_addr)) < 0) {
396*2b15cb3dSCy Schubert 		tt_abort_perror("bind");
397*2b15cb3dSCy Schubert 	}
398*2b15cb3dSCy Schubert 	slen = sizeof(ss);
399*2b15cb3dSCy Schubert 	if (getsockname(sock, (struct sockaddr*)&ss, &slen) < 0) {
400*2b15cb3dSCy Schubert 		tt_abort_perror("getsockname");
401*2b15cb3dSCy Schubert 	}
402*2b15cb3dSCy Schubert 
403*2b15cb3dSCy Schubert 	port = evdns_add_server_port(sock, 0, dns_server_request_cb, NULL);
404*2b15cb3dSCy Schubert 
405*2b15cb3dSCy Schubert 	/* Add ourself as the only nameserver, and make sure we really are
406*2b15cb3dSCy Schubert 	 * the only nameserver. */
407*2b15cb3dSCy Schubert 	evdns_base_nameserver_sockaddr_add(base, (struct sockaddr*)&ss, slen, 0);
408*2b15cb3dSCy Schubert 	tt_int_op(evdns_base_count_nameservers(base), ==, 1);
409*2b15cb3dSCy Schubert 
410*2b15cb3dSCy Schubert 	/* Send some queries. */
411*2b15cb3dSCy Schubert 	evdns_base_resolve_ipv4(base, "zz.example.com", DNS_QUERY_NO_SEARCH,
412*2b15cb3dSCy Schubert 					   dns_server_gethostbyname_cb, NULL);
413*2b15cb3dSCy Schubert 	evdns_base_resolve_ipv6(base, "zz.example.com", DNS_QUERY_NO_SEARCH,
414*2b15cb3dSCy Schubert 					   dns_server_gethostbyname_cb, NULL);
415*2b15cb3dSCy Schubert 	resolve_addr.s_addr = htonl(0xc0a80b0bUL); /* 192.168.11.11 */
416*2b15cb3dSCy Schubert 	evdns_base_resolve_reverse(base, &resolve_addr, 0,
417*2b15cb3dSCy Schubert 	    dns_server_gethostbyname_cb, NULL);
418*2b15cb3dSCy Schubert 	memcpy(resolve_addr6.s6_addr,
419*2b15cb3dSCy Schubert 	    "\xff\xf0\x00\x00\x00\x00\xaa\xaa"
420*2b15cb3dSCy Schubert 	    "\x11\x11\x00\x00\x00\x00\xef\xef", 16);
421*2b15cb3dSCy Schubert 	evdns_base_resolve_reverse_ipv6(base, &resolve_addr6, 0,
422*2b15cb3dSCy Schubert 	    dns_server_gethostbyname_cb, (void*)6);
423*2b15cb3dSCy Schubert 
424*2b15cb3dSCy Schubert 	req = evdns_base_resolve_ipv4(base,
425*2b15cb3dSCy Schubert 	    "drop.example.com", DNS_QUERY_NO_SEARCH,
426*2b15cb3dSCy Schubert 	    dns_server_gethostbyname_cb, (void*)(char*)90909);
427*2b15cb3dSCy Schubert 
428*2b15cb3dSCy Schubert 	evdns_cancel_request(base, req);
429*2b15cb3dSCy Schubert 
430*2b15cb3dSCy Schubert 	event_dispatch();
431*2b15cb3dSCy Schubert 
432*2b15cb3dSCy Schubert 	tt_assert(dns_got_cancel);
433*2b15cb3dSCy Schubert 	test_ok = dns_ok;
434*2b15cb3dSCy Schubert 
435*2b15cb3dSCy Schubert end:
436*2b15cb3dSCy Schubert 	if (port)
437*2b15cb3dSCy Schubert 		evdns_close_server_port(port);
438*2b15cb3dSCy Schubert 	if (sock >= 0)
439*2b15cb3dSCy Schubert 		evutil_closesocket(sock);
440*2b15cb3dSCy Schubert 	if (base)
441*2b15cb3dSCy Schubert 		evdns_base_free(base, 0);
442*2b15cb3dSCy Schubert }
443*2b15cb3dSCy Schubert 
444*2b15cb3dSCy Schubert static int n_replies_left;
445*2b15cb3dSCy Schubert static struct event_base *exit_base;
446*2b15cb3dSCy Schubert 
447*2b15cb3dSCy Schubert struct generic_dns_callback_result {
448*2b15cb3dSCy Schubert 	int result;
449*2b15cb3dSCy Schubert 	char type;
450*2b15cb3dSCy Schubert 	int count;
451*2b15cb3dSCy Schubert 	int ttl;
452*2b15cb3dSCy Schubert 	size_t addrs_len;
453*2b15cb3dSCy Schubert 	void *addrs;
454*2b15cb3dSCy Schubert 	char addrs_buf[256];
455*2b15cb3dSCy Schubert };
456*2b15cb3dSCy Schubert 
457*2b15cb3dSCy Schubert static void
458*2b15cb3dSCy Schubert generic_dns_callback(int result, char type, int count, int ttl, void *addresses,
459*2b15cb3dSCy Schubert     void *arg)
460*2b15cb3dSCy Schubert {
461*2b15cb3dSCy Schubert 	size_t len;
462*2b15cb3dSCy Schubert 	struct generic_dns_callback_result *res = arg;
463*2b15cb3dSCy Schubert 	res->result = result;
464*2b15cb3dSCy Schubert 	res->type = type;
465*2b15cb3dSCy Schubert 	res->count = count;
466*2b15cb3dSCy Schubert 	res->ttl = ttl;
467*2b15cb3dSCy Schubert 
468*2b15cb3dSCy Schubert 	if (type == DNS_IPv4_A)
469*2b15cb3dSCy Schubert 		len = count * 4;
470*2b15cb3dSCy Schubert 	else if (type == DNS_IPv6_AAAA)
471*2b15cb3dSCy Schubert 		len = count * 16;
472*2b15cb3dSCy Schubert 	else if (type == DNS_PTR)
473*2b15cb3dSCy Schubert 		len = strlen(addresses)+1;
474*2b15cb3dSCy Schubert 	else {
475*2b15cb3dSCy Schubert 		res->addrs_len = len = 0;
476*2b15cb3dSCy Schubert 		res->addrs = NULL;
477*2b15cb3dSCy Schubert 	}
478*2b15cb3dSCy Schubert 	if (len) {
479*2b15cb3dSCy Schubert 		res->addrs_len = len;
480*2b15cb3dSCy Schubert 		if (len > 256)
481*2b15cb3dSCy Schubert 			len = 256;
482*2b15cb3dSCy Schubert 		memcpy(res->addrs_buf, addresses, len);
483*2b15cb3dSCy Schubert 		res->addrs = res->addrs_buf;
484*2b15cb3dSCy Schubert 	}
485*2b15cb3dSCy Schubert 
486*2b15cb3dSCy Schubert 	if (--n_replies_left == 0)
487*2b15cb3dSCy Schubert 		event_base_loopexit(exit_base, NULL);
488*2b15cb3dSCy Schubert }
489*2b15cb3dSCy Schubert 
490*2b15cb3dSCy Schubert static struct regress_dns_server_table search_table[] = {
491*2b15cb3dSCy Schubert 	{ "host.a.example.com", "err", "3", 0 },
492*2b15cb3dSCy Schubert 	{ "host.b.example.com", "err", "3", 0 },
493*2b15cb3dSCy Schubert 	{ "host.c.example.com", "A", "11.22.33.44", 0 },
494*2b15cb3dSCy Schubert 	{ "host2.a.example.com", "err", "3", 0 },
495*2b15cb3dSCy Schubert 	{ "host2.b.example.com", "A", "200.100.0.100", 0 },
496*2b15cb3dSCy Schubert 	{ "host2.c.example.com", "err", "3", 0 },
497*2b15cb3dSCy Schubert 	{ "hostn.a.example.com", "errsoa", "0", 0 },
498*2b15cb3dSCy Schubert 	{ "hostn.b.example.com", "errsoa", "3", 0 },
499*2b15cb3dSCy Schubert 	{ "hostn.c.example.com", "err", "0", 0 },
500*2b15cb3dSCy Schubert 
501*2b15cb3dSCy Schubert 	{ "host", "err", "3", 0 },
502*2b15cb3dSCy Schubert 	{ "host2", "err", "3", 0 },
503*2b15cb3dSCy Schubert 	{ "*", "err", "3", 0 },
504*2b15cb3dSCy Schubert 	{ NULL, NULL, NULL, 0 }
505*2b15cb3dSCy Schubert };
506*2b15cb3dSCy Schubert 
507*2b15cb3dSCy Schubert static void
508*2b15cb3dSCy Schubert dns_search_test(void *arg)
509*2b15cb3dSCy Schubert {
510*2b15cb3dSCy Schubert 	struct basic_test_data *data = arg;
511*2b15cb3dSCy Schubert 	struct event_base *base = data->base;
512*2b15cb3dSCy Schubert 	struct evdns_base *dns = NULL;
513*2b15cb3dSCy Schubert 	ev_uint16_t portnum = 0;
514*2b15cb3dSCy Schubert 	char buf[64];
515*2b15cb3dSCy Schubert 
516*2b15cb3dSCy Schubert 	struct generic_dns_callback_result r[8];
517*2b15cb3dSCy Schubert 
518*2b15cb3dSCy Schubert 	tt_assert(regress_dnsserver(base, &portnum, search_table));
519*2b15cb3dSCy Schubert 	evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum);
520*2b15cb3dSCy Schubert 
521*2b15cb3dSCy Schubert 	dns = evdns_base_new(base, 0);
522*2b15cb3dSCy Schubert 	tt_assert(!evdns_base_nameserver_ip_add(dns, buf));
523*2b15cb3dSCy Schubert 
524*2b15cb3dSCy Schubert 	evdns_base_search_add(dns, "a.example.com");
525*2b15cb3dSCy Schubert 	evdns_base_search_add(dns, "b.example.com");
526*2b15cb3dSCy Schubert 	evdns_base_search_add(dns, "c.example.com");
527*2b15cb3dSCy Schubert 
528*2b15cb3dSCy Schubert 	n_replies_left = sizeof(r)/sizeof(r[0]);
529*2b15cb3dSCy Schubert 	exit_base = base;
530*2b15cb3dSCy Schubert 
531*2b15cb3dSCy Schubert 	evdns_base_resolve_ipv4(dns, "host", 0, generic_dns_callback, &r[0]);
532*2b15cb3dSCy Schubert 	evdns_base_resolve_ipv4(dns, "host2", 0, generic_dns_callback, &r[1]);
533*2b15cb3dSCy Schubert 	evdns_base_resolve_ipv4(dns, "host", DNS_NO_SEARCH, generic_dns_callback, &r[2]);
534*2b15cb3dSCy Schubert 	evdns_base_resolve_ipv4(dns, "host2", DNS_NO_SEARCH, generic_dns_callback, &r[3]);
535*2b15cb3dSCy Schubert 	evdns_base_resolve_ipv4(dns, "host3", 0, generic_dns_callback, &r[4]);
536*2b15cb3dSCy Schubert 	evdns_base_resolve_ipv4(dns, "hostn.a.example.com", DNS_NO_SEARCH, generic_dns_callback, &r[5]);
537*2b15cb3dSCy Schubert 	evdns_base_resolve_ipv4(dns, "hostn.b.example.com", DNS_NO_SEARCH, generic_dns_callback, &r[6]);
538*2b15cb3dSCy Schubert 	evdns_base_resolve_ipv4(dns, "hostn.c.example.com", DNS_NO_SEARCH, generic_dns_callback, &r[7]);
539*2b15cb3dSCy Schubert 
540*2b15cb3dSCy Schubert 	event_base_dispatch(base);
541*2b15cb3dSCy Schubert 
542*2b15cb3dSCy Schubert 	tt_int_op(r[0].type, ==, DNS_IPv4_A);
543*2b15cb3dSCy Schubert 	tt_int_op(r[0].count, ==, 1);
544*2b15cb3dSCy Schubert 	tt_int_op(((ev_uint32_t*)r[0].addrs)[0], ==, htonl(0x0b16212c));
545*2b15cb3dSCy Schubert 	tt_int_op(r[1].type, ==, DNS_IPv4_A);
546*2b15cb3dSCy Schubert 	tt_int_op(r[1].count, ==, 1);
547*2b15cb3dSCy Schubert 	tt_int_op(((ev_uint32_t*)r[1].addrs)[0], ==, htonl(0xc8640064));
548*2b15cb3dSCy Schubert 	tt_int_op(r[2].result, ==, DNS_ERR_NOTEXIST);
549*2b15cb3dSCy Schubert 	tt_int_op(r[3].result, ==, DNS_ERR_NOTEXIST);
550*2b15cb3dSCy Schubert 	tt_int_op(r[4].result, ==, DNS_ERR_NOTEXIST);
551*2b15cb3dSCy Schubert 	tt_int_op(r[5].result, ==, DNS_ERR_NODATA);
552*2b15cb3dSCy Schubert 	tt_int_op(r[5].ttl, ==, 42);
553*2b15cb3dSCy Schubert 	tt_int_op(r[6].result, ==, DNS_ERR_NOTEXIST);
554*2b15cb3dSCy Schubert 	tt_int_op(r[6].ttl, ==, 42);
555*2b15cb3dSCy Schubert 	tt_int_op(r[7].result, ==, DNS_ERR_NODATA);
556*2b15cb3dSCy Schubert 	tt_int_op(r[7].ttl, ==, 0);
557*2b15cb3dSCy Schubert 
558*2b15cb3dSCy Schubert end:
559*2b15cb3dSCy Schubert 	if (dns)
560*2b15cb3dSCy Schubert 		evdns_base_free(dns, 0);
561*2b15cb3dSCy Schubert 
562*2b15cb3dSCy Schubert 	regress_clean_dnsserver();
563*2b15cb3dSCy Schubert }
564*2b15cb3dSCy Schubert 
565*2b15cb3dSCy Schubert static int request_count = 0;
566*2b15cb3dSCy Schubert static struct evdns_request *current_req = NULL;
567*2b15cb3dSCy Schubert 
568*2b15cb3dSCy Schubert static void
569*2b15cb3dSCy Schubert search_cancel_server_cb(struct evdns_server_request *req, void *data)
570*2b15cb3dSCy Schubert {
571*2b15cb3dSCy Schubert 	const char *question;
572*2b15cb3dSCy Schubert 
573*2b15cb3dSCy Schubert 	if (req->nquestions != 1)
574*2b15cb3dSCy Schubert 		TT_DIE(("Only handling one question at a time; got %d",
575*2b15cb3dSCy Schubert 			req->nquestions));
576*2b15cb3dSCy Schubert 
577*2b15cb3dSCy Schubert 	question = req->questions[0]->name;
578*2b15cb3dSCy Schubert 
579*2b15cb3dSCy Schubert 	TT_BLATHER(("got question, %s", question));
580*2b15cb3dSCy Schubert 
581*2b15cb3dSCy Schubert 	tt_assert(request_count > 0);
582*2b15cb3dSCy Schubert 	tt_assert(!evdns_server_request_respond(req, 3));
583*2b15cb3dSCy Schubert 
584*2b15cb3dSCy Schubert 	if (!--request_count)
585*2b15cb3dSCy Schubert 		evdns_cancel_request(NULL, current_req);
586*2b15cb3dSCy Schubert 
587*2b15cb3dSCy Schubert end:
588*2b15cb3dSCy Schubert 	;
589*2b15cb3dSCy Schubert }
590*2b15cb3dSCy Schubert 
591*2b15cb3dSCy Schubert static void
592*2b15cb3dSCy Schubert dns_search_cancel_test(void *arg)
593*2b15cb3dSCy Schubert {
594*2b15cb3dSCy Schubert 	struct basic_test_data *data = arg;
595*2b15cb3dSCy Schubert 	struct event_base *base = data->base;
596*2b15cb3dSCy Schubert 	struct evdns_base *dns = NULL;
597*2b15cb3dSCy Schubert 	struct evdns_server_port *port = NULL;
598*2b15cb3dSCy Schubert 	ev_uint16_t portnum = 0;
599*2b15cb3dSCy Schubert 	struct generic_dns_callback_result r1;
600*2b15cb3dSCy Schubert 	char buf[64];
601*2b15cb3dSCy Schubert 
602*2b15cb3dSCy Schubert 	port = regress_get_dnsserver(base, &portnum, NULL,
603*2b15cb3dSCy Schubert 	    search_cancel_server_cb, NULL);
604*2b15cb3dSCy Schubert 	tt_assert(port);
605*2b15cb3dSCy Schubert 	evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum);
606*2b15cb3dSCy Schubert 
607*2b15cb3dSCy Schubert 	dns = evdns_base_new(base, 0);
608*2b15cb3dSCy Schubert 	tt_assert(!evdns_base_nameserver_ip_add(dns, buf));
609*2b15cb3dSCy Schubert 
610*2b15cb3dSCy Schubert 	evdns_base_search_add(dns, "a.example.com");
611*2b15cb3dSCy Schubert 	evdns_base_search_add(dns, "b.example.com");
612*2b15cb3dSCy Schubert 	evdns_base_search_add(dns, "c.example.com");
613*2b15cb3dSCy Schubert 	evdns_base_search_add(dns, "d.example.com");
614*2b15cb3dSCy Schubert 
615*2b15cb3dSCy Schubert 	exit_base = base;
616*2b15cb3dSCy Schubert 	request_count = 3;
617*2b15cb3dSCy Schubert 	n_replies_left = 1;
618*2b15cb3dSCy Schubert 
619*2b15cb3dSCy Schubert 	current_req = evdns_base_resolve_ipv4(dns, "host", 0,
620*2b15cb3dSCy Schubert 					generic_dns_callback, &r1);
621*2b15cb3dSCy Schubert 	event_base_dispatch(base);
622*2b15cb3dSCy Schubert 
623*2b15cb3dSCy Schubert 	tt_int_op(r1.result, ==, DNS_ERR_CANCEL);
624*2b15cb3dSCy Schubert 
625*2b15cb3dSCy Schubert end:
626*2b15cb3dSCy Schubert 	if (port)
627*2b15cb3dSCy Schubert 		evdns_close_server_port(port);
628*2b15cb3dSCy Schubert 	if (dns)
629*2b15cb3dSCy Schubert 		evdns_base_free(dns, 0);
630*2b15cb3dSCy Schubert }
631*2b15cb3dSCy Schubert 
632*2b15cb3dSCy Schubert static void
633*2b15cb3dSCy Schubert fail_server_cb(struct evdns_server_request *req, void *data)
634*2b15cb3dSCy Schubert {
635*2b15cb3dSCy Schubert 	const char *question;
636*2b15cb3dSCy Schubert 	int *count = data;
637*2b15cb3dSCy Schubert 	struct in_addr in;
638*2b15cb3dSCy Schubert 
639*2b15cb3dSCy Schubert 	/* Drop the first N requests that we get. */
640*2b15cb3dSCy Schubert 	if (*count > 0) {
641*2b15cb3dSCy Schubert 		--*count;
642*2b15cb3dSCy Schubert 		tt_want(! evdns_server_request_drop(req));
643*2b15cb3dSCy Schubert 		return;
644*2b15cb3dSCy Schubert 	}
645*2b15cb3dSCy Schubert 
646*2b15cb3dSCy Schubert 	if (req->nquestions != 1)
647*2b15cb3dSCy Schubert 		TT_DIE(("Only handling one question at a time; got %d",
648*2b15cb3dSCy Schubert 			req->nquestions));
649*2b15cb3dSCy Schubert 
650*2b15cb3dSCy Schubert 	question = req->questions[0]->name;
651*2b15cb3dSCy Schubert 
652*2b15cb3dSCy Schubert 	if (!evutil_ascii_strcasecmp(question, "google.com")) {
653*2b15cb3dSCy Schubert 		/* Detect a probe, and get out of the loop. */
654*2b15cb3dSCy Schubert 		event_base_loopexit(exit_base, NULL);
655*2b15cb3dSCy Schubert 	}
656*2b15cb3dSCy Schubert 
657*2b15cb3dSCy Schubert 	tt_assert(evutil_inet_pton(AF_INET, "16.32.64.128", &in));
658*2b15cb3dSCy Schubert 	evdns_server_request_add_a_reply(req, question, 1, &in.s_addr,
659*2b15cb3dSCy Schubert 	    100);
660*2b15cb3dSCy Schubert 	tt_assert(! evdns_server_request_respond(req, 0))
661*2b15cb3dSCy Schubert 	return;
662*2b15cb3dSCy Schubert end:
663*2b15cb3dSCy Schubert 	tt_want(! evdns_server_request_drop(req));
664*2b15cb3dSCy Schubert }
665*2b15cb3dSCy Schubert 
666*2b15cb3dSCy Schubert static void
667*2b15cb3dSCy Schubert dns_retry_test(void *arg)
668*2b15cb3dSCy Schubert {
669*2b15cb3dSCy Schubert 	struct basic_test_data *data = arg;
670*2b15cb3dSCy Schubert 	struct event_base *base = data->base;
671*2b15cb3dSCy Schubert 	struct evdns_server_port *port = NULL;
672*2b15cb3dSCy Schubert 	struct evdns_base *dns = NULL;
673*2b15cb3dSCy Schubert 	int drop_count = 2;
674*2b15cb3dSCy Schubert 	ev_uint16_t portnum = 0;
675*2b15cb3dSCy Schubert 	char buf[64];
676*2b15cb3dSCy Schubert 
677*2b15cb3dSCy Schubert 	struct generic_dns_callback_result r1;
678*2b15cb3dSCy Schubert 
679*2b15cb3dSCy Schubert 	port = regress_get_dnsserver(base, &portnum, NULL,
680*2b15cb3dSCy Schubert 	    fail_server_cb, &drop_count);
681*2b15cb3dSCy Schubert 	tt_assert(port);
682*2b15cb3dSCy Schubert 	evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum);
683*2b15cb3dSCy Schubert 
684*2b15cb3dSCy Schubert 	dns = evdns_base_new(base, 0);
685*2b15cb3dSCy Schubert 	tt_assert(!evdns_base_nameserver_ip_add(dns, buf));
686*2b15cb3dSCy Schubert 	tt_assert(! evdns_base_set_option(dns, "timeout", "0.2"));
687*2b15cb3dSCy Schubert 	tt_assert(! evdns_base_set_option(dns, "max-timeouts:", "10"));
688*2b15cb3dSCy Schubert 	tt_assert(! evdns_base_set_option(dns, "initial-probe-timeout", "0.1"));
689*2b15cb3dSCy Schubert 
690*2b15cb3dSCy Schubert 	evdns_base_resolve_ipv4(dns, "host.example.com", 0,
691*2b15cb3dSCy Schubert 	    generic_dns_callback, &r1);
692*2b15cb3dSCy Schubert 
693*2b15cb3dSCy Schubert 	n_replies_left = 1;
694*2b15cb3dSCy Schubert 	exit_base = base;
695*2b15cb3dSCy Schubert 
696*2b15cb3dSCy Schubert 	event_base_dispatch(base);
697*2b15cb3dSCy Schubert 
698*2b15cb3dSCy Schubert 	tt_int_op(drop_count, ==, 0);
699*2b15cb3dSCy Schubert 
700*2b15cb3dSCy Schubert 	tt_int_op(r1.type, ==, DNS_IPv4_A);
701*2b15cb3dSCy Schubert 	tt_int_op(r1.count, ==, 1);
702*2b15cb3dSCy Schubert 	tt_int_op(((ev_uint32_t*)r1.addrs)[0], ==, htonl(0x10204080));
703*2b15cb3dSCy Schubert 
704*2b15cb3dSCy Schubert 	/* Now try again, but this time have the server get treated as
705*2b15cb3dSCy Schubert 	 * failed, so we can send it a test probe. */
706*2b15cb3dSCy Schubert 	drop_count = 4;
707*2b15cb3dSCy Schubert 	tt_assert(! evdns_base_set_option(dns, "max-timeouts:", "2"));
708*2b15cb3dSCy Schubert 	tt_assert(! evdns_base_set_option(dns, "attempts:", "3"));
709*2b15cb3dSCy Schubert 	memset(&r1, 0, sizeof(r1));
710*2b15cb3dSCy Schubert 
711*2b15cb3dSCy Schubert 	evdns_base_resolve_ipv4(dns, "host.example.com", 0,
712*2b15cb3dSCy Schubert 	    generic_dns_callback, &r1);
713*2b15cb3dSCy Schubert 
714*2b15cb3dSCy Schubert 	n_replies_left = 2;
715*2b15cb3dSCy Schubert 
716*2b15cb3dSCy Schubert 	/* This will run until it answers the "google.com" probe request. */
717*2b15cb3dSCy Schubert 	event_base_dispatch(base);
718*2b15cb3dSCy Schubert 
719*2b15cb3dSCy Schubert 	/* We'll treat the server as failed here. */
720*2b15cb3dSCy Schubert 	tt_int_op(r1.result, ==, DNS_ERR_TIMEOUT);
721*2b15cb3dSCy Schubert 
722*2b15cb3dSCy Schubert 	/* It should work this time. */
723*2b15cb3dSCy Schubert 	tt_int_op(drop_count, ==, 0);
724*2b15cb3dSCy Schubert 	evdns_base_resolve_ipv4(dns, "host.example.com", 0,
725*2b15cb3dSCy Schubert 	    generic_dns_callback, &r1);
726*2b15cb3dSCy Schubert 
727*2b15cb3dSCy Schubert 	event_base_dispatch(base);
728*2b15cb3dSCy Schubert 	tt_int_op(r1.result, ==, DNS_ERR_NONE);
729*2b15cb3dSCy Schubert 	tt_int_op(r1.type, ==, DNS_IPv4_A);
730*2b15cb3dSCy Schubert 	tt_int_op(r1.count, ==, 1);
731*2b15cb3dSCy Schubert 	tt_int_op(((ev_uint32_t*)r1.addrs)[0], ==, htonl(0x10204080));
732*2b15cb3dSCy Schubert 
733*2b15cb3dSCy Schubert end:
734*2b15cb3dSCy Schubert 	if (dns)
735*2b15cb3dSCy Schubert 		evdns_base_free(dns, 0);
736*2b15cb3dSCy Schubert 	if (port)
737*2b15cb3dSCy Schubert 		evdns_close_server_port(port);
738*2b15cb3dSCy Schubert }
739*2b15cb3dSCy Schubert 
740*2b15cb3dSCy Schubert static struct regress_dns_server_table internal_error_table[] = {
741*2b15cb3dSCy Schubert 	/* Error 4 (NOTIMPL) makes us reissue the request to another server
742*2b15cb3dSCy Schubert 	   if we can.
743*2b15cb3dSCy Schubert 
744*2b15cb3dSCy Schubert 	   XXXX we should reissue under a much wider set of circumstances!
745*2b15cb3dSCy Schubert 	 */
746*2b15cb3dSCy Schubert 	{ "foof.example.com", "err", "4", 0 },
747*2b15cb3dSCy Schubert 	{ NULL, NULL, NULL, 0 }
748*2b15cb3dSCy Schubert };
749*2b15cb3dSCy Schubert 
750*2b15cb3dSCy Schubert static struct regress_dns_server_table reissue_table[] = {
751*2b15cb3dSCy Schubert 	{ "foof.example.com", "A", "240.15.240.15", 0 },
752*2b15cb3dSCy Schubert 	{ NULL, NULL, NULL, 0 }
753*2b15cb3dSCy Schubert };
754*2b15cb3dSCy Schubert 
755*2b15cb3dSCy Schubert static void
756*2b15cb3dSCy Schubert dns_reissue_test(void *arg)
757*2b15cb3dSCy Schubert {
758*2b15cb3dSCy Schubert 	struct basic_test_data *data = arg;
759*2b15cb3dSCy Schubert 	struct event_base *base = data->base;
760*2b15cb3dSCy Schubert 	struct evdns_server_port *port1 = NULL, *port2 = NULL;
761*2b15cb3dSCy Schubert 	struct evdns_base *dns = NULL;
762*2b15cb3dSCy Schubert 	struct generic_dns_callback_result r1;
763*2b15cb3dSCy Schubert 	ev_uint16_t portnum1 = 0, portnum2=0;
764*2b15cb3dSCy Schubert 	char buf1[64], buf2[64];
765*2b15cb3dSCy Schubert 
766*2b15cb3dSCy Schubert 	port1 = regress_get_dnsserver(base, &portnum1, NULL,
767*2b15cb3dSCy Schubert 	    regress_dns_server_cb, internal_error_table);
768*2b15cb3dSCy Schubert 	tt_assert(port1);
769*2b15cb3dSCy Schubert 	port2 = regress_get_dnsserver(base, &portnum2, NULL,
770*2b15cb3dSCy Schubert 	    regress_dns_server_cb, reissue_table);
771*2b15cb3dSCy Schubert 	tt_assert(port2);
772*2b15cb3dSCy Schubert 	evutil_snprintf(buf1, sizeof(buf1), "127.0.0.1:%d", (int)portnum1);
773*2b15cb3dSCy Schubert 	evutil_snprintf(buf2, sizeof(buf2), "127.0.0.1:%d", (int)portnum2);
774*2b15cb3dSCy Schubert 
775*2b15cb3dSCy Schubert 	dns = evdns_base_new(base, 0);
776*2b15cb3dSCy Schubert 	tt_assert(!evdns_base_nameserver_ip_add(dns, buf1));
777*2b15cb3dSCy Schubert 	tt_assert(! evdns_base_set_option(dns, "timeout:", "0.3"));
778*2b15cb3dSCy Schubert 	tt_assert(! evdns_base_set_option(dns, "max-timeouts:", "2"));
779*2b15cb3dSCy Schubert 	tt_assert(! evdns_base_set_option(dns, "attempts:", "5"));
780*2b15cb3dSCy Schubert 
781*2b15cb3dSCy Schubert 	memset(&r1, 0, sizeof(r1));
782*2b15cb3dSCy Schubert 	evdns_base_resolve_ipv4(dns, "foof.example.com", 0,
783*2b15cb3dSCy Schubert 	    generic_dns_callback, &r1);
784*2b15cb3dSCy Schubert 
785*2b15cb3dSCy Schubert 	/* Add this after, so that we are sure to get a reissue. */
786*2b15cb3dSCy Schubert 	tt_assert(!evdns_base_nameserver_ip_add(dns, buf2));
787*2b15cb3dSCy Schubert 
788*2b15cb3dSCy Schubert 	n_replies_left = 1;
789*2b15cb3dSCy Schubert 	exit_base = base;
790*2b15cb3dSCy Schubert 
791*2b15cb3dSCy Schubert 	event_base_dispatch(base);
792*2b15cb3dSCy Schubert 	tt_int_op(r1.result, ==, DNS_ERR_NONE);
793*2b15cb3dSCy Schubert 	tt_int_op(r1.type, ==, DNS_IPv4_A);
794*2b15cb3dSCy Schubert 	tt_int_op(r1.count, ==, 1);
795*2b15cb3dSCy Schubert 	tt_int_op(((ev_uint32_t*)r1.addrs)[0], ==, htonl(0xf00ff00f));
796*2b15cb3dSCy Schubert 
797*2b15cb3dSCy Schubert 	/* Make sure we dropped at least once. */
798*2b15cb3dSCy Schubert 	tt_int_op(internal_error_table[0].seen, >, 0);
799*2b15cb3dSCy Schubert 
800*2b15cb3dSCy Schubert end:
801*2b15cb3dSCy Schubert 	if (dns)
802*2b15cb3dSCy Schubert 		evdns_base_free(dns, 0);
803*2b15cb3dSCy Schubert 	if (port1)
804*2b15cb3dSCy Schubert 		evdns_close_server_port(port1);
805*2b15cb3dSCy Schubert 	if (port2)
806*2b15cb3dSCy Schubert 		evdns_close_server_port(port2);
807*2b15cb3dSCy Schubert }
808*2b15cb3dSCy Schubert 
809*2b15cb3dSCy Schubert #if 0
810*2b15cb3dSCy Schubert static void
811*2b15cb3dSCy Schubert dumb_bytes_fn(char *p, size_t n)
812*2b15cb3dSCy Schubert {
813*2b15cb3dSCy Schubert 	unsigned i;
814*2b15cb3dSCy Schubert 	/* This gets us 6 bits of entropy per transaction ID, which means we
815*2b15cb3dSCy Schubert 	 * will have probably have collisions and need to pick again. */
816*2b15cb3dSCy Schubert 	for (i=0;i<n;++i)
817*2b15cb3dSCy Schubert 		p[i] = (char)(rand() & 7);
818*2b15cb3dSCy Schubert }
819*2b15cb3dSCy Schubert #endif
820*2b15cb3dSCy Schubert 
821*2b15cb3dSCy Schubert static void
822*2b15cb3dSCy Schubert dns_inflight_test(void *arg)
823*2b15cb3dSCy Schubert {
824*2b15cb3dSCy Schubert 	struct basic_test_data *data = arg;
825*2b15cb3dSCy Schubert 	struct event_base *base = data->base;
826*2b15cb3dSCy Schubert 	struct evdns_base *dns = NULL;
827*2b15cb3dSCy Schubert 	ev_uint16_t portnum = 0;
828*2b15cb3dSCy Schubert 	char buf[64];
829*2b15cb3dSCy Schubert 
830*2b15cb3dSCy Schubert 	struct generic_dns_callback_result r[20];
831*2b15cb3dSCy Schubert 	int i;
832*2b15cb3dSCy Schubert 
833*2b15cb3dSCy Schubert 	tt_assert(regress_dnsserver(base, &portnum, reissue_table));
834*2b15cb3dSCy Schubert 	evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum);
835*2b15cb3dSCy Schubert 
836*2b15cb3dSCy Schubert 	dns = evdns_base_new(base, 0);
837*2b15cb3dSCy Schubert 	tt_assert(!evdns_base_nameserver_ip_add(dns, buf));
838*2b15cb3dSCy Schubert 	tt_assert(! evdns_base_set_option(dns, "max-inflight:", "3"));
839*2b15cb3dSCy Schubert 	tt_assert(! evdns_base_set_option(dns, "randomize-case:", "0"));
840*2b15cb3dSCy Schubert 
841*2b15cb3dSCy Schubert 	for (i=0;i<20;++i)
842*2b15cb3dSCy Schubert 		evdns_base_resolve_ipv4(dns, "foof.example.com", 0, generic_dns_callback, &r[i]);
843*2b15cb3dSCy Schubert 
844*2b15cb3dSCy Schubert 	n_replies_left = 20;
845*2b15cb3dSCy Schubert 	exit_base = base;
846*2b15cb3dSCy Schubert 
847*2b15cb3dSCy Schubert 	event_base_dispatch(base);
848*2b15cb3dSCy Schubert 
849*2b15cb3dSCy Schubert 	for (i=0;i<20;++i) {
850*2b15cb3dSCy Schubert 		tt_int_op(r[i].type, ==, DNS_IPv4_A);
851*2b15cb3dSCy Schubert 		tt_int_op(r[i].count, ==, 1);
852*2b15cb3dSCy Schubert 		tt_int_op(((ev_uint32_t*)r[i].addrs)[0], ==, htonl(0xf00ff00f));
853*2b15cb3dSCy Schubert 	}
854*2b15cb3dSCy Schubert 
855*2b15cb3dSCy Schubert end:
856*2b15cb3dSCy Schubert 	if (dns)
857*2b15cb3dSCy Schubert 		evdns_base_free(dns, 0);
858*2b15cb3dSCy Schubert 	regress_clean_dnsserver();
859*2b15cb3dSCy Schubert }
860*2b15cb3dSCy Schubert 
861*2b15cb3dSCy Schubert /* === Test for bufferevent_socket_connect_hostname */
862*2b15cb3dSCy Schubert 
863*2b15cb3dSCy Schubert static int total_connected_or_failed = 0;
864*2b15cb3dSCy Schubert static int total_n_accepted = 0;
865*2b15cb3dSCy Schubert static struct event_base *be_connect_hostname_base = NULL;
866*2b15cb3dSCy Schubert 
867*2b15cb3dSCy Schubert /* Implements a DNS server for the connect_hostname test and the
868*2b15cb3dSCy Schubert  * getaddrinfo_async test */
869*2b15cb3dSCy Schubert static void
870*2b15cb3dSCy Schubert be_getaddrinfo_server_cb(struct evdns_server_request *req, void *data)
871*2b15cb3dSCy Schubert {
872*2b15cb3dSCy Schubert 	int i;
873*2b15cb3dSCy Schubert 	int *n_got_p=data;
874*2b15cb3dSCy Schubert 	int added_any=0;
875*2b15cb3dSCy Schubert 	++*n_got_p;
876*2b15cb3dSCy Schubert 
877*2b15cb3dSCy Schubert 	for (i=0;i<req->nquestions;++i) {
878*2b15cb3dSCy Schubert 		const int qtype = req->questions[i]->type;
879*2b15cb3dSCy Schubert 		const int qclass = req->questions[i]->dns_question_class;
880*2b15cb3dSCy Schubert 		const char *qname = req->questions[i]->name;
881*2b15cb3dSCy Schubert 		struct in_addr ans;
882*2b15cb3dSCy Schubert 		struct in6_addr ans6;
883*2b15cb3dSCy Schubert 		memset(&ans6, 0, sizeof(ans6));
884*2b15cb3dSCy Schubert 
885*2b15cb3dSCy Schubert 		TT_BLATHER(("Got question about %s, type=%d", qname, qtype));
886*2b15cb3dSCy Schubert 
887*2b15cb3dSCy Schubert 		if (qtype == EVDNS_TYPE_A &&
888*2b15cb3dSCy Schubert 		    qclass == EVDNS_CLASS_INET &&
889*2b15cb3dSCy Schubert 		    !evutil_ascii_strcasecmp(qname, "nobodaddy.example.com")) {
890*2b15cb3dSCy Schubert 			ans.s_addr = htonl(0x7f000001);
891*2b15cb3dSCy Schubert 			evdns_server_request_add_a_reply(req, qname,
892*2b15cb3dSCy Schubert 			    1, &ans.s_addr, 2000);
893*2b15cb3dSCy Schubert 			added_any = 1;
894*2b15cb3dSCy Schubert 		} else if (!evutil_ascii_strcasecmp(qname,
895*2b15cb3dSCy Schubert 			"nosuchplace.example.com")) {
896*2b15cb3dSCy Schubert 			/* ok, just say notfound. */
897*2b15cb3dSCy Schubert 		} else if (!evutil_ascii_strcasecmp(qname,
898*2b15cb3dSCy Schubert 			"both.example.com")) {
899*2b15cb3dSCy Schubert 			if (qtype == EVDNS_TYPE_A) {
900*2b15cb3dSCy Schubert 				ans.s_addr = htonl(0x50502020);
901*2b15cb3dSCy Schubert 				evdns_server_request_add_a_reply(req, qname,
902*2b15cb3dSCy Schubert 				    1, &ans.s_addr, 2000);
903*2b15cb3dSCy Schubert 				added_any = 1;
904*2b15cb3dSCy Schubert 			} else if (qtype == EVDNS_TYPE_AAAA) {
905*2b15cb3dSCy Schubert 				ans6.s6_addr[0] = 0x80;
906*2b15cb3dSCy Schubert 				ans6.s6_addr[1] = 0xff;
907*2b15cb3dSCy Schubert 				ans6.s6_addr[14] = 0xbb;
908*2b15cb3dSCy Schubert 				ans6.s6_addr[15] = 0xbb;
909*2b15cb3dSCy Schubert 				evdns_server_request_add_aaaa_reply(req, qname,
910*2b15cb3dSCy Schubert 				    1, &ans6.s6_addr, 2000);
911*2b15cb3dSCy Schubert 				added_any = 1;
912*2b15cb3dSCy Schubert 			}
913*2b15cb3dSCy Schubert 			evdns_server_request_add_cname_reply(req, qname,
914*2b15cb3dSCy Schubert 			    "both-canonical.example.com", 1000);
915*2b15cb3dSCy Schubert 		} else if (!evutil_ascii_strcasecmp(qname,
916*2b15cb3dSCy Schubert 			"v4only.example.com") ||
917*2b15cb3dSCy Schubert 		    !evutil_ascii_strcasecmp(qname, "v4assert.example.com")) {
918*2b15cb3dSCy Schubert 			if (qtype == EVDNS_TYPE_A) {
919*2b15cb3dSCy Schubert 				ans.s_addr = htonl(0x12345678);
920*2b15cb3dSCy Schubert 				evdns_server_request_add_a_reply(req, qname,
921*2b15cb3dSCy Schubert 				    1, &ans.s_addr, 2000);
922*2b15cb3dSCy Schubert 				added_any = 1;
923*2b15cb3dSCy Schubert 			} else if (!evutil_ascii_strcasecmp(qname,
924*2b15cb3dSCy Schubert 				"v4assert.example.com")) {
925*2b15cb3dSCy Schubert 				TT_FAIL(("Got an AAAA request for v4assert"));
926*2b15cb3dSCy Schubert 			}
927*2b15cb3dSCy Schubert 		} else if (!evutil_ascii_strcasecmp(qname,
928*2b15cb3dSCy Schubert 			"v6only.example.com") ||
929*2b15cb3dSCy Schubert 		    !evutil_ascii_strcasecmp(qname, "v6assert.example.com")) {
930*2b15cb3dSCy Schubert 			if (qtype == EVDNS_TYPE_AAAA) {
931*2b15cb3dSCy Schubert 				ans6.s6_addr[0] = 0x0b;
932*2b15cb3dSCy Schubert 				ans6.s6_addr[1] = 0x0b;
933*2b15cb3dSCy Schubert 				ans6.s6_addr[14] = 0xf0;
934*2b15cb3dSCy Schubert 				ans6.s6_addr[15] = 0x0d;
935*2b15cb3dSCy Schubert 				evdns_server_request_add_aaaa_reply(req, qname,
936*2b15cb3dSCy Schubert 				    1, &ans6.s6_addr, 2000);
937*2b15cb3dSCy Schubert 				added_any = 1;
938*2b15cb3dSCy Schubert 			}  else if (!evutil_ascii_strcasecmp(qname,
939*2b15cb3dSCy Schubert 				"v6assert.example.com")) {
940*2b15cb3dSCy Schubert 				TT_FAIL(("Got a A request for v6assert"));
941*2b15cb3dSCy Schubert 			}
942*2b15cb3dSCy Schubert 		} else if (!evutil_ascii_strcasecmp(qname,
943*2b15cb3dSCy Schubert 			"v6timeout.example.com")) {
944*2b15cb3dSCy Schubert 			if (qtype == EVDNS_TYPE_A) {
945*2b15cb3dSCy Schubert 				ans.s_addr = htonl(0xabcdef01);
946*2b15cb3dSCy Schubert 				evdns_server_request_add_a_reply(req, qname,
947*2b15cb3dSCy Schubert 				    1, &ans.s_addr, 2000);
948*2b15cb3dSCy Schubert 				added_any = 1;
949*2b15cb3dSCy Schubert 			} else if (qtype == EVDNS_TYPE_AAAA) {
950*2b15cb3dSCy Schubert 				/* Let the v6 request time out.*/
951*2b15cb3dSCy Schubert 				evdns_server_request_drop(req);
952*2b15cb3dSCy Schubert 				return;
953*2b15cb3dSCy Schubert 			}
954*2b15cb3dSCy Schubert 		} else if (!evutil_ascii_strcasecmp(qname,
955*2b15cb3dSCy Schubert 			"v4timeout.example.com")) {
956*2b15cb3dSCy Schubert 			if (qtype == EVDNS_TYPE_AAAA) {
957*2b15cb3dSCy Schubert 				ans6.s6_addr[0] = 0x0a;
958*2b15cb3dSCy Schubert 				ans6.s6_addr[1] = 0x0a;
959*2b15cb3dSCy Schubert 				ans6.s6_addr[14] = 0xff;
960*2b15cb3dSCy Schubert 				ans6.s6_addr[15] = 0x01;
961*2b15cb3dSCy Schubert 				evdns_server_request_add_aaaa_reply(req, qname,
962*2b15cb3dSCy Schubert 				    1, &ans6.s6_addr, 2000);
963*2b15cb3dSCy Schubert 				added_any = 1;
964*2b15cb3dSCy Schubert 			} else if (qtype == EVDNS_TYPE_A) {
965*2b15cb3dSCy Schubert 				/* Let the v4 request time out.*/
966*2b15cb3dSCy Schubert 				evdns_server_request_drop(req);
967*2b15cb3dSCy Schubert 				return;
968*2b15cb3dSCy Schubert 			}
969*2b15cb3dSCy Schubert 		} else if (!evutil_ascii_strcasecmp(qname,
970*2b15cb3dSCy Schubert 			"v6timeout-nonexist.example.com")) {
971*2b15cb3dSCy Schubert 			if (qtype == EVDNS_TYPE_A) {
972*2b15cb3dSCy Schubert 				/* Fall through, give an nexist. */
973*2b15cb3dSCy Schubert 			} else if (qtype == EVDNS_TYPE_AAAA) {
974*2b15cb3dSCy Schubert 				/* Let the v6 request time out.*/
975*2b15cb3dSCy Schubert 				evdns_server_request_drop(req);
976*2b15cb3dSCy Schubert 				return;
977*2b15cb3dSCy Schubert 			}
978*2b15cb3dSCy Schubert 		} else if (!evutil_ascii_strcasecmp(qname,
979*2b15cb3dSCy Schubert 			"all-timeout.example.com")) {
980*2b15cb3dSCy Schubert 			/* drop all requests */
981*2b15cb3dSCy Schubert 			evdns_server_request_drop(req);
982*2b15cb3dSCy Schubert 			return;
983*2b15cb3dSCy Schubert 		} else {
984*2b15cb3dSCy Schubert 			TT_GRIPE(("Got weird request for %s",qname));
985*2b15cb3dSCy Schubert 		}
986*2b15cb3dSCy Schubert 	}
987*2b15cb3dSCy Schubert 	if (added_any) {
988*2b15cb3dSCy Schubert 		TT_BLATHER(("answering"));
989*2b15cb3dSCy Schubert 		evdns_server_request_respond(req, 0);
990*2b15cb3dSCy Schubert 	} else {
991*2b15cb3dSCy Schubert 		TT_BLATHER(("saying nexist."));
992*2b15cb3dSCy Schubert 		evdns_server_request_respond(req, 3);
993*2b15cb3dSCy Schubert 	}
994*2b15cb3dSCy Schubert }
995*2b15cb3dSCy Schubert 
996*2b15cb3dSCy Schubert /* Implements a listener for connect_hostname test. */
997*2b15cb3dSCy Schubert static void
998*2b15cb3dSCy Schubert nil_accept_cb(struct evconnlistener *l, evutil_socket_t fd, struct sockaddr *s,
999*2b15cb3dSCy Schubert     int socklen, void *arg)
1000*2b15cb3dSCy Schubert {
1001*2b15cb3dSCy Schubert 	int *p = arg;
1002*2b15cb3dSCy Schubert 	(*p)++;
1003*2b15cb3dSCy Schubert 	++total_n_accepted;
1004*2b15cb3dSCy Schubert 	/* don't do anything with the socket; let it close when we exit() */
1005*2b15cb3dSCy Schubert 	if (total_n_accepted >= 3 && total_connected_or_failed >= 5)
1006*2b15cb3dSCy Schubert 		event_base_loopexit(be_connect_hostname_base,
1007*2b15cb3dSCy Schubert 		    NULL);
1008*2b15cb3dSCy Schubert }
1009*2b15cb3dSCy Schubert 
1010*2b15cb3dSCy Schubert struct be_conn_hostname_result {
1011*2b15cb3dSCy Schubert 	int dnserr;
1012*2b15cb3dSCy Schubert 	int what;
1013*2b15cb3dSCy Schubert };
1014*2b15cb3dSCy Schubert 
1015*2b15cb3dSCy Schubert /* Bufferevent event callback for the connect_hostname test: remembers what
1016*2b15cb3dSCy Schubert  * event we got. */
1017*2b15cb3dSCy Schubert static void
1018*2b15cb3dSCy Schubert be_connect_hostname_event_cb(struct bufferevent *bev, short what, void *ctx)
1019*2b15cb3dSCy Schubert {
1020*2b15cb3dSCy Schubert 	struct be_conn_hostname_result *got = ctx;
1021*2b15cb3dSCy Schubert 	if (!got->what) {
1022*2b15cb3dSCy Schubert 		TT_BLATHER(("Got a bufferevent event %d", what));
1023*2b15cb3dSCy Schubert 		got->what = what;
1024*2b15cb3dSCy Schubert 
1025*2b15cb3dSCy Schubert 		if ((what & BEV_EVENT_CONNECTED) || (what & BEV_EVENT_ERROR)) {
1026*2b15cb3dSCy Schubert 			int r;
1027*2b15cb3dSCy Schubert 			if ((r = bufferevent_socket_get_dns_error(bev))) {
1028*2b15cb3dSCy Schubert 				got->dnserr = r;
1029*2b15cb3dSCy Schubert 				TT_BLATHER(("DNS error %d: %s", r,
1030*2b15cb3dSCy Schubert 					   evutil_gai_strerror(r)));
1031*2b15cb3dSCy Schubert 			}			++total_connected_or_failed;
1032*2b15cb3dSCy Schubert 			TT_BLATHER(("Got %d connections or errors.", total_connected_or_failed));
1033*2b15cb3dSCy Schubert 
1034*2b15cb3dSCy Schubert 			if (total_n_accepted >= 3 && total_connected_or_failed >= 5)
1035*2b15cb3dSCy Schubert 				event_base_loopexit(be_connect_hostname_base,
1036*2b15cb3dSCy Schubert 				    NULL);
1037*2b15cb3dSCy Schubert 		}
1038*2b15cb3dSCy Schubert 	} else {
1039*2b15cb3dSCy Schubert 		TT_FAIL(("Two events on one bufferevent. %d,%d",
1040*2b15cb3dSCy Schubert 			got->what, (int)what));
1041*2b15cb3dSCy Schubert 	}
1042*2b15cb3dSCy Schubert }
1043*2b15cb3dSCy Schubert 
1044*2b15cb3dSCy Schubert static void
1045*2b15cb3dSCy Schubert test_bufferevent_connect_hostname(void *arg)
1046*2b15cb3dSCy Schubert {
1047*2b15cb3dSCy Schubert 	struct basic_test_data *data = arg;
1048*2b15cb3dSCy Schubert 	struct evconnlistener *listener = NULL;
1049*2b15cb3dSCy Schubert 	struct bufferevent *be1=NULL, *be2=NULL, *be3=NULL, *be4=NULL, *be5=NULL;
1050*2b15cb3dSCy Schubert 	struct be_conn_hostname_result be1_outcome={0,0}, be2_outcome={0,0},
1051*2b15cb3dSCy Schubert 	       be3_outcome={0,0}, be4_outcome={0,0}, be5_outcome={0,0};
1052*2b15cb3dSCy Schubert 	int expect_err5;
1053*2b15cb3dSCy Schubert 	struct evdns_base *dns=NULL;
1054*2b15cb3dSCy Schubert 	struct evdns_server_port *port=NULL;
1055*2b15cb3dSCy Schubert 	struct sockaddr_in sin;
1056*2b15cb3dSCy Schubert 	int listener_port=-1;
1057*2b15cb3dSCy Schubert 	ev_uint16_t dns_port=0;
1058*2b15cb3dSCy Schubert 	int n_accept=0, n_dns=0;
1059*2b15cb3dSCy Schubert 	char buf[128];
1060*2b15cb3dSCy Schubert 
1061*2b15cb3dSCy Schubert 	be_connect_hostname_base = data->base;
1062*2b15cb3dSCy Schubert 
1063*2b15cb3dSCy Schubert 	/* Bind an address and figure out what port it's on. */
1064*2b15cb3dSCy Schubert 	memset(&sin, 0, sizeof(sin));
1065*2b15cb3dSCy Schubert 	sin.sin_family = AF_INET;
1066*2b15cb3dSCy Schubert 	sin.sin_addr.s_addr = htonl(0x7f000001); /* 127.0.0.1 */
1067*2b15cb3dSCy Schubert 	sin.sin_port = 0;
1068*2b15cb3dSCy Schubert 	listener = evconnlistener_new_bind(data->base, nil_accept_cb,
1069*2b15cb3dSCy Schubert 	    &n_accept,
1070*2b15cb3dSCy Schubert 	    LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_EXEC,
1071*2b15cb3dSCy Schubert 	    -1, (struct sockaddr *)&sin, sizeof(sin));
1072*2b15cb3dSCy Schubert 	tt_assert(listener);
1073*2b15cb3dSCy Schubert 	listener_port = regress_get_socket_port(
1074*2b15cb3dSCy Schubert 		evconnlistener_get_fd(listener));
1075*2b15cb3dSCy Schubert 
1076*2b15cb3dSCy Schubert 	port = regress_get_dnsserver(data->base, &dns_port, NULL,
1077*2b15cb3dSCy Schubert 	    be_getaddrinfo_server_cb, &n_dns);
1078*2b15cb3dSCy Schubert 	tt_assert(port);
1079*2b15cb3dSCy Schubert 	tt_int_op(dns_port, >=, 0);
1080*2b15cb3dSCy Schubert 
1081*2b15cb3dSCy Schubert 	/* Start an evdns_base that uses the server as its resolver. */
1082*2b15cb3dSCy Schubert 	dns = evdns_base_new(data->base, 0);
1083*2b15cb3dSCy Schubert 	evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)dns_port);
1084*2b15cb3dSCy Schubert 	evdns_base_nameserver_ip_add(dns, buf);
1085*2b15cb3dSCy Schubert 
1086*2b15cb3dSCy Schubert 	/* Now, finally, at long last, launch the bufferevents.	 One should do
1087*2b15cb3dSCy Schubert 	 * a failing lookup IP, one should do a successful lookup by IP,
1088*2b15cb3dSCy Schubert 	 * and one should do a successful lookup by hostname. */
1089*2b15cb3dSCy Schubert 	be1 = bufferevent_socket_new(data->base, -1, BEV_OPT_CLOSE_ON_FREE);
1090*2b15cb3dSCy Schubert 	be2 = bufferevent_socket_new(data->base, -1, BEV_OPT_CLOSE_ON_FREE);
1091*2b15cb3dSCy Schubert 	be3 = bufferevent_socket_new(data->base, -1, BEV_OPT_CLOSE_ON_FREE);
1092*2b15cb3dSCy Schubert 	be4 = bufferevent_socket_new(data->base, -1, BEV_OPT_CLOSE_ON_FREE);
1093*2b15cb3dSCy Schubert 	be5 = bufferevent_socket_new(data->base, -1, BEV_OPT_CLOSE_ON_FREE);
1094*2b15cb3dSCy Schubert 
1095*2b15cb3dSCy Schubert 	bufferevent_setcb(be1, NULL, NULL, be_connect_hostname_event_cb,
1096*2b15cb3dSCy Schubert 	    &be1_outcome);
1097*2b15cb3dSCy Schubert 	bufferevent_setcb(be2, NULL, NULL, be_connect_hostname_event_cb,
1098*2b15cb3dSCy Schubert 	    &be2_outcome);
1099*2b15cb3dSCy Schubert 	bufferevent_setcb(be3, NULL, NULL, be_connect_hostname_event_cb,
1100*2b15cb3dSCy Schubert 	    &be3_outcome);
1101*2b15cb3dSCy Schubert 	bufferevent_setcb(be4, NULL, NULL, be_connect_hostname_event_cb,
1102*2b15cb3dSCy Schubert 	    &be4_outcome);
1103*2b15cb3dSCy Schubert 	bufferevent_setcb(be5, NULL, NULL, be_connect_hostname_event_cb,
1104*2b15cb3dSCy Schubert 	    &be5_outcome);
1105*2b15cb3dSCy Schubert 
1106*2b15cb3dSCy Schubert 	/* Launch an async resolve that will fail. */
1107*2b15cb3dSCy Schubert 	tt_assert(!bufferevent_socket_connect_hostname(be1, dns, AF_INET,
1108*2b15cb3dSCy Schubert 		"nosuchplace.example.com", listener_port));
1109*2b15cb3dSCy Schubert 	/* Connect to the IP without resolving. */
1110*2b15cb3dSCy Schubert 	tt_assert(!bufferevent_socket_connect_hostname(be2, dns, AF_INET,
1111*2b15cb3dSCy Schubert 		"127.0.0.1", listener_port));
1112*2b15cb3dSCy Schubert 	/* Launch an async resolve that will succeed. */
1113*2b15cb3dSCy Schubert 	tt_assert(!bufferevent_socket_connect_hostname(be3, dns, AF_INET,
1114*2b15cb3dSCy Schubert 		"nobodaddy.example.com", listener_port));
1115*2b15cb3dSCy Schubert 	/* Use the blocking resolver.  This one will fail if your resolver
1116*2b15cb3dSCy Schubert 	 * can't resolve localhost to 127.0.0.1 */
1117*2b15cb3dSCy Schubert 	tt_assert(!bufferevent_socket_connect_hostname(be4, NULL, AF_INET,
1118*2b15cb3dSCy Schubert 		"localhost", listener_port));
1119*2b15cb3dSCy Schubert 	/* Use the blocking resolver with a nonexistent hostname. */
1120*2b15cb3dSCy Schubert 	tt_assert(!bufferevent_socket_connect_hostname(be5, NULL, AF_INET,
1121*2b15cb3dSCy Schubert 		"nonesuch.nowhere.example.com", 80));
1122*2b15cb3dSCy Schubert 	{
1123*2b15cb3dSCy Schubert 		/* The blocking resolver will use the system nameserver, which
1124*2b15cb3dSCy Schubert 		 * might tell us anything.  (Yes, some twits even pretend that
1125*2b15cb3dSCy Schubert 		 * example.com is real.) Let's see what answer to expect. */
1126*2b15cb3dSCy Schubert 		struct evutil_addrinfo hints, *ai = NULL;
1127*2b15cb3dSCy Schubert 		memset(&hints, 0, sizeof(hints));
1128*2b15cb3dSCy Schubert 		hints.ai_family = AF_INET;
1129*2b15cb3dSCy Schubert 		hints.ai_socktype = SOCK_STREAM;
1130*2b15cb3dSCy Schubert 		hints.ai_protocol = IPPROTO_TCP;
1131*2b15cb3dSCy Schubert 		expect_err5 = evutil_getaddrinfo(
1132*2b15cb3dSCy Schubert 			"nonesuch.nowhere.example.com", "80", &hints, &ai);
1133*2b15cb3dSCy Schubert 	}
1134*2b15cb3dSCy Schubert 
1135*2b15cb3dSCy Schubert 	event_base_dispatch(data->base);
1136*2b15cb3dSCy Schubert 
1137*2b15cb3dSCy Schubert 	tt_int_op(be1_outcome.what, ==, BEV_EVENT_ERROR);
1138*2b15cb3dSCy Schubert 	tt_int_op(be1_outcome.dnserr, ==, EVUTIL_EAI_NONAME);
1139*2b15cb3dSCy Schubert 	tt_int_op(be2_outcome.what, ==, BEV_EVENT_CONNECTED);
1140*2b15cb3dSCy Schubert 	tt_int_op(be2_outcome.dnserr, ==, 0);
1141*2b15cb3dSCy Schubert 	tt_int_op(be3_outcome.what, ==, BEV_EVENT_CONNECTED);
1142*2b15cb3dSCy Schubert 	tt_int_op(be3_outcome.dnserr, ==, 0);
1143*2b15cb3dSCy Schubert 	tt_int_op(be4_outcome.what, ==, BEV_EVENT_CONNECTED);
1144*2b15cb3dSCy Schubert 	tt_int_op(be4_outcome.dnserr, ==, 0);
1145*2b15cb3dSCy Schubert 	if (expect_err5) {
1146*2b15cb3dSCy Schubert 		tt_int_op(be5_outcome.what, ==, BEV_EVENT_ERROR);
1147*2b15cb3dSCy Schubert 		tt_int_op(be5_outcome.dnserr, ==, expect_err5);
1148*2b15cb3dSCy Schubert 	}
1149*2b15cb3dSCy Schubert 
1150*2b15cb3dSCy Schubert 	tt_int_op(n_accept, ==, 3);
1151*2b15cb3dSCy Schubert 	tt_int_op(n_dns, ==, 2);
1152*2b15cb3dSCy Schubert 
1153*2b15cb3dSCy Schubert end:
1154*2b15cb3dSCy Schubert 	if (listener)
1155*2b15cb3dSCy Schubert 		evconnlistener_free(listener);
1156*2b15cb3dSCy Schubert 	if (port)
1157*2b15cb3dSCy Schubert 		evdns_close_server_port(port);
1158*2b15cb3dSCy Schubert 	if (dns)
1159*2b15cb3dSCy Schubert 		evdns_base_free(dns, 0);
1160*2b15cb3dSCy Schubert 	if (be1)
1161*2b15cb3dSCy Schubert 		bufferevent_free(be1);
1162*2b15cb3dSCy Schubert 	if (be2)
1163*2b15cb3dSCy Schubert 		bufferevent_free(be2);
1164*2b15cb3dSCy Schubert 	if (be3)
1165*2b15cb3dSCy Schubert 		bufferevent_free(be3);
1166*2b15cb3dSCy Schubert 	if (be4)
1167*2b15cb3dSCy Schubert 		bufferevent_free(be4);
1168*2b15cb3dSCy Schubert 	if (be5)
1169*2b15cb3dSCy Schubert 		bufferevent_free(be5);
1170*2b15cb3dSCy Schubert }
1171*2b15cb3dSCy Schubert 
1172*2b15cb3dSCy Schubert 
1173*2b15cb3dSCy Schubert struct gai_outcome {
1174*2b15cb3dSCy Schubert 	int err;
1175*2b15cb3dSCy Schubert 	struct evutil_addrinfo *ai;
1176*2b15cb3dSCy Schubert };
1177*2b15cb3dSCy Schubert 
1178*2b15cb3dSCy Schubert static int n_gai_results_pending = 0;
1179*2b15cb3dSCy Schubert static struct event_base *exit_base_on_no_pending_results = NULL;
1180*2b15cb3dSCy Schubert 
1181*2b15cb3dSCy Schubert static void
1182*2b15cb3dSCy Schubert gai_cb(int err, struct evutil_addrinfo *res, void *ptr)
1183*2b15cb3dSCy Schubert {
1184*2b15cb3dSCy Schubert 	struct gai_outcome *go = ptr;
1185*2b15cb3dSCy Schubert 	go->err = err;
1186*2b15cb3dSCy Schubert 	go->ai = res;
1187*2b15cb3dSCy Schubert 	if (--n_gai_results_pending <= 0 && exit_base_on_no_pending_results)
1188*2b15cb3dSCy Schubert 		event_base_loopexit(exit_base_on_no_pending_results, NULL);
1189*2b15cb3dSCy Schubert 	if (n_gai_results_pending < 900)
1190*2b15cb3dSCy Schubert 		TT_BLATHER(("Got an answer; expecting %d more.",
1191*2b15cb3dSCy Schubert 			n_gai_results_pending));
1192*2b15cb3dSCy Schubert }
1193*2b15cb3dSCy Schubert 
1194*2b15cb3dSCy Schubert static void
1195*2b15cb3dSCy Schubert cancel_gai_cb(evutil_socket_t fd, short what, void *ptr)
1196*2b15cb3dSCy Schubert {
1197*2b15cb3dSCy Schubert 	struct evdns_getaddrinfo_request *r = ptr;
1198*2b15cb3dSCy Schubert 	evdns_getaddrinfo_cancel(r);
1199*2b15cb3dSCy Schubert }
1200*2b15cb3dSCy Schubert 
1201*2b15cb3dSCy Schubert static void
1202*2b15cb3dSCy Schubert test_getaddrinfo_async(void *arg)
1203*2b15cb3dSCy Schubert {
1204*2b15cb3dSCy Schubert 	struct basic_test_data *data = arg;
1205*2b15cb3dSCy Schubert 	struct evutil_addrinfo hints, *a;
1206*2b15cb3dSCy Schubert 	struct gai_outcome local_outcome;
1207*2b15cb3dSCy Schubert 	struct gai_outcome a_out[12];
1208*2b15cb3dSCy Schubert 	int i;
1209*2b15cb3dSCy Schubert 	struct evdns_getaddrinfo_request *r;
1210*2b15cb3dSCy Schubert 	char buf[128];
1211*2b15cb3dSCy Schubert 	struct evdns_server_port *port = NULL;
1212*2b15cb3dSCy Schubert 	ev_uint16_t dns_port = 0;
1213*2b15cb3dSCy Schubert 	int n_dns_questions = 0;
1214*2b15cb3dSCy Schubert 	struct evdns_base *dns_base;
1215*2b15cb3dSCy Schubert 
1216*2b15cb3dSCy Schubert 	memset(a_out, 0, sizeof(a_out));
1217*2b15cb3dSCy Schubert 	memset(&local_outcome, 0, sizeof(local_outcome));
1218*2b15cb3dSCy Schubert 
1219*2b15cb3dSCy Schubert 	dns_base = evdns_base_new(data->base, 0);
1220*2b15cb3dSCy Schubert 	tt_assert(dns_base);
1221*2b15cb3dSCy Schubert 
1222*2b15cb3dSCy Schubert 	/* for localhost */
1223*2b15cb3dSCy Schubert 	evdns_base_load_hosts(dns_base, NULL);
1224*2b15cb3dSCy Schubert 
1225*2b15cb3dSCy Schubert 	tt_assert(! evdns_base_set_option(dns_base, "timeout", "0.3"));
1226*2b15cb3dSCy Schubert 	tt_assert(! evdns_base_set_option(dns_base, "getaddrinfo-allow-skew", "0.2"));
1227*2b15cb3dSCy Schubert 
1228*2b15cb3dSCy Schubert 	n_gai_results_pending = 10000; /* don't think about exiting yet. */
1229*2b15cb3dSCy Schubert 
1230*2b15cb3dSCy Schubert 	/* 1. Try some cases that will never hit the asynchronous resolver. */
1231*2b15cb3dSCy Schubert 	/* 1a. Simple case with a symbolic service name */
1232*2b15cb3dSCy Schubert 	memset(&hints, 0, sizeof(hints));
1233*2b15cb3dSCy Schubert 	hints.ai_family = PF_UNSPEC;
1234*2b15cb3dSCy Schubert 	hints.ai_socktype = SOCK_STREAM;
1235*2b15cb3dSCy Schubert 	memset(&local_outcome, 0, sizeof(local_outcome));
1236*2b15cb3dSCy Schubert 	r = evdns_getaddrinfo(dns_base, "1.2.3.4", "http",
1237*2b15cb3dSCy Schubert 	    &hints, gai_cb, &local_outcome);
1238*2b15cb3dSCy Schubert 	tt_assert(! r);
1239*2b15cb3dSCy Schubert 	if (!local_outcome.err) {
1240*2b15cb3dSCy Schubert 		tt_ptr_op(local_outcome.ai,!=,NULL);
1241*2b15cb3dSCy Schubert 		test_ai_eq(local_outcome.ai, "1.2.3.4:80", SOCK_STREAM, IPPROTO_TCP);
1242*2b15cb3dSCy Schubert 		evutil_freeaddrinfo(local_outcome.ai);
1243*2b15cb3dSCy Schubert 		local_outcome.ai = NULL;
1244*2b15cb3dSCy Schubert 	} else {
1245*2b15cb3dSCy Schubert 		TT_BLATHER(("Apparently we have no getservbyname."));
1246*2b15cb3dSCy Schubert 	}
1247*2b15cb3dSCy Schubert 
1248*2b15cb3dSCy Schubert 	/* 1b. EVUTIL_AI_NUMERICHOST is set */
1249*2b15cb3dSCy Schubert 	memset(&hints, 0, sizeof(hints));
1250*2b15cb3dSCy Schubert 	hints.ai_family = PF_UNSPEC;
1251*2b15cb3dSCy Schubert 	hints.ai_flags = EVUTIL_AI_NUMERICHOST;
1252*2b15cb3dSCy Schubert 	memset(&local_outcome, 0, sizeof(local_outcome));
1253*2b15cb3dSCy Schubert 	r = evdns_getaddrinfo(dns_base, "www.google.com", "80",
1254*2b15cb3dSCy Schubert 	    &hints, gai_cb, &local_outcome);
1255*2b15cb3dSCy Schubert 	tt_ptr_op(r,==,NULL);
1256*2b15cb3dSCy Schubert 	tt_int_op(local_outcome.err,==,EVUTIL_EAI_NONAME);
1257*2b15cb3dSCy Schubert 	tt_ptr_op(local_outcome.ai,==,NULL);
1258*2b15cb3dSCy Schubert 
1259*2b15cb3dSCy Schubert 	/* 1c. We give a numeric address (ipv6) */
1260*2b15cb3dSCy Schubert 	memset(&hints, 0, sizeof(hints));
1261*2b15cb3dSCy Schubert 	memset(&local_outcome, 0, sizeof(local_outcome));
1262*2b15cb3dSCy Schubert 	hints.ai_family = PF_UNSPEC;
1263*2b15cb3dSCy Schubert 	hints.ai_protocol = IPPROTO_TCP;
1264*2b15cb3dSCy Schubert 	r = evdns_getaddrinfo(dns_base, "f::f", "8008",
1265*2b15cb3dSCy Schubert 	    &hints, gai_cb, &local_outcome);
1266*2b15cb3dSCy Schubert 	tt_assert(!r);
1267*2b15cb3dSCy Schubert 	tt_int_op(local_outcome.err,==,0);
1268*2b15cb3dSCy Schubert 	tt_assert(local_outcome.ai);
1269*2b15cb3dSCy Schubert 	tt_ptr_op(local_outcome.ai->ai_next,==,NULL);
1270*2b15cb3dSCy Schubert 	test_ai_eq(local_outcome.ai, "[f::f]:8008", SOCK_STREAM, IPPROTO_TCP);
1271*2b15cb3dSCy Schubert 	evutil_freeaddrinfo(local_outcome.ai);
1272*2b15cb3dSCy Schubert 	local_outcome.ai = NULL;
1273*2b15cb3dSCy Schubert 
1274*2b15cb3dSCy Schubert 	/* 1d. We give a numeric address (ipv4) */
1275*2b15cb3dSCy Schubert 	memset(&hints, 0, sizeof(hints));
1276*2b15cb3dSCy Schubert 	memset(&local_outcome, 0, sizeof(local_outcome));
1277*2b15cb3dSCy Schubert 	hints.ai_family = PF_UNSPEC;
1278*2b15cb3dSCy Schubert 	r = evdns_getaddrinfo(dns_base, "5.6.7.8", NULL,
1279*2b15cb3dSCy Schubert 	    &hints, gai_cb, &local_outcome);
1280*2b15cb3dSCy Schubert 	tt_assert(!r);
1281*2b15cb3dSCy Schubert 	tt_int_op(local_outcome.err,==,0);
1282*2b15cb3dSCy Schubert 	tt_assert(local_outcome.ai);
1283*2b15cb3dSCy Schubert 	a = ai_find_by_protocol(local_outcome.ai, IPPROTO_TCP);
1284*2b15cb3dSCy Schubert 	tt_assert(a);
1285*2b15cb3dSCy Schubert 	test_ai_eq(a, "5.6.7.8", SOCK_STREAM, IPPROTO_TCP);
1286*2b15cb3dSCy Schubert 	a = ai_find_by_protocol(local_outcome.ai, IPPROTO_UDP);
1287*2b15cb3dSCy Schubert 	tt_assert(a);
1288*2b15cb3dSCy Schubert 	test_ai_eq(a, "5.6.7.8", SOCK_DGRAM, IPPROTO_UDP);
1289*2b15cb3dSCy Schubert 	evutil_freeaddrinfo(local_outcome.ai);
1290*2b15cb3dSCy Schubert 	local_outcome.ai = NULL;
1291*2b15cb3dSCy Schubert 
1292*2b15cb3dSCy Schubert 	/* 1e. nodename is NULL (bind) */
1293*2b15cb3dSCy Schubert 	memset(&hints, 0, sizeof(hints));
1294*2b15cb3dSCy Schubert 	memset(&local_outcome, 0, sizeof(local_outcome));
1295*2b15cb3dSCy Schubert 	hints.ai_family = PF_UNSPEC;
1296*2b15cb3dSCy Schubert 	hints.ai_socktype = SOCK_DGRAM;
1297*2b15cb3dSCy Schubert 	hints.ai_flags = EVUTIL_AI_PASSIVE;
1298*2b15cb3dSCy Schubert 	r = evdns_getaddrinfo(dns_base, NULL, "9090",
1299*2b15cb3dSCy Schubert 	    &hints, gai_cb, &local_outcome);
1300*2b15cb3dSCy Schubert 	tt_assert(!r);
1301*2b15cb3dSCy Schubert 	tt_int_op(local_outcome.err,==,0);
1302*2b15cb3dSCy Schubert 	tt_assert(local_outcome.ai);
1303*2b15cb3dSCy Schubert 	/* we should get a v4 address of 0.0.0.0... */
1304*2b15cb3dSCy Schubert 	a = ai_find_by_family(local_outcome.ai, PF_INET);
1305*2b15cb3dSCy Schubert 	tt_assert(a);
1306*2b15cb3dSCy Schubert 	test_ai_eq(a, "0.0.0.0:9090", SOCK_DGRAM, IPPROTO_UDP);
1307*2b15cb3dSCy Schubert 	/* ... and a v6 address of ::0 */
1308*2b15cb3dSCy Schubert 	a = ai_find_by_family(local_outcome.ai, PF_INET6);
1309*2b15cb3dSCy Schubert 	tt_assert(a);
1310*2b15cb3dSCy Schubert 	test_ai_eq(a, "[::]:9090", SOCK_DGRAM, IPPROTO_UDP);
1311*2b15cb3dSCy Schubert 	evutil_freeaddrinfo(local_outcome.ai);
1312*2b15cb3dSCy Schubert 	local_outcome.ai = NULL;
1313*2b15cb3dSCy Schubert 
1314*2b15cb3dSCy Schubert 	/* 1f. nodename is NULL (connect) */
1315*2b15cb3dSCy Schubert 	memset(&hints, 0, sizeof(hints));
1316*2b15cb3dSCy Schubert 	memset(&local_outcome, 0, sizeof(local_outcome));
1317*2b15cb3dSCy Schubert 	hints.ai_family = PF_UNSPEC;
1318*2b15cb3dSCy Schubert 	hints.ai_socktype = SOCK_STREAM;
1319*2b15cb3dSCy Schubert 	r = evdns_getaddrinfo(dns_base, NULL, "2",
1320*2b15cb3dSCy Schubert 	    &hints, gai_cb, &local_outcome);
1321*2b15cb3dSCy Schubert 	tt_assert(!r);
1322*2b15cb3dSCy Schubert 	tt_int_op(local_outcome.err,==,0);
1323*2b15cb3dSCy Schubert 	tt_assert(local_outcome.ai);
1324*2b15cb3dSCy Schubert 	/* we should get a v4 address of 127.0.0.1 .... */
1325*2b15cb3dSCy Schubert 	a = ai_find_by_family(local_outcome.ai, PF_INET);
1326*2b15cb3dSCy Schubert 	tt_assert(a);
1327*2b15cb3dSCy Schubert 	test_ai_eq(a, "127.0.0.1:2", SOCK_STREAM, IPPROTO_TCP);
1328*2b15cb3dSCy Schubert 	/* ... and a v6 address of ::1 */
1329*2b15cb3dSCy Schubert 	a = ai_find_by_family(local_outcome.ai, PF_INET6);
1330*2b15cb3dSCy Schubert 	tt_assert(a);
1331*2b15cb3dSCy Schubert 	test_ai_eq(a, "[::1]:2", SOCK_STREAM, IPPROTO_TCP);
1332*2b15cb3dSCy Schubert 	evutil_freeaddrinfo(local_outcome.ai);
1333*2b15cb3dSCy Schubert 	local_outcome.ai = NULL;
1334*2b15cb3dSCy Schubert 
1335*2b15cb3dSCy Schubert 	/* 1g. We find localhost immediately. (pf_unspec) */
1336*2b15cb3dSCy Schubert 	memset(&hints, 0, sizeof(hints));
1337*2b15cb3dSCy Schubert 	memset(&local_outcome, 0, sizeof(local_outcome));
1338*2b15cb3dSCy Schubert 	hints.ai_family = PF_UNSPEC;
1339*2b15cb3dSCy Schubert 	hints.ai_socktype = SOCK_STREAM;
1340*2b15cb3dSCy Schubert 	r = evdns_getaddrinfo(dns_base, "LOCALHOST", "80",
1341*2b15cb3dSCy Schubert 	    &hints, gai_cb, &local_outcome);
1342*2b15cb3dSCy Schubert 	tt_assert(!r);
1343*2b15cb3dSCy Schubert 	tt_int_op(local_outcome.err,==,0);
1344*2b15cb3dSCy Schubert 	tt_assert(local_outcome.ai);
1345*2b15cb3dSCy Schubert 	/* we should get a v4 address of 127.0.0.1 .... */
1346*2b15cb3dSCy Schubert 	a = ai_find_by_family(local_outcome.ai, PF_INET);
1347*2b15cb3dSCy Schubert 	tt_assert(a);
1348*2b15cb3dSCy Schubert 	test_ai_eq(a, "127.0.0.1:80", SOCK_STREAM, IPPROTO_TCP);
1349*2b15cb3dSCy Schubert 	/* ... and a v6 address of ::1 */
1350*2b15cb3dSCy Schubert 	a = ai_find_by_family(local_outcome.ai, PF_INET6);
1351*2b15cb3dSCy Schubert 	tt_assert(a);
1352*2b15cb3dSCy Schubert 	test_ai_eq(a, "[::1]:80", SOCK_STREAM, IPPROTO_TCP);
1353*2b15cb3dSCy Schubert 	evutil_freeaddrinfo(local_outcome.ai);
1354*2b15cb3dSCy Schubert 	local_outcome.ai = NULL;
1355*2b15cb3dSCy Schubert 
1356*2b15cb3dSCy Schubert 	/* 1g. We find localhost immediately. (pf_inet6) */
1357*2b15cb3dSCy Schubert 	memset(&hints, 0, sizeof(hints));
1358*2b15cb3dSCy Schubert 	memset(&local_outcome, 0, sizeof(local_outcome));
1359*2b15cb3dSCy Schubert 	hints.ai_family = PF_INET6;
1360*2b15cb3dSCy Schubert 	hints.ai_socktype = SOCK_STREAM;
1361*2b15cb3dSCy Schubert 	r = evdns_getaddrinfo(dns_base, "LOCALHOST", "9999",
1362*2b15cb3dSCy Schubert 	    &hints, gai_cb, &local_outcome);
1363*2b15cb3dSCy Schubert 	tt_assert(! r);
1364*2b15cb3dSCy Schubert 	tt_int_op(local_outcome.err,==,0);
1365*2b15cb3dSCy Schubert 	tt_assert(local_outcome.ai);
1366*2b15cb3dSCy Schubert 	a = local_outcome.ai;
1367*2b15cb3dSCy Schubert 	test_ai_eq(a, "[::1]:9999", SOCK_STREAM, IPPROTO_TCP);
1368*2b15cb3dSCy Schubert 	tt_ptr_op(a->ai_next, ==, NULL);
1369*2b15cb3dSCy Schubert 	evutil_freeaddrinfo(local_outcome.ai);
1370*2b15cb3dSCy Schubert 	local_outcome.ai = NULL;
1371*2b15cb3dSCy Schubert 
1372*2b15cb3dSCy Schubert 	/* 2. Okay, now we can actually test the asynchronous resolver. */
1373*2b15cb3dSCy Schubert 	/* Start a dummy local dns server... */
1374*2b15cb3dSCy Schubert 	port = regress_get_dnsserver(data->base, &dns_port, NULL,
1375*2b15cb3dSCy Schubert 	    be_getaddrinfo_server_cb, &n_dns_questions);
1376*2b15cb3dSCy Schubert 	tt_assert(port);
1377*2b15cb3dSCy Schubert 	tt_int_op(dns_port, >=, 0);
1378*2b15cb3dSCy Schubert 	/* ... and tell the evdns_base about it. */
1379*2b15cb3dSCy Schubert 	evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", dns_port);
1380*2b15cb3dSCy Schubert 	evdns_base_nameserver_ip_add(dns_base, buf);
1381*2b15cb3dSCy Schubert 
1382*2b15cb3dSCy Schubert 	memset(&hints, 0, sizeof(hints));
1383*2b15cb3dSCy Schubert 	hints.ai_family = PF_UNSPEC;
1384*2b15cb3dSCy Schubert 	hints.ai_socktype = SOCK_STREAM;
1385*2b15cb3dSCy Schubert 	hints.ai_flags = EVUTIL_AI_CANONNAME;
1386*2b15cb3dSCy Schubert 	/* 0: Request for both.example.com should return both addresses. */
1387*2b15cb3dSCy Schubert 	r = evdns_getaddrinfo(dns_base, "both.example.com", "8000",
1388*2b15cb3dSCy Schubert 	    &hints, gai_cb, &a_out[0]);
1389*2b15cb3dSCy Schubert 	tt_assert(r);
1390*2b15cb3dSCy Schubert 
1391*2b15cb3dSCy Schubert 	/* 1: Request for v4only.example.com should return one address. */
1392*2b15cb3dSCy Schubert 	r = evdns_getaddrinfo(dns_base, "v4only.example.com", "8001",
1393*2b15cb3dSCy Schubert 	    &hints, gai_cb, &a_out[1]);
1394*2b15cb3dSCy Schubert 	tt_assert(r);
1395*2b15cb3dSCy Schubert 
1396*2b15cb3dSCy Schubert 	/* 2: Request for v6only.example.com should return one address. */
1397*2b15cb3dSCy Schubert 	hints.ai_flags = 0;
1398*2b15cb3dSCy Schubert 	r = evdns_getaddrinfo(dns_base, "v6only.example.com", "8002",
1399*2b15cb3dSCy Schubert 	    &hints, gai_cb, &a_out[2]);
1400*2b15cb3dSCy Schubert 	tt_assert(r);
1401*2b15cb3dSCy Schubert 
1402*2b15cb3dSCy Schubert 	/* 3: PF_INET request for v4assert.example.com should not generate a
1403*2b15cb3dSCy Schubert 	 * v6 request.	The server will fail the test if it does. */
1404*2b15cb3dSCy Schubert 	hints.ai_family = PF_INET;
1405*2b15cb3dSCy Schubert 	r = evdns_getaddrinfo(dns_base, "v4assert.example.com", "8003",
1406*2b15cb3dSCy Schubert 	    &hints, gai_cb, &a_out[3]);
1407*2b15cb3dSCy Schubert 	tt_assert(r);
1408*2b15cb3dSCy Schubert 
1409*2b15cb3dSCy Schubert 	/* 4: PF_INET6 request for v6assert.example.com should not generate a
1410*2b15cb3dSCy Schubert 	 * v4 request.	The server will fail the test if it does. */
1411*2b15cb3dSCy Schubert 	hints.ai_family = PF_INET6;
1412*2b15cb3dSCy Schubert 	r = evdns_getaddrinfo(dns_base, "v6assert.example.com", "8004",
1413*2b15cb3dSCy Schubert 	    &hints, gai_cb, &a_out[4]);
1414*2b15cb3dSCy Schubert 	tt_assert(r);
1415*2b15cb3dSCy Schubert 
1416*2b15cb3dSCy Schubert 	/* 5: PF_INET request for nosuchplace.example.com should give NEXIST. */
1417*2b15cb3dSCy Schubert 	hints.ai_family = PF_INET;
1418*2b15cb3dSCy Schubert 	r = evdns_getaddrinfo(dns_base, "nosuchplace.example.com", "8005",
1419*2b15cb3dSCy Schubert 	    &hints, gai_cb, &a_out[5]);
1420*2b15cb3dSCy Schubert 	tt_assert(r);
1421*2b15cb3dSCy Schubert 
1422*2b15cb3dSCy Schubert 	/* 6: PF_UNSPEC request for nosuchplace.example.com should give NEXIST.
1423*2b15cb3dSCy Schubert 	 */
1424*2b15cb3dSCy Schubert 	hints.ai_family = PF_UNSPEC;
1425*2b15cb3dSCy Schubert 	r = evdns_getaddrinfo(dns_base, "nosuchplace.example.com", "8006",
1426*2b15cb3dSCy Schubert 	    &hints, gai_cb, &a_out[6]);
1427*2b15cb3dSCy Schubert 	tt_assert(r);
1428*2b15cb3dSCy Schubert 
1429*2b15cb3dSCy Schubert 	/* 7: PF_UNSPEC request for v6timeout.example.com should give an ipv4
1430*2b15cb3dSCy Schubert 	 * address only. */
1431*2b15cb3dSCy Schubert 	hints.ai_family = PF_UNSPEC;
1432*2b15cb3dSCy Schubert 	r = evdns_getaddrinfo(dns_base, "v6timeout.example.com", "8007",
1433*2b15cb3dSCy Schubert 	    &hints, gai_cb, &a_out[7]);
1434*2b15cb3dSCy Schubert 	tt_assert(r);
1435*2b15cb3dSCy Schubert 
1436*2b15cb3dSCy Schubert 	/* 8: PF_UNSPEC request for v6timeout-nonexist.example.com should give
1437*2b15cb3dSCy Schubert 	 * a NEXIST */
1438*2b15cb3dSCy Schubert 	hints.ai_family = PF_UNSPEC;
1439*2b15cb3dSCy Schubert 	r = evdns_getaddrinfo(dns_base, "v6timeout-nonexist.example.com",
1440*2b15cb3dSCy Schubert 	    "8008", &hints, gai_cb, &a_out[8]);
1441*2b15cb3dSCy Schubert 	tt_assert(r);
1442*2b15cb3dSCy Schubert 
1443*2b15cb3dSCy Schubert 	/* 9: AI_ADDRCONFIG should at least not crash.	Can't test it more
1444*2b15cb3dSCy Schubert 	 * without knowing what kind of internet we have. */
1445*2b15cb3dSCy Schubert 	hints.ai_flags |= EVUTIL_AI_ADDRCONFIG;
1446*2b15cb3dSCy Schubert 	r = evdns_getaddrinfo(dns_base, "both.example.com",
1447*2b15cb3dSCy Schubert 	    "8009", &hints, gai_cb, &a_out[9]);
1448*2b15cb3dSCy Schubert 	tt_assert(r);
1449*2b15cb3dSCy Schubert 
1450*2b15cb3dSCy Schubert 	/* 10: PF_UNSPEC for v4timeout.example.com should give an ipv6 address
1451*2b15cb3dSCy Schubert 	 * only. */
1452*2b15cb3dSCy Schubert 	hints.ai_family = PF_UNSPEC;
1453*2b15cb3dSCy Schubert 	hints.ai_flags = 0;
1454*2b15cb3dSCy Schubert 	r = evdns_getaddrinfo(dns_base, "v4timeout.example.com", "8010",
1455*2b15cb3dSCy Schubert 	    &hints, gai_cb, &a_out[10]);
1456*2b15cb3dSCy Schubert 	tt_assert(r);
1457*2b15cb3dSCy Schubert 
1458*2b15cb3dSCy Schubert 	/* 11: timeout.example.com: cancel it after 100 msec. */
1459*2b15cb3dSCy Schubert 	r = evdns_getaddrinfo(dns_base, "all-timeout.example.com", "8011",
1460*2b15cb3dSCy Schubert 	    &hints, gai_cb, &a_out[11]);
1461*2b15cb3dSCy Schubert 	tt_assert(r);
1462*2b15cb3dSCy Schubert 	{
1463*2b15cb3dSCy Schubert 		struct timeval tv;
1464*2b15cb3dSCy Schubert 		tv.tv_sec = 0;
1465*2b15cb3dSCy Schubert 		tv.tv_usec = 100*1000; /* 100 msec */
1466*2b15cb3dSCy Schubert 		event_base_once(data->base, -1, EV_TIMEOUT, cancel_gai_cb,
1467*2b15cb3dSCy Schubert 		    r, &tv);
1468*2b15cb3dSCy Schubert 	}
1469*2b15cb3dSCy Schubert 
1470*2b15cb3dSCy Schubert 	/* XXXXX There are more tests we could do, including:
1471*2b15cb3dSCy Schubert 
1472*2b15cb3dSCy Schubert 	   - A test to elicit NODATA.
1473*2b15cb3dSCy Schubert 
1474*2b15cb3dSCy Schubert 	 */
1475*2b15cb3dSCy Schubert 
1476*2b15cb3dSCy Schubert 	n_gai_results_pending = 12;
1477*2b15cb3dSCy Schubert 	exit_base_on_no_pending_results = data->base;
1478*2b15cb3dSCy Schubert 
1479*2b15cb3dSCy Schubert 	event_base_dispatch(data->base);
1480*2b15cb3dSCy Schubert 
1481*2b15cb3dSCy Schubert 	/* 0: both.example.com */
1482*2b15cb3dSCy Schubert 	tt_int_op(a_out[0].err, ==, 0);
1483*2b15cb3dSCy Schubert 	tt_assert(a_out[0].ai);
1484*2b15cb3dSCy Schubert 	tt_assert(a_out[0].ai->ai_next);
1485*2b15cb3dSCy Schubert 	tt_assert(!a_out[0].ai->ai_next->ai_next);
1486*2b15cb3dSCy Schubert 	a = ai_find_by_family(a_out[0].ai, PF_INET);
1487*2b15cb3dSCy Schubert 	tt_assert(a);
1488*2b15cb3dSCy Schubert 	test_ai_eq(a, "80.80.32.32:8000", SOCK_STREAM, IPPROTO_TCP);
1489*2b15cb3dSCy Schubert 	a = ai_find_by_family(a_out[0].ai, PF_INET6);
1490*2b15cb3dSCy Schubert 	tt_assert(a);
1491*2b15cb3dSCy Schubert 	test_ai_eq(a, "[80ff::bbbb]:8000", SOCK_STREAM, IPPROTO_TCP);
1492*2b15cb3dSCy Schubert 	tt_assert(a_out[0].ai->ai_canonname);
1493*2b15cb3dSCy Schubert 	tt_str_op(a_out[0].ai->ai_canonname, ==, "both-canonical.example.com");
1494*2b15cb3dSCy Schubert 
1495*2b15cb3dSCy Schubert 	/* 1: v4only.example.com */
1496*2b15cb3dSCy Schubert 	tt_int_op(a_out[1].err, ==, 0);
1497*2b15cb3dSCy Schubert 	tt_assert(a_out[1].ai);
1498*2b15cb3dSCy Schubert 	tt_assert(! a_out[1].ai->ai_next);
1499*2b15cb3dSCy Schubert 	test_ai_eq(a_out[1].ai, "18.52.86.120:8001", SOCK_STREAM, IPPROTO_TCP);
1500*2b15cb3dSCy Schubert 	tt_assert(a_out[1].ai->ai_canonname == NULL);
1501*2b15cb3dSCy Schubert 
1502*2b15cb3dSCy Schubert 
1503*2b15cb3dSCy Schubert 	/* 2: v6only.example.com */
1504*2b15cb3dSCy Schubert 	tt_int_op(a_out[2].err, ==, 0);
1505*2b15cb3dSCy Schubert 	tt_assert(a_out[2].ai);
1506*2b15cb3dSCy Schubert 	tt_assert(! a_out[2].ai->ai_next);
1507*2b15cb3dSCy Schubert 	test_ai_eq(a_out[2].ai, "[b0b::f00d]:8002", SOCK_STREAM, IPPROTO_TCP);
1508*2b15cb3dSCy Schubert 
1509*2b15cb3dSCy Schubert 	/* 3: v4assert.example.com */
1510*2b15cb3dSCy Schubert 	tt_int_op(a_out[3].err, ==, 0);
1511*2b15cb3dSCy Schubert 	tt_assert(a_out[3].ai);
1512*2b15cb3dSCy Schubert 	tt_assert(! a_out[3].ai->ai_next);
1513*2b15cb3dSCy Schubert 	test_ai_eq(a_out[3].ai, "18.52.86.120:8003", SOCK_STREAM, IPPROTO_TCP);
1514*2b15cb3dSCy Schubert 
1515*2b15cb3dSCy Schubert 	/* 4: v6assert.example.com */
1516*2b15cb3dSCy Schubert 	tt_int_op(a_out[4].err, ==, 0);
1517*2b15cb3dSCy Schubert 	tt_assert(a_out[4].ai);
1518*2b15cb3dSCy Schubert 	tt_assert(! a_out[4].ai->ai_next);
1519*2b15cb3dSCy Schubert 	test_ai_eq(a_out[4].ai, "[b0b::f00d]:8004", SOCK_STREAM, IPPROTO_TCP);
1520*2b15cb3dSCy Schubert 
1521*2b15cb3dSCy Schubert 	/* 5: nosuchplace.example.com (inet) */
1522*2b15cb3dSCy Schubert 	tt_int_op(a_out[5].err, ==, EVUTIL_EAI_NONAME);
1523*2b15cb3dSCy Schubert 	tt_assert(! a_out[5].ai);
1524*2b15cb3dSCy Schubert 
1525*2b15cb3dSCy Schubert 	/* 6: nosuchplace.example.com (unspec) */
1526*2b15cb3dSCy Schubert 	tt_int_op(a_out[6].err, ==, EVUTIL_EAI_NONAME);
1527*2b15cb3dSCy Schubert 	tt_assert(! a_out[6].ai);
1528*2b15cb3dSCy Schubert 
1529*2b15cb3dSCy Schubert 	/* 7: v6timeout.example.com */
1530*2b15cb3dSCy Schubert 	tt_int_op(a_out[7].err, ==, 0);
1531*2b15cb3dSCy Schubert 	tt_assert(a_out[7].ai);
1532*2b15cb3dSCy Schubert 	tt_assert(! a_out[7].ai->ai_next);
1533*2b15cb3dSCy Schubert 	test_ai_eq(a_out[7].ai, "171.205.239.1:8007", SOCK_STREAM, IPPROTO_TCP);
1534*2b15cb3dSCy Schubert 
1535*2b15cb3dSCy Schubert 	/* 8: v6timeout-nonexist.example.com */
1536*2b15cb3dSCy Schubert 	tt_int_op(a_out[8].err, ==, EVUTIL_EAI_NONAME);
1537*2b15cb3dSCy Schubert 	tt_assert(! a_out[8].ai);
1538*2b15cb3dSCy Schubert 
1539*2b15cb3dSCy Schubert 	/* 9: both (ADDRCONFIG) */
1540*2b15cb3dSCy Schubert 	tt_int_op(a_out[9].err, ==, 0);
1541*2b15cb3dSCy Schubert 	tt_assert(a_out[9].ai);
1542*2b15cb3dSCy Schubert 	a = ai_find_by_family(a_out[9].ai, PF_INET);
1543*2b15cb3dSCy Schubert 	if (a)
1544*2b15cb3dSCy Schubert 		test_ai_eq(a, "80.80.32.32:8009", SOCK_STREAM, IPPROTO_TCP);
1545*2b15cb3dSCy Schubert 	else
1546*2b15cb3dSCy Schubert 		tt_assert(ai_find_by_family(a_out[9].ai, PF_INET6));
1547*2b15cb3dSCy Schubert 	a = ai_find_by_family(a_out[9].ai, PF_INET6);
1548*2b15cb3dSCy Schubert 	if (a)
1549*2b15cb3dSCy Schubert 		test_ai_eq(a, "[80ff::bbbb]:8009", SOCK_STREAM, IPPROTO_TCP);
1550*2b15cb3dSCy Schubert 	else
1551*2b15cb3dSCy Schubert 		tt_assert(ai_find_by_family(a_out[9].ai, PF_INET));
1552*2b15cb3dSCy Schubert 
1553*2b15cb3dSCy Schubert 	/* 10: v4timeout.example.com */
1554*2b15cb3dSCy Schubert 	tt_int_op(a_out[10].err, ==, 0);
1555*2b15cb3dSCy Schubert 	tt_assert(a_out[10].ai);
1556*2b15cb3dSCy Schubert 	tt_assert(! a_out[10].ai->ai_next);
1557*2b15cb3dSCy Schubert 	test_ai_eq(a_out[10].ai, "[a0a::ff01]:8010", SOCK_STREAM, IPPROTO_TCP);
1558*2b15cb3dSCy Schubert 
1559*2b15cb3dSCy Schubert 	/* 11: cancelled request. */
1560*2b15cb3dSCy Schubert 	tt_int_op(a_out[11].err, ==, EVUTIL_EAI_CANCEL);
1561*2b15cb3dSCy Schubert 	tt_assert(a_out[11].ai == NULL);
1562*2b15cb3dSCy Schubert 
1563*2b15cb3dSCy Schubert end:
1564*2b15cb3dSCy Schubert 	if (local_outcome.ai)
1565*2b15cb3dSCy Schubert 		evutil_freeaddrinfo(local_outcome.ai);
1566*2b15cb3dSCy Schubert 	for (i=0;i<10;++i) {
1567*2b15cb3dSCy Schubert 		if (a_out[i].ai)
1568*2b15cb3dSCy Schubert 			evutil_freeaddrinfo(a_out[i].ai);
1569*2b15cb3dSCy Schubert 	}
1570*2b15cb3dSCy Schubert 	if (port)
1571*2b15cb3dSCy Schubert 		evdns_close_server_port(port);
1572*2b15cb3dSCy Schubert 	if (dns_base)
1573*2b15cb3dSCy Schubert 		evdns_base_free(dns_base, 0);
1574*2b15cb3dSCy Schubert }
1575*2b15cb3dSCy Schubert 
1576*2b15cb3dSCy Schubert struct gaic_request_status {
1577*2b15cb3dSCy Schubert 	int magic;
1578*2b15cb3dSCy Schubert 	struct event_base *base;
1579*2b15cb3dSCy Schubert 	struct evdns_base *dns_base;
1580*2b15cb3dSCy Schubert 	struct evdns_getaddrinfo_request *request;
1581*2b15cb3dSCy Schubert 	struct event cancel_event;
1582*2b15cb3dSCy Schubert 	int canceled;
1583*2b15cb3dSCy Schubert };
1584*2b15cb3dSCy Schubert 
1585*2b15cb3dSCy Schubert #define GAIC_MAGIC 0x1234abcd
1586*2b15cb3dSCy Schubert 
1587*2b15cb3dSCy Schubert static int pending = 0;
1588*2b15cb3dSCy Schubert 
1589*2b15cb3dSCy Schubert static void
1590*2b15cb3dSCy Schubert gaic_cancel_request_cb(evutil_socket_t fd, short what, void *arg)
1591*2b15cb3dSCy Schubert {
1592*2b15cb3dSCy Schubert 	struct gaic_request_status *status = arg;
1593*2b15cb3dSCy Schubert 
1594*2b15cb3dSCy Schubert 	tt_assert(status->magic == GAIC_MAGIC);
1595*2b15cb3dSCy Schubert 	status->canceled = 1;
1596*2b15cb3dSCy Schubert 	evdns_getaddrinfo_cancel(status->request);
1597*2b15cb3dSCy Schubert 	return;
1598*2b15cb3dSCy Schubert end:
1599*2b15cb3dSCy Schubert 	event_base_loopexit(status->base, NULL);
1600*2b15cb3dSCy Schubert }
1601*2b15cb3dSCy Schubert 
1602*2b15cb3dSCy Schubert static void
1603*2b15cb3dSCy Schubert gaic_server_cb(struct evdns_server_request *req, void *arg)
1604*2b15cb3dSCy Schubert {
1605*2b15cb3dSCy Schubert 	ev_uint32_t answer = 0x7f000001;
1606*2b15cb3dSCy Schubert 	tt_assert(req->nquestions);
1607*2b15cb3dSCy Schubert 	evdns_server_request_add_a_reply(req, req->questions[0]->name, 1,
1608*2b15cb3dSCy Schubert 	    &answer, 100);
1609*2b15cb3dSCy Schubert 	evdns_server_request_respond(req, 0);
1610*2b15cb3dSCy Schubert 	return;
1611*2b15cb3dSCy Schubert end:
1612*2b15cb3dSCy Schubert 	evdns_server_request_respond(req, DNS_ERR_REFUSED);
1613*2b15cb3dSCy Schubert }
1614*2b15cb3dSCy Schubert 
1615*2b15cb3dSCy Schubert 
1616*2b15cb3dSCy Schubert static void
1617*2b15cb3dSCy Schubert gaic_getaddrinfo_cb(int result, struct evutil_addrinfo *res, void *arg)
1618*2b15cb3dSCy Schubert {
1619*2b15cb3dSCy Schubert 	struct gaic_request_status *status = arg;
1620*2b15cb3dSCy Schubert 	struct event_base *base = status->base;
1621*2b15cb3dSCy Schubert 	tt_assert(status->magic == GAIC_MAGIC);
1622*2b15cb3dSCy Schubert 
1623*2b15cb3dSCy Schubert 	if (result == EVUTIL_EAI_CANCEL) {
1624*2b15cb3dSCy Schubert 		tt_assert(status->canceled);
1625*2b15cb3dSCy Schubert 	}
1626*2b15cb3dSCy Schubert 	event_del(&status->cancel_event);
1627*2b15cb3dSCy Schubert 
1628*2b15cb3dSCy Schubert 	memset(status, 0xf0, sizeof(*status));
1629*2b15cb3dSCy Schubert 	free(status);
1630*2b15cb3dSCy Schubert 
1631*2b15cb3dSCy Schubert end:
1632*2b15cb3dSCy Schubert 	if (--pending <= 0)
1633*2b15cb3dSCy Schubert 		event_base_loopexit(base, NULL);
1634*2b15cb3dSCy Schubert }
1635*2b15cb3dSCy Schubert 
1636*2b15cb3dSCy Schubert static void
1637*2b15cb3dSCy Schubert gaic_launch(struct event_base *base, struct evdns_base *dns_base)
1638*2b15cb3dSCy Schubert {
1639*2b15cb3dSCy Schubert 	struct gaic_request_status *status = calloc(1,sizeof(*status));
1640*2b15cb3dSCy Schubert 	struct timeval tv = { 0, 10000 };
1641*2b15cb3dSCy Schubert 	status->magic = GAIC_MAGIC;
1642*2b15cb3dSCy Schubert 	status->base = base;
1643*2b15cb3dSCy Schubert 	status->dns_base = dns_base;
1644*2b15cb3dSCy Schubert 	event_assign(&status->cancel_event, base, -1, 0, gaic_cancel_request_cb,
1645*2b15cb3dSCy Schubert 	    status);
1646*2b15cb3dSCy Schubert 	status->request = evdns_getaddrinfo(dns_base,
1647*2b15cb3dSCy Schubert 	    "foobar.bazquux.example.com", "80", NULL, gaic_getaddrinfo_cb,
1648*2b15cb3dSCy Schubert 	    status);
1649*2b15cb3dSCy Schubert 	event_add(&status->cancel_event, &tv);
1650*2b15cb3dSCy Schubert 	++pending;
1651*2b15cb3dSCy Schubert }
1652*2b15cb3dSCy Schubert 
1653*2b15cb3dSCy Schubert #ifdef EVENT_SET_MEM_FUNCTIONS_IMPLEMENTED
1654*2b15cb3dSCy Schubert /* FIXME: We should move this to regress_main.c if anything else needs it.*/
1655*2b15cb3dSCy Schubert 
1656*2b15cb3dSCy Schubert /* Trivial replacements for malloc/free/realloc to check for memory leaks.
1657*2b15cb3dSCy Schubert  * Not threadsafe. */
1658*2b15cb3dSCy Schubert static int allocated_chunks = 0;
1659*2b15cb3dSCy Schubert 
1660*2b15cb3dSCy Schubert static void *
1661*2b15cb3dSCy Schubert cnt_malloc(size_t sz)
1662*2b15cb3dSCy Schubert {
1663*2b15cb3dSCy Schubert 	allocated_chunks += 1;
1664*2b15cb3dSCy Schubert 	return malloc(sz);
1665*2b15cb3dSCy Schubert }
1666*2b15cb3dSCy Schubert 
1667*2b15cb3dSCy Schubert static void *
1668*2b15cb3dSCy Schubert cnt_realloc(void *old, size_t sz)
1669*2b15cb3dSCy Schubert {
1670*2b15cb3dSCy Schubert 	if (!old)
1671*2b15cb3dSCy Schubert 		allocated_chunks += 1;
1672*2b15cb3dSCy Schubert 	if (!sz)
1673*2b15cb3dSCy Schubert 		allocated_chunks -= 1;
1674*2b15cb3dSCy Schubert 	return realloc(old, sz);
1675*2b15cb3dSCy Schubert }
1676*2b15cb3dSCy Schubert 
1677*2b15cb3dSCy Schubert static void
1678*2b15cb3dSCy Schubert cnt_free(void *ptr)
1679*2b15cb3dSCy Schubert {
1680*2b15cb3dSCy Schubert 	allocated_chunks -= 1;
1681*2b15cb3dSCy Schubert 	free(ptr);
1682*2b15cb3dSCy Schubert }
1683*2b15cb3dSCy Schubert 
1684*2b15cb3dSCy Schubert struct testleak_env_t {
1685*2b15cb3dSCy Schubert 	struct event_base *base;
1686*2b15cb3dSCy Schubert 	struct evdns_base *dns_base;
1687*2b15cb3dSCy Schubert 	struct evdns_request *req;
1688*2b15cb3dSCy Schubert 	struct generic_dns_callback_result r;
1689*2b15cb3dSCy Schubert };
1690*2b15cb3dSCy Schubert 
1691*2b15cb3dSCy Schubert static void *
1692*2b15cb3dSCy Schubert testleak_setup(const struct testcase_t *testcase)
1693*2b15cb3dSCy Schubert {
1694*2b15cb3dSCy Schubert 	struct testleak_env_t *env;
1695*2b15cb3dSCy Schubert 
1696*2b15cb3dSCy Schubert 	allocated_chunks = 0;
1697*2b15cb3dSCy Schubert 	event_set_mem_functions(cnt_malloc, cnt_realloc, cnt_free);
1698*2b15cb3dSCy Schubert 	if (!libevent_tests_running_in_debug_mode)
1699*2b15cb3dSCy Schubert 		event_enable_debug_mode();
1700*2b15cb3dSCy Schubert 
1701*2b15cb3dSCy Schubert 	/* not mm_calloc: we don't want to mess with the count. */
1702*2b15cb3dSCy Schubert 	env = calloc(1, sizeof(struct testleak_env_t));
1703*2b15cb3dSCy Schubert 	env->base = event_base_new();
1704*2b15cb3dSCy Schubert 	env->dns_base = evdns_base_new(env->base, 0);
1705*2b15cb3dSCy Schubert 	env->req = evdns_base_resolve_ipv4(
1706*2b15cb3dSCy Schubert 		env->dns_base, "example.com", DNS_QUERY_NO_SEARCH,
1707*2b15cb3dSCy Schubert 		generic_dns_callback, &env->r);
1708*2b15cb3dSCy Schubert 	return env;
1709*2b15cb3dSCy Schubert }
1710*2b15cb3dSCy Schubert 
1711*2b15cb3dSCy Schubert static int
1712*2b15cb3dSCy Schubert testleak_cleanup(const struct testcase_t *testcase, void *env_)
1713*2b15cb3dSCy Schubert {
1714*2b15cb3dSCy Schubert 	int ok = 0;
1715*2b15cb3dSCy Schubert 	struct testleak_env_t *env = env_;
1716*2b15cb3dSCy Schubert 	tt_assert(env);
1717*2b15cb3dSCy Schubert #ifdef EVENT__DISABLE_DEBUG_MODE
1718*2b15cb3dSCy Schubert 	tt_int_op(allocated_chunks, ==, 0);
1719*2b15cb3dSCy Schubert #else
1720*2b15cb3dSCy Schubert 	/* FIXME: that's `1' because of event_debug_map_HT_GROW */
1721*2b15cb3dSCy Schubert 	tt_int_op(allocated_chunks, ==, 1);
1722*2b15cb3dSCy Schubert #endif
1723*2b15cb3dSCy Schubert 	ok = 1;
1724*2b15cb3dSCy Schubert end:
1725*2b15cb3dSCy Schubert 	if (env) {
1726*2b15cb3dSCy Schubert 		if (env->dns_base)
1727*2b15cb3dSCy Schubert 			evdns_base_free(env->dns_base, 0);
1728*2b15cb3dSCy Schubert 		if (env->base)
1729*2b15cb3dSCy Schubert 			event_base_free(env->base);
1730*2b15cb3dSCy Schubert 		free(env);
1731*2b15cb3dSCy Schubert 	}
1732*2b15cb3dSCy Schubert 	return ok;
1733*2b15cb3dSCy Schubert }
1734*2b15cb3dSCy Schubert 
1735*2b15cb3dSCy Schubert static struct testcase_setup_t testleak_funcs = {
1736*2b15cb3dSCy Schubert 	testleak_setup, testleak_cleanup
1737*2b15cb3dSCy Schubert };
1738*2b15cb3dSCy Schubert 
1739*2b15cb3dSCy Schubert static void
1740*2b15cb3dSCy Schubert test_dbg_leak_cancel(void *env_)
1741*2b15cb3dSCy Schubert {
1742*2b15cb3dSCy Schubert 	/* cancel, loop, free/dns, free/base */
1743*2b15cb3dSCy Schubert 	struct testleak_env_t *env = env_;
1744*2b15cb3dSCy Schubert 	int send_err_shutdown = 1;
1745*2b15cb3dSCy Schubert 	evdns_cancel_request(env->dns_base, env->req);
1746*2b15cb3dSCy Schubert 	env->req = 0;
1747*2b15cb3dSCy Schubert 
1748*2b15cb3dSCy Schubert 	/* `req` is freed in callback, that's why one loop is required. */
1749*2b15cb3dSCy Schubert 	event_base_loop(env->base, EVLOOP_NONBLOCK);
1750*2b15cb3dSCy Schubert 
1751*2b15cb3dSCy Schubert 	/* send_err_shutdown means nothing as soon as our request is
1752*2b15cb3dSCy Schubert 	 * already canceled */
1753*2b15cb3dSCy Schubert 	evdns_base_free(env->dns_base, send_err_shutdown);
1754*2b15cb3dSCy Schubert 	env->dns_base = 0;
1755*2b15cb3dSCy Schubert 	event_base_free(env->base);
1756*2b15cb3dSCy Schubert 	env->base = 0;
1757*2b15cb3dSCy Schubert }
1758*2b15cb3dSCy Schubert 
1759*2b15cb3dSCy Schubert static void
1760*2b15cb3dSCy Schubert dbg_leak_resume(void *env_, int cancel, int send_err_shutdown)
1761*2b15cb3dSCy Schubert {
1762*2b15cb3dSCy Schubert 	/* cancel, loop, free/dns, free/base */
1763*2b15cb3dSCy Schubert 	struct testleak_env_t *env = env_;
1764*2b15cb3dSCy Schubert 	if (cancel) {
1765*2b15cb3dSCy Schubert 		evdns_cancel_request(env->dns_base, env->req);
1766*2b15cb3dSCy Schubert 		tt_assert(!evdns_base_resume(env->dns_base));
1767*2b15cb3dSCy Schubert 	} else {
1768*2b15cb3dSCy Schubert 		/* TODO: No nameservers, request can't be processed, must be errored */
1769*2b15cb3dSCy Schubert 		tt_assert(!evdns_base_resume(env->dns_base));
1770*2b15cb3dSCy Schubert 	}
1771*2b15cb3dSCy Schubert 
1772*2b15cb3dSCy Schubert 	/**
1773*2b15cb3dSCy Schubert 	 * Because we don't cancel request,
1774*2b15cb3dSCy Schubert 	 * and want our callback to recieve DNS_ERR_SHUTDOWN,
1775*2b15cb3dSCy Schubert 	 * we use deferred callback, and there was
1776*2b15cb3dSCy Schubert 	 * - one extra malloc(),
1777*2b15cb3dSCy Schubert 	 *   @see reply_schedule_callback()
1778*2b15cb3dSCy Schubert 	 * - and one missing free
1779*2b15cb3dSCy Schubert 	 *   @see request_finished() (req->handle->pending_cb = 1)
1780*2b15cb3dSCy Schubert 	 * than we don't need to count in testleak_cleanup()
1781*2b15cb3dSCy Schubert 	 *
1782*2b15cb3dSCy Schubert 	 * So just decrement allocated_chunks to 2,
1783*2b15cb3dSCy Schubert 	 * like we already take care about it.
1784*2b15cb3dSCy Schubert 	 */
1785*2b15cb3dSCy Schubert 	if (!cancel && send_err_shutdown) {
1786*2b15cb3dSCy Schubert 		allocated_chunks -= 2;
1787*2b15cb3dSCy Schubert 	}
1788*2b15cb3dSCy Schubert 
1789*2b15cb3dSCy Schubert 	event_base_loop(env->base, EVLOOP_NONBLOCK);
1790*2b15cb3dSCy Schubert 
1791*2b15cb3dSCy Schubert end:
1792*2b15cb3dSCy Schubert 	evdns_base_free(env->dns_base, send_err_shutdown);
1793*2b15cb3dSCy Schubert 	env->dns_base = 0;
1794*2b15cb3dSCy Schubert 	event_base_free(env->base);
1795*2b15cb3dSCy Schubert 	env->base = 0;
1796*2b15cb3dSCy Schubert }
1797*2b15cb3dSCy Schubert 
1798*2b15cb3dSCy Schubert #define IMPL_DBG_LEAK_RESUME(name, cancel, send_err_shutdown)      \
1799*2b15cb3dSCy Schubert 	static void                                                    \
1800*2b15cb3dSCy Schubert 	test_dbg_leak_##name##_(void *env_)                            \
1801*2b15cb3dSCy Schubert 	{                                                              \
1802*2b15cb3dSCy Schubert 		dbg_leak_resume(env_, cancel, send_err_shutdown);          \
1803*2b15cb3dSCy Schubert 	}
1804*2b15cb3dSCy Schubert IMPL_DBG_LEAK_RESUME(resume, 0, 0)
1805*2b15cb3dSCy Schubert IMPL_DBG_LEAK_RESUME(cancel_and_resume, 1, 0)
1806*2b15cb3dSCy Schubert IMPL_DBG_LEAK_RESUME(resume_send_err, 0, 1)
1807*2b15cb3dSCy Schubert IMPL_DBG_LEAK_RESUME(cancel_and_resume_send_err, 1, 1)
1808*2b15cb3dSCy Schubert 
1809*2b15cb3dSCy Schubert static void
1810*2b15cb3dSCy Schubert test_dbg_leak_shutdown(void *env_)
1811*2b15cb3dSCy Schubert {
1812*2b15cb3dSCy Schubert 	/* free/dns, loop, free/base */
1813*2b15cb3dSCy Schubert 	struct testleak_env_t *env = env_;
1814*2b15cb3dSCy Schubert 	int send_err_shutdown = 1;
1815*2b15cb3dSCy Schubert 
1816*2b15cb3dSCy Schubert 	/* `req` is freed both with `send_err_shutdown` and without it,
1817*2b15cb3dSCy Schubert 	 * the only difference is `evdns_callback` call */
1818*2b15cb3dSCy Schubert 	env->req = 0;
1819*2b15cb3dSCy Schubert 
1820*2b15cb3dSCy Schubert 	evdns_base_free(env->dns_base, send_err_shutdown);
1821*2b15cb3dSCy Schubert 	env->dns_base = 0;
1822*2b15cb3dSCy Schubert 
1823*2b15cb3dSCy Schubert 	/* `req` is freed in callback, that's why one loop is required */
1824*2b15cb3dSCy Schubert 	event_base_loop(env->base, EVLOOP_NONBLOCK);
1825*2b15cb3dSCy Schubert 	event_base_free(env->base);
1826*2b15cb3dSCy Schubert 	env->base = 0;
1827*2b15cb3dSCy Schubert }
1828*2b15cb3dSCy Schubert #endif
1829*2b15cb3dSCy Schubert 
1830*2b15cb3dSCy Schubert static void
1831*2b15cb3dSCy Schubert test_getaddrinfo_async_cancel_stress(void *ptr)
1832*2b15cb3dSCy Schubert {
1833*2b15cb3dSCy Schubert 	struct event_base *base;
1834*2b15cb3dSCy Schubert 	struct evdns_base *dns_base = NULL;
1835*2b15cb3dSCy Schubert 	struct evdns_server_port *server = NULL;
1836*2b15cb3dSCy Schubert 	evutil_socket_t fd = -1;
1837*2b15cb3dSCy Schubert 	struct sockaddr_in sin;
1838*2b15cb3dSCy Schubert 	struct sockaddr_storage ss;
1839*2b15cb3dSCy Schubert 	ev_socklen_t slen;
1840*2b15cb3dSCy Schubert 	int i;
1841*2b15cb3dSCy Schubert 
1842*2b15cb3dSCy Schubert 	base = event_base_new();
1843*2b15cb3dSCy Schubert 	dns_base = evdns_base_new(base, 0);
1844*2b15cb3dSCy Schubert 
1845*2b15cb3dSCy Schubert 	memset(&sin, 0, sizeof(sin));
1846*2b15cb3dSCy Schubert 	sin.sin_family = AF_INET;
1847*2b15cb3dSCy Schubert 	sin.sin_port = 0;
1848*2b15cb3dSCy Schubert 	sin.sin_addr.s_addr = htonl(0x7f000001);
1849*2b15cb3dSCy Schubert 	if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1850*2b15cb3dSCy Schubert 		tt_abort_perror("socket");
1851*2b15cb3dSCy Schubert 	}
1852*2b15cb3dSCy Schubert 	evutil_make_socket_nonblocking(fd);
1853*2b15cb3dSCy Schubert 	if (bind(fd, (struct sockaddr*)&sin, sizeof(sin))<0) {
1854*2b15cb3dSCy Schubert 		tt_abort_perror("bind");
1855*2b15cb3dSCy Schubert 	}
1856*2b15cb3dSCy Schubert 	server = evdns_add_server_port_with_base(base, fd, 0, gaic_server_cb,
1857*2b15cb3dSCy Schubert 	    base);
1858*2b15cb3dSCy Schubert 
1859*2b15cb3dSCy Schubert 	memset(&ss, 0, sizeof(ss));
1860*2b15cb3dSCy Schubert 	slen = sizeof(ss);
1861*2b15cb3dSCy Schubert 	if (getsockname(fd, (struct sockaddr*)&ss, &slen)<0) {
1862*2b15cb3dSCy Schubert 		tt_abort_perror("getsockname");
1863*2b15cb3dSCy Schubert 	}
1864*2b15cb3dSCy Schubert 	evdns_base_nameserver_sockaddr_add(dns_base,
1865*2b15cb3dSCy Schubert 	    (struct sockaddr*)&ss, slen, 0);
1866*2b15cb3dSCy Schubert 
1867*2b15cb3dSCy Schubert 	for (i = 0; i < 1000; ++i) {
1868*2b15cb3dSCy Schubert 		gaic_launch(base, dns_base);
1869*2b15cb3dSCy Schubert 	}
1870*2b15cb3dSCy Schubert 
1871*2b15cb3dSCy Schubert 	event_base_dispatch(base);
1872*2b15cb3dSCy Schubert 
1873*2b15cb3dSCy Schubert end:
1874*2b15cb3dSCy Schubert 	if (dns_base)
1875*2b15cb3dSCy Schubert 		evdns_base_free(dns_base, 1);
1876*2b15cb3dSCy Schubert 	if (server)
1877*2b15cb3dSCy Schubert 		evdns_close_server_port(server);
1878*2b15cb3dSCy Schubert 	if (fd >= 0)
1879*2b15cb3dSCy Schubert 		evutil_closesocket(fd);
1880*2b15cb3dSCy Schubert }
1881*2b15cb3dSCy Schubert 
1882*2b15cb3dSCy Schubert 
1883*2b15cb3dSCy Schubert #define DNS_LEGACY(name, flags)					       \
1884*2b15cb3dSCy Schubert 	{ #name, run_legacy_test_fn, flags|TT_LEGACY, &legacy_setup,   \
1885*2b15cb3dSCy Schubert 		    dns_##name }
1886*2b15cb3dSCy Schubert 
1887*2b15cb3dSCy Schubert struct testcase_t dns_testcases[] = {
1888*2b15cb3dSCy Schubert 	DNS_LEGACY(server, TT_FORK|TT_NEED_BASE),
1889*2b15cb3dSCy Schubert 	DNS_LEGACY(gethostbyname, TT_FORK|TT_NEED_BASE|TT_NEED_DNS|TT_OFF_BY_DEFAULT),
1890*2b15cb3dSCy Schubert 	DNS_LEGACY(gethostbyname6, TT_FORK|TT_NEED_BASE|TT_NEED_DNS|TT_OFF_BY_DEFAULT),
1891*2b15cb3dSCy Schubert 	DNS_LEGACY(gethostbyaddr, TT_FORK|TT_NEED_BASE|TT_NEED_DNS|TT_OFF_BY_DEFAULT),
1892*2b15cb3dSCy Schubert 	{ "resolve_reverse", dns_resolve_reverse, TT_FORK|TT_OFF_BY_DEFAULT, NULL, NULL },
1893*2b15cb3dSCy Schubert 	{ "search", dns_search_test, TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
1894*2b15cb3dSCy Schubert 	{ "search_cancel", dns_search_cancel_test,
1895*2b15cb3dSCy Schubert 	  TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
1896*2b15cb3dSCy Schubert 	{ "retry", dns_retry_test, TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, NULL },
1897*2b15cb3dSCy Schubert 	{ "reissue", dns_reissue_test, TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, NULL },
1898*2b15cb3dSCy Schubert 	{ "inflight", dns_inflight_test, TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
1899*2b15cb3dSCy Schubert 	{ "bufferevent_connect_hostname", test_bufferevent_connect_hostname,
1900*2b15cb3dSCy Schubert 	  TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
1901*2b15cb3dSCy Schubert 
1902*2b15cb3dSCy Schubert 	{ "getaddrinfo_async", test_getaddrinfo_async,
1903*2b15cb3dSCy Schubert 	  TT_FORK|TT_NEED_BASE, &basic_setup, (char*)"" },
1904*2b15cb3dSCy Schubert 	{ "getaddrinfo_cancel_stress", test_getaddrinfo_async_cancel_stress,
1905*2b15cb3dSCy Schubert 	  TT_FORK, NULL, NULL },
1906*2b15cb3dSCy Schubert 
1907*2b15cb3dSCy Schubert #ifdef EVENT_SET_MEM_FUNCTIONS_IMPLEMENTED
1908*2b15cb3dSCy Schubert 	{ "leak_shutdown", test_dbg_leak_shutdown, TT_FORK, &testleak_funcs, NULL },
1909*2b15cb3dSCy Schubert 	{ "leak_cancel", test_dbg_leak_cancel, TT_FORK, &testleak_funcs, NULL },
1910*2b15cb3dSCy Schubert 
1911*2b15cb3dSCy Schubert 	{ "leak_resume", test_dbg_leak_resume_, TT_FORK, &testleak_funcs, NULL },
1912*2b15cb3dSCy Schubert 	{ "leak_cancel_and_resume", test_dbg_leak_cancel_and_resume_,
1913*2b15cb3dSCy Schubert 	  TT_FORK, &testleak_funcs, NULL },
1914*2b15cb3dSCy Schubert 	{ "leak_resume_send_err", test_dbg_leak_resume_send_err_,
1915*2b15cb3dSCy Schubert 	  TT_FORK, &testleak_funcs, NULL },
1916*2b15cb3dSCy Schubert 	{ "leak_cancel_and_resume_send_err", test_dbg_leak_cancel_and_resume_send_err_,
1917*2b15cb3dSCy Schubert 	  TT_FORK, &testleak_funcs, NULL },
1918*2b15cb3dSCy Schubert #endif
1919*2b15cb3dSCy Schubert 
1920*2b15cb3dSCy Schubert 	END_OF_TESTCASES
1921*2b15cb3dSCy Schubert };
1922*2b15cb3dSCy Schubert 
1923