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 #include "event2/dns.h" 63 #include "event2/dns_compat.h" 64 #include "event2/dns_struct.h" 65 #include "event2/event.h" 66 #include "event2/event_compat.h" 67 #include "event2/event_struct.h" 68 #include "event2/util.h" 69 #include "event2/listener.h" 70 #include "event2/bufferevent.h" 71 #include "log-internal.h" 72 #include "regress.h" 73 #include "regress_testutils.h" 74 75 static int dns_ok = 0; 76 static int dns_got_cancel = 0; 77 static int dns_err = 0; 78 79 80 static void 81 dns_gethostbyname_cb(int result, char type, int count, int ttl, 82 void *addresses, void *arg) 83 { 84 dns_ok = dns_err = 0; 85 86 if (result == DNS_ERR_TIMEOUT) { 87 printf("[Timed out] "); 88 dns_err = result; 89 goto out; 90 } 91 92 if (result != DNS_ERR_NONE) { 93 printf("[Error code %d] ", result); 94 goto out; 95 } 96 97 TT_BLATHER(("type: %d, count: %d, ttl: %d: ", type, count, ttl)); 98 99 switch (type) { 100 case DNS_IPv6_AAAA: { 101 #if defined(EVENT__HAVE_STRUCT_IN6_ADDR) && defined(EVENT__HAVE_INET_NTOP) && defined(INET6_ADDRSTRLEN) 102 struct in6_addr *in6_addrs = addresses; 103 char buf[INET6_ADDRSTRLEN+1]; 104 int i; 105 /* a resolution that's not valid does not help */ 106 if (ttl < 0) 107 goto out; 108 for (i = 0; i < count; ++i) { 109 const char *b = evutil_inet_ntop(AF_INET6, &in6_addrs[i], buf,sizeof(buf)); 110 if (b) 111 TT_BLATHER(("%s ", b)); 112 else 113 TT_BLATHER(("%s ", strerror(errno))); 114 } 115 #endif 116 break; 117 } 118 case DNS_IPv4_A: { 119 struct in_addr *in_addrs = addresses; 120 int i; 121 /* a resolution that's not valid does not help */ 122 if (ttl < 0) 123 goto out; 124 for (i = 0; i < count; ++i) 125 TT_BLATHER(("%s ", inet_ntoa(in_addrs[i]))); 126 break; 127 } 128 case DNS_PTR: 129 /* may get at most one PTR */ 130 if (count != 1) 131 goto out; 132 133 TT_BLATHER(("%s ", *(char **)addresses)); 134 break; 135 default: 136 goto out; 137 } 138 139 dns_ok = type; 140 141 out: 142 if (arg == NULL) 143 event_loopexit(NULL); 144 else 145 event_base_loopexit((struct event_base *)arg, NULL); 146 } 147 148 static void 149 dns_gethostbyname(void) 150 { 151 dns_ok = 0; 152 evdns_resolve_ipv4("www.monkey.org", 0, dns_gethostbyname_cb, NULL); 153 event_dispatch(); 154 155 tt_int_op(dns_ok, ==, DNS_IPv4_A); 156 test_ok = dns_ok; 157 end: 158 ; 159 } 160 161 static void 162 dns_gethostbyname6(void) 163 { 164 dns_ok = 0; 165 evdns_resolve_ipv6("www.ietf.org", 0, dns_gethostbyname_cb, NULL); 166 event_dispatch(); 167 168 if (!dns_ok && dns_err == DNS_ERR_TIMEOUT) { 169 tt_skip(); 170 } 171 172 tt_int_op(dns_ok, ==, DNS_IPv6_AAAA); 173 test_ok = 1; 174 end: 175 ; 176 } 177 178 static void 179 dns_gethostbyaddr(void) 180 { 181 struct in_addr in; 182 in.s_addr = htonl(0x7f000001ul); /* 127.0.0.1 */ 183 dns_ok = 0; 184 evdns_resolve_reverse(&in, 0, dns_gethostbyname_cb, NULL); 185 event_dispatch(); 186 187 tt_int_op(dns_ok, ==, DNS_PTR); 188 test_ok = dns_ok; 189 end: 190 ; 191 } 192 193 static void 194 dns_resolve_reverse(void *ptr) 195 { 196 struct in_addr in; 197 struct event_base *base = event_base_new(); 198 struct evdns_base *dns = evdns_base_new(base, 1/* init name servers */); 199 struct evdns_request *req = NULL; 200 201 tt_assert(base); 202 tt_assert(dns); 203 in.s_addr = htonl(0x7f000001ul); /* 127.0.0.1 */ 204 dns_ok = 0; 205 206 req = evdns_base_resolve_reverse( 207 dns, &in, 0, dns_gethostbyname_cb, base); 208 tt_assert(req); 209 210 event_base_dispatch(base); 211 212 tt_int_op(dns_ok, ==, DNS_PTR); 213 214 end: 215 if (dns) 216 evdns_base_free(dns, 0); 217 if (base) 218 event_base_free(base); 219 } 220 221 static int n_server_responses = 0; 222 223 static void 224 dns_server_request_cb(struct evdns_server_request *req, void *data) 225 { 226 int i, r; 227 const char TEST_ARPA[] = "11.11.168.192.in-addr.arpa"; 228 const char TEST_IN6[] = 229 "f.e.f.e." "0.0.0.0." "0.0.0.0." "1.1.1.1." 230 "a.a.a.a." "0.0.0.0." "0.0.0.0." "0.f.f.f.ip6.arpa"; 231 232 for (i = 0; i < req->nquestions; ++i) { 233 const int qtype = req->questions[i]->type; 234 const int qclass = req->questions[i]->dns_question_class; 235 const char *qname = req->questions[i]->name; 236 237 struct in_addr ans; 238 ans.s_addr = htonl(0xc0a80b0bUL); /* 192.168.11.11 */ 239 if (qtype == EVDNS_TYPE_A && 240 qclass == EVDNS_CLASS_INET && 241 !evutil_ascii_strcasecmp(qname, "zz.example.com")) { 242 r = evdns_server_request_add_a_reply(req, qname, 243 1, &ans.s_addr, 12345); 244 if (r<0) 245 dns_ok = 0; 246 } else if (qtype == EVDNS_TYPE_AAAA && 247 qclass == EVDNS_CLASS_INET && 248 !evutil_ascii_strcasecmp(qname, "zz.example.com")) { 249 char addr6[17] = "abcdefghijklmnop"; 250 r = evdns_server_request_add_aaaa_reply(req, 251 qname, 1, addr6, 123); 252 if (r<0) 253 dns_ok = 0; 254 } else if (qtype == EVDNS_TYPE_PTR && 255 qclass == EVDNS_CLASS_INET && 256 !evutil_ascii_strcasecmp(qname, TEST_ARPA)) { 257 r = evdns_server_request_add_ptr_reply(req, NULL, 258 qname, "ZZ.EXAMPLE.COM", 54321); 259 if (r<0) 260 dns_ok = 0; 261 } else if (qtype == EVDNS_TYPE_PTR && 262 qclass == EVDNS_CLASS_INET && 263 !evutil_ascii_strcasecmp(qname, TEST_IN6)){ 264 r = evdns_server_request_add_ptr_reply(req, NULL, 265 qname, 266 "ZZ-INET6.EXAMPLE.COM", 54322); 267 if (r<0) 268 dns_ok = 0; 269 } else if (qtype == EVDNS_TYPE_A && 270 qclass == EVDNS_CLASS_INET && 271 !evutil_ascii_strcasecmp(qname, "drop.example.com")) { 272 if (evdns_server_request_drop(req)<0) 273 dns_ok = 0; 274 return; 275 } else { 276 printf("Unexpected question %d %d \"%s\" ", 277 qtype, qclass, qname); 278 dns_ok = 0; 279 } 280 } 281 r = evdns_server_request_respond(req, 0); 282 if (r<0) { 283 printf("Couldn't send reply. "); 284 dns_ok = 0; 285 } 286 } 287 288 static void 289 dns_server_gethostbyname_cb(int result, char type, int count, int ttl, 290 void *addresses, void *arg) 291 { 292 if (result == DNS_ERR_CANCEL) { 293 if (arg != (void*)(char*)90909) { 294 printf("Unexpected cancelation"); 295 dns_ok = 0; 296 } 297 dns_got_cancel = 1; 298 goto out; 299 } 300 if (result != DNS_ERR_NONE) { 301 printf("Unexpected result %d. ", result); 302 dns_ok = 0; 303 goto out; 304 } 305 if (count != 1) { 306 printf("Unexpected answer count %d. ", count); 307 dns_ok = 0; 308 goto out; 309 } 310 switch (type) { 311 case DNS_IPv4_A: { 312 struct in_addr *in_addrs = addresses; 313 if (in_addrs[0].s_addr != htonl(0xc0a80b0bUL) || ttl != 12345) { 314 printf("Bad IPv4 response \"%s\" %d. ", 315 inet_ntoa(in_addrs[0]), ttl); 316 dns_ok = 0; 317 goto out; 318 } 319 break; 320 } 321 case DNS_IPv6_AAAA: { 322 #if defined (EVENT__HAVE_STRUCT_IN6_ADDR) && defined(EVENT__HAVE_INET_NTOP) && defined(INET6_ADDRSTRLEN) 323 struct in6_addr *in6_addrs = addresses; 324 char buf[INET6_ADDRSTRLEN+1]; 325 if (memcmp(&in6_addrs[0].s6_addr, "abcdefghijklmnop", 16) 326 || ttl != 123) { 327 const char *b = evutil_inet_ntop(AF_INET6, &in6_addrs[0],buf,sizeof(buf)); 328 printf("Bad IPv6 response \"%s\" %d. ", b, ttl); 329 dns_ok = 0; 330 goto out; 331 } 332 #endif 333 break; 334 } 335 case DNS_PTR: { 336 char **addrs = addresses; 337 if (arg != (void*)6) { 338 if (strcmp(addrs[0], "ZZ.EXAMPLE.COM") || 339 ttl != 54321) { 340 printf("Bad PTR response \"%s\" %d. ", 341 addrs[0], ttl); 342 dns_ok = 0; 343 goto out; 344 } 345 } else { 346 if (strcmp(addrs[0], "ZZ-INET6.EXAMPLE.COM") || 347 ttl != 54322) { 348 printf("Bad ipv6 PTR response \"%s\" %d. ", 349 addrs[0], ttl); 350 dns_ok = 0; 351 goto out; 352 } 353 } 354 break; 355 } 356 default: 357 printf("Bad response type %d. ", type); 358 dns_ok = 0; 359 } 360 out: 361 if (++n_server_responses == 3) { 362 event_loopexit(NULL); 363 } 364 } 365 366 static void 367 dns_server(void) 368 { 369 evutil_socket_t sock=-1; 370 struct sockaddr_in my_addr; 371 struct sockaddr_storage ss; 372 ev_socklen_t slen; 373 struct evdns_server_port *port=NULL; 374 struct in_addr resolve_addr; 375 struct in6_addr resolve_addr6; 376 struct evdns_base *base=NULL; 377 struct evdns_request *req=NULL; 378 379 dns_ok = 1; 380 381 base = evdns_base_new(NULL, 0); 382 383 /* Now configure a nameserver port. */ 384 sock = socket(AF_INET, SOCK_DGRAM, 0); 385 if (sock<0) { 386 tt_abort_perror("socket"); 387 } 388 389 evutil_make_socket_nonblocking(sock); 390 391 memset(&my_addr, 0, sizeof(my_addr)); 392 my_addr.sin_family = AF_INET; 393 my_addr.sin_port = 0; /* kernel picks */ 394 my_addr.sin_addr.s_addr = htonl(0x7f000001UL); 395 if (bind(sock, (struct sockaddr*)&my_addr, sizeof(my_addr)) < 0) { 396 tt_abort_perror("bind"); 397 } 398 slen = sizeof(ss); 399 if (getsockname(sock, (struct sockaddr*)&ss, &slen) < 0) { 400 tt_abort_perror("getsockname"); 401 } 402 403 port = evdns_add_server_port(sock, 0, dns_server_request_cb, NULL); 404 405 /* Add ourself as the only nameserver, and make sure we really are 406 * the only nameserver. */ 407 evdns_base_nameserver_sockaddr_add(base, (struct sockaddr*)&ss, slen, 0); 408 tt_int_op(evdns_base_count_nameservers(base), ==, 1); 409 410 /* Send some queries. */ 411 evdns_base_resolve_ipv4(base, "zz.example.com", DNS_QUERY_NO_SEARCH, 412 dns_server_gethostbyname_cb, NULL); 413 evdns_base_resolve_ipv6(base, "zz.example.com", DNS_QUERY_NO_SEARCH, 414 dns_server_gethostbyname_cb, NULL); 415 resolve_addr.s_addr = htonl(0xc0a80b0bUL); /* 192.168.11.11 */ 416 evdns_base_resolve_reverse(base, &resolve_addr, 0, 417 dns_server_gethostbyname_cb, NULL); 418 memcpy(resolve_addr6.s6_addr, 419 "\xff\xf0\x00\x00\x00\x00\xaa\xaa" 420 "\x11\x11\x00\x00\x00\x00\xef\xef", 16); 421 evdns_base_resolve_reverse_ipv6(base, &resolve_addr6, 0, 422 dns_server_gethostbyname_cb, (void*)6); 423 424 req = evdns_base_resolve_ipv4(base, 425 "drop.example.com", DNS_QUERY_NO_SEARCH, 426 dns_server_gethostbyname_cb, (void*)(char*)90909); 427 428 evdns_cancel_request(base, req); 429 430 event_dispatch(); 431 432 tt_assert(dns_got_cancel); 433 test_ok = dns_ok; 434 435 end: 436 if (port) 437 evdns_close_server_port(port); 438 if (sock >= 0) 439 evutil_closesocket(sock); 440 if (base) 441 evdns_base_free(base, 0); 442 } 443 444 static int n_replies_left; 445 static struct event_base *exit_base; 446 447 struct generic_dns_callback_result { 448 int result; 449 char type; 450 int count; 451 int ttl; 452 size_t addrs_len; 453 void *addrs; 454 char addrs_buf[256]; 455 }; 456 457 static void 458 generic_dns_callback(int result, char type, int count, int ttl, void *addresses, 459 void *arg) 460 { 461 size_t len; 462 struct generic_dns_callback_result *res = arg; 463 res->result = result; 464 res->type = type; 465 res->count = count; 466 res->ttl = ttl; 467 468 if (type == DNS_IPv4_A) 469 len = count * 4; 470 else if (type == DNS_IPv6_AAAA) 471 len = count * 16; 472 else if (type == DNS_PTR) 473 len = strlen(addresses)+1; 474 else { 475 res->addrs_len = len = 0; 476 res->addrs = NULL; 477 } 478 if (len) { 479 res->addrs_len = len; 480 if (len > 256) 481 len = 256; 482 memcpy(res->addrs_buf, addresses, len); 483 res->addrs = res->addrs_buf; 484 } 485 486 if (--n_replies_left == 0) 487 event_base_loopexit(exit_base, NULL); 488 } 489 490 static struct regress_dns_server_table search_table[] = { 491 { "host.a.example.com", "err", "3", 0 }, 492 { "host.b.example.com", "err", "3", 0 }, 493 { "host.c.example.com", "A", "11.22.33.44", 0 }, 494 { "host2.a.example.com", "err", "3", 0 }, 495 { "host2.b.example.com", "A", "200.100.0.100", 0 }, 496 { "host2.c.example.com", "err", "3", 0 }, 497 { "hostn.a.example.com", "errsoa", "0", 0 }, 498 { "hostn.b.example.com", "errsoa", "3", 0 }, 499 { "hostn.c.example.com", "err", "0", 0 }, 500 501 { "host", "err", "3", 0 }, 502 { "host2", "err", "3", 0 }, 503 { "*", "err", "3", 0 }, 504 { NULL, NULL, NULL, 0 } 505 }; 506 507 static void 508 dns_search_test(void *arg) 509 { 510 struct basic_test_data *data = arg; 511 struct event_base *base = data->base; 512 struct evdns_base *dns = NULL; 513 ev_uint16_t portnum = 0; 514 char buf[64]; 515 516 struct generic_dns_callback_result r[8]; 517 518 tt_assert(regress_dnsserver(base, &portnum, search_table)); 519 evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum); 520 521 dns = evdns_base_new(base, 0); 522 tt_assert(!evdns_base_nameserver_ip_add(dns, buf)); 523 524 evdns_base_search_add(dns, "a.example.com"); 525 evdns_base_search_add(dns, "b.example.com"); 526 evdns_base_search_add(dns, "c.example.com"); 527 528 n_replies_left = sizeof(r)/sizeof(r[0]); 529 exit_base = base; 530 531 evdns_base_resolve_ipv4(dns, "host", 0, generic_dns_callback, &r[0]); 532 evdns_base_resolve_ipv4(dns, "host2", 0, generic_dns_callback, &r[1]); 533 evdns_base_resolve_ipv4(dns, "host", DNS_NO_SEARCH, generic_dns_callback, &r[2]); 534 evdns_base_resolve_ipv4(dns, "host2", DNS_NO_SEARCH, generic_dns_callback, &r[3]); 535 evdns_base_resolve_ipv4(dns, "host3", 0, generic_dns_callback, &r[4]); 536 evdns_base_resolve_ipv4(dns, "hostn.a.example.com", DNS_NO_SEARCH, generic_dns_callback, &r[5]); 537 evdns_base_resolve_ipv4(dns, "hostn.b.example.com", DNS_NO_SEARCH, generic_dns_callback, &r[6]); 538 evdns_base_resolve_ipv4(dns, "hostn.c.example.com", DNS_NO_SEARCH, generic_dns_callback, &r[7]); 539 540 event_base_dispatch(base); 541 542 tt_int_op(r[0].type, ==, DNS_IPv4_A); 543 tt_int_op(r[0].count, ==, 1); 544 tt_int_op(((ev_uint32_t*)r[0].addrs)[0], ==, htonl(0x0b16212c)); 545 tt_int_op(r[1].type, ==, DNS_IPv4_A); 546 tt_int_op(r[1].count, ==, 1); 547 tt_int_op(((ev_uint32_t*)r[1].addrs)[0], ==, htonl(0xc8640064)); 548 tt_int_op(r[2].result, ==, DNS_ERR_NOTEXIST); 549 tt_int_op(r[3].result, ==, DNS_ERR_NOTEXIST); 550 tt_int_op(r[4].result, ==, DNS_ERR_NOTEXIST); 551 tt_int_op(r[5].result, ==, DNS_ERR_NODATA); 552 tt_int_op(r[5].ttl, ==, 42); 553 tt_int_op(r[6].result, ==, DNS_ERR_NOTEXIST); 554 tt_int_op(r[6].ttl, ==, 42); 555 tt_int_op(r[7].result, ==, DNS_ERR_NODATA); 556 tt_int_op(r[7].ttl, ==, 0); 557 558 end: 559 if (dns) 560 evdns_base_free(dns, 0); 561 562 regress_clean_dnsserver(); 563 } 564 565 static int request_count = 0; 566 static struct evdns_request *current_req = NULL; 567 568 static void 569 search_cancel_server_cb(struct evdns_server_request *req, void *data) 570 { 571 const char *question; 572 573 if (req->nquestions != 1) 574 TT_DIE(("Only handling one question at a time; got %d", 575 req->nquestions)); 576 577 question = req->questions[0]->name; 578 579 TT_BLATHER(("got question, %s", question)); 580 581 tt_assert(request_count > 0); 582 tt_assert(!evdns_server_request_respond(req, 3)); 583 584 if (!--request_count) 585 evdns_cancel_request(NULL, current_req); 586 587 end: 588 ; 589 } 590 591 static void 592 dns_search_cancel_test(void *arg) 593 { 594 struct basic_test_data *data = arg; 595 struct event_base *base = data->base; 596 struct evdns_base *dns = NULL; 597 struct evdns_server_port *port = NULL; 598 ev_uint16_t portnum = 0; 599 struct generic_dns_callback_result r1; 600 char buf[64]; 601 602 port = regress_get_dnsserver(base, &portnum, NULL, 603 search_cancel_server_cb, NULL); 604 tt_assert(port); 605 evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum); 606 607 dns = evdns_base_new(base, 0); 608 tt_assert(!evdns_base_nameserver_ip_add(dns, buf)); 609 610 evdns_base_search_add(dns, "a.example.com"); 611 evdns_base_search_add(dns, "b.example.com"); 612 evdns_base_search_add(dns, "c.example.com"); 613 evdns_base_search_add(dns, "d.example.com"); 614 615 exit_base = base; 616 request_count = 3; 617 n_replies_left = 1; 618 619 current_req = evdns_base_resolve_ipv4(dns, "host", 0, 620 generic_dns_callback, &r1); 621 event_base_dispatch(base); 622 623 tt_int_op(r1.result, ==, DNS_ERR_CANCEL); 624 625 end: 626 if (port) 627 evdns_close_server_port(port); 628 if (dns) 629 evdns_base_free(dns, 0); 630 } 631 632 static void 633 fail_server_cb(struct evdns_server_request *req, void *data) 634 { 635 const char *question; 636 int *count = data; 637 struct in_addr in; 638 639 /* Drop the first N requests that we get. */ 640 if (*count > 0) { 641 --*count; 642 tt_want(! evdns_server_request_drop(req)); 643 return; 644 } 645 646 if (req->nquestions != 1) 647 TT_DIE(("Only handling one question at a time; got %d", 648 req->nquestions)); 649 650 question = req->questions[0]->name; 651 652 if (!evutil_ascii_strcasecmp(question, "google.com")) { 653 /* Detect a probe, and get out of the loop. */ 654 event_base_loopexit(exit_base, NULL); 655 } 656 657 tt_assert(evutil_inet_pton(AF_INET, "16.32.64.128", &in)); 658 evdns_server_request_add_a_reply(req, question, 1, &in.s_addr, 659 100); 660 tt_assert(! evdns_server_request_respond(req, 0)) 661 return; 662 end: 663 tt_want(! evdns_server_request_drop(req)); 664 } 665 666 static void 667 dns_retry_test(void *arg) 668 { 669 struct basic_test_data *data = arg; 670 struct event_base *base = data->base; 671 struct evdns_server_port *port = NULL; 672 struct evdns_base *dns = NULL; 673 int drop_count = 2; 674 ev_uint16_t portnum = 0; 675 char buf[64]; 676 677 struct generic_dns_callback_result r1; 678 679 port = regress_get_dnsserver(base, &portnum, NULL, 680 fail_server_cb, &drop_count); 681 tt_assert(port); 682 evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum); 683 684 dns = evdns_base_new(base, 0); 685 tt_assert(!evdns_base_nameserver_ip_add(dns, buf)); 686 tt_assert(! evdns_base_set_option(dns, "timeout", "0.2")); 687 tt_assert(! evdns_base_set_option(dns, "max-timeouts:", "10")); 688 tt_assert(! evdns_base_set_option(dns, "initial-probe-timeout", "0.1")); 689 690 evdns_base_resolve_ipv4(dns, "host.example.com", 0, 691 generic_dns_callback, &r1); 692 693 n_replies_left = 1; 694 exit_base = base; 695 696 event_base_dispatch(base); 697 698 tt_int_op(drop_count, ==, 0); 699 700 tt_int_op(r1.type, ==, DNS_IPv4_A); 701 tt_int_op(r1.count, ==, 1); 702 tt_int_op(((ev_uint32_t*)r1.addrs)[0], ==, htonl(0x10204080)); 703 704 /* Now try again, but this time have the server get treated as 705 * failed, so we can send it a test probe. */ 706 drop_count = 4; 707 tt_assert(! evdns_base_set_option(dns, "max-timeouts:", "2")); 708 tt_assert(! evdns_base_set_option(dns, "attempts:", "3")); 709 memset(&r1, 0, sizeof(r1)); 710 711 evdns_base_resolve_ipv4(dns, "host.example.com", 0, 712 generic_dns_callback, &r1); 713 714 n_replies_left = 2; 715 716 /* This will run until it answers the "google.com" probe request. */ 717 event_base_dispatch(base); 718 719 /* We'll treat the server as failed here. */ 720 tt_int_op(r1.result, ==, DNS_ERR_TIMEOUT); 721 722 /* It should work this time. */ 723 tt_int_op(drop_count, ==, 0); 724 evdns_base_resolve_ipv4(dns, "host.example.com", 0, 725 generic_dns_callback, &r1); 726 727 event_base_dispatch(base); 728 tt_int_op(r1.result, ==, DNS_ERR_NONE); 729 tt_int_op(r1.type, ==, DNS_IPv4_A); 730 tt_int_op(r1.count, ==, 1); 731 tt_int_op(((ev_uint32_t*)r1.addrs)[0], ==, htonl(0x10204080)); 732 733 end: 734 if (dns) 735 evdns_base_free(dns, 0); 736 if (port) 737 evdns_close_server_port(port); 738 } 739 740 static struct regress_dns_server_table internal_error_table[] = { 741 /* Error 4 (NOTIMPL) makes us reissue the request to another server 742 if we can. 743 744 XXXX we should reissue under a much wider set of circumstances! 745 */ 746 { "foof.example.com", "err", "4", 0 }, 747 { NULL, NULL, NULL, 0 } 748 }; 749 750 static struct regress_dns_server_table reissue_table[] = { 751 { "foof.example.com", "A", "240.15.240.15", 0 }, 752 { NULL, NULL, NULL, 0 } 753 }; 754 755 static void 756 dns_reissue_test(void *arg) 757 { 758 struct basic_test_data *data = arg; 759 struct event_base *base = data->base; 760 struct evdns_server_port *port1 = NULL, *port2 = NULL; 761 struct evdns_base *dns = NULL; 762 struct generic_dns_callback_result r1; 763 ev_uint16_t portnum1 = 0, portnum2=0; 764 char buf1[64], buf2[64]; 765 766 port1 = regress_get_dnsserver(base, &portnum1, NULL, 767 regress_dns_server_cb, internal_error_table); 768 tt_assert(port1); 769 port2 = regress_get_dnsserver(base, &portnum2, NULL, 770 regress_dns_server_cb, reissue_table); 771 tt_assert(port2); 772 evutil_snprintf(buf1, sizeof(buf1), "127.0.0.1:%d", (int)portnum1); 773 evutil_snprintf(buf2, sizeof(buf2), "127.0.0.1:%d", (int)portnum2); 774 775 dns = evdns_base_new(base, 0); 776 tt_assert(!evdns_base_nameserver_ip_add(dns, buf1)); 777 tt_assert(! evdns_base_set_option(dns, "timeout:", "0.3")); 778 tt_assert(! evdns_base_set_option(dns, "max-timeouts:", "2")); 779 tt_assert(! evdns_base_set_option(dns, "attempts:", "5")); 780 781 memset(&r1, 0, sizeof(r1)); 782 evdns_base_resolve_ipv4(dns, "foof.example.com", 0, 783 generic_dns_callback, &r1); 784 785 /* Add this after, so that we are sure to get a reissue. */ 786 tt_assert(!evdns_base_nameserver_ip_add(dns, buf2)); 787 788 n_replies_left = 1; 789 exit_base = base; 790 791 event_base_dispatch(base); 792 tt_int_op(r1.result, ==, DNS_ERR_NONE); 793 tt_int_op(r1.type, ==, DNS_IPv4_A); 794 tt_int_op(r1.count, ==, 1); 795 tt_int_op(((ev_uint32_t*)r1.addrs)[0], ==, htonl(0xf00ff00f)); 796 797 /* Make sure we dropped at least once. */ 798 tt_int_op(internal_error_table[0].seen, >, 0); 799 800 end: 801 if (dns) 802 evdns_base_free(dns, 0); 803 if (port1) 804 evdns_close_server_port(port1); 805 if (port2) 806 evdns_close_server_port(port2); 807 } 808 809 #if 0 810 static void 811 dumb_bytes_fn(char *p, size_t n) 812 { 813 unsigned i; 814 /* This gets us 6 bits of entropy per transaction ID, which means we 815 * will have probably have collisions and need to pick again. */ 816 for (i=0;i<n;++i) 817 p[i] = (char)(rand() & 7); 818 } 819 #endif 820 821 static void 822 dns_inflight_test(void *arg) 823 { 824 struct basic_test_data *data = arg; 825 struct event_base *base = data->base; 826 struct evdns_base *dns = NULL; 827 ev_uint16_t portnum = 0; 828 char buf[64]; 829 830 struct generic_dns_callback_result r[20]; 831 int i; 832 833 tt_assert(regress_dnsserver(base, &portnum, reissue_table)); 834 evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum); 835 836 dns = evdns_base_new(base, 0); 837 tt_assert(!evdns_base_nameserver_ip_add(dns, buf)); 838 tt_assert(! evdns_base_set_option(dns, "max-inflight:", "3")); 839 tt_assert(! evdns_base_set_option(dns, "randomize-case:", "0")); 840 841 for (i=0;i<20;++i) 842 evdns_base_resolve_ipv4(dns, "foof.example.com", 0, generic_dns_callback, &r[i]); 843 844 n_replies_left = 20; 845 exit_base = base; 846 847 event_base_dispatch(base); 848 849 for (i=0;i<20;++i) { 850 tt_int_op(r[i].type, ==, DNS_IPv4_A); 851 tt_int_op(r[i].count, ==, 1); 852 tt_int_op(((ev_uint32_t*)r[i].addrs)[0], ==, htonl(0xf00ff00f)); 853 } 854 855 end: 856 if (dns) 857 evdns_base_free(dns, 0); 858 regress_clean_dnsserver(); 859 } 860 861 /* === Test for bufferevent_socket_connect_hostname */ 862 863 static int total_connected_or_failed = 0; 864 static int total_n_accepted = 0; 865 static struct event_base *be_connect_hostname_base = NULL; 866 867 /* Implements a DNS server for the connect_hostname test and the 868 * getaddrinfo_async test */ 869 static void 870 be_getaddrinfo_server_cb(struct evdns_server_request *req, void *data) 871 { 872 int i; 873 int *n_got_p=data; 874 int added_any=0; 875 ++*n_got_p; 876 877 for (i=0;i<req->nquestions;++i) { 878 const int qtype = req->questions[i]->type; 879 const int qclass = req->questions[i]->dns_question_class; 880 const char *qname = req->questions[i]->name; 881 struct in_addr ans; 882 struct in6_addr ans6; 883 memset(&ans6, 0, sizeof(ans6)); 884 885 TT_BLATHER(("Got question about %s, type=%d", qname, qtype)); 886 887 if (qtype == EVDNS_TYPE_A && 888 qclass == EVDNS_CLASS_INET && 889 !evutil_ascii_strcasecmp(qname, "nobodaddy.example.com")) { 890 ans.s_addr = htonl(0x7f000001); 891 evdns_server_request_add_a_reply(req, qname, 892 1, &ans.s_addr, 2000); 893 added_any = 1; 894 } else if (!evutil_ascii_strcasecmp(qname, 895 "nosuchplace.example.com")) { 896 /* ok, just say notfound. */ 897 } else if (!evutil_ascii_strcasecmp(qname, 898 "both.example.com")) { 899 if (qtype == EVDNS_TYPE_A) { 900 ans.s_addr = htonl(0x50502020); 901 evdns_server_request_add_a_reply(req, qname, 902 1, &ans.s_addr, 2000); 903 added_any = 1; 904 } else if (qtype == EVDNS_TYPE_AAAA) { 905 ans6.s6_addr[0] = 0x80; 906 ans6.s6_addr[1] = 0xff; 907 ans6.s6_addr[14] = 0xbb; 908 ans6.s6_addr[15] = 0xbb; 909 evdns_server_request_add_aaaa_reply(req, qname, 910 1, &ans6.s6_addr, 2000); 911 added_any = 1; 912 } 913 evdns_server_request_add_cname_reply(req, qname, 914 "both-canonical.example.com", 1000); 915 } else if (!evutil_ascii_strcasecmp(qname, 916 "v4only.example.com") || 917 !evutil_ascii_strcasecmp(qname, "v4assert.example.com")) { 918 if (qtype == EVDNS_TYPE_A) { 919 ans.s_addr = htonl(0x12345678); 920 evdns_server_request_add_a_reply(req, qname, 921 1, &ans.s_addr, 2000); 922 added_any = 1; 923 } else if (!evutil_ascii_strcasecmp(qname, 924 "v4assert.example.com")) { 925 TT_FAIL(("Got an AAAA request for v4assert")); 926 } 927 } else if (!evutil_ascii_strcasecmp(qname, 928 "v6only.example.com") || 929 !evutil_ascii_strcasecmp(qname, "v6assert.example.com")) { 930 if (qtype == EVDNS_TYPE_AAAA) { 931 ans6.s6_addr[0] = 0x0b; 932 ans6.s6_addr[1] = 0x0b; 933 ans6.s6_addr[14] = 0xf0; 934 ans6.s6_addr[15] = 0x0d; 935 evdns_server_request_add_aaaa_reply(req, qname, 936 1, &ans6.s6_addr, 2000); 937 added_any = 1; 938 } else if (!evutil_ascii_strcasecmp(qname, 939 "v6assert.example.com")) { 940 TT_FAIL(("Got a A request for v6assert")); 941 } 942 } else if (!evutil_ascii_strcasecmp(qname, 943 "v6timeout.example.com")) { 944 if (qtype == EVDNS_TYPE_A) { 945 ans.s_addr = htonl(0xabcdef01); 946 evdns_server_request_add_a_reply(req, qname, 947 1, &ans.s_addr, 2000); 948 added_any = 1; 949 } else if (qtype == EVDNS_TYPE_AAAA) { 950 /* Let the v6 request time out.*/ 951 evdns_server_request_drop(req); 952 return; 953 } 954 } else if (!evutil_ascii_strcasecmp(qname, 955 "v4timeout.example.com")) { 956 if (qtype == EVDNS_TYPE_AAAA) { 957 ans6.s6_addr[0] = 0x0a; 958 ans6.s6_addr[1] = 0x0a; 959 ans6.s6_addr[14] = 0xff; 960 ans6.s6_addr[15] = 0x01; 961 evdns_server_request_add_aaaa_reply(req, qname, 962 1, &ans6.s6_addr, 2000); 963 added_any = 1; 964 } else if (qtype == EVDNS_TYPE_A) { 965 /* Let the v4 request time out.*/ 966 evdns_server_request_drop(req); 967 return; 968 } 969 } else if (!evutil_ascii_strcasecmp(qname, 970 "v6timeout-nonexist.example.com")) { 971 if (qtype == EVDNS_TYPE_A) { 972 /* Fall through, give an nexist. */ 973 } else if (qtype == EVDNS_TYPE_AAAA) { 974 /* Let the v6 request time out.*/ 975 evdns_server_request_drop(req); 976 return; 977 } 978 } else if (!evutil_ascii_strcasecmp(qname, 979 "all-timeout.example.com")) { 980 /* drop all requests */ 981 evdns_server_request_drop(req); 982 return; 983 } else { 984 TT_GRIPE(("Got weird request for %s",qname)); 985 } 986 } 987 if (added_any) { 988 TT_BLATHER(("answering")); 989 evdns_server_request_respond(req, 0); 990 } else { 991 TT_BLATHER(("saying nexist.")); 992 evdns_server_request_respond(req, 3); 993 } 994 } 995 996 /* Implements a listener for connect_hostname test. */ 997 static void 998 nil_accept_cb(struct evconnlistener *l, evutil_socket_t fd, struct sockaddr *s, 999 int socklen, void *arg) 1000 { 1001 int *p = arg; 1002 (*p)++; 1003 ++total_n_accepted; 1004 /* don't do anything with the socket; let it close when we exit() */ 1005 if (total_n_accepted >= 3 && total_connected_or_failed >= 5) 1006 event_base_loopexit(be_connect_hostname_base, 1007 NULL); 1008 } 1009 1010 struct be_conn_hostname_result { 1011 int dnserr; 1012 int what; 1013 }; 1014 1015 /* Bufferevent event callback for the connect_hostname test: remembers what 1016 * event we got. */ 1017 static void 1018 be_connect_hostname_event_cb(struct bufferevent *bev, short what, void *ctx) 1019 { 1020 struct be_conn_hostname_result *got = ctx; 1021 if (!got->what) { 1022 TT_BLATHER(("Got a bufferevent event %d", what)); 1023 got->what = what; 1024 1025 if ((what & BEV_EVENT_CONNECTED) || (what & BEV_EVENT_ERROR)) { 1026 int r; 1027 if ((r = bufferevent_socket_get_dns_error(bev))) { 1028 got->dnserr = r; 1029 TT_BLATHER(("DNS error %d: %s", r, 1030 evutil_gai_strerror(r))); 1031 } ++total_connected_or_failed; 1032 TT_BLATHER(("Got %d connections or errors.", total_connected_or_failed)); 1033 1034 if (total_n_accepted >= 3 && total_connected_or_failed >= 5) 1035 event_base_loopexit(be_connect_hostname_base, 1036 NULL); 1037 } 1038 } else { 1039 TT_FAIL(("Two events on one bufferevent. %d,%d", 1040 got->what, (int)what)); 1041 } 1042 } 1043 1044 static void 1045 test_bufferevent_connect_hostname(void *arg) 1046 { 1047 struct basic_test_data *data = arg; 1048 struct evconnlistener *listener = NULL; 1049 struct bufferevent *be1=NULL, *be2=NULL, *be3=NULL, *be4=NULL, *be5=NULL; 1050 struct be_conn_hostname_result be1_outcome={0,0}, be2_outcome={0,0}, 1051 be3_outcome={0,0}, be4_outcome={0,0}, be5_outcome={0,0}; 1052 int expect_err5; 1053 struct evdns_base *dns=NULL; 1054 struct evdns_server_port *port=NULL; 1055 struct sockaddr_in sin; 1056 int listener_port=-1; 1057 ev_uint16_t dns_port=0; 1058 int n_accept=0, n_dns=0; 1059 char buf[128]; 1060 1061 be_connect_hostname_base = data->base; 1062 1063 /* Bind an address and figure out what port it's on. */ 1064 memset(&sin, 0, sizeof(sin)); 1065 sin.sin_family = AF_INET; 1066 sin.sin_addr.s_addr = htonl(0x7f000001); /* 127.0.0.1 */ 1067 sin.sin_port = 0; 1068 listener = evconnlistener_new_bind(data->base, nil_accept_cb, 1069 &n_accept, 1070 LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_EXEC, 1071 -1, (struct sockaddr *)&sin, sizeof(sin)); 1072 tt_assert(listener); 1073 listener_port = regress_get_socket_port( 1074 evconnlistener_get_fd(listener)); 1075 1076 port = regress_get_dnsserver(data->base, &dns_port, NULL, 1077 be_getaddrinfo_server_cb, &n_dns); 1078 tt_assert(port); 1079 tt_int_op(dns_port, >=, 0); 1080 1081 /* Start an evdns_base that uses the server as its resolver. */ 1082 dns = evdns_base_new(data->base, 0); 1083 evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)dns_port); 1084 evdns_base_nameserver_ip_add(dns, buf); 1085 1086 /* Now, finally, at long last, launch the bufferevents. One should do 1087 * a failing lookup IP, one should do a successful lookup by IP, 1088 * and one should do a successful lookup by hostname. */ 1089 be1 = bufferevent_socket_new(data->base, -1, BEV_OPT_CLOSE_ON_FREE); 1090 be2 = bufferevent_socket_new(data->base, -1, BEV_OPT_CLOSE_ON_FREE); 1091 be3 = bufferevent_socket_new(data->base, -1, BEV_OPT_CLOSE_ON_FREE); 1092 be4 = bufferevent_socket_new(data->base, -1, BEV_OPT_CLOSE_ON_FREE); 1093 be5 = bufferevent_socket_new(data->base, -1, BEV_OPT_CLOSE_ON_FREE); 1094 1095 bufferevent_setcb(be1, NULL, NULL, be_connect_hostname_event_cb, 1096 &be1_outcome); 1097 bufferevent_setcb(be2, NULL, NULL, be_connect_hostname_event_cb, 1098 &be2_outcome); 1099 bufferevent_setcb(be3, NULL, NULL, be_connect_hostname_event_cb, 1100 &be3_outcome); 1101 bufferevent_setcb(be4, NULL, NULL, be_connect_hostname_event_cb, 1102 &be4_outcome); 1103 bufferevent_setcb(be5, NULL, NULL, be_connect_hostname_event_cb, 1104 &be5_outcome); 1105 1106 /* Launch an async resolve that will fail. */ 1107 tt_assert(!bufferevent_socket_connect_hostname(be1, dns, AF_INET, 1108 "nosuchplace.example.com", listener_port)); 1109 /* Connect to the IP without resolving. */ 1110 tt_assert(!bufferevent_socket_connect_hostname(be2, dns, AF_INET, 1111 "127.0.0.1", listener_port)); 1112 /* Launch an async resolve that will succeed. */ 1113 tt_assert(!bufferevent_socket_connect_hostname(be3, dns, AF_INET, 1114 "nobodaddy.example.com", listener_port)); 1115 /* Use the blocking resolver. This one will fail if your resolver 1116 * can't resolve localhost to 127.0.0.1 */ 1117 tt_assert(!bufferevent_socket_connect_hostname(be4, NULL, AF_INET, 1118 "localhost", listener_port)); 1119 /* Use the blocking resolver with a nonexistent hostname. */ 1120 tt_assert(!bufferevent_socket_connect_hostname(be5, NULL, AF_INET, 1121 "nonesuch.nowhere.example.com", 80)); 1122 { 1123 /* The blocking resolver will use the system nameserver, which 1124 * might tell us anything. (Yes, some twits even pretend that 1125 * example.com is real.) Let's see what answer to expect. */ 1126 struct evutil_addrinfo hints, *ai = NULL; 1127 memset(&hints, 0, sizeof(hints)); 1128 hints.ai_family = AF_INET; 1129 hints.ai_socktype = SOCK_STREAM; 1130 hints.ai_protocol = IPPROTO_TCP; 1131 expect_err5 = evutil_getaddrinfo( 1132 "nonesuch.nowhere.example.com", "80", &hints, &ai); 1133 } 1134 1135 event_base_dispatch(data->base); 1136 1137 tt_int_op(be1_outcome.what, ==, BEV_EVENT_ERROR); 1138 tt_int_op(be1_outcome.dnserr, ==, EVUTIL_EAI_NONAME); 1139 tt_int_op(be2_outcome.what, ==, BEV_EVENT_CONNECTED); 1140 tt_int_op(be2_outcome.dnserr, ==, 0); 1141 tt_int_op(be3_outcome.what, ==, BEV_EVENT_CONNECTED); 1142 tt_int_op(be3_outcome.dnserr, ==, 0); 1143 tt_int_op(be4_outcome.what, ==, BEV_EVENT_CONNECTED); 1144 tt_int_op(be4_outcome.dnserr, ==, 0); 1145 if (expect_err5) { 1146 tt_int_op(be5_outcome.what, ==, BEV_EVENT_ERROR); 1147 tt_int_op(be5_outcome.dnserr, ==, expect_err5); 1148 } 1149 1150 tt_int_op(n_accept, ==, 3); 1151 tt_int_op(n_dns, ==, 2); 1152 1153 end: 1154 if (listener) 1155 evconnlistener_free(listener); 1156 if (port) 1157 evdns_close_server_port(port); 1158 if (dns) 1159 evdns_base_free(dns, 0); 1160 if (be1) 1161 bufferevent_free(be1); 1162 if (be2) 1163 bufferevent_free(be2); 1164 if (be3) 1165 bufferevent_free(be3); 1166 if (be4) 1167 bufferevent_free(be4); 1168 if (be5) 1169 bufferevent_free(be5); 1170 } 1171 1172 1173 struct gai_outcome { 1174 int err; 1175 struct evutil_addrinfo *ai; 1176 }; 1177 1178 static int n_gai_results_pending = 0; 1179 static struct event_base *exit_base_on_no_pending_results = NULL; 1180 1181 static void 1182 gai_cb(int err, struct evutil_addrinfo *res, void *ptr) 1183 { 1184 struct gai_outcome *go = ptr; 1185 go->err = err; 1186 go->ai = res; 1187 if (--n_gai_results_pending <= 0 && exit_base_on_no_pending_results) 1188 event_base_loopexit(exit_base_on_no_pending_results, NULL); 1189 if (n_gai_results_pending < 900) 1190 TT_BLATHER(("Got an answer; expecting %d more.", 1191 n_gai_results_pending)); 1192 } 1193 1194 static void 1195 cancel_gai_cb(evutil_socket_t fd, short what, void *ptr) 1196 { 1197 struct evdns_getaddrinfo_request *r = ptr; 1198 evdns_getaddrinfo_cancel(r); 1199 } 1200 1201 static void 1202 test_getaddrinfo_async(void *arg) 1203 { 1204 struct basic_test_data *data = arg; 1205 struct evutil_addrinfo hints, *a; 1206 struct gai_outcome local_outcome; 1207 struct gai_outcome a_out[12]; 1208 int i; 1209 struct evdns_getaddrinfo_request *r; 1210 char buf[128]; 1211 struct evdns_server_port *port = NULL; 1212 ev_uint16_t dns_port = 0; 1213 int n_dns_questions = 0; 1214 struct evdns_base *dns_base; 1215 1216 memset(a_out, 0, sizeof(a_out)); 1217 memset(&local_outcome, 0, sizeof(local_outcome)); 1218 1219 dns_base = evdns_base_new(data->base, 0); 1220 tt_assert(dns_base); 1221 1222 /* for localhost */ 1223 evdns_base_load_hosts(dns_base, NULL); 1224 1225 tt_assert(! evdns_base_set_option(dns_base, "timeout", "0.3")); 1226 tt_assert(! evdns_base_set_option(dns_base, "getaddrinfo-allow-skew", "0.2")); 1227 1228 n_gai_results_pending = 10000; /* don't think about exiting yet. */ 1229 1230 /* 1. Try some cases that will never hit the asynchronous resolver. */ 1231 /* 1a. Simple case with a symbolic service name */ 1232 memset(&hints, 0, sizeof(hints)); 1233 hints.ai_family = PF_UNSPEC; 1234 hints.ai_socktype = SOCK_STREAM; 1235 memset(&local_outcome, 0, sizeof(local_outcome)); 1236 r = evdns_getaddrinfo(dns_base, "1.2.3.4", "http", 1237 &hints, gai_cb, &local_outcome); 1238 tt_assert(! r); 1239 if (!local_outcome.err) { 1240 tt_ptr_op(local_outcome.ai,!=,NULL); 1241 test_ai_eq(local_outcome.ai, "1.2.3.4:80", SOCK_STREAM, IPPROTO_TCP); 1242 evutil_freeaddrinfo(local_outcome.ai); 1243 local_outcome.ai = NULL; 1244 } else { 1245 TT_BLATHER(("Apparently we have no getservbyname.")); 1246 } 1247 1248 /* 1b. EVUTIL_AI_NUMERICHOST is set */ 1249 memset(&hints, 0, sizeof(hints)); 1250 hints.ai_family = PF_UNSPEC; 1251 hints.ai_flags = EVUTIL_AI_NUMERICHOST; 1252 memset(&local_outcome, 0, sizeof(local_outcome)); 1253 r = evdns_getaddrinfo(dns_base, "www.google.com", "80", 1254 &hints, gai_cb, &local_outcome); 1255 tt_ptr_op(r,==,NULL); 1256 tt_int_op(local_outcome.err,==,EVUTIL_EAI_NONAME); 1257 tt_ptr_op(local_outcome.ai,==,NULL); 1258 1259 /* 1c. We give a numeric address (ipv6) */ 1260 memset(&hints, 0, sizeof(hints)); 1261 memset(&local_outcome, 0, sizeof(local_outcome)); 1262 hints.ai_family = PF_UNSPEC; 1263 hints.ai_protocol = IPPROTO_TCP; 1264 r = evdns_getaddrinfo(dns_base, "f::f", "8008", 1265 &hints, gai_cb, &local_outcome); 1266 tt_assert(!r); 1267 tt_int_op(local_outcome.err,==,0); 1268 tt_assert(local_outcome.ai); 1269 tt_ptr_op(local_outcome.ai->ai_next,==,NULL); 1270 test_ai_eq(local_outcome.ai, "[f::f]:8008", SOCK_STREAM, IPPROTO_TCP); 1271 evutil_freeaddrinfo(local_outcome.ai); 1272 local_outcome.ai = NULL; 1273 1274 /* 1d. We give a numeric address (ipv4) */ 1275 memset(&hints, 0, sizeof(hints)); 1276 memset(&local_outcome, 0, sizeof(local_outcome)); 1277 hints.ai_family = PF_UNSPEC; 1278 r = evdns_getaddrinfo(dns_base, "5.6.7.8", NULL, 1279 &hints, gai_cb, &local_outcome); 1280 tt_assert(!r); 1281 tt_int_op(local_outcome.err,==,0); 1282 tt_assert(local_outcome.ai); 1283 a = ai_find_by_protocol(local_outcome.ai, IPPROTO_TCP); 1284 tt_assert(a); 1285 test_ai_eq(a, "5.6.7.8", SOCK_STREAM, IPPROTO_TCP); 1286 a = ai_find_by_protocol(local_outcome.ai, IPPROTO_UDP); 1287 tt_assert(a); 1288 test_ai_eq(a, "5.6.7.8", SOCK_DGRAM, IPPROTO_UDP); 1289 evutil_freeaddrinfo(local_outcome.ai); 1290 local_outcome.ai = NULL; 1291 1292 /* 1e. nodename is NULL (bind) */ 1293 memset(&hints, 0, sizeof(hints)); 1294 memset(&local_outcome, 0, sizeof(local_outcome)); 1295 hints.ai_family = PF_UNSPEC; 1296 hints.ai_socktype = SOCK_DGRAM; 1297 hints.ai_flags = EVUTIL_AI_PASSIVE; 1298 r = evdns_getaddrinfo(dns_base, NULL, "9090", 1299 &hints, gai_cb, &local_outcome); 1300 tt_assert(!r); 1301 tt_int_op(local_outcome.err,==,0); 1302 tt_assert(local_outcome.ai); 1303 /* we should get a v4 address of 0.0.0.0... */ 1304 a = ai_find_by_family(local_outcome.ai, PF_INET); 1305 tt_assert(a); 1306 test_ai_eq(a, "0.0.0.0:9090", SOCK_DGRAM, IPPROTO_UDP); 1307 /* ... and a v6 address of ::0 */ 1308 a = ai_find_by_family(local_outcome.ai, PF_INET6); 1309 tt_assert(a); 1310 test_ai_eq(a, "[::]:9090", SOCK_DGRAM, IPPROTO_UDP); 1311 evutil_freeaddrinfo(local_outcome.ai); 1312 local_outcome.ai = NULL; 1313 1314 /* 1f. nodename is NULL (connect) */ 1315 memset(&hints, 0, sizeof(hints)); 1316 memset(&local_outcome, 0, sizeof(local_outcome)); 1317 hints.ai_family = PF_UNSPEC; 1318 hints.ai_socktype = SOCK_STREAM; 1319 r = evdns_getaddrinfo(dns_base, NULL, "2", 1320 &hints, gai_cb, &local_outcome); 1321 tt_assert(!r); 1322 tt_int_op(local_outcome.err,==,0); 1323 tt_assert(local_outcome.ai); 1324 /* we should get a v4 address of 127.0.0.1 .... */ 1325 a = ai_find_by_family(local_outcome.ai, PF_INET); 1326 tt_assert(a); 1327 test_ai_eq(a, "127.0.0.1:2", SOCK_STREAM, IPPROTO_TCP); 1328 /* ... and a v6 address of ::1 */ 1329 a = ai_find_by_family(local_outcome.ai, PF_INET6); 1330 tt_assert(a); 1331 test_ai_eq(a, "[::1]:2", SOCK_STREAM, IPPROTO_TCP); 1332 evutil_freeaddrinfo(local_outcome.ai); 1333 local_outcome.ai = NULL; 1334 1335 /* 1g. We find localhost immediately. (pf_unspec) */ 1336 memset(&hints, 0, sizeof(hints)); 1337 memset(&local_outcome, 0, sizeof(local_outcome)); 1338 hints.ai_family = PF_UNSPEC; 1339 hints.ai_socktype = SOCK_STREAM; 1340 r = evdns_getaddrinfo(dns_base, "LOCALHOST", "80", 1341 &hints, gai_cb, &local_outcome); 1342 tt_assert(!r); 1343 tt_int_op(local_outcome.err,==,0); 1344 tt_assert(local_outcome.ai); 1345 /* we should get a v4 address of 127.0.0.1 .... */ 1346 a = ai_find_by_family(local_outcome.ai, PF_INET); 1347 tt_assert(a); 1348 test_ai_eq(a, "127.0.0.1:80", SOCK_STREAM, IPPROTO_TCP); 1349 /* ... and a v6 address of ::1 */ 1350 a = ai_find_by_family(local_outcome.ai, PF_INET6); 1351 tt_assert(a); 1352 test_ai_eq(a, "[::1]:80", SOCK_STREAM, IPPROTO_TCP); 1353 evutil_freeaddrinfo(local_outcome.ai); 1354 local_outcome.ai = NULL; 1355 1356 /* 1g. We find localhost immediately. (pf_inet6) */ 1357 memset(&hints, 0, sizeof(hints)); 1358 memset(&local_outcome, 0, sizeof(local_outcome)); 1359 hints.ai_family = PF_INET6; 1360 hints.ai_socktype = SOCK_STREAM; 1361 r = evdns_getaddrinfo(dns_base, "LOCALHOST", "9999", 1362 &hints, gai_cb, &local_outcome); 1363 tt_assert(! r); 1364 tt_int_op(local_outcome.err,==,0); 1365 tt_assert(local_outcome.ai); 1366 a = local_outcome.ai; 1367 test_ai_eq(a, "[::1]:9999", SOCK_STREAM, IPPROTO_TCP); 1368 tt_ptr_op(a->ai_next, ==, NULL); 1369 evutil_freeaddrinfo(local_outcome.ai); 1370 local_outcome.ai = NULL; 1371 1372 /* 2. Okay, now we can actually test the asynchronous resolver. */ 1373 /* Start a dummy local dns server... */ 1374 port = regress_get_dnsserver(data->base, &dns_port, NULL, 1375 be_getaddrinfo_server_cb, &n_dns_questions); 1376 tt_assert(port); 1377 tt_int_op(dns_port, >=, 0); 1378 /* ... and tell the evdns_base about it. */ 1379 evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", dns_port); 1380 evdns_base_nameserver_ip_add(dns_base, buf); 1381 1382 memset(&hints, 0, sizeof(hints)); 1383 hints.ai_family = PF_UNSPEC; 1384 hints.ai_socktype = SOCK_STREAM; 1385 hints.ai_flags = EVUTIL_AI_CANONNAME; 1386 /* 0: Request for both.example.com should return both addresses. */ 1387 r = evdns_getaddrinfo(dns_base, "both.example.com", "8000", 1388 &hints, gai_cb, &a_out[0]); 1389 tt_assert(r); 1390 1391 /* 1: Request for v4only.example.com should return one address. */ 1392 r = evdns_getaddrinfo(dns_base, "v4only.example.com", "8001", 1393 &hints, gai_cb, &a_out[1]); 1394 tt_assert(r); 1395 1396 /* 2: Request for v6only.example.com should return one address. */ 1397 hints.ai_flags = 0; 1398 r = evdns_getaddrinfo(dns_base, "v6only.example.com", "8002", 1399 &hints, gai_cb, &a_out[2]); 1400 tt_assert(r); 1401 1402 /* 3: PF_INET request for v4assert.example.com should not generate a 1403 * v6 request. The server will fail the test if it does. */ 1404 hints.ai_family = PF_INET; 1405 r = evdns_getaddrinfo(dns_base, "v4assert.example.com", "8003", 1406 &hints, gai_cb, &a_out[3]); 1407 tt_assert(r); 1408 1409 /* 4: PF_INET6 request for v6assert.example.com should not generate a 1410 * v4 request. The server will fail the test if it does. */ 1411 hints.ai_family = PF_INET6; 1412 r = evdns_getaddrinfo(dns_base, "v6assert.example.com", "8004", 1413 &hints, gai_cb, &a_out[4]); 1414 tt_assert(r); 1415 1416 /* 5: PF_INET request for nosuchplace.example.com should give NEXIST. */ 1417 hints.ai_family = PF_INET; 1418 r = evdns_getaddrinfo(dns_base, "nosuchplace.example.com", "8005", 1419 &hints, gai_cb, &a_out[5]); 1420 tt_assert(r); 1421 1422 /* 6: PF_UNSPEC request for nosuchplace.example.com should give NEXIST. 1423 */ 1424 hints.ai_family = PF_UNSPEC; 1425 r = evdns_getaddrinfo(dns_base, "nosuchplace.example.com", "8006", 1426 &hints, gai_cb, &a_out[6]); 1427 tt_assert(r); 1428 1429 /* 7: PF_UNSPEC request for v6timeout.example.com should give an ipv4 1430 * address only. */ 1431 hints.ai_family = PF_UNSPEC; 1432 r = evdns_getaddrinfo(dns_base, "v6timeout.example.com", "8007", 1433 &hints, gai_cb, &a_out[7]); 1434 tt_assert(r); 1435 1436 /* 8: PF_UNSPEC request for v6timeout-nonexist.example.com should give 1437 * a NEXIST */ 1438 hints.ai_family = PF_UNSPEC; 1439 r = evdns_getaddrinfo(dns_base, "v6timeout-nonexist.example.com", 1440 "8008", &hints, gai_cb, &a_out[8]); 1441 tt_assert(r); 1442 1443 /* 9: AI_ADDRCONFIG should at least not crash. Can't test it more 1444 * without knowing what kind of internet we have. */ 1445 hints.ai_flags |= EVUTIL_AI_ADDRCONFIG; 1446 r = evdns_getaddrinfo(dns_base, "both.example.com", 1447 "8009", &hints, gai_cb, &a_out[9]); 1448 tt_assert(r); 1449 1450 /* 10: PF_UNSPEC for v4timeout.example.com should give an ipv6 address 1451 * only. */ 1452 hints.ai_family = PF_UNSPEC; 1453 hints.ai_flags = 0; 1454 r = evdns_getaddrinfo(dns_base, "v4timeout.example.com", "8010", 1455 &hints, gai_cb, &a_out[10]); 1456 tt_assert(r); 1457 1458 /* 11: timeout.example.com: cancel it after 100 msec. */ 1459 r = evdns_getaddrinfo(dns_base, "all-timeout.example.com", "8011", 1460 &hints, gai_cb, &a_out[11]); 1461 tt_assert(r); 1462 { 1463 struct timeval tv; 1464 tv.tv_sec = 0; 1465 tv.tv_usec = 100*1000; /* 100 msec */ 1466 event_base_once(data->base, -1, EV_TIMEOUT, cancel_gai_cb, 1467 r, &tv); 1468 } 1469 1470 /* XXXXX There are more tests we could do, including: 1471 1472 - A test to elicit NODATA. 1473 1474 */ 1475 1476 n_gai_results_pending = 12; 1477 exit_base_on_no_pending_results = data->base; 1478 1479 event_base_dispatch(data->base); 1480 1481 /* 0: both.example.com */ 1482 tt_int_op(a_out[0].err, ==, 0); 1483 tt_assert(a_out[0].ai); 1484 tt_assert(a_out[0].ai->ai_next); 1485 tt_assert(!a_out[0].ai->ai_next->ai_next); 1486 a = ai_find_by_family(a_out[0].ai, PF_INET); 1487 tt_assert(a); 1488 test_ai_eq(a, "80.80.32.32:8000", SOCK_STREAM, IPPROTO_TCP); 1489 a = ai_find_by_family(a_out[0].ai, PF_INET6); 1490 tt_assert(a); 1491 test_ai_eq(a, "[80ff::bbbb]:8000", SOCK_STREAM, IPPROTO_TCP); 1492 tt_assert(a_out[0].ai->ai_canonname); 1493 tt_str_op(a_out[0].ai->ai_canonname, ==, "both-canonical.example.com"); 1494 1495 /* 1: v4only.example.com */ 1496 tt_int_op(a_out[1].err, ==, 0); 1497 tt_assert(a_out[1].ai); 1498 tt_assert(! a_out[1].ai->ai_next); 1499 test_ai_eq(a_out[1].ai, "18.52.86.120:8001", SOCK_STREAM, IPPROTO_TCP); 1500 tt_assert(a_out[1].ai->ai_canonname == NULL); 1501 1502 1503 /* 2: v6only.example.com */ 1504 tt_int_op(a_out[2].err, ==, 0); 1505 tt_assert(a_out[2].ai); 1506 tt_assert(! a_out[2].ai->ai_next); 1507 test_ai_eq(a_out[2].ai, "[b0b::f00d]:8002", SOCK_STREAM, IPPROTO_TCP); 1508 1509 /* 3: v4assert.example.com */ 1510 tt_int_op(a_out[3].err, ==, 0); 1511 tt_assert(a_out[3].ai); 1512 tt_assert(! a_out[3].ai->ai_next); 1513 test_ai_eq(a_out[3].ai, "18.52.86.120:8003", SOCK_STREAM, IPPROTO_TCP); 1514 1515 /* 4: v6assert.example.com */ 1516 tt_int_op(a_out[4].err, ==, 0); 1517 tt_assert(a_out[4].ai); 1518 tt_assert(! a_out[4].ai->ai_next); 1519 test_ai_eq(a_out[4].ai, "[b0b::f00d]:8004", SOCK_STREAM, IPPROTO_TCP); 1520 1521 /* 5: nosuchplace.example.com (inet) */ 1522 tt_int_op(a_out[5].err, ==, EVUTIL_EAI_NONAME); 1523 tt_assert(! a_out[5].ai); 1524 1525 /* 6: nosuchplace.example.com (unspec) */ 1526 tt_int_op(a_out[6].err, ==, EVUTIL_EAI_NONAME); 1527 tt_assert(! a_out[6].ai); 1528 1529 /* 7: v6timeout.example.com */ 1530 tt_int_op(a_out[7].err, ==, 0); 1531 tt_assert(a_out[7].ai); 1532 tt_assert(! a_out[7].ai->ai_next); 1533 test_ai_eq(a_out[7].ai, "171.205.239.1:8007", SOCK_STREAM, IPPROTO_TCP); 1534 1535 /* 8: v6timeout-nonexist.example.com */ 1536 tt_int_op(a_out[8].err, ==, EVUTIL_EAI_NONAME); 1537 tt_assert(! a_out[8].ai); 1538 1539 /* 9: both (ADDRCONFIG) */ 1540 tt_int_op(a_out[9].err, ==, 0); 1541 tt_assert(a_out[9].ai); 1542 a = ai_find_by_family(a_out[9].ai, PF_INET); 1543 if (a) 1544 test_ai_eq(a, "80.80.32.32:8009", SOCK_STREAM, IPPROTO_TCP); 1545 else 1546 tt_assert(ai_find_by_family(a_out[9].ai, PF_INET6)); 1547 a = ai_find_by_family(a_out[9].ai, PF_INET6); 1548 if (a) 1549 test_ai_eq(a, "[80ff::bbbb]:8009", SOCK_STREAM, IPPROTO_TCP); 1550 else 1551 tt_assert(ai_find_by_family(a_out[9].ai, PF_INET)); 1552 1553 /* 10: v4timeout.example.com */ 1554 tt_int_op(a_out[10].err, ==, 0); 1555 tt_assert(a_out[10].ai); 1556 tt_assert(! a_out[10].ai->ai_next); 1557 test_ai_eq(a_out[10].ai, "[a0a::ff01]:8010", SOCK_STREAM, IPPROTO_TCP); 1558 1559 /* 11: cancelled request. */ 1560 tt_int_op(a_out[11].err, ==, EVUTIL_EAI_CANCEL); 1561 tt_assert(a_out[11].ai == NULL); 1562 1563 end: 1564 if (local_outcome.ai) 1565 evutil_freeaddrinfo(local_outcome.ai); 1566 for (i=0;i<10;++i) { 1567 if (a_out[i].ai) 1568 evutil_freeaddrinfo(a_out[i].ai); 1569 } 1570 if (port) 1571 evdns_close_server_port(port); 1572 if (dns_base) 1573 evdns_base_free(dns_base, 0); 1574 } 1575 1576 struct gaic_request_status { 1577 int magic; 1578 struct event_base *base; 1579 struct evdns_base *dns_base; 1580 struct evdns_getaddrinfo_request *request; 1581 struct event cancel_event; 1582 int canceled; 1583 }; 1584 1585 #define GAIC_MAGIC 0x1234abcd 1586 1587 static int pending = 0; 1588 1589 static void 1590 gaic_cancel_request_cb(evutil_socket_t fd, short what, void *arg) 1591 { 1592 struct gaic_request_status *status = arg; 1593 1594 tt_assert(status->magic == GAIC_MAGIC); 1595 status->canceled = 1; 1596 evdns_getaddrinfo_cancel(status->request); 1597 return; 1598 end: 1599 event_base_loopexit(status->base, NULL); 1600 } 1601 1602 static void 1603 gaic_server_cb(struct evdns_server_request *req, void *arg) 1604 { 1605 ev_uint32_t answer = 0x7f000001; 1606 tt_assert(req->nquestions); 1607 evdns_server_request_add_a_reply(req, req->questions[0]->name, 1, 1608 &answer, 100); 1609 evdns_server_request_respond(req, 0); 1610 return; 1611 end: 1612 evdns_server_request_respond(req, DNS_ERR_REFUSED); 1613 } 1614 1615 1616 static void 1617 gaic_getaddrinfo_cb(int result, struct evutil_addrinfo *res, void *arg) 1618 { 1619 struct gaic_request_status *status = arg; 1620 struct event_base *base = status->base; 1621 tt_assert(status->magic == GAIC_MAGIC); 1622 1623 if (result == EVUTIL_EAI_CANCEL) { 1624 tt_assert(status->canceled); 1625 } 1626 event_del(&status->cancel_event); 1627 1628 memset(status, 0xf0, sizeof(*status)); 1629 free(status); 1630 1631 end: 1632 if (--pending <= 0) 1633 event_base_loopexit(base, NULL); 1634 } 1635 1636 static void 1637 gaic_launch(struct event_base *base, struct evdns_base *dns_base) 1638 { 1639 struct gaic_request_status *status = calloc(1,sizeof(*status)); 1640 struct timeval tv = { 0, 10000 }; 1641 status->magic = GAIC_MAGIC; 1642 status->base = base; 1643 status->dns_base = dns_base; 1644 event_assign(&status->cancel_event, base, -1, 0, gaic_cancel_request_cb, 1645 status); 1646 status->request = evdns_getaddrinfo(dns_base, 1647 "foobar.bazquux.example.com", "80", NULL, gaic_getaddrinfo_cb, 1648 status); 1649 event_add(&status->cancel_event, &tv); 1650 ++pending; 1651 } 1652 1653 #ifdef EVENT_SET_MEM_FUNCTIONS_IMPLEMENTED 1654 /* FIXME: We should move this to regress_main.c if anything else needs it.*/ 1655 1656 /* Trivial replacements for malloc/free/realloc to check for memory leaks. 1657 * Not threadsafe. */ 1658 static int allocated_chunks = 0; 1659 1660 static void * 1661 cnt_malloc(size_t sz) 1662 { 1663 allocated_chunks += 1; 1664 return malloc(sz); 1665 } 1666 1667 static void * 1668 cnt_realloc(void *old, size_t sz) 1669 { 1670 if (!old) 1671 allocated_chunks += 1; 1672 if (!sz) 1673 allocated_chunks -= 1; 1674 return realloc(old, sz); 1675 } 1676 1677 static void 1678 cnt_free(void *ptr) 1679 { 1680 allocated_chunks -= 1; 1681 free(ptr); 1682 } 1683 1684 struct testleak_env_t { 1685 struct event_base *base; 1686 struct evdns_base *dns_base; 1687 struct evdns_request *req; 1688 struct generic_dns_callback_result r; 1689 }; 1690 1691 static void * 1692 testleak_setup(const struct testcase_t *testcase) 1693 { 1694 struct testleak_env_t *env; 1695 1696 allocated_chunks = 0; 1697 event_set_mem_functions(cnt_malloc, cnt_realloc, cnt_free); 1698 if (!libevent_tests_running_in_debug_mode) 1699 event_enable_debug_mode(); 1700 1701 /* not mm_calloc: we don't want to mess with the count. */ 1702 env = calloc(1, sizeof(struct testleak_env_t)); 1703 env->base = event_base_new(); 1704 env->dns_base = evdns_base_new(env->base, 0); 1705 env->req = evdns_base_resolve_ipv4( 1706 env->dns_base, "example.com", DNS_QUERY_NO_SEARCH, 1707 generic_dns_callback, &env->r); 1708 return env; 1709 } 1710 1711 static int 1712 testleak_cleanup(const struct testcase_t *testcase, void *env_) 1713 { 1714 int ok = 0; 1715 struct testleak_env_t *env = env_; 1716 tt_assert(env); 1717 #ifdef EVENT__DISABLE_DEBUG_MODE 1718 tt_int_op(allocated_chunks, ==, 0); 1719 #else 1720 /* FIXME: that's `1' because of event_debug_map_HT_GROW */ 1721 tt_int_op(allocated_chunks, ==, 1); 1722 #endif 1723 ok = 1; 1724 end: 1725 if (env) { 1726 if (env->dns_base) 1727 evdns_base_free(env->dns_base, 0); 1728 if (env->base) 1729 event_base_free(env->base); 1730 free(env); 1731 } 1732 return ok; 1733 } 1734 1735 static struct testcase_setup_t testleak_funcs = { 1736 testleak_setup, testleak_cleanup 1737 }; 1738 1739 static void 1740 test_dbg_leak_cancel(void *env_) 1741 { 1742 /* cancel, loop, free/dns, free/base */ 1743 struct testleak_env_t *env = env_; 1744 int send_err_shutdown = 1; 1745 evdns_cancel_request(env->dns_base, env->req); 1746 env->req = 0; 1747 1748 /* `req` is freed in callback, that's why one loop is required. */ 1749 event_base_loop(env->base, EVLOOP_NONBLOCK); 1750 1751 /* send_err_shutdown means nothing as soon as our request is 1752 * already canceled */ 1753 evdns_base_free(env->dns_base, send_err_shutdown); 1754 env->dns_base = 0; 1755 event_base_free(env->base); 1756 env->base = 0; 1757 } 1758 1759 static void 1760 dbg_leak_resume(void *env_, int cancel, int send_err_shutdown) 1761 { 1762 /* cancel, loop, free/dns, free/base */ 1763 struct testleak_env_t *env = env_; 1764 if (cancel) { 1765 evdns_cancel_request(env->dns_base, env->req); 1766 tt_assert(!evdns_base_resume(env->dns_base)); 1767 } else { 1768 /* TODO: No nameservers, request can't be processed, must be errored */ 1769 tt_assert(!evdns_base_resume(env->dns_base)); 1770 } 1771 1772 /** 1773 * Because we don't cancel request, 1774 * and want our callback to recieve DNS_ERR_SHUTDOWN, 1775 * we use deferred callback, and there was 1776 * - one extra malloc(), 1777 * @see reply_schedule_callback() 1778 * - and one missing free 1779 * @see request_finished() (req->handle->pending_cb = 1) 1780 * than we don't need to count in testleak_cleanup() 1781 * 1782 * So just decrement allocated_chunks to 2, 1783 * like we already take care about it. 1784 */ 1785 if (!cancel && send_err_shutdown) { 1786 allocated_chunks -= 2; 1787 } 1788 1789 event_base_loop(env->base, EVLOOP_NONBLOCK); 1790 1791 end: 1792 evdns_base_free(env->dns_base, send_err_shutdown); 1793 env->dns_base = 0; 1794 event_base_free(env->base); 1795 env->base = 0; 1796 } 1797 1798 #define IMPL_DBG_LEAK_RESUME(name, cancel, send_err_shutdown) \ 1799 static void \ 1800 test_dbg_leak_##name##_(void *env_) \ 1801 { \ 1802 dbg_leak_resume(env_, cancel, send_err_shutdown); \ 1803 } 1804 IMPL_DBG_LEAK_RESUME(resume, 0, 0) 1805 IMPL_DBG_LEAK_RESUME(cancel_and_resume, 1, 0) 1806 IMPL_DBG_LEAK_RESUME(resume_send_err, 0, 1) 1807 IMPL_DBG_LEAK_RESUME(cancel_and_resume_send_err, 1, 1) 1808 1809 static void 1810 test_dbg_leak_shutdown(void *env_) 1811 { 1812 /* free/dns, loop, free/base */ 1813 struct testleak_env_t *env = env_; 1814 int send_err_shutdown = 1; 1815 1816 /* `req` is freed both with `send_err_shutdown` and without it, 1817 * the only difference is `evdns_callback` call */ 1818 env->req = 0; 1819 1820 evdns_base_free(env->dns_base, send_err_shutdown); 1821 env->dns_base = 0; 1822 1823 /* `req` is freed in callback, that's why one loop is required */ 1824 event_base_loop(env->base, EVLOOP_NONBLOCK); 1825 event_base_free(env->base); 1826 env->base = 0; 1827 } 1828 #endif 1829 1830 static void 1831 test_getaddrinfo_async_cancel_stress(void *ptr) 1832 { 1833 struct event_base *base; 1834 struct evdns_base *dns_base = NULL; 1835 struct evdns_server_port *server = NULL; 1836 evutil_socket_t fd = -1; 1837 struct sockaddr_in sin; 1838 struct sockaddr_storage ss; 1839 ev_socklen_t slen; 1840 int i; 1841 1842 base = event_base_new(); 1843 dns_base = evdns_base_new(base, 0); 1844 1845 memset(&sin, 0, sizeof(sin)); 1846 sin.sin_family = AF_INET; 1847 sin.sin_port = 0; 1848 sin.sin_addr.s_addr = htonl(0x7f000001); 1849 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 1850 tt_abort_perror("socket"); 1851 } 1852 evutil_make_socket_nonblocking(fd); 1853 if (bind(fd, (struct sockaddr*)&sin, sizeof(sin))<0) { 1854 tt_abort_perror("bind"); 1855 } 1856 server = evdns_add_server_port_with_base(base, fd, 0, gaic_server_cb, 1857 base); 1858 1859 memset(&ss, 0, sizeof(ss)); 1860 slen = sizeof(ss); 1861 if (getsockname(fd, (struct sockaddr*)&ss, &slen)<0) { 1862 tt_abort_perror("getsockname"); 1863 } 1864 evdns_base_nameserver_sockaddr_add(dns_base, 1865 (struct sockaddr*)&ss, slen, 0); 1866 1867 for (i = 0; i < 1000; ++i) { 1868 gaic_launch(base, dns_base); 1869 } 1870 1871 event_base_dispatch(base); 1872 1873 end: 1874 if (dns_base) 1875 evdns_base_free(dns_base, 1); 1876 if (server) 1877 evdns_close_server_port(server); 1878 if (fd >= 0) 1879 evutil_closesocket(fd); 1880 } 1881 1882 1883 #define DNS_LEGACY(name, flags) \ 1884 { #name, run_legacy_test_fn, flags|TT_LEGACY, &legacy_setup, \ 1885 dns_##name } 1886 1887 struct testcase_t dns_testcases[] = { 1888 DNS_LEGACY(server, TT_FORK|TT_NEED_BASE), 1889 DNS_LEGACY(gethostbyname, TT_FORK|TT_NEED_BASE|TT_NEED_DNS|TT_OFF_BY_DEFAULT), 1890 DNS_LEGACY(gethostbyname6, TT_FORK|TT_NEED_BASE|TT_NEED_DNS|TT_OFF_BY_DEFAULT), 1891 DNS_LEGACY(gethostbyaddr, TT_FORK|TT_NEED_BASE|TT_NEED_DNS|TT_OFF_BY_DEFAULT), 1892 { "resolve_reverse", dns_resolve_reverse, TT_FORK|TT_OFF_BY_DEFAULT, NULL, NULL }, 1893 { "search", dns_search_test, TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, 1894 { "search_cancel", dns_search_cancel_test, 1895 TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, 1896 { "retry", dns_retry_test, TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, NULL }, 1897 { "reissue", dns_reissue_test, TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, NULL }, 1898 { "inflight", dns_inflight_test, TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, 1899 { "bufferevent_connect_hostname", test_bufferevent_connect_hostname, 1900 TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, 1901 1902 { "getaddrinfo_async", test_getaddrinfo_async, 1903 TT_FORK|TT_NEED_BASE, &basic_setup, (char*)"" }, 1904 { "getaddrinfo_cancel_stress", test_getaddrinfo_async_cancel_stress, 1905 TT_FORK, NULL, NULL }, 1906 1907 #ifdef EVENT_SET_MEM_FUNCTIONS_IMPLEMENTED 1908 { "leak_shutdown", test_dbg_leak_shutdown, TT_FORK, &testleak_funcs, NULL }, 1909 { "leak_cancel", test_dbg_leak_cancel, TT_FORK, &testleak_funcs, NULL }, 1910 1911 { "leak_resume", test_dbg_leak_resume_, TT_FORK, &testleak_funcs, NULL }, 1912 { "leak_cancel_and_resume", test_dbg_leak_cancel_and_resume_, 1913 TT_FORK, &testleak_funcs, NULL }, 1914 { "leak_resume_send_err", test_dbg_leak_resume_send_err_, 1915 TT_FORK, &testleak_funcs, NULL }, 1916 { "leak_cancel_and_resume_send_err", test_dbg_leak_cancel_and_resume_send_err_, 1917 TT_FORK, &testleak_funcs, NULL }, 1918 #endif 1919 1920 END_OF_TESTCASES 1921 }; 1922 1923