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