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