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