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