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