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