1 /* $NetBSD: regress_dns.c,v 1.6 2016/01/08 21:35:41 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 struct sockaddr_storage ss2; 413 int slen2; 414 415 memset(&ss2, 0, sizeof(ss2)); 416 417 slen2 = evdns_base_get_nameserver_addr(base, 0, (struct sockaddr *)&ss2, 3); 418 tt_int_op(slen2, ==, slen); 419 tt_int_op(ss2.ss_family, ==, 0); 420 slen2 = evdns_base_get_nameserver_addr(base, 0, (struct sockaddr *)&ss2, sizeof(ss2)); 421 tt_int_op(slen2, ==, slen); 422 tt_mem_op(&ss2, ==, &ss, slen); 423 424 slen2 = evdns_base_get_nameserver_addr(base, 1, (struct sockaddr *)&ss2, sizeof(ss2)); 425 tt_int_op(-1, ==, slen2); 426 } 427 428 /* Send some queries. */ 429 evdns_base_resolve_ipv4(base, "zz.example.com", DNS_QUERY_NO_SEARCH, 430 dns_server_gethostbyname_cb, NULL); 431 evdns_base_resolve_ipv6(base, "zz.example.com", DNS_QUERY_NO_SEARCH, 432 dns_server_gethostbyname_cb, NULL); 433 resolve_addr.s_addr = htonl(0xc0a80b0bUL); /* 192.168.11.11 */ 434 evdns_base_resolve_reverse(base, &resolve_addr, 0, 435 dns_server_gethostbyname_cb, NULL); 436 memcpy(resolve_addr6.s6_addr, 437 "\xff\xf0\x00\x00\x00\x00\xaa\xaa" 438 "\x11\x11\x00\x00\x00\x00\xef\xef", 16); 439 evdns_base_resolve_reverse_ipv6(base, &resolve_addr6, 0, 440 dns_server_gethostbyname_cb, (void*)6); 441 442 req = evdns_base_resolve_ipv4(base, 443 "drop.example.com", DNS_QUERY_NO_SEARCH, 444 dns_server_gethostbyname_cb, (void*)(char*)90909); 445 446 evdns_cancel_request(base, req); 447 448 event_dispatch(); 449 450 tt_assert(dns_got_cancel); 451 test_ok = dns_ok; 452 453 end: 454 if (port) 455 evdns_close_server_port(port); 456 if (sock >= 0) 457 evutil_closesocket(sock); 458 if (base) 459 evdns_base_free(base, 0); 460 } 461 462 static int n_replies_left; 463 static struct event_base *exit_base; 464 static struct evdns_server_port *exit_port; 465 466 struct generic_dns_callback_result { 467 int result; 468 char type; 469 int count; 470 int ttl; 471 size_t addrs_len; 472 void *addrs; 473 char addrs_buf[256]; 474 }; 475 476 static void 477 generic_dns_callback(int result, char type, int count, int ttl, void *addresses, 478 void *arg) 479 { 480 size_t len; 481 struct generic_dns_callback_result *res = arg; 482 res->result = result; 483 res->type = type; 484 res->count = count; 485 res->ttl = ttl; 486 487 if (type == DNS_IPv4_A) 488 len = count * 4; 489 else if (type == DNS_IPv6_AAAA) 490 len = count * 16; 491 else if (type == DNS_PTR) 492 len = strlen(addresses)+1; 493 else { 494 res->addrs_len = len = 0; 495 res->addrs = NULL; 496 } 497 if (len) { 498 res->addrs_len = len; 499 if (len > 256) 500 len = 256; 501 memcpy(res->addrs_buf, addresses, len); 502 res->addrs = res->addrs_buf; 503 } 504 505 --n_replies_left; 506 if (n_replies_left == 0) { 507 if (exit_port) { 508 evdns_close_server_port(exit_port); 509 exit_port = NULL; 510 } else 511 event_base_loopexit(exit_base, NULL); 512 } 513 } 514 515 static struct regress_dns_server_table search_table[] = { 516 { "host.a.example.com", "err", "3", 0 }, 517 { "host.b.example.com", "err", "3", 0 }, 518 { "host.c.example.com", "A", "11.22.33.44", 0 }, 519 { "host2.a.example.com", "err", "3", 0 }, 520 { "host2.b.example.com", "A", "200.100.0.100", 0 }, 521 { "host2.c.example.com", "err", "3", 0 }, 522 { "hostn.a.example.com", "errsoa", "0", 0 }, 523 { "hostn.b.example.com", "errsoa", "3", 0 }, 524 { "hostn.c.example.com", "err", "0", 0 }, 525 526 { "host", "err", "3", 0 }, 527 { "host2", "err", "3", 0 }, 528 { "*", "err", "3", 0 }, 529 { NULL, NULL, NULL, 0 } 530 }; 531 532 static void 533 dns_search_test(void *arg) 534 { 535 struct basic_test_data *data = arg; 536 struct event_base *base = data->base; 537 struct evdns_base *dns = NULL; 538 ev_uint16_t portnum = 0; 539 char buf[64]; 540 541 struct generic_dns_callback_result r[8]; 542 543 tt_assert(regress_dnsserver(base, &portnum, search_table)); 544 evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum); 545 546 dns = evdns_base_new(base, 0); 547 tt_assert(!evdns_base_nameserver_ip_add(dns, buf)); 548 549 evdns_base_search_add(dns, "a.example.com"); 550 evdns_base_search_add(dns, "b.example.com"); 551 evdns_base_search_add(dns, "c.example.com"); 552 553 n_replies_left = sizeof(r)/sizeof(r[0]); 554 exit_base = base; 555 556 evdns_base_resolve_ipv4(dns, "host", 0, generic_dns_callback, &r[0]); 557 evdns_base_resolve_ipv4(dns, "host2", 0, generic_dns_callback, &r[1]); 558 evdns_base_resolve_ipv4(dns, "host", DNS_NO_SEARCH, generic_dns_callback, &r[2]); 559 evdns_base_resolve_ipv4(dns, "host2", DNS_NO_SEARCH, generic_dns_callback, &r[3]); 560 evdns_base_resolve_ipv4(dns, "host3", 0, generic_dns_callback, &r[4]); 561 evdns_base_resolve_ipv4(dns, "hostn.a.example.com", DNS_NO_SEARCH, generic_dns_callback, &r[5]); 562 evdns_base_resolve_ipv4(dns, "hostn.b.example.com", DNS_NO_SEARCH, generic_dns_callback, &r[6]); 563 evdns_base_resolve_ipv4(dns, "hostn.c.example.com", DNS_NO_SEARCH, generic_dns_callback, &r[7]); 564 565 event_base_dispatch(base); 566 567 tt_int_op(r[0].type, ==, DNS_IPv4_A); 568 tt_int_op(r[0].count, ==, 1); 569 tt_int_op(((ev_uint32_t*)r[0].addrs)[0], ==, htonl(0x0b16212c)); 570 tt_int_op(r[1].type, ==, DNS_IPv4_A); 571 tt_int_op(r[1].count, ==, 1); 572 tt_int_op(((ev_uint32_t*)r[1].addrs)[0], ==, htonl(0xc8640064)); 573 tt_int_op(r[2].result, ==, DNS_ERR_NOTEXIST); 574 tt_int_op(r[3].result, ==, DNS_ERR_NOTEXIST); 575 tt_int_op(r[4].result, ==, DNS_ERR_NOTEXIST); 576 tt_int_op(r[5].result, ==, DNS_ERR_NODATA); 577 tt_int_op(r[5].ttl, ==, 42); 578 tt_int_op(r[6].result, ==, DNS_ERR_NOTEXIST); 579 tt_int_op(r[6].ttl, ==, 42); 580 tt_int_op(r[7].result, ==, DNS_ERR_NODATA); 581 tt_int_op(r[7].ttl, ==, 0); 582 583 end: 584 if (dns) 585 evdns_base_free(dns, 0); 586 587 regress_clean_dnsserver(); 588 } 589 590 static int request_count = 0; 591 static struct evdns_request *current_req = NULL; 592 593 static void 594 search_cancel_server_cb(struct evdns_server_request *req, void *data) 595 { 596 const char *question; 597 598 if (req->nquestions != 1) 599 TT_DIE(("Only handling one question at a time; got %d", 600 req->nquestions)); 601 602 question = req->questions[0]->name; 603 604 TT_BLATHER(("got question, %s", question)); 605 606 tt_assert(request_count > 0); 607 tt_assert(!evdns_server_request_respond(req, 3)); 608 609 if (!--request_count) 610 evdns_cancel_request(NULL, current_req); 611 612 end: 613 ; 614 } 615 616 static void 617 dns_search_cancel_test(void *arg) 618 { 619 struct basic_test_data *data = arg; 620 struct event_base *base = data->base; 621 struct evdns_base *dns = NULL; 622 struct evdns_server_port *port = NULL; 623 ev_uint16_t portnum = 0; 624 struct generic_dns_callback_result r1; 625 char buf[64]; 626 627 port = regress_get_dnsserver(base, &portnum, NULL, 628 search_cancel_server_cb, NULL); 629 tt_assert(port); 630 evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum); 631 632 dns = evdns_base_new(base, 0); 633 tt_assert(!evdns_base_nameserver_ip_add(dns, buf)); 634 635 evdns_base_search_add(dns, "a.example.com"); 636 evdns_base_search_add(dns, "b.example.com"); 637 evdns_base_search_add(dns, "c.example.com"); 638 evdns_base_search_add(dns, "d.example.com"); 639 640 exit_base = base; 641 request_count = 3; 642 n_replies_left = 1; 643 644 current_req = evdns_base_resolve_ipv4(dns, "host", 0, 645 generic_dns_callback, &r1); 646 event_base_dispatch(base); 647 648 tt_int_op(r1.result, ==, DNS_ERR_CANCEL); 649 650 end: 651 if (port) 652 evdns_close_server_port(port); 653 if (dns) 654 evdns_base_free(dns, 0); 655 } 656 657 static void 658 fail_server_cb(struct evdns_server_request *req, void *data) 659 { 660 const char *question; 661 int *count = data; 662 struct in_addr in; 663 664 /* Drop the first N requests that we get. */ 665 if (*count > 0) { 666 --*count; 667 tt_want(! evdns_server_request_drop(req)); 668 return; 669 } 670 671 if (req->nquestions != 1) 672 TT_DIE(("Only handling one question at a time; got %d", 673 req->nquestions)); 674 675 question = req->questions[0]->name; 676 677 if (!evutil_ascii_strcasecmp(question, "google.com")) { 678 /* Detect a probe, and get out of the loop. */ 679 event_base_loopexit(exit_base, NULL); 680 } 681 682 tt_assert(evutil_inet_pton(AF_INET, "16.32.64.128", &in)); 683 evdns_server_request_add_a_reply(req, question, 1, &in.s_addr, 684 100); 685 tt_assert(! evdns_server_request_respond(req, 0)) 686 return; 687 end: 688 tt_want(! evdns_server_request_drop(req)); 689 } 690 691 static void 692 dns_retry_test_impl(void *arg, int flags) 693 { 694 struct basic_test_data *data = arg; 695 struct event_base *base = data->base; 696 struct evdns_server_port *port = NULL; 697 struct evdns_base *dns = NULL; 698 int drop_count = 2; 699 ev_uint16_t portnum = 0; 700 char buf[64]; 701 702 struct generic_dns_callback_result r1; 703 704 port = regress_get_dnsserver(base, &portnum, NULL, 705 fail_server_cb, &drop_count); 706 tt_assert(port); 707 evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum); 708 709 dns = evdns_base_new(base, flags); 710 tt_assert(!evdns_base_nameserver_ip_add(dns, buf)); 711 tt_assert(! evdns_base_set_option(dns, "timeout", "0.2")); 712 tt_assert(! evdns_base_set_option(dns, "max-timeouts:", "10")); 713 tt_assert(! evdns_base_set_option(dns, "initial-probe-timeout", "0.1")); 714 715 evdns_base_resolve_ipv4(dns, "host.example.com", 0, 716 generic_dns_callback, &r1); 717 718 n_replies_left = 1; 719 exit_base = base; 720 721 event_base_dispatch(base); 722 723 tt_int_op(drop_count, ==, 0); 724 725 tt_int_op(r1.type, ==, DNS_IPv4_A); 726 tt_int_op(r1.count, ==, 1); 727 tt_int_op(((ev_uint32_t*)r1.addrs)[0], ==, htonl(0x10204080)); 728 729 /* Now try again, but this time have the server get treated as 730 * failed, so we can send it a test probe. */ 731 drop_count = 4; 732 tt_assert(! evdns_base_set_option(dns, "max-timeouts:", "2")); 733 tt_assert(! evdns_base_set_option(dns, "attempts:", "3")); 734 memset(&r1, 0, sizeof(r1)); 735 736 evdns_base_resolve_ipv4(dns, "host.example.com", 0, 737 generic_dns_callback, &r1); 738 739 n_replies_left = 2; 740 741 /* This will run until it answers the "google.com" probe request. */ 742 event_base_dispatch(base); 743 744 /* We'll treat the server as failed here. */ 745 tt_int_op(r1.result, ==, DNS_ERR_TIMEOUT); 746 747 /* It should work this time. */ 748 tt_int_op(drop_count, ==, 0); 749 evdns_base_resolve_ipv4(dns, "host.example.com", 0, 750 generic_dns_callback, &r1); 751 752 event_base_dispatch(base); 753 tt_int_op(r1.result, ==, DNS_ERR_NONE); 754 tt_int_op(r1.type, ==, DNS_IPv4_A); 755 tt_int_op(r1.count, ==, 1); 756 tt_int_op(((ev_uint32_t*)r1.addrs)[0], ==, htonl(0x10204080)); 757 758 end: 759 if (dns) 760 evdns_base_free(dns, 0); 761 if (port) 762 evdns_close_server_port(port); 763 } 764 static void 765 dns_retry_test(void *arg) 766 { 767 dns_retry_test_impl(arg, 0); 768 } 769 static void 770 dns_retry_disable_when_inactive_test(void *arg) 771 { 772 dns_retry_test_impl(arg, EVDNS_BASE_DISABLE_WHEN_INACTIVE); 773 } 774 775 static struct regress_dns_server_table internal_error_table[] = { 776 /* Error 4 (NOTIMPL) makes us reissue the request to another server 777 if we can. 778 779 XXXX we should reissue under a much wider set of circumstances! 780 */ 781 { "foof.example.com", "err", "4", 0 }, 782 { NULL, NULL, NULL, 0 } 783 }; 784 785 static struct regress_dns_server_table reissue_table[] = { 786 { "foof.example.com", "A", "240.15.240.15", 0 }, 787 { NULL, NULL, NULL, 0 } 788 }; 789 790 static void 791 dns_reissue_test_impl(void *arg, int flags) 792 { 793 struct basic_test_data *data = arg; 794 struct event_base *base = data->base; 795 struct evdns_server_port *port1 = NULL, *port2 = NULL; 796 struct evdns_base *dns = NULL; 797 struct generic_dns_callback_result r1; 798 ev_uint16_t portnum1 = 0, portnum2=0; 799 char buf1[64], buf2[64]; 800 801 port1 = regress_get_dnsserver(base, &portnum1, NULL, 802 regress_dns_server_cb, internal_error_table); 803 tt_assert(port1); 804 port2 = regress_get_dnsserver(base, &portnum2, NULL, 805 regress_dns_server_cb, reissue_table); 806 tt_assert(port2); 807 evutil_snprintf(buf1, sizeof(buf1), "127.0.0.1:%d", (int)portnum1); 808 evutil_snprintf(buf2, sizeof(buf2), "127.0.0.1:%d", (int)portnum2); 809 810 dns = evdns_base_new(base, flags); 811 tt_assert(!evdns_base_nameserver_ip_add(dns, buf1)); 812 tt_assert(! evdns_base_set_option(dns, "timeout:", "0.3")); 813 tt_assert(! evdns_base_set_option(dns, "max-timeouts:", "2")); 814 tt_assert(! evdns_base_set_option(dns, "attempts:", "5")); 815 816 memset(&r1, 0, sizeof(r1)); 817 evdns_base_resolve_ipv4(dns, "foof.example.com", 0, 818 generic_dns_callback, &r1); 819 820 /* Add this after, so that we are sure to get a reissue. */ 821 tt_assert(!evdns_base_nameserver_ip_add(dns, buf2)); 822 823 n_replies_left = 1; 824 exit_base = base; 825 826 event_base_dispatch(base); 827 tt_int_op(r1.result, ==, DNS_ERR_NONE); 828 tt_int_op(r1.type, ==, DNS_IPv4_A); 829 tt_int_op(r1.count, ==, 1); 830 tt_int_op(((ev_uint32_t*)r1.addrs)[0], ==, htonl(0xf00ff00f)); 831 832 /* Make sure we dropped at least once. */ 833 tt_int_op(internal_error_table[0].seen, >, 0); 834 835 end: 836 if (dns) 837 evdns_base_free(dns, 0); 838 if (port1) 839 evdns_close_server_port(port1); 840 if (port2) 841 evdns_close_server_port(port2); 842 } 843 static void 844 dns_reissue_test(void *arg) 845 { 846 dns_reissue_test_impl(arg, 0); 847 } 848 static void 849 dns_reissue_disable_when_inactive_test(void *arg) 850 { 851 dns_reissue_test_impl(arg, EVDNS_BASE_DISABLE_WHEN_INACTIVE); 852 } 853 854 #if 0 855 static void 856 dumb_bytes_fn(char *p, size_t n) 857 { 858 unsigned i; 859 /* This gets us 6 bits of entropy per transaction ID, which means we 860 * will have probably have collisions and need to pick again. */ 861 for (i=0;i<n;++i) 862 p[i] = (char)(rand() & 7); 863 } 864 #endif 865 866 static void 867 dns_inflight_test_impl(void *arg, int flags) 868 { 869 struct basic_test_data *data = arg; 870 struct event_base *base = data->base; 871 struct evdns_base *dns = NULL; 872 struct evdns_server_port *dns_port = NULL; 873 ev_uint16_t portnum = 0; 874 char buf[64]; 875 int disable_when_inactive = flags & EVDNS_BASE_DISABLE_WHEN_INACTIVE; 876 877 struct generic_dns_callback_result r[20]; 878 int i; 879 880 dns_port = regress_get_dnsserver(base, &portnum, NULL, 881 regress_dns_server_cb, reissue_table); 882 tt_assert(dns_port); 883 if (disable_when_inactive) { 884 exit_port = dns_port; 885 } 886 887 evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum); 888 889 dns = evdns_base_new(base, flags); 890 tt_assert(!evdns_base_nameserver_ip_add(dns, buf)); 891 tt_assert(! evdns_base_set_option(dns, "max-inflight:", "3")); 892 tt_assert(! evdns_base_set_option(dns, "randomize-case:", "0")); 893 894 for (i=0;i<20;++i) 895 evdns_base_resolve_ipv4(dns, "foof.example.com", 0, generic_dns_callback, &r[i]); 896 897 n_replies_left = 20; 898 exit_base = base; 899 900 event_base_dispatch(base); 901 902 for (i=0;i<20;++i) { 903 tt_int_op(r[i].type, ==, DNS_IPv4_A); 904 tt_int_op(r[i].count, ==, 1); 905 tt_int_op(((ev_uint32_t*)r[i].addrs)[0], ==, htonl(0xf00ff00f)); 906 } 907 908 end: 909 if (dns) 910 evdns_base_free(dns, 0); 911 if (exit_port) { 912 evdns_close_server_port(exit_port); 913 exit_port = NULL; 914 } else if (! disable_when_inactive) { 915 evdns_close_server_port(dns_port); 916 } 917 } 918 919 static void 920 dns_inflight_test(void *arg) 921 { 922 dns_inflight_test_impl(arg, 0); 923 } 924 925 static void 926 dns_disable_when_inactive_test(void *arg) 927 { 928 dns_inflight_test_impl(arg, EVDNS_BASE_DISABLE_WHEN_INACTIVE); 929 } 930 931 static void 932 dns_disable_when_inactive_no_ns_test(void *arg) 933 { 934 struct basic_test_data *data = arg; 935 struct event_base *base = data->base, *inactive_base; 936 struct evdns_base *dns = NULL; 937 ev_uint16_t portnum = 0; 938 char buf[64]; 939 struct generic_dns_callback_result r; 940 941 inactive_base = event_base_new(); 942 tt_assert(inactive_base); 943 944 /** Create dns server with inactive base, to avoid replying to clients */ 945 tt_assert(regress_dnsserver(inactive_base, &portnum, search_table)); 946 evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum); 947 948 dns = evdns_base_new(base, EVDNS_BASE_DISABLE_WHEN_INACTIVE); 949 tt_assert(!evdns_base_nameserver_ip_add(dns, buf)); 950 tt_assert(! evdns_base_set_option(dns, "timeout:", "0.1")); 951 952 evdns_base_resolve_ipv4(dns, "foof.example.com", 0, generic_dns_callback, &r); 953 n_replies_left = 1; 954 exit_base = base; 955 956 event_base_dispatch(base); 957 958 tt_int_op(n_replies_left, ==, 0); 959 960 tt_int_op(r.result, ==, DNS_ERR_TIMEOUT); 961 tt_int_op(r.count, ==, 0); 962 tt_ptr_op(r.addrs, ==, NULL); 963 964 end: 965 if (dns) 966 evdns_base_free(dns, 0); 967 regress_clean_dnsserver(); 968 if (inactive_base) 969 event_base_free(inactive_base); 970 } 971 972 /* === Test for bufferevent_socket_connect_hostname */ 973 974 static int total_connected_or_failed = 0; 975 static int total_n_accepted = 0; 976 static struct event_base *be_connect_hostname_base = NULL; 977 978 /* Implements a DNS server for the connect_hostname test and the 979 * getaddrinfo_async test */ 980 static void 981 be_getaddrinfo_server_cb(struct evdns_server_request *req, void *data) 982 { 983 int i; 984 int *n_got_p=data; 985 int added_any=0; 986 ++*n_got_p; 987 988 for (i=0;i<req->nquestions;++i) { 989 const int qtype = req->questions[i]->type; 990 const int qclass = req->questions[i]->dns_question_class; 991 const char *qname = req->questions[i]->name; 992 struct in_addr ans; 993 struct in6_addr ans6; 994 memset(&ans6, 0, sizeof(ans6)); 995 996 TT_BLATHER(("Got question about %s, type=%d", qname, qtype)); 997 998 if (qtype == EVDNS_TYPE_A && 999 qclass == EVDNS_CLASS_INET && 1000 !evutil_ascii_strcasecmp(qname, "nobodaddy.example.com")) { 1001 ans.s_addr = htonl(0x7f000001); 1002 evdns_server_request_add_a_reply(req, qname, 1003 1, &ans.s_addr, 2000); 1004 added_any = 1; 1005 } else if (!evutil_ascii_strcasecmp(qname, 1006 "nosuchplace.example.com")) { 1007 /* ok, just say notfound. */ 1008 } else if (!evutil_ascii_strcasecmp(qname, 1009 "both.example.com")) { 1010 if (qtype == EVDNS_TYPE_A) { 1011 ans.s_addr = htonl(0x50502020); 1012 evdns_server_request_add_a_reply(req, qname, 1013 1, &ans.s_addr, 2000); 1014 added_any = 1; 1015 } else if (qtype == EVDNS_TYPE_AAAA) { 1016 ans6.s6_addr[0] = 0x80; 1017 ans6.s6_addr[1] = 0xff; 1018 ans6.s6_addr[14] = 0xbb; 1019 ans6.s6_addr[15] = 0xbb; 1020 evdns_server_request_add_aaaa_reply(req, qname, 1021 1, &ans6.s6_addr, 2000); 1022 added_any = 1; 1023 } 1024 evdns_server_request_add_cname_reply(req, qname, 1025 "both-canonical.example.com", 1000); 1026 } else if (!evutil_ascii_strcasecmp(qname, 1027 "v4only.example.com") || 1028 !evutil_ascii_strcasecmp(qname, "v4assert.example.com")) { 1029 if (qtype == EVDNS_TYPE_A) { 1030 ans.s_addr = htonl(0x12345678); 1031 evdns_server_request_add_a_reply(req, qname, 1032 1, &ans.s_addr, 2000); 1033 added_any = 1; 1034 } else if (!evutil_ascii_strcasecmp(qname, 1035 "v4assert.example.com")) { 1036 TT_FAIL(("Got an AAAA request for v4assert")); 1037 } 1038 } else if (!evutil_ascii_strcasecmp(qname, 1039 "v6only.example.com") || 1040 !evutil_ascii_strcasecmp(qname, "v6assert.example.com")) { 1041 if (qtype == EVDNS_TYPE_AAAA) { 1042 ans6.s6_addr[0] = 0x0b; 1043 ans6.s6_addr[1] = 0x0b; 1044 ans6.s6_addr[14] = 0xf0; 1045 ans6.s6_addr[15] = 0x0d; 1046 evdns_server_request_add_aaaa_reply(req, qname, 1047 1, &ans6.s6_addr, 2000); 1048 added_any = 1; 1049 } else if (!evutil_ascii_strcasecmp(qname, 1050 "v6assert.example.com")) { 1051 TT_FAIL(("Got a A request for v6assert")); 1052 } 1053 } else if (!evutil_ascii_strcasecmp(qname, 1054 "v6timeout.example.com")) { 1055 if (qtype == EVDNS_TYPE_A) { 1056 ans.s_addr = htonl(0xabcdef01); 1057 evdns_server_request_add_a_reply(req, qname, 1058 1, &ans.s_addr, 2000); 1059 added_any = 1; 1060 } else if (qtype == EVDNS_TYPE_AAAA) { 1061 /* Let the v6 request time out.*/ 1062 evdns_server_request_drop(req); 1063 return; 1064 } 1065 } else if (!evutil_ascii_strcasecmp(qname, 1066 "v4timeout.example.com")) { 1067 if (qtype == EVDNS_TYPE_AAAA) { 1068 ans6.s6_addr[0] = 0x0a; 1069 ans6.s6_addr[1] = 0x0a; 1070 ans6.s6_addr[14] = 0xff; 1071 ans6.s6_addr[15] = 0x01; 1072 evdns_server_request_add_aaaa_reply(req, qname, 1073 1, &ans6.s6_addr, 2000); 1074 added_any = 1; 1075 } else if (qtype == EVDNS_TYPE_A) { 1076 /* Let the v4 request time out.*/ 1077 evdns_server_request_drop(req); 1078 return; 1079 } 1080 } else if (!evutil_ascii_strcasecmp(qname, 1081 "v6timeout-nonexist.example.com")) { 1082 if (qtype == EVDNS_TYPE_A) { 1083 /* Fall through, give an nexist. */ 1084 } else if (qtype == EVDNS_TYPE_AAAA) { 1085 /* Let the v6 request time out.*/ 1086 evdns_server_request_drop(req); 1087 return; 1088 } 1089 } else if (!evutil_ascii_strcasecmp(qname, 1090 "all-timeout.example.com")) { 1091 /* drop all requests */ 1092 evdns_server_request_drop(req); 1093 return; 1094 } else { 1095 TT_GRIPE(("Got weird request for %s",qname)); 1096 } 1097 } 1098 if (added_any) { 1099 TT_BLATHER(("answering")); 1100 evdns_server_request_respond(req, 0); 1101 } else { 1102 TT_BLATHER(("saying nexist.")); 1103 evdns_server_request_respond(req, 3); 1104 } 1105 } 1106 1107 /* Implements a listener for connect_hostname test. */ 1108 static void 1109 nil_accept_cb(struct evconnlistener *l, evutil_socket_t fd, struct sockaddr *s, 1110 int socklen, void *arg) 1111 { 1112 int *p = arg; 1113 (*p)++; 1114 ++total_n_accepted; 1115 /* don't do anything with the socket; let it close when we exit() */ 1116 if (total_n_accepted >= 3 && total_connected_or_failed >= 5) 1117 event_base_loopexit(be_connect_hostname_base, 1118 NULL); 1119 } 1120 1121 struct be_conn_hostname_result { 1122 int dnserr; 1123 int what; 1124 }; 1125 1126 /* Bufferevent event callback for the connect_hostname test: remembers what 1127 * event we got. */ 1128 static void 1129 be_connect_hostname_event_cb(struct bufferevent *bev, short what, void *ctx) 1130 { 1131 struct be_conn_hostname_result *got = ctx; 1132 if (!got->what) { 1133 TT_BLATHER(("Got a bufferevent event %d", what)); 1134 got->what = what; 1135 1136 if ((what & BEV_EVENT_CONNECTED) || (what & BEV_EVENT_ERROR)) { 1137 int r; 1138 if ((r = bufferevent_socket_get_dns_error(bev))) { 1139 got->dnserr = r; 1140 TT_BLATHER(("DNS error %d: %s", r, 1141 evutil_gai_strerror(r))); 1142 } ++total_connected_or_failed; 1143 TT_BLATHER(("Got %d connections or errors.", total_connected_or_failed)); 1144 1145 if (total_n_accepted >= 3 && total_connected_or_failed >= 5) 1146 event_base_loopexit(be_connect_hostname_base, 1147 NULL); 1148 } 1149 } else { 1150 TT_FAIL(("Two events on one bufferevent. %d,%d", 1151 got->what, (int)what)); 1152 } 1153 } 1154 1155 static void 1156 test_bufferevent_connect_hostname(void *arg) 1157 { 1158 struct basic_test_data *data = arg; 1159 struct evconnlistener *listener = NULL; 1160 struct bufferevent *be1=NULL, *be2=NULL, *be3=NULL, *be4=NULL, *be5=NULL; 1161 struct be_conn_hostname_result be1_outcome={0,0}, be2_outcome={0,0}, 1162 be3_outcome={0,0}, be4_outcome={0,0}, be5_outcome={0,0}; 1163 int expect_err5; 1164 struct evdns_base *dns=NULL; 1165 struct evdns_server_port *port=NULL; 1166 struct sockaddr_in sin; 1167 int listener_port=-1; 1168 ev_uint16_t dns_port=0; 1169 int n_accept=0, n_dns=0; 1170 char buf[128]; 1171 1172 be_connect_hostname_base = data->base; 1173 1174 /* Bind an address and figure out what port it's on. */ 1175 memset(&sin, 0, sizeof(sin)); 1176 sin.sin_family = AF_INET; 1177 sin.sin_addr.s_addr = htonl(0x7f000001); /* 127.0.0.1 */ 1178 sin.sin_port = 0; 1179 listener = evconnlistener_new_bind(data->base, nil_accept_cb, 1180 &n_accept, 1181 LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_EXEC, 1182 -1, (struct sockaddr *)&sin, sizeof(sin)); 1183 tt_assert(listener); 1184 listener_port = regress_get_socket_port( 1185 evconnlistener_get_fd(listener)); 1186 1187 port = regress_get_dnsserver(data->base, &dns_port, NULL, 1188 be_getaddrinfo_server_cb, &n_dns); 1189 tt_assert(port); 1190 tt_int_op(dns_port, >=, 0); 1191 1192 /* Start an evdns_base that uses the server as its resolver. */ 1193 dns = evdns_base_new(data->base, 0); 1194 evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)dns_port); 1195 evdns_base_nameserver_ip_add(dns, buf); 1196 1197 /* Now, finally, at long last, launch the bufferevents. One should do 1198 * a failing lookup IP, one should do a successful lookup by IP, 1199 * and one should do a successful lookup by hostname. */ 1200 be1 = bufferevent_socket_new(data->base, -1, BEV_OPT_CLOSE_ON_FREE); 1201 be2 = bufferevent_socket_new(data->base, -1, BEV_OPT_CLOSE_ON_FREE); 1202 be3 = bufferevent_socket_new(data->base, -1, BEV_OPT_CLOSE_ON_FREE); 1203 be4 = bufferevent_socket_new(data->base, -1, BEV_OPT_CLOSE_ON_FREE); 1204 be5 = bufferevent_socket_new(data->base, -1, BEV_OPT_CLOSE_ON_FREE); 1205 1206 bufferevent_setcb(be1, NULL, NULL, be_connect_hostname_event_cb, 1207 &be1_outcome); 1208 bufferevent_setcb(be2, NULL, NULL, be_connect_hostname_event_cb, 1209 &be2_outcome); 1210 bufferevent_setcb(be3, NULL, NULL, be_connect_hostname_event_cb, 1211 &be3_outcome); 1212 bufferevent_setcb(be4, NULL, NULL, be_connect_hostname_event_cb, 1213 &be4_outcome); 1214 bufferevent_setcb(be5, NULL, NULL, be_connect_hostname_event_cb, 1215 &be5_outcome); 1216 1217 /* Launch an async resolve that will fail. */ 1218 tt_assert(!bufferevent_socket_connect_hostname(be1, dns, AF_INET, 1219 "nosuchplace.example.com", listener_port)); 1220 /* Connect to the IP without resolving. */ 1221 tt_assert(!bufferevent_socket_connect_hostname(be2, dns, AF_INET, 1222 "127.0.0.1", listener_port)); 1223 /* Launch an async resolve that will succeed. */ 1224 tt_assert(!bufferevent_socket_connect_hostname(be3, dns, AF_INET, 1225 "nobodaddy.example.com", listener_port)); 1226 /* Use the blocking resolver. This one will fail if your resolver 1227 * can't resolve localhost to 127.0.0.1 */ 1228 tt_assert(!bufferevent_socket_connect_hostname(be4, NULL, AF_INET, 1229 "localhost", listener_port)); 1230 /* Use the blocking resolver with a nonexistent hostname. */ 1231 tt_assert(!bufferevent_socket_connect_hostname(be5, NULL, AF_INET, 1232 "nonesuch.nowhere.example.com", 80)); 1233 { 1234 /* The blocking resolver will use the system nameserver, which 1235 * might tell us anything. (Yes, some twits even pretend that 1236 * example.com is real.) Let's see what answer to expect. */ 1237 struct evutil_addrinfo hints, *ai = NULL; 1238 memset(&hints, 0, sizeof(hints)); 1239 hints.ai_family = AF_INET; 1240 hints.ai_socktype = SOCK_STREAM; 1241 hints.ai_protocol = IPPROTO_TCP; 1242 expect_err5 = evutil_getaddrinfo( 1243 "nonesuch.nowhere.example.com", "80", &hints, &ai); 1244 } 1245 1246 event_base_dispatch(data->base); 1247 1248 tt_int_op(be1_outcome.what, ==, BEV_EVENT_ERROR); 1249 tt_int_op(be1_outcome.dnserr, ==, EVUTIL_EAI_NONAME); 1250 tt_int_op(be2_outcome.what, ==, BEV_EVENT_CONNECTED); 1251 tt_int_op(be2_outcome.dnserr, ==, 0); 1252 tt_int_op(be3_outcome.what, ==, BEV_EVENT_CONNECTED); 1253 tt_int_op(be3_outcome.dnserr, ==, 0); 1254 tt_int_op(be4_outcome.what, ==, BEV_EVENT_CONNECTED); 1255 tt_int_op(be4_outcome.dnserr, ==, 0); 1256 if (expect_err5) { 1257 tt_int_op(be5_outcome.what, ==, BEV_EVENT_ERROR); 1258 tt_int_op(be5_outcome.dnserr, ==, expect_err5); 1259 } 1260 1261 tt_int_op(n_accept, ==, 3); 1262 tt_int_op(n_dns, ==, 2); 1263 1264 end: 1265 if (listener) 1266 evconnlistener_free(listener); 1267 if (port) 1268 evdns_close_server_port(port); 1269 if (dns) 1270 evdns_base_free(dns, 0); 1271 if (be1) 1272 bufferevent_free(be1); 1273 if (be2) 1274 bufferevent_free(be2); 1275 if (be3) 1276 bufferevent_free(be3); 1277 if (be4) 1278 bufferevent_free(be4); 1279 if (be5) 1280 bufferevent_free(be5); 1281 } 1282 1283 1284 struct gai_outcome { 1285 int err; 1286 struct evutil_addrinfo *ai; 1287 }; 1288 1289 static int n_gai_results_pending = 0; 1290 static struct event_base *exit_base_on_no_pending_results = NULL; 1291 1292 static void 1293 gai_cb(int err, struct evutil_addrinfo *res, void *ptr) 1294 { 1295 struct gai_outcome *go = ptr; 1296 go->err = err; 1297 go->ai = res; 1298 if (--n_gai_results_pending <= 0 && exit_base_on_no_pending_results) 1299 event_base_loopexit(exit_base_on_no_pending_results, NULL); 1300 if (n_gai_results_pending < 900) 1301 TT_BLATHER(("Got an answer; expecting %d more.", 1302 n_gai_results_pending)); 1303 } 1304 1305 static void 1306 cancel_gai_cb(evutil_socket_t fd, short what, void *ptr) 1307 { 1308 struct evdns_getaddrinfo_request *r = ptr; 1309 evdns_getaddrinfo_cancel(r); 1310 } 1311 1312 static void 1313 test_getaddrinfo_async(void *arg) 1314 { 1315 struct basic_test_data *data = arg; 1316 struct evutil_addrinfo hints, *a; 1317 struct gai_outcome local_outcome; 1318 struct gai_outcome a_out[12]; 1319 int i; 1320 struct evdns_getaddrinfo_request *r; 1321 char buf[128]; 1322 struct evdns_server_port *port = NULL; 1323 ev_uint16_t dns_port = 0; 1324 int n_dns_questions = 0; 1325 struct evdns_base *dns_base; 1326 1327 memset(&a_out, 0, sizeof(a_out)); 1328 memset(&local_outcome, 0, sizeof(local_outcome)); 1329 1330 dns_base = evdns_base_new(data->base, 0); 1331 tt_assert(dns_base); 1332 1333 /* for localhost */ 1334 evdns_base_load_hosts(dns_base, NULL); 1335 1336 tt_assert(! evdns_base_set_option(dns_base, "timeout", "0.3")); 1337 tt_assert(! evdns_base_set_option(dns_base, "getaddrinfo-allow-skew", "0.2")); 1338 1339 n_gai_results_pending = 10000; /* don't think about exiting yet. */ 1340 1341 /* 1. Try some cases that will never hit the asynchronous resolver. */ 1342 /* 1a. Simple case with a symbolic service name */ 1343 memset(&hints, 0, sizeof(hints)); 1344 hints.ai_family = PF_UNSPEC; 1345 hints.ai_socktype = SOCK_STREAM; 1346 memset(&local_outcome, 0, sizeof(local_outcome)); 1347 r = evdns_getaddrinfo(dns_base, "1.2.3.4", "http", 1348 &hints, gai_cb, &local_outcome); 1349 tt_assert(! r); 1350 if (!local_outcome.err) { 1351 tt_ptr_op(local_outcome.ai,!=,NULL); 1352 test_ai_eq(local_outcome.ai, "1.2.3.4:80", SOCK_STREAM, IPPROTO_TCP); 1353 evutil_freeaddrinfo(local_outcome.ai); 1354 local_outcome.ai = NULL; 1355 } else { 1356 TT_BLATHER(("Apparently we have no getservbyname.")); 1357 } 1358 1359 /* 1b. EVUTIL_AI_NUMERICHOST is set */ 1360 memset(&hints, 0, sizeof(hints)); 1361 hints.ai_family = PF_UNSPEC; 1362 hints.ai_flags = EVUTIL_AI_NUMERICHOST; 1363 memset(&local_outcome, 0, sizeof(local_outcome)); 1364 r = evdns_getaddrinfo(dns_base, "www.google.com", "80", 1365 &hints, gai_cb, &local_outcome); 1366 tt_ptr_op(r,==,NULL); 1367 tt_int_op(local_outcome.err,==,EVUTIL_EAI_NONAME); 1368 tt_ptr_op(local_outcome.ai,==,NULL); 1369 1370 /* 1c. We give a numeric address (ipv6) */ 1371 memset(&hints, 0, sizeof(hints)); 1372 memset(&local_outcome, 0, sizeof(local_outcome)); 1373 hints.ai_family = PF_UNSPEC; 1374 hints.ai_protocol = IPPROTO_TCP; 1375 r = evdns_getaddrinfo(dns_base, "f::f", "8008", 1376 &hints, gai_cb, &local_outcome); 1377 tt_assert(!r); 1378 tt_int_op(local_outcome.err,==,0); 1379 tt_assert(local_outcome.ai); 1380 tt_ptr_op(local_outcome.ai->ai_next,==,NULL); 1381 test_ai_eq(local_outcome.ai, "[f::f]:8008", SOCK_STREAM, IPPROTO_TCP); 1382 evutil_freeaddrinfo(local_outcome.ai); 1383 local_outcome.ai = NULL; 1384 1385 /* 1d. We give a numeric address (ipv4) */ 1386 memset(&hints, 0, sizeof(hints)); 1387 memset(&local_outcome, 0, sizeof(local_outcome)); 1388 hints.ai_family = PF_UNSPEC; 1389 r = evdns_getaddrinfo(dns_base, "5.6.7.8", NULL, 1390 &hints, gai_cb, &local_outcome); 1391 tt_assert(!r); 1392 tt_int_op(local_outcome.err,==,0); 1393 tt_assert(local_outcome.ai); 1394 a = ai_find_by_protocol(local_outcome.ai, IPPROTO_TCP); 1395 tt_assert(a); 1396 test_ai_eq(a, "5.6.7.8", SOCK_STREAM, IPPROTO_TCP); 1397 a = ai_find_by_protocol(local_outcome.ai, IPPROTO_UDP); 1398 tt_assert(a); 1399 test_ai_eq(a, "5.6.7.8", SOCK_DGRAM, IPPROTO_UDP); 1400 evutil_freeaddrinfo(local_outcome.ai); 1401 local_outcome.ai = NULL; 1402 1403 /* 1e. nodename is NULL (bind) */ 1404 memset(&hints, 0, sizeof(hints)); 1405 memset(&local_outcome, 0, sizeof(local_outcome)); 1406 hints.ai_family = PF_UNSPEC; 1407 hints.ai_socktype = SOCK_DGRAM; 1408 hints.ai_flags = EVUTIL_AI_PASSIVE; 1409 r = evdns_getaddrinfo(dns_base, NULL, "9090", 1410 &hints, gai_cb, &local_outcome); 1411 tt_assert(!r); 1412 tt_int_op(local_outcome.err,==,0); 1413 tt_assert(local_outcome.ai); 1414 /* we should get a v4 address of 0.0.0.0... */ 1415 a = ai_find_by_family(local_outcome.ai, PF_INET); 1416 tt_assert(a); 1417 test_ai_eq(a, "0.0.0.0:9090", SOCK_DGRAM, IPPROTO_UDP); 1418 /* ... and a v6 address of ::0 */ 1419 a = ai_find_by_family(local_outcome.ai, PF_INET6); 1420 tt_assert(a); 1421 test_ai_eq(a, "[::]:9090", SOCK_DGRAM, IPPROTO_UDP); 1422 evutil_freeaddrinfo(local_outcome.ai); 1423 local_outcome.ai = NULL; 1424 1425 /* 1f. nodename is NULL (connect) */ 1426 memset(&hints, 0, sizeof(hints)); 1427 memset(&local_outcome, 0, sizeof(local_outcome)); 1428 hints.ai_family = PF_UNSPEC; 1429 hints.ai_socktype = SOCK_STREAM; 1430 r = evdns_getaddrinfo(dns_base, NULL, "2", 1431 &hints, gai_cb, &local_outcome); 1432 tt_assert(!r); 1433 tt_int_op(local_outcome.err,==,0); 1434 tt_assert(local_outcome.ai); 1435 /* we should get a v4 address of 127.0.0.1 .... */ 1436 a = ai_find_by_family(local_outcome.ai, PF_INET); 1437 tt_assert(a); 1438 test_ai_eq(a, "127.0.0.1:2", SOCK_STREAM, IPPROTO_TCP); 1439 /* ... and a v6 address of ::1 */ 1440 a = ai_find_by_family(local_outcome.ai, PF_INET6); 1441 tt_assert(a); 1442 test_ai_eq(a, "[::1]:2", SOCK_STREAM, IPPROTO_TCP); 1443 evutil_freeaddrinfo(local_outcome.ai); 1444 local_outcome.ai = NULL; 1445 1446 /* 1g. We find localhost immediately. (pf_unspec) */ 1447 memset(&hints, 0, sizeof(hints)); 1448 memset(&local_outcome, 0, sizeof(local_outcome)); 1449 hints.ai_family = PF_UNSPEC; 1450 hints.ai_socktype = SOCK_STREAM; 1451 r = evdns_getaddrinfo(dns_base, "LOCALHOST", "80", 1452 &hints, gai_cb, &local_outcome); 1453 tt_assert(!r); 1454 tt_int_op(local_outcome.err,==,0); 1455 tt_assert(local_outcome.ai); 1456 /* we should get a v4 address of 127.0.0.1 .... */ 1457 a = ai_find_by_family(local_outcome.ai, PF_INET); 1458 tt_assert(a); 1459 test_ai_eq(a, "127.0.0.1:80", SOCK_STREAM, IPPROTO_TCP); 1460 /* ... and a v6 address of ::1 */ 1461 a = ai_find_by_family(local_outcome.ai, PF_INET6); 1462 tt_assert(a); 1463 test_ai_eq(a, "[::1]:80", SOCK_STREAM, IPPROTO_TCP); 1464 evutil_freeaddrinfo(local_outcome.ai); 1465 local_outcome.ai = NULL; 1466 1467 /* 1g. We find localhost immediately. (pf_inet6) */ 1468 memset(&hints, 0, sizeof(hints)); 1469 memset(&local_outcome, 0, sizeof(local_outcome)); 1470 hints.ai_family = PF_INET6; 1471 hints.ai_socktype = SOCK_STREAM; 1472 r = evdns_getaddrinfo(dns_base, "LOCALHOST", "9999", 1473 &hints, gai_cb, &local_outcome); 1474 tt_assert(! r); 1475 tt_int_op(local_outcome.err,==,0); 1476 tt_assert(local_outcome.ai); 1477 a = local_outcome.ai; 1478 test_ai_eq(a, "[::1]:9999", SOCK_STREAM, IPPROTO_TCP); 1479 tt_ptr_op(a->ai_next, ==, NULL); 1480 evutil_freeaddrinfo(local_outcome.ai); 1481 local_outcome.ai = NULL; 1482 1483 /* 2. Okay, now we can actually test the asynchronous resolver. */ 1484 /* Start a dummy local dns server... */ 1485 port = regress_get_dnsserver(data->base, &dns_port, NULL, 1486 be_getaddrinfo_server_cb, &n_dns_questions); 1487 tt_assert(port); 1488 tt_int_op(dns_port, >=, 0); 1489 /* ... and tell the evdns_base about it. */ 1490 evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", dns_port); 1491 evdns_base_nameserver_ip_add(dns_base, buf); 1492 1493 memset(&hints, 0, sizeof(hints)); 1494 hints.ai_family = PF_UNSPEC; 1495 hints.ai_socktype = SOCK_STREAM; 1496 hints.ai_flags = EVUTIL_AI_CANONNAME; 1497 /* 0: Request for both.example.com should return both addresses. */ 1498 r = evdns_getaddrinfo(dns_base, "both.example.com", "8000", 1499 &hints, gai_cb, &a_out[0]); 1500 tt_assert(r); 1501 1502 /* 1: Request for v4only.example.com should return one address. */ 1503 r = evdns_getaddrinfo(dns_base, "v4only.example.com", "8001", 1504 &hints, gai_cb, &a_out[1]); 1505 tt_assert(r); 1506 1507 /* 2: Request for v6only.example.com should return one address. */ 1508 hints.ai_flags = 0; 1509 r = evdns_getaddrinfo(dns_base, "v6only.example.com", "8002", 1510 &hints, gai_cb, &a_out[2]); 1511 tt_assert(r); 1512 1513 /* 3: PF_INET request for v4assert.example.com should not generate a 1514 * v6 request. The server will fail the test if it does. */ 1515 hints.ai_family = PF_INET; 1516 r = evdns_getaddrinfo(dns_base, "v4assert.example.com", "8003", 1517 &hints, gai_cb, &a_out[3]); 1518 tt_assert(r); 1519 1520 /* 4: PF_INET6 request for v6assert.example.com should not generate a 1521 * v4 request. The server will fail the test if it does. */ 1522 hints.ai_family = PF_INET6; 1523 r = evdns_getaddrinfo(dns_base, "v6assert.example.com", "8004", 1524 &hints, gai_cb, &a_out[4]); 1525 tt_assert(r); 1526 1527 /* 5: PF_INET request for nosuchplace.example.com should give NEXIST. */ 1528 hints.ai_family = PF_INET; 1529 r = evdns_getaddrinfo(dns_base, "nosuchplace.example.com", "8005", 1530 &hints, gai_cb, &a_out[5]); 1531 tt_assert(r); 1532 1533 /* 6: PF_UNSPEC request for nosuchplace.example.com should give NEXIST. 1534 */ 1535 hints.ai_family = PF_UNSPEC; 1536 r = evdns_getaddrinfo(dns_base, "nosuchplace.example.com", "8006", 1537 &hints, gai_cb, &a_out[6]); 1538 tt_assert(r); 1539 1540 /* 7: PF_UNSPEC request for v6timeout.example.com should give an ipv4 1541 * address only. */ 1542 hints.ai_family = PF_UNSPEC; 1543 r = evdns_getaddrinfo(dns_base, "v6timeout.example.com", "8007", 1544 &hints, gai_cb, &a_out[7]); 1545 tt_assert(r); 1546 1547 /* 8: PF_UNSPEC request for v6timeout-nonexist.example.com should give 1548 * a NEXIST */ 1549 hints.ai_family = PF_UNSPEC; 1550 r = evdns_getaddrinfo(dns_base, "v6timeout-nonexist.example.com", 1551 "8008", &hints, gai_cb, &a_out[8]); 1552 tt_assert(r); 1553 1554 /* 9: AI_ADDRCONFIG should at least not crash. Can't test it more 1555 * without knowing what kind of internet we have. */ 1556 hints.ai_flags |= EVUTIL_AI_ADDRCONFIG; 1557 r = evdns_getaddrinfo(dns_base, "both.example.com", 1558 "8009", &hints, gai_cb, &a_out[9]); 1559 tt_assert(r); 1560 1561 /* 10: PF_UNSPEC for v4timeout.example.com should give an ipv6 address 1562 * only. */ 1563 hints.ai_family = PF_UNSPEC; 1564 hints.ai_flags = 0; 1565 r = evdns_getaddrinfo(dns_base, "v4timeout.example.com", "8010", 1566 &hints, gai_cb, &a_out[10]); 1567 tt_assert(r); 1568 1569 /* 11: timeout.example.com: cancel it after 100 msec. */ 1570 r = evdns_getaddrinfo(dns_base, "all-timeout.example.com", "8011", 1571 &hints, gai_cb, &a_out[11]); 1572 tt_assert(r); 1573 { 1574 struct timeval tv; 1575 tv.tv_sec = 0; 1576 tv.tv_usec = 100*1000; /* 100 msec */ 1577 event_base_once(data->base, -1, EV_TIMEOUT, cancel_gai_cb, 1578 r, &tv); 1579 } 1580 1581 /* XXXXX There are more tests we could do, including: 1582 1583 - A test to elicit NODATA. 1584 1585 */ 1586 1587 n_gai_results_pending = 12; 1588 exit_base_on_no_pending_results = data->base; 1589 1590 event_base_dispatch(data->base); 1591 1592 /* 0: both.example.com */ 1593 tt_int_op(a_out[0].err, ==, 0); 1594 tt_assert(a_out[0].ai); 1595 tt_assert(a_out[0].ai->ai_next); 1596 tt_assert(!a_out[0].ai->ai_next->ai_next); 1597 a = ai_find_by_family(a_out[0].ai, PF_INET); 1598 tt_assert(a); 1599 test_ai_eq(a, "80.80.32.32:8000", SOCK_STREAM, IPPROTO_TCP); 1600 a = ai_find_by_family(a_out[0].ai, PF_INET6); 1601 tt_assert(a); 1602 test_ai_eq(a, "[80ff::bbbb]:8000", SOCK_STREAM, IPPROTO_TCP); 1603 tt_assert(a_out[0].ai->ai_canonname); 1604 tt_str_op(a_out[0].ai->ai_canonname, ==, "both-canonical.example.com"); 1605 1606 /* 1: v4only.example.com */ 1607 tt_int_op(a_out[1].err, ==, 0); 1608 tt_assert(a_out[1].ai); 1609 tt_assert(! a_out[1].ai->ai_next); 1610 test_ai_eq(a_out[1].ai, "18.52.86.120:8001", SOCK_STREAM, IPPROTO_TCP); 1611 tt_assert(a_out[1].ai->ai_canonname == NULL); 1612 1613 1614 /* 2: v6only.example.com */ 1615 tt_int_op(a_out[2].err, ==, 0); 1616 tt_assert(a_out[2].ai); 1617 tt_assert(! a_out[2].ai->ai_next); 1618 test_ai_eq(a_out[2].ai, "[b0b::f00d]:8002", SOCK_STREAM, IPPROTO_TCP); 1619 1620 /* 3: v4assert.example.com */ 1621 tt_int_op(a_out[3].err, ==, 0); 1622 tt_assert(a_out[3].ai); 1623 tt_assert(! a_out[3].ai->ai_next); 1624 test_ai_eq(a_out[3].ai, "18.52.86.120:8003", SOCK_STREAM, IPPROTO_TCP); 1625 1626 /* 4: v6assert.example.com */ 1627 tt_int_op(a_out[4].err, ==, 0); 1628 tt_assert(a_out[4].ai); 1629 tt_assert(! a_out[4].ai->ai_next); 1630 test_ai_eq(a_out[4].ai, "[b0b::f00d]:8004", SOCK_STREAM, IPPROTO_TCP); 1631 1632 /* 5: nosuchplace.example.com (inet) */ 1633 tt_int_op(a_out[5].err, ==, EVUTIL_EAI_NONAME); 1634 tt_assert(! a_out[5].ai); 1635 1636 /* 6: nosuchplace.example.com (unspec) */ 1637 tt_int_op(a_out[6].err, ==, EVUTIL_EAI_NONAME); 1638 tt_assert(! a_out[6].ai); 1639 1640 /* 7: v6timeout.example.com */ 1641 tt_int_op(a_out[7].err, ==, 0); 1642 tt_assert(a_out[7].ai); 1643 tt_assert(! a_out[7].ai->ai_next); 1644 test_ai_eq(a_out[7].ai, "171.205.239.1:8007", SOCK_STREAM, IPPROTO_TCP); 1645 1646 /* 8: v6timeout-nonexist.example.com */ 1647 tt_int_op(a_out[8].err, ==, EVUTIL_EAI_NONAME); 1648 tt_assert(! a_out[8].ai); 1649 1650 /* 9: both (ADDRCONFIG) */ 1651 tt_int_op(a_out[9].err, ==, 0); 1652 tt_assert(a_out[9].ai); 1653 a = ai_find_by_family(a_out[9].ai, PF_INET); 1654 if (a) 1655 test_ai_eq(a, "80.80.32.32:8009", SOCK_STREAM, IPPROTO_TCP); 1656 else 1657 tt_assert(ai_find_by_family(a_out[9].ai, PF_INET6)); 1658 a = ai_find_by_family(a_out[9].ai, PF_INET6); 1659 if (a) 1660 test_ai_eq(a, "[80ff::bbbb]:8009", SOCK_STREAM, IPPROTO_TCP); 1661 else 1662 tt_assert(ai_find_by_family(a_out[9].ai, PF_INET)); 1663 1664 /* 10: v4timeout.example.com */ 1665 tt_int_op(a_out[10].err, ==, 0); 1666 tt_assert(a_out[10].ai); 1667 tt_assert(! a_out[10].ai->ai_next); 1668 test_ai_eq(a_out[10].ai, "[a0a::ff01]:8010", SOCK_STREAM, IPPROTO_TCP); 1669 1670 /* 11: cancelled request. */ 1671 tt_int_op(a_out[11].err, ==, EVUTIL_EAI_CANCEL); 1672 tt_assert(a_out[11].ai == NULL); 1673 1674 end: 1675 if (local_outcome.ai) 1676 evutil_freeaddrinfo(local_outcome.ai); 1677 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 1678 for (i=0;i<(int)ARRAY_SIZE(a_out);++i) { 1679 if (a_out[i].ai) 1680 evutil_freeaddrinfo(a_out[i].ai); 1681 } 1682 if (port) 1683 evdns_close_server_port(port); 1684 if (dns_base) 1685 evdns_base_free(dns_base, 0); 1686 } 1687 1688 struct gaic_request_status { 1689 int magic; 1690 struct event_base *base; 1691 struct evdns_base *dns_base; 1692 struct evdns_getaddrinfo_request *request; 1693 struct event cancel_event; 1694 int canceled; 1695 }; 1696 1697 #define GAIC_MAGIC 0x1234abcd 1698 1699 static int pending = 0; 1700 1701 static void 1702 gaic_cancel_request_cb(evutil_socket_t fd, short what, void *arg) 1703 { 1704 struct gaic_request_status *status = arg; 1705 1706 tt_assert(status->magic == GAIC_MAGIC); 1707 status->canceled = 1; 1708 evdns_getaddrinfo_cancel(status->request); 1709 return; 1710 end: 1711 event_base_loopexit(status->base, NULL); 1712 } 1713 1714 static void 1715 gaic_server_cb(struct evdns_server_request *req, void *arg) 1716 { 1717 ev_uint32_t answer = 0x7f000001; 1718 tt_assert(req->nquestions); 1719 evdns_server_request_add_a_reply(req, req->questions[0]->name, 1, 1720 &answer, 100); 1721 evdns_server_request_respond(req, 0); 1722 return; 1723 end: 1724 evdns_server_request_respond(req, DNS_ERR_REFUSED); 1725 } 1726 1727 1728 static void 1729 gaic_getaddrinfo_cb(int result, struct evutil_addrinfo *res, void *arg) 1730 { 1731 struct gaic_request_status *status = arg; 1732 struct event_base *base = status->base; 1733 tt_assert(status->magic == GAIC_MAGIC); 1734 1735 if (result == EVUTIL_EAI_CANCEL) { 1736 tt_assert(status->canceled); 1737 } 1738 event_del(&status->cancel_event); 1739 1740 memset(status, 0xf0, sizeof(*status)); 1741 free(status); 1742 1743 end: 1744 if (--pending <= 0) 1745 event_base_loopexit(base, NULL); 1746 } 1747 1748 static void 1749 gaic_launch(struct event_base *base, struct evdns_base *dns_base) 1750 { 1751 struct gaic_request_status *status = calloc(1, sizeof(*status)); 1752 tt_assert(status); 1753 struct timeval tv = { 0, 10000 }; 1754 status->magic = GAIC_MAGIC; 1755 status->base = base; 1756 status->dns_base = dns_base; 1757 event_assign(&status->cancel_event, base, -1, 0, gaic_cancel_request_cb, 1758 status); 1759 status->request = evdns_getaddrinfo(dns_base, 1760 "foobar.bazquux.example.com", "80", NULL, gaic_getaddrinfo_cb, 1761 status); 1762 event_add(&status->cancel_event, &tv); 1763 ++pending; 1764 } 1765 1766 #ifdef EVENT_SET_MEM_FUNCTIONS_IMPLEMENTED 1767 /* FIXME: We should move this to regress_main.c if anything else needs it.*/ 1768 1769 /* Trivial replacements for malloc/free/realloc to check for memory leaks. 1770 * Not threadsafe. */ 1771 static int allocated_chunks = 0; 1772 1773 static void * 1774 cnt_malloc(size_t sz) 1775 { 1776 allocated_chunks += 1; 1777 return malloc(sz); 1778 } 1779 1780 static void * 1781 cnt_realloc(void *old, size_t sz) 1782 { 1783 if (!old) 1784 allocated_chunks += 1; 1785 if (!sz) 1786 allocated_chunks -= 1; 1787 return realloc(old, sz); 1788 } 1789 1790 static void 1791 cnt_free(void *ptr) 1792 { 1793 allocated_chunks -= 1; 1794 free(ptr); 1795 } 1796 1797 struct testleak_env_t { 1798 struct event_base *base; 1799 struct evdns_base *dns_base; 1800 struct evdns_request *req; 1801 struct generic_dns_callback_result r; 1802 }; 1803 1804 static void * 1805 testleak_setup(const struct testcase_t *testcase) 1806 { 1807 struct testleak_env_t *env; 1808 1809 allocated_chunks = 0; 1810 1811 /* Reset allocation counter, to start allocations from the very beginning. 1812 * (this will avoid false-positive negative numbers for allocated_chunks) 1813 */ 1814 libevent_global_shutdown(); 1815 1816 event_set_mem_functions(cnt_malloc, cnt_realloc, cnt_free); 1817 1818 event_enable_debug_mode(); 1819 1820 /* not mm_calloc: we don't want to mess with the count. */ 1821 env = calloc(1, sizeof(struct testleak_env_t)); 1822 env->base = event_base_new(); 1823 env->dns_base = evdns_base_new(env->base, 0); 1824 env->req = evdns_base_resolve_ipv4( 1825 env->dns_base, "example.com", DNS_QUERY_NO_SEARCH, 1826 generic_dns_callback, &env->r); 1827 return env; 1828 } 1829 1830 static int 1831 testleak_cleanup(const struct testcase_t *testcase, void *env_) 1832 { 1833 int ok = 0; 1834 struct testleak_env_t *env = env_; 1835 tt_assert(env); 1836 #ifdef EVENT__DISABLE_DEBUG_MODE 1837 tt_int_op(allocated_chunks, ==, 0); 1838 #else 1839 libevent_global_shutdown(); 1840 tt_int_op(allocated_chunks, ==, 0); 1841 #endif 1842 ok = 1; 1843 end: 1844 if (env) { 1845 if (env->dns_base) 1846 evdns_base_free(env->dns_base, 0); 1847 if (env->base) 1848 event_base_free(env->base); 1849 free(env); 1850 } 1851 return ok; 1852 } 1853 1854 static struct testcase_setup_t testleak_funcs = { 1855 testleak_setup, testleak_cleanup 1856 }; 1857 1858 static void 1859 test_dbg_leak_cancel(void *env_) 1860 { 1861 /* cancel, loop, free/dns, free/base */ 1862 struct testleak_env_t *env = env_; 1863 int send_err_shutdown = 1; 1864 evdns_cancel_request(env->dns_base, env->req); 1865 env->req = 0; 1866 1867 /* `req` is freed in callback, that's why one loop is required. */ 1868 event_base_loop(env->base, EVLOOP_NONBLOCK); 1869 1870 /* send_err_shutdown means nothing as soon as our request is 1871 * already canceled */ 1872 evdns_base_free(env->dns_base, send_err_shutdown); 1873 env->dns_base = 0; 1874 event_base_free(env->base); 1875 env->base = 0; 1876 } 1877 1878 static void 1879 dbg_leak_resume(void *env_, int cancel, int send_err_shutdown) 1880 { 1881 /* cancel, loop, free/dns, free/base */ 1882 struct testleak_env_t *env = env_; 1883 if (cancel) { 1884 evdns_cancel_request(env->dns_base, env->req); 1885 tt_assert(!evdns_base_resume(env->dns_base)); 1886 } else { 1887 /* TODO: No nameservers, request can't be processed, must be errored */ 1888 tt_assert(!evdns_base_resume(env->dns_base)); 1889 } 1890 1891 /** 1892 * Because we don't cancel request, 1893 * and want our callback to recieve DNS_ERR_SHUTDOWN, 1894 * we use deferred callback, and there was 1895 * - one extra malloc(), 1896 * @see reply_schedule_callback() 1897 * - and one missing free 1898 * @see request_finished() (req->handle->pending_cb = 1) 1899 * than we don't need to count in testleak_cleanup() 1900 * 1901 * So just decrement allocated_chunks to 2, 1902 * like we already take care about it. 1903 */ 1904 if (!cancel && send_err_shutdown) { 1905 allocated_chunks -= 2; 1906 } 1907 1908 event_base_loop(env->base, EVLOOP_NONBLOCK); 1909 1910 end: 1911 evdns_base_free(env->dns_base, send_err_shutdown); 1912 env->dns_base = 0; 1913 1914 event_base_free(env->base); 1915 env->base = 0; 1916 } 1917 1918 #define IMPL_DBG_LEAK_RESUME(name, cancel, send_err_shutdown) \ 1919 static void \ 1920 test_dbg_leak_##name##_(void *env_) \ 1921 { \ 1922 dbg_leak_resume(env_, cancel, send_err_shutdown); \ 1923 } 1924 IMPL_DBG_LEAK_RESUME(resume, 0, 0) 1925 IMPL_DBG_LEAK_RESUME(cancel_and_resume, 1, 0) 1926 IMPL_DBG_LEAK_RESUME(resume_send_err, 0, 1) 1927 IMPL_DBG_LEAK_RESUME(cancel_and_resume_send_err, 1, 1) 1928 1929 static void 1930 test_dbg_leak_shutdown(void *env_) 1931 { 1932 /* free/dns, loop, free/base */ 1933 struct testleak_env_t *env = env_; 1934 int send_err_shutdown = 1; 1935 1936 /* `req` is freed both with `send_err_shutdown` and without it, 1937 * the only difference is `evdns_callback` call */ 1938 env->req = 0; 1939 1940 evdns_base_free(env->dns_base, send_err_shutdown); 1941 env->dns_base = 0; 1942 1943 /* `req` is freed in callback, that's why one loop is required */ 1944 event_base_loop(env->base, EVLOOP_NONBLOCK); 1945 event_base_free(env->base); 1946 env->base = 0; 1947 } 1948 #endif 1949 1950 static void 1951 test_getaddrinfo_async_cancel_stress(void *ptr) 1952 { 1953 struct event_base *base; 1954 struct evdns_base *dns_base = NULL; 1955 struct evdns_server_port *server = NULL; 1956 evutil_socket_t fd = -1; 1957 struct sockaddr_in sin; 1958 struct sockaddr_storage ss; 1959 ev_socklen_t slen; 1960 int i; 1961 1962 base = event_base_new(); 1963 dns_base = evdns_base_new(base, 0); 1964 1965 memset(&sin, 0, sizeof(sin)); 1966 sin.sin_family = AF_INET; 1967 sin.sin_port = 0; 1968 sin.sin_addr.s_addr = htonl(0x7f000001); 1969 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 1970 tt_abort_perror("socket"); 1971 } 1972 evutil_make_socket_nonblocking(fd); 1973 if (bind(fd, (struct sockaddr*)&sin, sizeof(sin))<0) { 1974 tt_abort_perror("bind"); 1975 } 1976 server = evdns_add_server_port_with_base(base, fd, 0, gaic_server_cb, 1977 base); 1978 1979 memset(&ss, 0, sizeof(ss)); 1980 slen = sizeof(ss); 1981 if (getsockname(fd, (struct sockaddr*)&ss, &slen)<0) { 1982 tt_abort_perror("getsockname"); 1983 } 1984 evdns_base_nameserver_sockaddr_add(dns_base, 1985 (struct sockaddr*)&ss, slen, 0); 1986 1987 for (i = 0; i < 1000; ++i) { 1988 gaic_launch(base, dns_base); 1989 } 1990 1991 event_base_dispatch(base); 1992 1993 end: 1994 if (dns_base) 1995 evdns_base_free(dns_base, 1); 1996 if (server) 1997 evdns_close_server_port(server); 1998 if (base) 1999 event_base_free(base); 2000 if (fd >= 0) 2001 evutil_closesocket(fd); 2002 } 2003 2004 2005 #define DNS_LEGACY(name, flags) \ 2006 { #name, run_legacy_test_fn, flags|TT_LEGACY, &legacy_setup, \ 2007 dns_##name } 2008 2009 struct testcase_t dns_testcases[] = { 2010 DNS_LEGACY(server, TT_FORK|TT_NEED_BASE), 2011 DNS_LEGACY(gethostbyname, TT_FORK|TT_NEED_BASE|TT_NEED_DNS|TT_OFF_BY_DEFAULT), 2012 DNS_LEGACY(gethostbyname6, TT_FORK|TT_NEED_BASE|TT_NEED_DNS|TT_OFF_BY_DEFAULT), 2013 DNS_LEGACY(gethostbyaddr, TT_FORK|TT_NEED_BASE|TT_NEED_DNS|TT_OFF_BY_DEFAULT), 2014 { "resolve_reverse", dns_resolve_reverse, TT_FORK|TT_OFF_BY_DEFAULT, NULL, NULL }, 2015 { "search", dns_search_test, TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, 2016 { "search_cancel", dns_search_cancel_test, 2017 TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, 2018 { "retry", dns_retry_test, TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, NULL }, 2019 { "retry_disable_when_inactive", dns_retry_disable_when_inactive_test, 2020 TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, NULL }, 2021 { "reissue", dns_reissue_test, TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, NULL }, 2022 { "reissue_disable_when_inactive", dns_reissue_disable_when_inactive_test, 2023 TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, NULL }, 2024 { "inflight", dns_inflight_test, TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, 2025 { "bufferevent_connect_hostname", test_bufferevent_connect_hostname, 2026 TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, 2027 { "disable_when_inactive", dns_disable_when_inactive_test, 2028 TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, 2029 { "disable_when_inactive_no_ns", dns_disable_when_inactive_no_ns_test, 2030 TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, 2031 2032 { "getaddrinfo_async", test_getaddrinfo_async, 2033 TT_FORK|TT_NEED_BASE, &basic_setup, (char*)"" }, 2034 { "getaddrinfo_cancel_stress", test_getaddrinfo_async_cancel_stress, 2035 TT_FORK, NULL, NULL }, 2036 2037 #ifdef EVENT_SET_MEM_FUNCTIONS_IMPLEMENTED 2038 { "leak_shutdown", test_dbg_leak_shutdown, TT_FORK, &testleak_funcs, NULL }, 2039 { "leak_cancel", test_dbg_leak_cancel, TT_FORK, &testleak_funcs, NULL }, 2040 2041 { "leak_resume", test_dbg_leak_resume_, TT_FORK, &testleak_funcs, NULL }, 2042 { "leak_cancel_and_resume", test_dbg_leak_cancel_and_resume_, 2043 TT_FORK, &testleak_funcs, NULL }, 2044 { "leak_resume_send_err", test_dbg_leak_resume_send_err_, 2045 TT_FORK, &testleak_funcs, NULL }, 2046 { "leak_cancel_and_resume_send_err", test_dbg_leak_cancel_and_resume_send_err_, 2047 TT_FORK, &testleak_funcs, NULL }, 2048 #endif 2049 2050 END_OF_TESTCASES 2051 }; 2052 2053