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