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 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 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 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 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 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 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 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 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 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 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 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 } 626 static void dns_search_test(void *arg) { dns_search_test_impl(arg, 0); } 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 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 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 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 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 804 dns_retry_test(void *arg) 805 { 806 dns_retry_test_impl(arg, 0); 807 } 808 static void 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 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 883 dns_reissue_test(void *arg) 884 { 885 dns_reissue_test_impl(arg, 0); 886 } 887 static void 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 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 959 dns_inflight_test(void *arg) 960 { 961 dns_inflight_test_impl(arg, 0); 962 } 963 964 static void 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 * 1896 cnt_malloc(size_t sz) 1897 { 1898 allocated_chunks += 1; 1899 return malloc(sz); 1900 } 1901 1902 static void * 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 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 * 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 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 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 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 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 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 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 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 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 * 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 * 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 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 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 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 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