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