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