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