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