1*eabc0478Schristos /* $NetBSD: regress_dns.c,v 1.8 2024/08/18 20:47:23 christos Exp $ */ 28585484eSchristos 38585484eSchristos /* 48585484eSchristos * Copyright (c) 2003-2007 Niels Provos <provos@citi.umich.edu> 58585484eSchristos * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson 68585484eSchristos * 78585484eSchristos * Redistribution and use in source and binary forms, with or without 88585484eSchristos * modification, are permitted provided that the following conditions 98585484eSchristos * are met: 108585484eSchristos * 1. Redistributions of source code must retain the above copyright 118585484eSchristos * notice, this list of conditions and the following disclaimer. 128585484eSchristos * 2. Redistributions in binary form must reproduce the above copyright 138585484eSchristos * notice, this list of conditions and the following disclaimer in the 148585484eSchristos * documentation and/or other materials provided with the distribution. 158585484eSchristos * 3. The name of the author may not be used to endorse or promote products 168585484eSchristos * derived from this software without specific prior written permission. 178585484eSchristos * 188585484eSchristos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 198585484eSchristos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 208585484eSchristos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 218585484eSchristos * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 228585484eSchristos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 238585484eSchristos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 248585484eSchristos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 258585484eSchristos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 268585484eSchristos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 278585484eSchristos * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 288585484eSchristos */ 298585484eSchristos #include "../util-internal.h" 308585484eSchristos 318585484eSchristos #ifdef _WIN32 328585484eSchristos #include <winsock2.h> 338585484eSchristos #include <windows.h> 348585484eSchristos #include <ws2tcpip.h> 358585484eSchristos #endif 368585484eSchristos 378585484eSchristos #include "event2/event-config.h" 388585484eSchristos 398585484eSchristos #include <sys/types.h> 408585484eSchristos #include <sys/stat.h> 418585484eSchristos #ifdef EVENT__HAVE_SYS_TIME_H 428585484eSchristos #include <sys/time.h> 438585484eSchristos #endif 448585484eSchristos #include <sys/queue.h> 458585484eSchristos #ifndef _WIN32 468585484eSchristos #include <sys/socket.h> 478585484eSchristos #include <signal.h> 488585484eSchristos #include <netinet/in.h> 498585484eSchristos #include <arpa/inet.h> 508585484eSchristos #include <unistd.h> 518585484eSchristos #endif 528585484eSchristos #ifdef EVENT__HAVE_NETINET_IN6_H 538585484eSchristos #include <netinet/in6.h> 548585484eSchristos #endif 558585484eSchristos #ifdef HAVE_NETDB_H 568585484eSchristos #include <netdb.h> 578585484eSchristos #endif 588585484eSchristos #include <fcntl.h> 598585484eSchristos #include <stdlib.h> 608585484eSchristos #include <stdio.h> 618585484eSchristos #include <string.h> 628585484eSchristos #include <errno.h> 638585484eSchristos 64*eabc0478Schristos #ifdef EVENT__HAVE_SYS_RESOURCE_H 65*eabc0478Schristos #include <sys/resource.h> 66*eabc0478Schristos #endif 67*eabc0478Schristos 688585484eSchristos #include "event2/dns.h" 698585484eSchristos #include "event2/dns_compat.h" 708585484eSchristos #include "event2/dns_struct.h" 718585484eSchristos #include "event2/event.h" 728585484eSchristos #include "event2/event_compat.h" 738585484eSchristos #include "event2/event_struct.h" 748585484eSchristos #include "event2/util.h" 758585484eSchristos #include "event2/listener.h" 768585484eSchristos #include "event2/bufferevent.h" 77*eabc0478Schristos #include <event2/thread.h> 788585484eSchristos #include "log-internal.h" 79*eabc0478Schristos #include "evthread-internal.h" 808585484eSchristos #include "regress.h" 818585484eSchristos #include "regress_testutils.h" 82*eabc0478Schristos #include "regress_thread.h" 83*eabc0478Schristos 84*eabc0478Schristos #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 858585484eSchristos 868585484eSchristos static int dns_ok = 0; 878585484eSchristos static int dns_got_cancel = 0; 888585484eSchristos static int dns_err = 0; 898585484eSchristos 908585484eSchristos 918585484eSchristos static void 928585484eSchristos dns_gethostbyname_cb(int result, char type, int count, int ttl, 938585484eSchristos void *addresses, void *arg) 948585484eSchristos { 958585484eSchristos dns_ok = dns_err = 0; 968585484eSchristos 978585484eSchristos if (result == DNS_ERR_TIMEOUT) { 988585484eSchristos printf("[Timed out] "); 998585484eSchristos dns_err = result; 1008585484eSchristos goto out; 1018585484eSchristos } 1028585484eSchristos 1038585484eSchristos if (result != DNS_ERR_NONE) { 1048585484eSchristos printf("[Error code %d] ", result); 1058585484eSchristos goto out; 1068585484eSchristos } 1078585484eSchristos 1088585484eSchristos TT_BLATHER(("type: %d, count: %d, ttl: %d: ", type, count, ttl)); 1098585484eSchristos 1108585484eSchristos switch (type) { 1118585484eSchristos case DNS_IPv6_AAAA: { 1128585484eSchristos #if defined(EVENT__HAVE_STRUCT_IN6_ADDR) && defined(EVENT__HAVE_INET_NTOP) && defined(INET6_ADDRSTRLEN) 1138585484eSchristos struct in6_addr *in6_addrs = addresses; 1148585484eSchristos char buf[INET6_ADDRSTRLEN+1]; 1158585484eSchristos int i; 1168585484eSchristos /* a resolution that's not valid does not help */ 1178585484eSchristos if (ttl < 0) 1188585484eSchristos goto out; 1198585484eSchristos for (i = 0; i < count; ++i) { 1208585484eSchristos const char *b = evutil_inet_ntop(AF_INET6, &in6_addrs[i], buf,sizeof(buf)); 1218585484eSchristos if (b) 1228585484eSchristos TT_BLATHER(("%s ", b)); 1238585484eSchristos else 1248585484eSchristos TT_BLATHER(("%s ", strerror(errno))); 1258585484eSchristos } 1268585484eSchristos #endif 1278585484eSchristos break; 1288585484eSchristos } 1298585484eSchristos case DNS_IPv4_A: { 1308585484eSchristos struct in_addr *in_addrs = addresses; 1318585484eSchristos int i; 1328585484eSchristos /* a resolution that's not valid does not help */ 1338585484eSchristos if (ttl < 0) 1348585484eSchristos goto out; 1358585484eSchristos for (i = 0; i < count; ++i) 1368585484eSchristos TT_BLATHER(("%s ", inet_ntoa(in_addrs[i]))); 1378585484eSchristos break; 1388585484eSchristos } 1398585484eSchristos case DNS_PTR: 1408585484eSchristos /* may get at most one PTR */ 1418585484eSchristos if (count != 1) 1428585484eSchristos goto out; 1438585484eSchristos 1448585484eSchristos TT_BLATHER(("%s ", *(char **)addresses)); 1458585484eSchristos break; 1468585484eSchristos default: 1478585484eSchristos goto out; 1488585484eSchristos } 1498585484eSchristos 1508585484eSchristos dns_ok = type; 1518585484eSchristos 1528585484eSchristos out: 1538585484eSchristos if (arg == NULL) 1548585484eSchristos event_loopexit(NULL); 1558585484eSchristos else 1568585484eSchristos event_base_loopexit((struct event_base *)arg, NULL); 1578585484eSchristos } 1588585484eSchristos 1598585484eSchristos static void 1608585484eSchristos dns_gethostbyname(void) 1618585484eSchristos { 1628585484eSchristos dns_ok = 0; 1638585484eSchristos evdns_resolve_ipv4("www.monkey.org", 0, dns_gethostbyname_cb, NULL); 1648585484eSchristos event_dispatch(); 1658585484eSchristos 1668585484eSchristos tt_int_op(dns_ok, ==, DNS_IPv4_A); 1678585484eSchristos test_ok = dns_ok; 1688585484eSchristos end: 1698585484eSchristos ; 1708585484eSchristos } 1718585484eSchristos 1728585484eSchristos static void 1738585484eSchristos dns_gethostbyname6(void) 1748585484eSchristos { 1758585484eSchristos dns_ok = 0; 1768585484eSchristos evdns_resolve_ipv6("www.ietf.org", 0, dns_gethostbyname_cb, NULL); 1778585484eSchristos event_dispatch(); 1788585484eSchristos 1798585484eSchristos if (!dns_ok && dns_err == DNS_ERR_TIMEOUT) { 1808585484eSchristos tt_skip(); 1818585484eSchristos } 1828585484eSchristos 1838585484eSchristos tt_int_op(dns_ok, ==, DNS_IPv6_AAAA); 1848585484eSchristos test_ok = 1; 1858585484eSchristos end: 1868585484eSchristos ; 1878585484eSchristos } 1888585484eSchristos 1898585484eSchristos static void 1908585484eSchristos dns_gethostbyaddr(void) 1918585484eSchristos { 1928585484eSchristos struct in_addr in; 1938585484eSchristos in.s_addr = htonl(0x7f000001ul); /* 127.0.0.1 */ 1948585484eSchristos dns_ok = 0; 1958585484eSchristos evdns_resolve_reverse(&in, 0, dns_gethostbyname_cb, NULL); 1968585484eSchristos event_dispatch(); 1978585484eSchristos 1988585484eSchristos tt_int_op(dns_ok, ==, DNS_PTR); 1998585484eSchristos test_ok = dns_ok; 2008585484eSchristos end: 2018585484eSchristos ; 2028585484eSchristos } 2038585484eSchristos 2048585484eSchristos static void 2058585484eSchristos dns_resolve_reverse(void *ptr) 2068585484eSchristos { 2078585484eSchristos struct in_addr in; 2088585484eSchristos struct event_base *base = event_base_new(); 209*eabc0478Schristos struct evdns_base *dns = evdns_base_new(base, EVDNS_BASE_INITIALIZE_NAMESERVERS); 2108585484eSchristos struct evdns_request *req = NULL; 2118585484eSchristos 2128585484eSchristos tt_assert(base); 2138585484eSchristos tt_assert(dns); 2148585484eSchristos in.s_addr = htonl(0x7f000001ul); /* 127.0.0.1 */ 2158585484eSchristos dns_ok = 0; 2168585484eSchristos 2178585484eSchristos req = evdns_base_resolve_reverse( 2188585484eSchristos dns, &in, 0, dns_gethostbyname_cb, base); 2198585484eSchristos tt_assert(req); 2208585484eSchristos 2218585484eSchristos event_base_dispatch(base); 2228585484eSchristos 2238585484eSchristos tt_int_op(dns_ok, ==, DNS_PTR); 2248585484eSchristos 2258585484eSchristos end: 2268585484eSchristos if (dns) 2278585484eSchristos evdns_base_free(dns, 0); 2288585484eSchristos if (base) 2298585484eSchristos event_base_free(base); 2308585484eSchristos } 2318585484eSchristos 2328585484eSchristos static int n_server_responses = 0; 2338585484eSchristos 2348585484eSchristos static void 2358585484eSchristos dns_server_request_cb(struct evdns_server_request *req, void *data) 2368585484eSchristos { 2378585484eSchristos int i, r; 2388585484eSchristos const char TEST_ARPA[] = "11.11.168.192.in-addr.arpa"; 2398585484eSchristos const char TEST_IN6[] = 2408585484eSchristos "f.e.f.e." "0.0.0.0." "0.0.0.0." "1.1.1.1." 2418585484eSchristos "a.a.a.a." "0.0.0.0." "0.0.0.0." "0.f.f.f.ip6.arpa"; 2428585484eSchristos 2438585484eSchristos for (i = 0; i < req->nquestions; ++i) { 2448585484eSchristos const int qtype = req->questions[i]->type; 2458585484eSchristos const int qclass = req->questions[i]->dns_question_class; 2468585484eSchristos const char *qname = req->questions[i]->name; 2478585484eSchristos 2488585484eSchristos struct in_addr ans; 2498585484eSchristos ans.s_addr = htonl(0xc0a80b0bUL); /* 192.168.11.11 */ 2508585484eSchristos if (qtype == EVDNS_TYPE_A && 2518585484eSchristos qclass == EVDNS_CLASS_INET && 2528585484eSchristos !evutil_ascii_strcasecmp(qname, "zz.example.com")) { 2538585484eSchristos r = evdns_server_request_add_a_reply(req, qname, 2548585484eSchristos 1, &ans.s_addr, 12345); 2558585484eSchristos if (r<0) 2568585484eSchristos dns_ok = 0; 2578585484eSchristos } else if (qtype == EVDNS_TYPE_AAAA && 2588585484eSchristos qclass == EVDNS_CLASS_INET && 2598585484eSchristos !evutil_ascii_strcasecmp(qname, "zz.example.com")) { 2608585484eSchristos char addr6[17] = "abcdefghijklmnop"; 2618585484eSchristos r = evdns_server_request_add_aaaa_reply(req, 2628585484eSchristos qname, 1, addr6, 123); 2638585484eSchristos if (r<0) 2648585484eSchristos dns_ok = 0; 2658585484eSchristos } else if (qtype == EVDNS_TYPE_PTR && 2668585484eSchristos qclass == EVDNS_CLASS_INET && 2678585484eSchristos !evutil_ascii_strcasecmp(qname, TEST_ARPA)) { 2688585484eSchristos r = evdns_server_request_add_ptr_reply(req, NULL, 2698585484eSchristos qname, "ZZ.EXAMPLE.COM", 54321); 2708585484eSchristos if (r<0) 2718585484eSchristos dns_ok = 0; 2728585484eSchristos } else if (qtype == EVDNS_TYPE_PTR && 2738585484eSchristos qclass == EVDNS_CLASS_INET && 2748585484eSchristos !evutil_ascii_strcasecmp(qname, TEST_IN6)){ 2758585484eSchristos r = evdns_server_request_add_ptr_reply(req, NULL, 2768585484eSchristos qname, 2778585484eSchristos "ZZ-INET6.EXAMPLE.COM", 54322); 2788585484eSchristos if (r<0) 2798585484eSchristos dns_ok = 0; 2808585484eSchristos } else if (qtype == EVDNS_TYPE_A && 2818585484eSchristos qclass == EVDNS_CLASS_INET && 2828585484eSchristos !evutil_ascii_strcasecmp(qname, "drop.example.com")) { 2838585484eSchristos if (evdns_server_request_drop(req)<0) 2848585484eSchristos dns_ok = 0; 2858585484eSchristos return; 2868585484eSchristos } else { 2878585484eSchristos printf("Unexpected question %d %d \"%s\" ", 2888585484eSchristos qtype, qclass, qname); 2898585484eSchristos dns_ok = 0; 2908585484eSchristos } 2918585484eSchristos } 2928585484eSchristos r = evdns_server_request_respond(req, 0); 2938585484eSchristos if (r<0) { 2948585484eSchristos printf("Couldn't send reply. "); 2958585484eSchristos dns_ok = 0; 2968585484eSchristos } 2978585484eSchristos } 2988585484eSchristos 2998585484eSchristos static void 3008585484eSchristos dns_server_gethostbyname_cb(int result, char type, int count, int ttl, 3018585484eSchristos void *addresses, void *arg) 3028585484eSchristos { 3038585484eSchristos if (result == DNS_ERR_CANCEL) { 3048585484eSchristos if (arg != (void*)(char*)90909) { 3058585484eSchristos printf("Unexpected cancelation"); 3068585484eSchristos dns_ok = 0; 3078585484eSchristos } 3088585484eSchristos dns_got_cancel = 1; 3098585484eSchristos goto out; 3108585484eSchristos } 3118585484eSchristos if (result != DNS_ERR_NONE) { 3128585484eSchristos printf("Unexpected result %d. ", result); 3138585484eSchristos dns_ok = 0; 3148585484eSchristos goto out; 3158585484eSchristos } 3168585484eSchristos if (count != 1) { 3178585484eSchristos printf("Unexpected answer count %d. ", count); 3188585484eSchristos dns_ok = 0; 3198585484eSchristos goto out; 3208585484eSchristos } 3218585484eSchristos switch (type) { 3228585484eSchristos case DNS_IPv4_A: { 3238585484eSchristos struct in_addr *in_addrs = addresses; 3248585484eSchristos if (in_addrs[0].s_addr != htonl(0xc0a80b0bUL) || ttl != 12345) { 3258585484eSchristos printf("Bad IPv4 response \"%s\" %d. ", 3268585484eSchristos inet_ntoa(in_addrs[0]), ttl); 3278585484eSchristos dns_ok = 0; 3288585484eSchristos goto out; 3298585484eSchristos } 3308585484eSchristos break; 3318585484eSchristos } 3328585484eSchristos case DNS_IPv6_AAAA: { 3338585484eSchristos #if defined (EVENT__HAVE_STRUCT_IN6_ADDR) && defined(EVENT__HAVE_INET_NTOP) && defined(INET6_ADDRSTRLEN) 3348585484eSchristos struct in6_addr *in6_addrs = addresses; 3358585484eSchristos char buf[INET6_ADDRSTRLEN+1]; 3368585484eSchristos if (memcmp(&in6_addrs[0].s6_addr, "abcdefghijklmnop", 16) 3378585484eSchristos || ttl != 123) { 3388585484eSchristos const char *b = evutil_inet_ntop(AF_INET6, &in6_addrs[0],buf,sizeof(buf)); 3398585484eSchristos printf("Bad IPv6 response \"%s\" %d. ", b, ttl); 3408585484eSchristos dns_ok = 0; 3418585484eSchristos goto out; 3428585484eSchristos } 3438585484eSchristos #endif 3448585484eSchristos break; 3458585484eSchristos } 3468585484eSchristos case DNS_PTR: { 3478585484eSchristos char **addrs = addresses; 3488585484eSchristos if (arg != (void*)6) { 3498585484eSchristos if (strcmp(addrs[0], "ZZ.EXAMPLE.COM") || 3508585484eSchristos ttl != 54321) { 3518585484eSchristos printf("Bad PTR response \"%s\" %d. ", 3528585484eSchristos addrs[0], ttl); 3538585484eSchristos dns_ok = 0; 3548585484eSchristos goto out; 3558585484eSchristos } 3568585484eSchristos } else { 3578585484eSchristos if (strcmp(addrs[0], "ZZ-INET6.EXAMPLE.COM") || 3588585484eSchristos ttl != 54322) { 3598585484eSchristos printf("Bad ipv6 PTR response \"%s\" %d. ", 3608585484eSchristos addrs[0], ttl); 3618585484eSchristos dns_ok = 0; 3628585484eSchristos goto out; 3638585484eSchristos } 3648585484eSchristos } 3658585484eSchristos break; 3668585484eSchristos } 3678585484eSchristos default: 3688585484eSchristos printf("Bad response type %d. ", type); 3698585484eSchristos dns_ok = 0; 3708585484eSchristos } 3718585484eSchristos out: 3728585484eSchristos if (++n_server_responses == 3) { 3738585484eSchristos event_loopexit(NULL); 3748585484eSchristos } 3758585484eSchristos } 3768585484eSchristos 3778585484eSchristos static void 3788585484eSchristos dns_server(void) 3798585484eSchristos { 3808585484eSchristos evutil_socket_t sock=-1; 3818585484eSchristos struct sockaddr_in my_addr; 3828585484eSchristos struct sockaddr_storage ss; 3838585484eSchristos ev_socklen_t slen; 3848585484eSchristos struct evdns_server_port *port=NULL; 3858585484eSchristos struct in_addr resolve_addr; 3868585484eSchristos struct in6_addr resolve_addr6; 3878585484eSchristos struct evdns_base *base=NULL; 3888585484eSchristos struct evdns_request *req=NULL; 3898585484eSchristos 3908585484eSchristos dns_ok = 1; 3918585484eSchristos 3928585484eSchristos base = evdns_base_new(NULL, 0); 3938585484eSchristos 3948585484eSchristos /* Now configure a nameserver port. */ 3958585484eSchristos sock = socket(AF_INET, SOCK_DGRAM, 0); 3968585484eSchristos if (sock<0) { 3978585484eSchristos tt_abort_perror("socket"); 3988585484eSchristos } 3998585484eSchristos 4008585484eSchristos evutil_make_socket_nonblocking(sock); 4018585484eSchristos 4028585484eSchristos memset(&my_addr, 0, sizeof(my_addr)); 4038585484eSchristos my_addr.sin_family = AF_INET; 4048585484eSchristos my_addr.sin_port = 0; /* kernel picks */ 4058585484eSchristos my_addr.sin_addr.s_addr = htonl(0x7f000001UL); 4068585484eSchristos if (bind(sock, (struct sockaddr*)&my_addr, sizeof(my_addr)) < 0) { 4078585484eSchristos tt_abort_perror("bind"); 4088585484eSchristos } 4098585484eSchristos slen = sizeof(ss); 4108585484eSchristos if (getsockname(sock, (struct sockaddr*)&ss, &slen) < 0) { 4118585484eSchristos tt_abort_perror("getsockname"); 4128585484eSchristos } 4138585484eSchristos 4148585484eSchristos port = evdns_add_server_port(sock, 0, dns_server_request_cb, NULL); 4158585484eSchristos 4168585484eSchristos /* Add ourself as the only nameserver, and make sure we really are 4178585484eSchristos * the only nameserver. */ 4188585484eSchristos evdns_base_nameserver_sockaddr_add(base, (struct sockaddr*)&ss, slen, 0); 4198585484eSchristos tt_int_op(evdns_base_count_nameservers(base), ==, 1); 4207476e6e4Schristos { 4217476e6e4Schristos struct sockaddr_storage ss2; 4227476e6e4Schristos int slen2; 4237476e6e4Schristos 4247476e6e4Schristos memset(&ss2, 0, sizeof(ss2)); 4257476e6e4Schristos 4267476e6e4Schristos slen2 = evdns_base_get_nameserver_addr(base, 0, (struct sockaddr *)&ss2, 3); 4277476e6e4Schristos tt_int_op(slen2, ==, slen); 4287476e6e4Schristos tt_int_op(ss2.ss_family, ==, 0); 4297476e6e4Schristos slen2 = evdns_base_get_nameserver_addr(base, 0, (struct sockaddr *)&ss2, sizeof(ss2)); 4307476e6e4Schristos tt_int_op(slen2, ==, slen); 4317476e6e4Schristos tt_mem_op(&ss2, ==, &ss, slen); 4327476e6e4Schristos 4337476e6e4Schristos slen2 = evdns_base_get_nameserver_addr(base, 1, (struct sockaddr *)&ss2, sizeof(ss2)); 4347476e6e4Schristos tt_int_op(-1, ==, slen2); 4357476e6e4Schristos } 4368585484eSchristos 4378585484eSchristos /* Send some queries. */ 4388585484eSchristos evdns_base_resolve_ipv4(base, "zz.example.com", DNS_QUERY_NO_SEARCH, 4398585484eSchristos dns_server_gethostbyname_cb, NULL); 4408585484eSchristos evdns_base_resolve_ipv6(base, "zz.example.com", DNS_QUERY_NO_SEARCH, 4418585484eSchristos dns_server_gethostbyname_cb, NULL); 4428585484eSchristos resolve_addr.s_addr = htonl(0xc0a80b0bUL); /* 192.168.11.11 */ 4438585484eSchristos evdns_base_resolve_reverse(base, &resolve_addr, 0, 4448585484eSchristos dns_server_gethostbyname_cb, NULL); 4458585484eSchristos memcpy(resolve_addr6.s6_addr, 4468585484eSchristos "\xff\xf0\x00\x00\x00\x00\xaa\xaa" 4478585484eSchristos "\x11\x11\x00\x00\x00\x00\xef\xef", 16); 4488585484eSchristos evdns_base_resolve_reverse_ipv6(base, &resolve_addr6, 0, 4498585484eSchristos dns_server_gethostbyname_cb, (void*)6); 4508585484eSchristos 4518585484eSchristos req = evdns_base_resolve_ipv4(base, 4528585484eSchristos "drop.example.com", DNS_QUERY_NO_SEARCH, 4538585484eSchristos dns_server_gethostbyname_cb, (void*)(char*)90909); 4548585484eSchristos 4558585484eSchristos evdns_cancel_request(base, req); 4568585484eSchristos 4578585484eSchristos event_dispatch(); 4588585484eSchristos 4598585484eSchristos tt_assert(dns_got_cancel); 4608585484eSchristos test_ok = dns_ok; 4618585484eSchristos 4628585484eSchristos end: 4638585484eSchristos if (port) 4648585484eSchristos evdns_close_server_port(port); 4658585484eSchristos if (sock >= 0) 4668585484eSchristos evutil_closesocket(sock); 4678585484eSchristos if (base) 4688585484eSchristos evdns_base_free(base, 0); 4698585484eSchristos } 4708585484eSchristos 4718585484eSchristos static int n_replies_left; 4728585484eSchristos static struct event_base *exit_base; 4737476e6e4Schristos static struct evdns_server_port *exit_port; 4748585484eSchristos 4758585484eSchristos struct generic_dns_callback_result { 4768585484eSchristos int result; 4778585484eSchristos char type; 4788585484eSchristos int count; 4798585484eSchristos int ttl; 4808585484eSchristos size_t addrs_len; 4818585484eSchristos void *addrs; 4828585484eSchristos char addrs_buf[256]; 4838585484eSchristos }; 4848585484eSchristos 4858585484eSchristos static void 4868585484eSchristos generic_dns_callback(int result, char type, int count, int ttl, void *addresses, 4878585484eSchristos void *arg) 4888585484eSchristos { 4898585484eSchristos size_t len; 4908585484eSchristos struct generic_dns_callback_result *res = arg; 4918585484eSchristos res->result = result; 4928585484eSchristos res->type = type; 4938585484eSchristos res->count = count; 4948585484eSchristos res->ttl = ttl; 4958585484eSchristos 4968585484eSchristos if (type == DNS_IPv4_A) 4978585484eSchristos len = count * 4; 4988585484eSchristos else if (type == DNS_IPv6_AAAA) 4998585484eSchristos len = count * 16; 5008585484eSchristos else if (type == DNS_PTR) 5018585484eSchristos len = strlen(addresses)+1; 5028585484eSchristos else { 5038585484eSchristos res->addrs_len = len = 0; 5048585484eSchristos res->addrs = NULL; 5058585484eSchristos } 5068585484eSchristos if (len) { 5078585484eSchristos res->addrs_len = len; 5088585484eSchristos if (len > 256) 5098585484eSchristos len = 256; 5108585484eSchristos memcpy(res->addrs_buf, addresses, len); 5118585484eSchristos res->addrs = res->addrs_buf; 5128585484eSchristos } 5138585484eSchristos 5147476e6e4Schristos --n_replies_left; 5157476e6e4Schristos if (n_replies_left == 0) { 5167476e6e4Schristos if (exit_port) { 5177476e6e4Schristos evdns_close_server_port(exit_port); 5187476e6e4Schristos exit_port = NULL; 5197476e6e4Schristos } else 5208585484eSchristos event_base_loopexit(exit_base, NULL); 5218585484eSchristos } 5227476e6e4Schristos } 5238585484eSchristos 5248585484eSchristos static struct regress_dns_server_table search_table[] = { 525*eabc0478Schristos { "host.a.example.com", "err", "3", 0, 0 }, 526*eabc0478Schristos { "host.b.example.com", "err", "3", 0, 0 }, 527*eabc0478Schristos { "host.c.example.com", "A", "11.22.33.44", 0, 0 }, 528*eabc0478Schristos { "host2.a.example.com", "err", "3", 0, 0 }, 529*eabc0478Schristos { "host2.b.example.com", "A", "200.100.0.100", 0, 0 }, 530*eabc0478Schristos { "host2.c.example.com", "err", "3", 0, 0 }, 531*eabc0478Schristos { "hostn.a.example.com", "errsoa", "0", 0, 0 }, 532*eabc0478Schristos { "hostn.b.example.com", "errsoa", "3", 0, 0 }, 533*eabc0478Schristos { "hostn.c.example.com", "err", "0", 0, 0 }, 5348585484eSchristos 535*eabc0478Schristos { "host", "err", "3", 0, 0 }, 536*eabc0478Schristos { "host2", "err", "3", 0, 0 }, 537*eabc0478Schristos { "*", "err", "3", 0, 0 }, 538*eabc0478Schristos { NULL, NULL, NULL, 0, 0 } 5398585484eSchristos }; 5408585484eSchristos static void 541*eabc0478Schristos dns_search_test_impl(void *arg, int lower) 5428585484eSchristos { 543*eabc0478Schristos struct regress_dns_server_table table[ARRAY_SIZE(search_table)]; 5448585484eSchristos struct basic_test_data *data = arg; 5458585484eSchristos struct event_base *base = data->base; 5468585484eSchristos struct evdns_base *dns = NULL; 5478585484eSchristos ev_uint16_t portnum = 0; 5488585484eSchristos char buf[64]; 5498585484eSchristos 5508585484eSchristos struct generic_dns_callback_result r[8]; 551*eabc0478Schristos size_t i; 5528585484eSchristos 553*eabc0478Schristos for (i = 0; i < ARRAY_SIZE(table); ++i) { 554*eabc0478Schristos table[i] = search_table[i]; 555*eabc0478Schristos table[i].lower = lower; 556*eabc0478Schristos } 557*eabc0478Schristos 558*eabc0478Schristos tt_assert(regress_dnsserver(base, &portnum, table)); 5598585484eSchristos evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum); 5608585484eSchristos 5618585484eSchristos dns = evdns_base_new(base, 0); 5628585484eSchristos tt_assert(!evdns_base_nameserver_ip_add(dns, buf)); 5638585484eSchristos 5648585484eSchristos evdns_base_search_add(dns, "a.example.com"); 5658585484eSchristos evdns_base_search_add(dns, "b.example.com"); 5668585484eSchristos evdns_base_search_add(dns, "c.example.com"); 5678585484eSchristos 568*eabc0478Schristos n_replies_left = ARRAY_SIZE(r); 5698585484eSchristos exit_base = base; 5708585484eSchristos 5718585484eSchristos evdns_base_resolve_ipv4(dns, "host", 0, generic_dns_callback, &r[0]); 5728585484eSchristos evdns_base_resolve_ipv4(dns, "host2", 0, generic_dns_callback, &r[1]); 5738585484eSchristos evdns_base_resolve_ipv4(dns, "host", DNS_NO_SEARCH, generic_dns_callback, &r[2]); 5748585484eSchristos evdns_base_resolve_ipv4(dns, "host2", DNS_NO_SEARCH, generic_dns_callback, &r[3]); 5758585484eSchristos evdns_base_resolve_ipv4(dns, "host3", 0, generic_dns_callback, &r[4]); 5768585484eSchristos evdns_base_resolve_ipv4(dns, "hostn.a.example.com", DNS_NO_SEARCH, generic_dns_callback, &r[5]); 5778585484eSchristos evdns_base_resolve_ipv4(dns, "hostn.b.example.com", DNS_NO_SEARCH, generic_dns_callback, &r[6]); 5788585484eSchristos evdns_base_resolve_ipv4(dns, "hostn.c.example.com", DNS_NO_SEARCH, generic_dns_callback, &r[7]); 5798585484eSchristos 5808585484eSchristos event_base_dispatch(base); 5818585484eSchristos 5828585484eSchristos tt_int_op(r[0].type, ==, DNS_IPv4_A); 5838585484eSchristos tt_int_op(r[0].count, ==, 1); 5848585484eSchristos tt_int_op(((ev_uint32_t*)r[0].addrs)[0], ==, htonl(0x0b16212c)); 5858585484eSchristos tt_int_op(r[1].type, ==, DNS_IPv4_A); 5868585484eSchristos tt_int_op(r[1].count, ==, 1); 5878585484eSchristos tt_int_op(((ev_uint32_t*)r[1].addrs)[0], ==, htonl(0xc8640064)); 5888585484eSchristos tt_int_op(r[2].result, ==, DNS_ERR_NOTEXIST); 5898585484eSchristos tt_int_op(r[3].result, ==, DNS_ERR_NOTEXIST); 5908585484eSchristos tt_int_op(r[4].result, ==, DNS_ERR_NOTEXIST); 5918585484eSchristos tt_int_op(r[5].result, ==, DNS_ERR_NODATA); 5928585484eSchristos tt_int_op(r[5].ttl, ==, 42); 5938585484eSchristos tt_int_op(r[6].result, ==, DNS_ERR_NOTEXIST); 5948585484eSchristos tt_int_op(r[6].ttl, ==, 42); 5958585484eSchristos tt_int_op(r[7].result, ==, DNS_ERR_NODATA); 5968585484eSchristos tt_int_op(r[7].ttl, ==, 0); 5978585484eSchristos 5988585484eSchristos end: 5998585484eSchristos if (dns) 6008585484eSchristos evdns_base_free(dns, 0); 6018585484eSchristos 6028585484eSchristos regress_clean_dnsserver(); 6038585484eSchristos } 604*eabc0478Schristos static void 605*eabc0478Schristos dns_search_empty_test(void *arg) 606*eabc0478Schristos { 607*eabc0478Schristos struct basic_test_data *data = arg; 608*eabc0478Schristos struct event_base *base = data->base; 609*eabc0478Schristos struct evdns_base *dns = NULL; 610*eabc0478Schristos 611*eabc0478Schristos dns = evdns_base_new(base, 0); 612*eabc0478Schristos 613*eabc0478Schristos evdns_base_search_add(dns, "whatever.example.com"); 614*eabc0478Schristos 615*eabc0478Schristos n_replies_left = 1; 616*eabc0478Schristos exit_base = base; 617*eabc0478Schristos 618*eabc0478Schristos tt_ptr_op(evdns_base_resolve_ipv4(dns, "", 0, generic_dns_callback, NULL), ==, NULL); 619*eabc0478Schristos 620*eabc0478Schristos end: 621*eabc0478Schristos if (dns) 622*eabc0478Schristos evdns_base_free(dns, 0); 623*eabc0478Schristos } 624*eabc0478Schristos static void dns_search_test(void *arg) { dns_search_test_impl(arg, 0); } 625*eabc0478Schristos static void dns_search_lower_test(void *arg) { dns_search_test_impl(arg, 1); } 6268585484eSchristos 6278585484eSchristos static int request_count = 0; 6288585484eSchristos static struct evdns_request *current_req = NULL; 6298585484eSchristos 6308585484eSchristos static void 6318585484eSchristos search_cancel_server_cb(struct evdns_server_request *req, void *data) 6328585484eSchristos { 6338585484eSchristos const char *question; 6348585484eSchristos 6358585484eSchristos if (req->nquestions != 1) 6368585484eSchristos TT_DIE(("Only handling one question at a time; got %d", 6378585484eSchristos req->nquestions)); 6388585484eSchristos 6398585484eSchristos question = req->questions[0]->name; 6408585484eSchristos 6418585484eSchristos TT_BLATHER(("got question, %s", question)); 6428585484eSchristos 6438585484eSchristos tt_assert(request_count > 0); 6448585484eSchristos tt_assert(!evdns_server_request_respond(req, 3)); 6458585484eSchristos 6468585484eSchristos if (!--request_count) 6478585484eSchristos evdns_cancel_request(NULL, current_req); 6488585484eSchristos 6498585484eSchristos end: 6508585484eSchristos ; 6518585484eSchristos } 6528585484eSchristos 6538585484eSchristos static void 6548585484eSchristos dns_search_cancel_test(void *arg) 6558585484eSchristos { 6568585484eSchristos struct basic_test_data *data = arg; 6578585484eSchristos struct event_base *base = data->base; 6588585484eSchristos struct evdns_base *dns = NULL; 6598585484eSchristos struct evdns_server_port *port = NULL; 6608585484eSchristos ev_uint16_t portnum = 0; 6618585484eSchristos struct generic_dns_callback_result r1; 6628585484eSchristos char buf[64]; 6638585484eSchristos 6648585484eSchristos port = regress_get_dnsserver(base, &portnum, NULL, 6658585484eSchristos search_cancel_server_cb, NULL); 6668585484eSchristos tt_assert(port); 6678585484eSchristos evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum); 6688585484eSchristos 6698585484eSchristos dns = evdns_base_new(base, 0); 6708585484eSchristos tt_assert(!evdns_base_nameserver_ip_add(dns, buf)); 6718585484eSchristos 6728585484eSchristos evdns_base_search_add(dns, "a.example.com"); 6738585484eSchristos evdns_base_search_add(dns, "b.example.com"); 6748585484eSchristos evdns_base_search_add(dns, "c.example.com"); 6758585484eSchristos evdns_base_search_add(dns, "d.example.com"); 6768585484eSchristos 6778585484eSchristos exit_base = base; 6788585484eSchristos request_count = 3; 6798585484eSchristos n_replies_left = 1; 6808585484eSchristos 6818585484eSchristos current_req = evdns_base_resolve_ipv4(dns, "host", 0, 6828585484eSchristos generic_dns_callback, &r1); 6838585484eSchristos event_base_dispatch(base); 6848585484eSchristos 6858585484eSchristos tt_int_op(r1.result, ==, DNS_ERR_CANCEL); 6868585484eSchristos 6878585484eSchristos end: 6888585484eSchristos if (port) 6898585484eSchristos evdns_close_server_port(port); 6908585484eSchristos if (dns) 6918585484eSchristos evdns_base_free(dns, 0); 6928585484eSchristos } 6938585484eSchristos 6948585484eSchristos static void 6958585484eSchristos fail_server_cb(struct evdns_server_request *req, void *data) 6968585484eSchristos { 6978585484eSchristos const char *question; 6988585484eSchristos int *count = data; 6998585484eSchristos struct in_addr in; 7008585484eSchristos 7018585484eSchristos /* Drop the first N requests that we get. */ 7028585484eSchristos if (*count > 0) { 7038585484eSchristos --*count; 7048585484eSchristos tt_want(! evdns_server_request_drop(req)); 7058585484eSchristos return; 7068585484eSchristos } 7078585484eSchristos 7088585484eSchristos if (req->nquestions != 1) 7098585484eSchristos TT_DIE(("Only handling one question at a time; got %d", 7108585484eSchristos req->nquestions)); 7118585484eSchristos 7128585484eSchristos question = req->questions[0]->name; 7138585484eSchristos 7148585484eSchristos if (!evutil_ascii_strcasecmp(question, "google.com")) { 7158585484eSchristos /* Detect a probe, and get out of the loop. */ 7168585484eSchristos event_base_loopexit(exit_base, NULL); 7178585484eSchristos } 7188585484eSchristos 719b8ecfcfeSchristos tt_assert(evutil_inet_pton(AF_INET, "16.32.64.128", &in)); 7208585484eSchristos evdns_server_request_add_a_reply(req, question, 1, &in.s_addr, 7218585484eSchristos 100); 7228585484eSchristos tt_assert(! evdns_server_request_respond(req, 0)) 7238585484eSchristos return; 7248585484eSchristos end: 7258585484eSchristos tt_want(! evdns_server_request_drop(req)); 7268585484eSchristos } 7278585484eSchristos 7288585484eSchristos static void 7297476e6e4Schristos dns_retry_test_impl(void *arg, int flags) 7308585484eSchristos { 7318585484eSchristos struct basic_test_data *data = arg; 7328585484eSchristos struct event_base *base = data->base; 7338585484eSchristos struct evdns_server_port *port = NULL; 7348585484eSchristos struct evdns_base *dns = NULL; 7358585484eSchristos int drop_count = 2; 7368585484eSchristos ev_uint16_t portnum = 0; 7378585484eSchristos char buf[64]; 7388585484eSchristos 7398585484eSchristos struct generic_dns_callback_result r1; 7408585484eSchristos 7418585484eSchristos port = regress_get_dnsserver(base, &portnum, NULL, 7428585484eSchristos fail_server_cb, &drop_count); 7438585484eSchristos tt_assert(port); 7448585484eSchristos evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum); 7458585484eSchristos 7467476e6e4Schristos dns = evdns_base_new(base, flags); 7478585484eSchristos tt_assert(!evdns_base_nameserver_ip_add(dns, buf)); 7488585484eSchristos tt_assert(! evdns_base_set_option(dns, "timeout", "0.2")); 7498585484eSchristos tt_assert(! evdns_base_set_option(dns, "max-timeouts:", "10")); 7508585484eSchristos tt_assert(! evdns_base_set_option(dns, "initial-probe-timeout", "0.1")); 7518585484eSchristos 7528585484eSchristos evdns_base_resolve_ipv4(dns, "host.example.com", 0, 7538585484eSchristos generic_dns_callback, &r1); 7548585484eSchristos 7558585484eSchristos n_replies_left = 1; 7568585484eSchristos exit_base = base; 7578585484eSchristos 7588585484eSchristos event_base_dispatch(base); 7598585484eSchristos 7608585484eSchristos tt_int_op(drop_count, ==, 0); 7618585484eSchristos 7628585484eSchristos tt_int_op(r1.type, ==, DNS_IPv4_A); 7638585484eSchristos tt_int_op(r1.count, ==, 1); 7648585484eSchristos tt_int_op(((ev_uint32_t*)r1.addrs)[0], ==, htonl(0x10204080)); 7658585484eSchristos 7668585484eSchristos /* Now try again, but this time have the server get treated as 7678585484eSchristos * failed, so we can send it a test probe. */ 7688585484eSchristos drop_count = 4; 7698585484eSchristos tt_assert(! evdns_base_set_option(dns, "max-timeouts:", "2")); 7708585484eSchristos tt_assert(! evdns_base_set_option(dns, "attempts:", "3")); 7718585484eSchristos memset(&r1, 0, sizeof(r1)); 7728585484eSchristos 7738585484eSchristos evdns_base_resolve_ipv4(dns, "host.example.com", 0, 7748585484eSchristos generic_dns_callback, &r1); 7758585484eSchristos 7768585484eSchristos n_replies_left = 2; 7778585484eSchristos 7788585484eSchristos /* This will run until it answers the "google.com" probe request. */ 7798585484eSchristos event_base_dispatch(base); 7808585484eSchristos 7818585484eSchristos /* We'll treat the server as failed here. */ 7828585484eSchristos tt_int_op(r1.result, ==, DNS_ERR_TIMEOUT); 7838585484eSchristos 7848585484eSchristos /* It should work this time. */ 7858585484eSchristos tt_int_op(drop_count, ==, 0); 7868585484eSchristos evdns_base_resolve_ipv4(dns, "host.example.com", 0, 7878585484eSchristos generic_dns_callback, &r1); 7888585484eSchristos 7898585484eSchristos event_base_dispatch(base); 7908585484eSchristos tt_int_op(r1.result, ==, DNS_ERR_NONE); 7918585484eSchristos tt_int_op(r1.type, ==, DNS_IPv4_A); 7928585484eSchristos tt_int_op(r1.count, ==, 1); 7938585484eSchristos tt_int_op(((ev_uint32_t*)r1.addrs)[0], ==, htonl(0x10204080)); 7948585484eSchristos 7958585484eSchristos end: 7968585484eSchristos if (dns) 7978585484eSchristos evdns_base_free(dns, 0); 7988585484eSchristos if (port) 7998585484eSchristos evdns_close_server_port(port); 8008585484eSchristos } 8017476e6e4Schristos static void 8027476e6e4Schristos dns_retry_test(void *arg) 8037476e6e4Schristos { 8047476e6e4Schristos dns_retry_test_impl(arg, 0); 8057476e6e4Schristos } 8067476e6e4Schristos static void 8077476e6e4Schristos dns_retry_disable_when_inactive_test(void *arg) 8087476e6e4Schristos { 8097476e6e4Schristos dns_retry_test_impl(arg, EVDNS_BASE_DISABLE_WHEN_INACTIVE); 8107476e6e4Schristos } 8118585484eSchristos 8128585484eSchristos static struct regress_dns_server_table internal_error_table[] = { 8138585484eSchristos /* Error 4 (NOTIMPL) makes us reissue the request to another server 8148585484eSchristos if we can. 8158585484eSchristos 8168585484eSchristos XXXX we should reissue under a much wider set of circumstances! 8178585484eSchristos */ 818*eabc0478Schristos { "foof.example.com", "err", "4", 0, 0 }, 819*eabc0478Schristos { NULL, NULL, NULL, 0, 0 } 8208585484eSchristos }; 8218585484eSchristos 8228585484eSchristos static struct regress_dns_server_table reissue_table[] = { 823*eabc0478Schristos { "foof.example.com", "A", "240.15.240.15", 0, 0 }, 824*eabc0478Schristos { NULL, NULL, NULL, 0, 0 } 8258585484eSchristos }; 8268585484eSchristos 8278585484eSchristos static void 8287476e6e4Schristos dns_reissue_test_impl(void *arg, int flags) 8298585484eSchristos { 8308585484eSchristos struct basic_test_data *data = arg; 8318585484eSchristos struct event_base *base = data->base; 8328585484eSchristos struct evdns_server_port *port1 = NULL, *port2 = NULL; 8338585484eSchristos struct evdns_base *dns = NULL; 8348585484eSchristos struct generic_dns_callback_result r1; 8358585484eSchristos ev_uint16_t portnum1 = 0, portnum2=0; 8368585484eSchristos char buf1[64], buf2[64]; 8378585484eSchristos 8388585484eSchristos port1 = regress_get_dnsserver(base, &portnum1, NULL, 8398585484eSchristos regress_dns_server_cb, internal_error_table); 8408585484eSchristos tt_assert(port1); 8418585484eSchristos port2 = regress_get_dnsserver(base, &portnum2, NULL, 8428585484eSchristos regress_dns_server_cb, reissue_table); 8438585484eSchristos tt_assert(port2); 8448585484eSchristos evutil_snprintf(buf1, sizeof(buf1), "127.0.0.1:%d", (int)portnum1); 8458585484eSchristos evutil_snprintf(buf2, sizeof(buf2), "127.0.0.1:%d", (int)portnum2); 8468585484eSchristos 8477476e6e4Schristos dns = evdns_base_new(base, flags); 8488585484eSchristos tt_assert(!evdns_base_nameserver_ip_add(dns, buf1)); 8498585484eSchristos tt_assert(! evdns_base_set_option(dns, "timeout:", "0.3")); 8508585484eSchristos tt_assert(! evdns_base_set_option(dns, "max-timeouts:", "2")); 8518585484eSchristos tt_assert(! evdns_base_set_option(dns, "attempts:", "5")); 8528585484eSchristos 8538585484eSchristos memset(&r1, 0, sizeof(r1)); 8548585484eSchristos evdns_base_resolve_ipv4(dns, "foof.example.com", 0, 8558585484eSchristos generic_dns_callback, &r1); 8568585484eSchristos 8578585484eSchristos /* Add this after, so that we are sure to get a reissue. */ 8588585484eSchristos tt_assert(!evdns_base_nameserver_ip_add(dns, buf2)); 8598585484eSchristos 8608585484eSchristos n_replies_left = 1; 8618585484eSchristos exit_base = base; 8628585484eSchristos 8638585484eSchristos event_base_dispatch(base); 8648585484eSchristos tt_int_op(r1.result, ==, DNS_ERR_NONE); 8658585484eSchristos tt_int_op(r1.type, ==, DNS_IPv4_A); 8668585484eSchristos tt_int_op(r1.count, ==, 1); 8678585484eSchristos tt_int_op(((ev_uint32_t*)r1.addrs)[0], ==, htonl(0xf00ff00f)); 8688585484eSchristos 8698585484eSchristos /* Make sure we dropped at least once. */ 8708585484eSchristos tt_int_op(internal_error_table[0].seen, >, 0); 8718585484eSchristos 8728585484eSchristos end: 8738585484eSchristos if (dns) 8748585484eSchristos evdns_base_free(dns, 0); 8758585484eSchristos if (port1) 8768585484eSchristos evdns_close_server_port(port1); 8778585484eSchristos if (port2) 8788585484eSchristos evdns_close_server_port(port2); 8798585484eSchristos } 8807476e6e4Schristos static void 8817476e6e4Schristos dns_reissue_test(void *arg) 8827476e6e4Schristos { 8837476e6e4Schristos dns_reissue_test_impl(arg, 0); 8847476e6e4Schristos } 8857476e6e4Schristos static void 8867476e6e4Schristos dns_reissue_disable_when_inactive_test(void *arg) 8877476e6e4Schristos { 8887476e6e4Schristos dns_reissue_test_impl(arg, EVDNS_BASE_DISABLE_WHEN_INACTIVE); 8897476e6e4Schristos } 8908585484eSchristos 8918585484eSchristos #if 0 8928585484eSchristos static void 8938585484eSchristos dumb_bytes_fn(char *p, size_t n) 8948585484eSchristos { 8958585484eSchristos unsigned i; 8968585484eSchristos /* This gets us 6 bits of entropy per transaction ID, which means we 8978585484eSchristos * will have probably have collisions and need to pick again. */ 8988585484eSchristos for (i=0;i<n;++i) 8998585484eSchristos p[i] = (char)(rand() & 7); 9008585484eSchristos } 9018585484eSchristos #endif 9028585484eSchristos 9038585484eSchristos static void 9047476e6e4Schristos dns_inflight_test_impl(void *arg, int flags) 9058585484eSchristos { 9068585484eSchristos struct basic_test_data *data = arg; 9078585484eSchristos struct event_base *base = data->base; 9088585484eSchristos struct evdns_base *dns = NULL; 9097476e6e4Schristos struct evdns_server_port *dns_port = NULL; 9108585484eSchristos ev_uint16_t portnum = 0; 9118585484eSchristos char buf[64]; 9127476e6e4Schristos int disable_when_inactive = flags & EVDNS_BASE_DISABLE_WHEN_INACTIVE; 9138585484eSchristos 9148585484eSchristos struct generic_dns_callback_result r[20]; 9158585484eSchristos int i; 9168585484eSchristos 9177476e6e4Schristos dns_port = regress_get_dnsserver(base, &portnum, NULL, 9187476e6e4Schristos regress_dns_server_cb, reissue_table); 9197476e6e4Schristos tt_assert(dns_port); 9207476e6e4Schristos if (disable_when_inactive) { 9217476e6e4Schristos exit_port = dns_port; 9227476e6e4Schristos } 9237476e6e4Schristos 9248585484eSchristos evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum); 9258585484eSchristos 9267476e6e4Schristos dns = evdns_base_new(base, flags); 9278585484eSchristos tt_assert(!evdns_base_nameserver_ip_add(dns, buf)); 9288585484eSchristos tt_assert(! evdns_base_set_option(dns, "max-inflight:", "3")); 9298585484eSchristos tt_assert(! evdns_base_set_option(dns, "randomize-case:", "0")); 9308585484eSchristos 9318585484eSchristos for (i=0;i<20;++i) 9328585484eSchristos evdns_base_resolve_ipv4(dns, "foof.example.com", 0, generic_dns_callback, &r[i]); 9338585484eSchristos 9348585484eSchristos n_replies_left = 20; 9358585484eSchristos exit_base = base; 9368585484eSchristos 9378585484eSchristos event_base_dispatch(base); 9388585484eSchristos 9398585484eSchristos for (i=0;i<20;++i) { 9408585484eSchristos tt_int_op(r[i].type, ==, DNS_IPv4_A); 9418585484eSchristos tt_int_op(r[i].count, ==, 1); 9428585484eSchristos tt_int_op(((ev_uint32_t*)r[i].addrs)[0], ==, htonl(0xf00ff00f)); 9438585484eSchristos } 9448585484eSchristos 9458585484eSchristos end: 9468585484eSchristos if (dns) 9478585484eSchristos evdns_base_free(dns, 0); 9487476e6e4Schristos if (exit_port) { 9497476e6e4Schristos evdns_close_server_port(exit_port); 9507476e6e4Schristos exit_port = NULL; 9517476e6e4Schristos } else if (! disable_when_inactive) { 9527476e6e4Schristos evdns_close_server_port(dns_port); 9537476e6e4Schristos } 9547476e6e4Schristos } 9557476e6e4Schristos 9567476e6e4Schristos static void 9577476e6e4Schristos dns_inflight_test(void *arg) 9587476e6e4Schristos { 9597476e6e4Schristos dns_inflight_test_impl(arg, 0); 9607476e6e4Schristos } 9617476e6e4Schristos 9627476e6e4Schristos static void 9637476e6e4Schristos dns_disable_when_inactive_test(void *arg) 9647476e6e4Schristos { 9657476e6e4Schristos dns_inflight_test_impl(arg, EVDNS_BASE_DISABLE_WHEN_INACTIVE); 9667476e6e4Schristos } 9677476e6e4Schristos 9687476e6e4Schristos static void 9697476e6e4Schristos dns_disable_when_inactive_no_ns_test(void *arg) 9707476e6e4Schristos { 9717476e6e4Schristos struct basic_test_data *data = arg; 9727476e6e4Schristos struct event_base *base = data->base, *inactive_base; 9737476e6e4Schristos struct evdns_base *dns = NULL; 9747476e6e4Schristos ev_uint16_t portnum = 0; 9757476e6e4Schristos char buf[64]; 9767476e6e4Schristos struct generic_dns_callback_result r; 9777476e6e4Schristos 9787476e6e4Schristos inactive_base = event_base_new(); 9797476e6e4Schristos tt_assert(inactive_base); 9807476e6e4Schristos 9817476e6e4Schristos /** Create dns server with inactive base, to avoid replying to clients */ 9827476e6e4Schristos tt_assert(regress_dnsserver(inactive_base, &portnum, search_table)); 9837476e6e4Schristos evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum); 9847476e6e4Schristos 9857476e6e4Schristos dns = evdns_base_new(base, EVDNS_BASE_DISABLE_WHEN_INACTIVE); 9867476e6e4Schristos tt_assert(!evdns_base_nameserver_ip_add(dns, buf)); 9877476e6e4Schristos tt_assert(! evdns_base_set_option(dns, "timeout:", "0.1")); 9887476e6e4Schristos 9897476e6e4Schristos evdns_base_resolve_ipv4(dns, "foof.example.com", 0, generic_dns_callback, &r); 9907476e6e4Schristos n_replies_left = 1; 9917476e6e4Schristos exit_base = base; 9927476e6e4Schristos 9937476e6e4Schristos event_base_dispatch(base); 9947476e6e4Schristos 9957476e6e4Schristos tt_int_op(n_replies_left, ==, 0); 9967476e6e4Schristos 9977476e6e4Schristos tt_int_op(r.result, ==, DNS_ERR_TIMEOUT); 9987476e6e4Schristos tt_int_op(r.count, ==, 0); 9997476e6e4Schristos tt_ptr_op(r.addrs, ==, NULL); 10007476e6e4Schristos 10017476e6e4Schristos end: 10027476e6e4Schristos if (dns) 10037476e6e4Schristos evdns_base_free(dns, 0); 10048585484eSchristos regress_clean_dnsserver(); 10057476e6e4Schristos if (inactive_base) 10067476e6e4Schristos event_base_free(inactive_base); 10078585484eSchristos } 10088585484eSchristos 1009*eabc0478Schristos static void 1010*eabc0478Schristos dns_initialize_nameservers_test(void *arg) 1011*eabc0478Schristos { 1012*eabc0478Schristos struct basic_test_data *data = arg; 1013*eabc0478Schristos struct event_base *base = data->base; 1014*eabc0478Schristos struct evdns_base *dns = NULL; 1015*eabc0478Schristos 1016*eabc0478Schristos dns = evdns_base_new(base, 0); 1017*eabc0478Schristos tt_assert(dns); 1018*eabc0478Schristos tt_int_op(evdns_base_get_nameserver_addr(dns, 0, NULL, 0), ==, -1); 1019*eabc0478Schristos evdns_base_free(dns, 0); 1020*eabc0478Schristos 1021*eabc0478Schristos dns = evdns_base_new(base, EVDNS_BASE_INITIALIZE_NAMESERVERS); 1022*eabc0478Schristos tt_assert(dns); 1023*eabc0478Schristos tt_int_op(evdns_base_get_nameserver_addr(dns, 0, NULL, 0), ==, sizeof(struct sockaddr)); 1024*eabc0478Schristos 1025*eabc0478Schristos end: 1026*eabc0478Schristos if (dns) 1027*eabc0478Schristos evdns_base_free(dns, 0); 1028*eabc0478Schristos } 1029*eabc0478Schristos #ifndef _WIN32 1030*eabc0478Schristos #define RESOLV_FILE "empty-resolv.conf" 1031*eabc0478Schristos static void 1032*eabc0478Schristos dns_nameservers_no_default_test(void *arg) 1033*eabc0478Schristos { 1034*eabc0478Schristos struct basic_test_data *data = arg; 1035*eabc0478Schristos struct event_base *base = data->base; 1036*eabc0478Schristos struct evdns_base *dns = NULL; 1037*eabc0478Schristos int ok = access(RESOLV_FILE, R_OK); 1038*eabc0478Schristos 1039*eabc0478Schristos tt_assert(ok); 1040*eabc0478Schristos 1041*eabc0478Schristos dns = evdns_base_new(base, 0); 1042*eabc0478Schristos tt_assert(dns); 1043*eabc0478Schristos tt_int_op(evdns_base_get_nameserver_addr(dns, 0, NULL, 0), ==, -1); 1044*eabc0478Schristos 1045*eabc0478Schristos /* We cannot test 1046*eabc0478Schristos * EVDNS_BASE_INITIALIZE_NAMESERVERS|EVDNS_BASE_NAMESERVERS_NO_DEFAULT 1047*eabc0478Schristos * because we cannot mock "/etc/resolv.conf" (yet). */ 1048*eabc0478Schristos 1049*eabc0478Schristos evdns_base_resolv_conf_parse(dns, 1050*eabc0478Schristos DNS_OPTIONS_ALL|DNS_OPTION_NAMESERVERS_NO_DEFAULT, RESOLV_FILE); 1051*eabc0478Schristos tt_int_op(evdns_base_get_nameserver_addr(dns, 0, NULL, 0), ==, -1); 1052*eabc0478Schristos 1053*eabc0478Schristos evdns_base_resolv_conf_parse(dns, DNS_OPTIONS_ALL, RESOLV_FILE); 1054*eabc0478Schristos tt_int_op(evdns_base_get_nameserver_addr(dns, 0, NULL, 0), ==, sizeof(struct sockaddr)); 1055*eabc0478Schristos 1056*eabc0478Schristos end: 1057*eabc0478Schristos if (dns) 1058*eabc0478Schristos evdns_base_free(dns, 0); 1059*eabc0478Schristos } 1060*eabc0478Schristos #endif 1061*eabc0478Schristos 10628585484eSchristos /* === Test for bufferevent_socket_connect_hostname */ 10638585484eSchristos 10648585484eSchristos static int total_connected_or_failed = 0; 10658585484eSchristos static int total_n_accepted = 0; 10668585484eSchristos static struct event_base *be_connect_hostname_base = NULL; 10678585484eSchristos 10688585484eSchristos /* Implements a DNS server for the connect_hostname test and the 10698585484eSchristos * getaddrinfo_async test */ 10708585484eSchristos static void 10718585484eSchristos be_getaddrinfo_server_cb(struct evdns_server_request *req, void *data) 10728585484eSchristos { 10738585484eSchristos int i; 10748585484eSchristos int *n_got_p=data; 10758585484eSchristos int added_any=0; 10768585484eSchristos ++*n_got_p; 10778585484eSchristos 10788585484eSchristos for (i = 0; i < req->nquestions; ++i) { 10798585484eSchristos const int qtype = req->questions[i]->type; 10808585484eSchristos const int qclass = req->questions[i]->dns_question_class; 10818585484eSchristos const char *qname = req->questions[i]->name; 10828585484eSchristos struct in_addr ans; 10838585484eSchristos struct in6_addr ans6; 10848585484eSchristos memset(&ans6, 0, sizeof(ans6)); 10858585484eSchristos 10868585484eSchristos TT_BLATHER(("Got question about %s, type=%d", qname, qtype)); 10878585484eSchristos 10888585484eSchristos if (qtype == EVDNS_TYPE_A && 10898585484eSchristos qclass == EVDNS_CLASS_INET && 10908585484eSchristos !evutil_ascii_strcasecmp(qname, "nobodaddy.example.com")) { 10918585484eSchristos ans.s_addr = htonl(0x7f000001); 10928585484eSchristos evdns_server_request_add_a_reply(req, qname, 10938585484eSchristos 1, &ans.s_addr, 2000); 10948585484eSchristos added_any = 1; 10958585484eSchristos } else if (!evutil_ascii_strcasecmp(qname, 10968585484eSchristos "nosuchplace.example.com")) { 10978585484eSchristos /* ok, just say notfound. */ 10988585484eSchristos } else if (!evutil_ascii_strcasecmp(qname, 10998585484eSchristos "both.example.com")) { 11008585484eSchristos if (qtype == EVDNS_TYPE_A) { 11018585484eSchristos ans.s_addr = htonl(0x50502020); 11028585484eSchristos evdns_server_request_add_a_reply(req, qname, 11038585484eSchristos 1, &ans.s_addr, 2000); 11048585484eSchristos added_any = 1; 11058585484eSchristos } else if (qtype == EVDNS_TYPE_AAAA) { 11068585484eSchristos ans6.s6_addr[0] = 0x80; 11078585484eSchristos ans6.s6_addr[1] = 0xff; 11088585484eSchristos ans6.s6_addr[14] = 0xbb; 11098585484eSchristos ans6.s6_addr[15] = 0xbb; 11108585484eSchristos evdns_server_request_add_aaaa_reply(req, qname, 11118585484eSchristos 1, &ans6.s6_addr, 2000); 11128585484eSchristos added_any = 1; 11138585484eSchristos } 11148585484eSchristos evdns_server_request_add_cname_reply(req, qname, 11158585484eSchristos "both-canonical.example.com", 1000); 11168585484eSchristos } else if (!evutil_ascii_strcasecmp(qname, 11178585484eSchristos "v4only.example.com") || 11188585484eSchristos !evutil_ascii_strcasecmp(qname, "v4assert.example.com")) { 11198585484eSchristos if (qtype == EVDNS_TYPE_A) { 11208585484eSchristos ans.s_addr = htonl(0x12345678); 11218585484eSchristos evdns_server_request_add_a_reply(req, qname, 11228585484eSchristos 1, &ans.s_addr, 2000); 11238585484eSchristos added_any = 1; 11248585484eSchristos } else if (!evutil_ascii_strcasecmp(qname, 11258585484eSchristos "v4assert.example.com")) { 11268585484eSchristos TT_FAIL(("Got an AAAA request for v4assert")); 11278585484eSchristos } 11288585484eSchristos } else if (!evutil_ascii_strcasecmp(qname, 11298585484eSchristos "v6only.example.com") || 11308585484eSchristos !evutil_ascii_strcasecmp(qname, "v6assert.example.com")) { 11318585484eSchristos if (qtype == EVDNS_TYPE_AAAA) { 11328585484eSchristos ans6.s6_addr[0] = 0x0b; 11338585484eSchristos ans6.s6_addr[1] = 0x0b; 11348585484eSchristos ans6.s6_addr[14] = 0xf0; 11358585484eSchristos ans6.s6_addr[15] = 0x0d; 11368585484eSchristos evdns_server_request_add_aaaa_reply(req, qname, 11378585484eSchristos 1, &ans6.s6_addr, 2000); 11388585484eSchristos added_any = 1; 11398585484eSchristos } else if (!evutil_ascii_strcasecmp(qname, 11408585484eSchristos "v6assert.example.com")) { 11418585484eSchristos TT_FAIL(("Got a A request for v6assert")); 11428585484eSchristos } 11438585484eSchristos } else if (!evutil_ascii_strcasecmp(qname, 11448585484eSchristos "v6timeout.example.com")) { 11458585484eSchristos if (qtype == EVDNS_TYPE_A) { 11468585484eSchristos ans.s_addr = htonl(0xabcdef01); 11478585484eSchristos evdns_server_request_add_a_reply(req, qname, 11488585484eSchristos 1, &ans.s_addr, 2000); 11498585484eSchristos added_any = 1; 11508585484eSchristos } else if (qtype == EVDNS_TYPE_AAAA) { 11518585484eSchristos /* Let the v6 request time out.*/ 11528585484eSchristos evdns_server_request_drop(req); 11538585484eSchristos return; 11548585484eSchristos } 11558585484eSchristos } else if (!evutil_ascii_strcasecmp(qname, 11568585484eSchristos "v4timeout.example.com")) { 11578585484eSchristos if (qtype == EVDNS_TYPE_AAAA) { 11588585484eSchristos ans6.s6_addr[0] = 0x0a; 11598585484eSchristos ans6.s6_addr[1] = 0x0a; 11608585484eSchristos ans6.s6_addr[14] = 0xff; 11618585484eSchristos ans6.s6_addr[15] = 0x01; 11628585484eSchristos evdns_server_request_add_aaaa_reply(req, qname, 11638585484eSchristos 1, &ans6.s6_addr, 2000); 11648585484eSchristos added_any = 1; 11658585484eSchristos } else if (qtype == EVDNS_TYPE_A) { 11668585484eSchristos /* Let the v4 request time out.*/ 11678585484eSchristos evdns_server_request_drop(req); 11688585484eSchristos return; 11698585484eSchristos } 11708585484eSchristos } else if (!evutil_ascii_strcasecmp(qname, 11718585484eSchristos "v6timeout-nonexist.example.com")) { 11728585484eSchristos if (qtype == EVDNS_TYPE_A) { 11738585484eSchristos /* Fall through, give an nexist. */ 11748585484eSchristos } else if (qtype == EVDNS_TYPE_AAAA) { 11758585484eSchristos /* Let the v6 request time out.*/ 11768585484eSchristos evdns_server_request_drop(req); 11778585484eSchristos return; 11788585484eSchristos } 11798585484eSchristos } else if (!evutil_ascii_strcasecmp(qname, 11808585484eSchristos "all-timeout.example.com")) { 11818585484eSchristos /* drop all requests */ 11828585484eSchristos evdns_server_request_drop(req); 11838585484eSchristos return; 11848585484eSchristos } else { 11858585484eSchristos TT_GRIPE(("Got weird request for %s",qname)); 11868585484eSchristos } 11878585484eSchristos } 11888585484eSchristos if (added_any) { 11898585484eSchristos TT_BLATHER(("answering")); 11908585484eSchristos evdns_server_request_respond(req, 0); 11918585484eSchristos } else { 11928585484eSchristos TT_BLATHER(("saying nexist.")); 11938585484eSchristos evdns_server_request_respond(req, 3); 11948585484eSchristos } 11958585484eSchristos } 11968585484eSchristos 11978585484eSchristos /* Implements a listener for connect_hostname test. */ 11988585484eSchristos static void 11998585484eSchristos nil_accept_cb(struct evconnlistener *l, evutil_socket_t fd, struct sockaddr *s, 12008585484eSchristos int socklen, void *arg) 12018585484eSchristos { 12028585484eSchristos int *p = arg; 12038585484eSchristos (*p)++; 12048585484eSchristos ++total_n_accepted; 12058585484eSchristos /* don't do anything with the socket; let it close when we exit() */ 12068585484eSchristos if (total_n_accepted >= 3 && total_connected_or_failed >= 5) 12078585484eSchristos event_base_loopexit(be_connect_hostname_base, 12088585484eSchristos NULL); 12098585484eSchristos } 12108585484eSchristos 12118585484eSchristos struct be_conn_hostname_result { 12128585484eSchristos int dnserr; 12138585484eSchristos int what; 12148585484eSchristos }; 12158585484eSchristos 12168585484eSchristos /* Bufferevent event callback for the connect_hostname test: remembers what 12178585484eSchristos * event we got. */ 12188585484eSchristos static void 12198585484eSchristos be_connect_hostname_event_cb(struct bufferevent *bev, short what, void *ctx) 12208585484eSchristos { 12218585484eSchristos struct be_conn_hostname_result *got = ctx; 1222*eabc0478Schristos 1223*eabc0478Schristos if (got->what) { 1224*eabc0478Schristos TT_FAIL(("Two events on one bufferevent. %d,%d", 1225*eabc0478Schristos got->what, (int)what)); 1226*eabc0478Schristos } 1227*eabc0478Schristos 12288585484eSchristos TT_BLATHER(("Got a bufferevent event %d", what)); 12298585484eSchristos got->what = what; 12308585484eSchristos 12318585484eSchristos if ((what & BEV_EVENT_CONNECTED) || (what & BEV_EVENT_ERROR)) { 1232*eabc0478Schristos int expected = 3; 1233*eabc0478Schristos int r = bufferevent_socket_get_dns_error(bev); 1234*eabc0478Schristos 1235*eabc0478Schristos if (r) { 12368585484eSchristos got->dnserr = r; 12378585484eSchristos TT_BLATHER(("DNS error %d: %s", r, 12388585484eSchristos evutil_gai_strerror(r))); 1239*eabc0478Schristos } 1240*eabc0478Schristos ++total_connected_or_failed; 12418585484eSchristos TT_BLATHER(("Got %d connections or errors.", total_connected_or_failed)); 12428585484eSchristos 1243*eabc0478Schristos /** emfile test */ 1244*eabc0478Schristos if (errno == EMFILE) { 1245*eabc0478Schristos expected = 0; 1246*eabc0478Schristos } 1247*eabc0478Schristos 1248*eabc0478Schristos if (total_n_accepted >= expected && total_connected_or_failed >= 5) 12498585484eSchristos event_base_loopexit(be_connect_hostname_base, 12508585484eSchristos NULL); 12518585484eSchristos } 12528585484eSchristos } 12538585484eSchristos 12548585484eSchristos static void 12558585484eSchristos test_bufferevent_connect_hostname(void *arg) 12568585484eSchristos { 12578585484eSchristos struct basic_test_data *data = arg; 12588585484eSchristos struct evconnlistener *listener = NULL; 1259*eabc0478Schristos struct bufferevent *be[5]; 1260*eabc0478Schristos struct be_conn_hostname_result be_outcome[ARRAY_SIZE(be)]; 1261*eabc0478Schristos int expect_err; 12628585484eSchristos struct evdns_base *dns=NULL; 12638585484eSchristos struct evdns_server_port *port=NULL; 12648585484eSchristos struct sockaddr_in sin; 12658585484eSchristos int listener_port=-1; 12668585484eSchristos ev_uint16_t dns_port=0; 12678585484eSchristos int n_accept=0, n_dns=0; 12688585484eSchristos char buf[128]; 1269*eabc0478Schristos int emfile = data->setup_data && !strcmp(data->setup_data, "emfile"); 1270*eabc0478Schristos unsigned i; 1271*eabc0478Schristos int ret; 12728585484eSchristos 12738585484eSchristos be_connect_hostname_base = data->base; 12748585484eSchristos 12758585484eSchristos /* Bind an address and figure out what port it's on. */ 12768585484eSchristos memset(&sin, 0, sizeof(sin)); 12778585484eSchristos sin.sin_family = AF_INET; 12788585484eSchristos sin.sin_addr.s_addr = htonl(0x7f000001); /* 127.0.0.1 */ 12798585484eSchristos sin.sin_port = 0; 12808585484eSchristos listener = evconnlistener_new_bind(data->base, nil_accept_cb, 12818585484eSchristos &n_accept, 12828585484eSchristos LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_EXEC, 12838585484eSchristos -1, (struct sockaddr *)&sin, sizeof(sin)); 12848585484eSchristos tt_assert(listener); 12858585484eSchristos listener_port = regress_get_socket_port( 12868585484eSchristos evconnlistener_get_fd(listener)); 12878585484eSchristos 12888585484eSchristos port = regress_get_dnsserver(data->base, &dns_port, NULL, 12898585484eSchristos be_getaddrinfo_server_cb, &n_dns); 12908585484eSchristos tt_assert(port); 12918585484eSchristos tt_int_op(dns_port, >=, 0); 12928585484eSchristos 12938585484eSchristos /* Start an evdns_base that uses the server as its resolver. */ 12948585484eSchristos dns = evdns_base_new(data->base, 0); 12958585484eSchristos evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)dns_port); 12968585484eSchristos evdns_base_nameserver_ip_add(dns, buf); 12978585484eSchristos 1298*eabc0478Schristos #ifdef EVENT__HAVE_SETRLIMIT 1299*eabc0478Schristos if (emfile) { 1300*eabc0478Schristos int fd = socket(AF_INET, SOCK_STREAM, 0); 1301*eabc0478Schristos struct rlimit file = { fd, fd }; 1302*eabc0478Schristos 1303*eabc0478Schristos tt_int_op(fd, >=, 0); 1304*eabc0478Schristos tt_assert(!close(fd)); 1305*eabc0478Schristos 1306*eabc0478Schristos tt_assert(!setrlimit(RLIMIT_NOFILE, &file)); 1307*eabc0478Schristos } 1308*eabc0478Schristos #endif 1309*eabc0478Schristos 13108585484eSchristos /* Now, finally, at long last, launch the bufferevents. One should do 13118585484eSchristos * a failing lookup IP, one should do a successful lookup by IP, 13128585484eSchristos * and one should do a successful lookup by hostname. */ 1313*eabc0478Schristos for (i = 0; i < ARRAY_SIZE(be); ++i) { 1314*eabc0478Schristos memset(&be_outcome[i], 0, sizeof(be_outcome[i])); 1315*eabc0478Schristos be[i] = bufferevent_socket_new(data->base, -1, BEV_OPT_CLOSE_ON_FREE); 1316*eabc0478Schristos bufferevent_setcb(be[i], NULL, NULL, be_connect_hostname_event_cb, 1317*eabc0478Schristos &be_outcome[i]); 1318*eabc0478Schristos } 13198585484eSchristos 13208585484eSchristos /* Use the blocking resolver. This one will fail if your resolver 13218585484eSchristos * can't resolve localhost to 127.0.0.1 */ 1322*eabc0478Schristos tt_assert(!bufferevent_socket_connect_hostname(be[3], NULL, AF_INET, 13238585484eSchristos "localhost", listener_port)); 13248585484eSchristos /* Use the blocking resolver with a nonexistent hostname. */ 1325*eabc0478Schristos tt_assert(!bufferevent_socket_connect_hostname(be[4], NULL, AF_INET, 13268585484eSchristos "nonesuch.nowhere.example.com", 80)); 13278585484eSchristos { 13288585484eSchristos /* The blocking resolver will use the system nameserver, which 13298585484eSchristos * might tell us anything. (Yes, some twits even pretend that 13308585484eSchristos * example.com is real.) Let's see what answer to expect. */ 13318585484eSchristos struct evutil_addrinfo hints, *ai = NULL; 13328585484eSchristos memset(&hints, 0, sizeof(hints)); 13338585484eSchristos hints.ai_family = AF_INET; 13348585484eSchristos hints.ai_socktype = SOCK_STREAM; 13358585484eSchristos hints.ai_protocol = IPPROTO_TCP; 1336*eabc0478Schristos expect_err = evutil_getaddrinfo( 13378585484eSchristos "nonesuch.nowhere.example.com", "80", &hints, &ai); 13388585484eSchristos } 1339*eabc0478Schristos /* Launch an async resolve that will fail. */ 1340*eabc0478Schristos tt_assert(!bufferevent_socket_connect_hostname(be[0], dns, AF_INET, 1341*eabc0478Schristos "nosuchplace.example.com", listener_port)); 1342*eabc0478Schristos /* Connect to the IP without resolving. */ 1343*eabc0478Schristos tt_assert(!bufferevent_socket_connect_hostname(be[1], dns, AF_INET, 1344*eabc0478Schristos "127.0.0.1", listener_port)); 1345*eabc0478Schristos /* Launch an async resolve that will succeed. */ 1346*eabc0478Schristos tt_assert(!bufferevent_socket_connect_hostname(be[2], dns, AF_INET, 1347*eabc0478Schristos "nobodaddy.example.com", listener_port)); 13488585484eSchristos 1349*eabc0478Schristos ret = event_base_dispatch(data->base); 1350*eabc0478Schristos #ifdef __sun__ 1351*eabc0478Schristos if (emfile && !strcmp(event_base_get_method(data->base), "devpoll")) { 1352*eabc0478Schristos tt_int_op(ret, ==, -1); 1353*eabc0478Schristos /** DP_POLL failed */ 1354*eabc0478Schristos tt_skip(); 1355*eabc0478Schristos } else 1356*eabc0478Schristos #endif 1357*eabc0478Schristos { 1358*eabc0478Schristos tt_int_op(ret, ==, 0); 13598585484eSchristos } 13608585484eSchristos 1361*eabc0478Schristos tt_int_op(be_outcome[0].what, ==, BEV_EVENT_ERROR); 1362*eabc0478Schristos tt_int_op(be_outcome[0].dnserr, ==, EVUTIL_EAI_NONAME); 1363*eabc0478Schristos tt_int_op(be_outcome[1].what, ==, !emfile ? BEV_EVENT_CONNECTED : BEV_EVENT_ERROR); 1364*eabc0478Schristos tt_int_op(be_outcome[1].dnserr, ==, 0); 1365*eabc0478Schristos tt_int_op(be_outcome[2].what, ==, !emfile ? BEV_EVENT_CONNECTED : BEV_EVENT_ERROR); 1366*eabc0478Schristos tt_int_op(be_outcome[2].dnserr, ==, 0); 1367*eabc0478Schristos tt_int_op(be_outcome[3].what, ==, !emfile ? BEV_EVENT_CONNECTED : BEV_EVENT_ERROR); 1368*eabc0478Schristos if (!emfile) { 1369*eabc0478Schristos tt_int_op(be_outcome[3].dnserr, ==, 0); 1370*eabc0478Schristos } else { 1371*eabc0478Schristos tt_int_op(be_outcome[3].dnserr, !=, 0); 1372*eabc0478Schristos } 1373*eabc0478Schristos if (expect_err) { 1374*eabc0478Schristos tt_int_op(be_outcome[4].what, ==, BEV_EVENT_ERROR); 1375*eabc0478Schristos tt_int_op(be_outcome[4].dnserr, ==, expect_err); 1376*eabc0478Schristos } 1377*eabc0478Schristos 1378*eabc0478Schristos if (emfile) { 1379*eabc0478Schristos tt_int_op(n_accept, ==, 0); 1380*eabc0478Schristos } else { 13818585484eSchristos tt_int_op(n_accept, ==, 3); 1382*eabc0478Schristos } 13838585484eSchristos tt_int_op(n_dns, ==, 2); 13848585484eSchristos 13858585484eSchristos end: 13868585484eSchristos if (listener) 13878585484eSchristos evconnlistener_free(listener); 13888585484eSchristos if (port) 13898585484eSchristos evdns_close_server_port(port); 13908585484eSchristos if (dns) 13918585484eSchristos evdns_base_free(dns, 0); 1392*eabc0478Schristos for (i = 0; i < ARRAY_SIZE(be); ++i) { 1393*eabc0478Schristos if (be[i]) 1394*eabc0478Schristos bufferevent_free(be[i]); 1395*eabc0478Schristos } 13968585484eSchristos } 13978585484eSchristos 13988585484eSchristos 13998585484eSchristos struct gai_outcome { 14008585484eSchristos int err; 14018585484eSchristos struct evutil_addrinfo *ai; 14028585484eSchristos }; 14038585484eSchristos 14048585484eSchristos static int n_gai_results_pending = 0; 14058585484eSchristos static struct event_base *exit_base_on_no_pending_results = NULL; 14068585484eSchristos 14078585484eSchristos static void 14088585484eSchristos gai_cb(int err, struct evutil_addrinfo *res, void *ptr) 14098585484eSchristos { 14108585484eSchristos struct gai_outcome *go = ptr; 14118585484eSchristos go->err = err; 14128585484eSchristos go->ai = res; 14138585484eSchristos if (--n_gai_results_pending <= 0 && exit_base_on_no_pending_results) 14148585484eSchristos event_base_loopexit(exit_base_on_no_pending_results, NULL); 14158585484eSchristos if (n_gai_results_pending < 900) 14168585484eSchristos TT_BLATHER(("Got an answer; expecting %d more.", 14178585484eSchristos n_gai_results_pending)); 14188585484eSchristos } 14198585484eSchristos 14208585484eSchristos static void 14218585484eSchristos cancel_gai_cb(evutil_socket_t fd, short what, void *ptr) 14228585484eSchristos { 14238585484eSchristos struct evdns_getaddrinfo_request *r = ptr; 14248585484eSchristos evdns_getaddrinfo_cancel(r); 14258585484eSchristos } 14268585484eSchristos 14278585484eSchristos static void 14288585484eSchristos test_getaddrinfo_async(void *arg) 14298585484eSchristos { 14308585484eSchristos struct basic_test_data *data = arg; 14318585484eSchristos struct evutil_addrinfo hints, *a; 14328585484eSchristos struct gai_outcome local_outcome; 14338585484eSchristos struct gai_outcome a_out[12]; 1434*eabc0478Schristos unsigned i; 14358585484eSchristos struct evdns_getaddrinfo_request *r; 14368585484eSchristos char buf[128]; 14378585484eSchristos struct evdns_server_port *port = NULL; 14388585484eSchristos ev_uint16_t dns_port = 0; 14398585484eSchristos int n_dns_questions = 0; 1440b8ecfcfeSchristos struct evdns_base *dns_base; 14418585484eSchristos 1442*eabc0478Schristos memset(a_out, 0, sizeof(a_out)); 1443b8ecfcfeSchristos memset(&local_outcome, 0, sizeof(local_outcome)); 1444b8ecfcfeSchristos 1445b8ecfcfeSchristos dns_base = evdns_base_new(data->base, 0); 14468585484eSchristos tt_assert(dns_base); 14478585484eSchristos 14488585484eSchristos /* for localhost */ 14498585484eSchristos evdns_base_load_hosts(dns_base, NULL); 14508585484eSchristos 14518585484eSchristos tt_assert(! evdns_base_set_option(dns_base, "timeout", "0.3")); 14528585484eSchristos tt_assert(! evdns_base_set_option(dns_base, "getaddrinfo-allow-skew", "0.2")); 14538585484eSchristos 14548585484eSchristos n_gai_results_pending = 10000; /* don't think about exiting yet. */ 14558585484eSchristos 14568585484eSchristos /* 1. Try some cases that will never hit the asynchronous resolver. */ 14578585484eSchristos /* 1a. Simple case with a symbolic service name */ 14588585484eSchristos memset(&hints, 0, sizeof(hints)); 14598585484eSchristos hints.ai_family = PF_UNSPEC; 14608585484eSchristos hints.ai_socktype = SOCK_STREAM; 14618585484eSchristos memset(&local_outcome, 0, sizeof(local_outcome)); 14628585484eSchristos r = evdns_getaddrinfo(dns_base, "1.2.3.4", "http", 14638585484eSchristos &hints, gai_cb, &local_outcome); 14648585484eSchristos tt_assert(! r); 14658585484eSchristos if (!local_outcome.err) { 14668585484eSchristos tt_ptr_op(local_outcome.ai,!=,NULL); 14678585484eSchristos test_ai_eq(local_outcome.ai, "1.2.3.4:80", SOCK_STREAM, IPPROTO_TCP); 14688585484eSchristos evutil_freeaddrinfo(local_outcome.ai); 14698585484eSchristos local_outcome.ai = NULL; 14708585484eSchristos } else { 14718585484eSchristos TT_BLATHER(("Apparently we have no getservbyname.")); 14728585484eSchristos } 14738585484eSchristos 14748585484eSchristos /* 1b. EVUTIL_AI_NUMERICHOST is set */ 14758585484eSchristos memset(&hints, 0, sizeof(hints)); 14768585484eSchristos hints.ai_family = PF_UNSPEC; 14778585484eSchristos hints.ai_flags = EVUTIL_AI_NUMERICHOST; 14788585484eSchristos memset(&local_outcome, 0, sizeof(local_outcome)); 14798585484eSchristos r = evdns_getaddrinfo(dns_base, "www.google.com", "80", 14808585484eSchristos &hints, gai_cb, &local_outcome); 14818585484eSchristos tt_ptr_op(r,==,NULL); 14828585484eSchristos tt_int_op(local_outcome.err,==,EVUTIL_EAI_NONAME); 14838585484eSchristos tt_ptr_op(local_outcome.ai,==,NULL); 14848585484eSchristos 14858585484eSchristos /* 1c. We give a numeric address (ipv6) */ 14868585484eSchristos memset(&hints, 0, sizeof(hints)); 14878585484eSchristos memset(&local_outcome, 0, sizeof(local_outcome)); 14888585484eSchristos hints.ai_family = PF_UNSPEC; 14898585484eSchristos hints.ai_protocol = IPPROTO_TCP; 14908585484eSchristos r = evdns_getaddrinfo(dns_base, "f::f", "8008", 14918585484eSchristos &hints, gai_cb, &local_outcome); 14928585484eSchristos tt_assert(!r); 14938585484eSchristos tt_int_op(local_outcome.err,==,0); 14948585484eSchristos tt_assert(local_outcome.ai); 14958585484eSchristos tt_ptr_op(local_outcome.ai->ai_next,==,NULL); 14968585484eSchristos test_ai_eq(local_outcome.ai, "[f::f]:8008", SOCK_STREAM, IPPROTO_TCP); 14978585484eSchristos evutil_freeaddrinfo(local_outcome.ai); 14988585484eSchristos local_outcome.ai = NULL; 14998585484eSchristos 15008585484eSchristos /* 1d. We give a numeric address (ipv4) */ 15018585484eSchristos memset(&hints, 0, sizeof(hints)); 15028585484eSchristos memset(&local_outcome, 0, sizeof(local_outcome)); 15038585484eSchristos hints.ai_family = PF_UNSPEC; 15048585484eSchristos r = evdns_getaddrinfo(dns_base, "5.6.7.8", NULL, 15058585484eSchristos &hints, gai_cb, &local_outcome); 15068585484eSchristos tt_assert(!r); 15078585484eSchristos tt_int_op(local_outcome.err,==,0); 15088585484eSchristos tt_assert(local_outcome.ai); 15098585484eSchristos a = ai_find_by_protocol(local_outcome.ai, IPPROTO_TCP); 15108585484eSchristos tt_assert(a); 15118585484eSchristos test_ai_eq(a, "5.6.7.8", SOCK_STREAM, IPPROTO_TCP); 15128585484eSchristos a = ai_find_by_protocol(local_outcome.ai, IPPROTO_UDP); 15138585484eSchristos tt_assert(a); 15148585484eSchristos test_ai_eq(a, "5.6.7.8", SOCK_DGRAM, IPPROTO_UDP); 15158585484eSchristos evutil_freeaddrinfo(local_outcome.ai); 15168585484eSchristos local_outcome.ai = NULL; 15178585484eSchristos 15188585484eSchristos /* 1e. nodename is NULL (bind) */ 15198585484eSchristos memset(&hints, 0, sizeof(hints)); 15208585484eSchristos memset(&local_outcome, 0, sizeof(local_outcome)); 15218585484eSchristos hints.ai_family = PF_UNSPEC; 15228585484eSchristos hints.ai_socktype = SOCK_DGRAM; 15238585484eSchristos hints.ai_flags = EVUTIL_AI_PASSIVE; 15248585484eSchristos r = evdns_getaddrinfo(dns_base, NULL, "9090", 15258585484eSchristos &hints, gai_cb, &local_outcome); 15268585484eSchristos tt_assert(!r); 15278585484eSchristos tt_int_op(local_outcome.err,==,0); 15288585484eSchristos tt_assert(local_outcome.ai); 15298585484eSchristos /* we should get a v4 address of 0.0.0.0... */ 15308585484eSchristos a = ai_find_by_family(local_outcome.ai, PF_INET); 15318585484eSchristos tt_assert(a); 15328585484eSchristos test_ai_eq(a, "0.0.0.0:9090", SOCK_DGRAM, IPPROTO_UDP); 15338585484eSchristos /* ... and a v6 address of ::0 */ 15348585484eSchristos a = ai_find_by_family(local_outcome.ai, PF_INET6); 15358585484eSchristos tt_assert(a); 15368585484eSchristos test_ai_eq(a, "[::]:9090", SOCK_DGRAM, IPPROTO_UDP); 15378585484eSchristos evutil_freeaddrinfo(local_outcome.ai); 15388585484eSchristos local_outcome.ai = NULL; 15398585484eSchristos 15408585484eSchristos /* 1f. nodename is NULL (connect) */ 15418585484eSchristos memset(&hints, 0, sizeof(hints)); 15428585484eSchristos memset(&local_outcome, 0, sizeof(local_outcome)); 15438585484eSchristos hints.ai_family = PF_UNSPEC; 15448585484eSchristos hints.ai_socktype = SOCK_STREAM; 15458585484eSchristos r = evdns_getaddrinfo(dns_base, NULL, "2", 15468585484eSchristos &hints, gai_cb, &local_outcome); 15478585484eSchristos tt_assert(!r); 15488585484eSchristos tt_int_op(local_outcome.err,==,0); 15498585484eSchristos tt_assert(local_outcome.ai); 15508585484eSchristos /* we should get a v4 address of 127.0.0.1 .... */ 15518585484eSchristos a = ai_find_by_family(local_outcome.ai, PF_INET); 15528585484eSchristos tt_assert(a); 15538585484eSchristos test_ai_eq(a, "127.0.0.1:2", SOCK_STREAM, IPPROTO_TCP); 15548585484eSchristos /* ... and a v6 address of ::1 */ 15558585484eSchristos a = ai_find_by_family(local_outcome.ai, PF_INET6); 15568585484eSchristos tt_assert(a); 15578585484eSchristos test_ai_eq(a, "[::1]:2", SOCK_STREAM, IPPROTO_TCP); 15588585484eSchristos evutil_freeaddrinfo(local_outcome.ai); 15598585484eSchristos local_outcome.ai = NULL; 15608585484eSchristos 15618585484eSchristos /* 1g. We find localhost immediately. (pf_unspec) */ 15628585484eSchristos memset(&hints, 0, sizeof(hints)); 15638585484eSchristos memset(&local_outcome, 0, sizeof(local_outcome)); 15648585484eSchristos hints.ai_family = PF_UNSPEC; 15658585484eSchristos hints.ai_socktype = SOCK_STREAM; 15668585484eSchristos r = evdns_getaddrinfo(dns_base, "LOCALHOST", "80", 15678585484eSchristos &hints, gai_cb, &local_outcome); 15688585484eSchristos tt_assert(!r); 15698585484eSchristos tt_int_op(local_outcome.err,==,0); 15708585484eSchristos tt_assert(local_outcome.ai); 15718585484eSchristos /* we should get a v4 address of 127.0.0.1 .... */ 15728585484eSchristos a = ai_find_by_family(local_outcome.ai, PF_INET); 15738585484eSchristos tt_assert(a); 15748585484eSchristos test_ai_eq(a, "127.0.0.1:80", SOCK_STREAM, IPPROTO_TCP); 15758585484eSchristos /* ... and a v6 address of ::1 */ 15768585484eSchristos a = ai_find_by_family(local_outcome.ai, PF_INET6); 15778585484eSchristos tt_assert(a); 15788585484eSchristos test_ai_eq(a, "[::1]:80", SOCK_STREAM, IPPROTO_TCP); 15798585484eSchristos evutil_freeaddrinfo(local_outcome.ai); 15808585484eSchristos local_outcome.ai = NULL; 15818585484eSchristos 15828585484eSchristos /* 1g. We find localhost immediately. (pf_inet6) */ 15838585484eSchristos memset(&hints, 0, sizeof(hints)); 15848585484eSchristos memset(&local_outcome, 0, sizeof(local_outcome)); 15858585484eSchristos hints.ai_family = PF_INET6; 15868585484eSchristos hints.ai_socktype = SOCK_STREAM; 15878585484eSchristos r = evdns_getaddrinfo(dns_base, "LOCALHOST", "9999", 15888585484eSchristos &hints, gai_cb, &local_outcome); 15898585484eSchristos tt_assert(! r); 15908585484eSchristos tt_int_op(local_outcome.err,==,0); 15918585484eSchristos tt_assert(local_outcome.ai); 15928585484eSchristos a = local_outcome.ai; 15938585484eSchristos test_ai_eq(a, "[::1]:9999", SOCK_STREAM, IPPROTO_TCP); 15948585484eSchristos tt_ptr_op(a->ai_next, ==, NULL); 15958585484eSchristos evutil_freeaddrinfo(local_outcome.ai); 15968585484eSchristos local_outcome.ai = NULL; 15978585484eSchristos 15988585484eSchristos /* 2. Okay, now we can actually test the asynchronous resolver. */ 15998585484eSchristos /* Start a dummy local dns server... */ 16008585484eSchristos port = regress_get_dnsserver(data->base, &dns_port, NULL, 16018585484eSchristos be_getaddrinfo_server_cb, &n_dns_questions); 16028585484eSchristos tt_assert(port); 16038585484eSchristos tt_int_op(dns_port, >=, 0); 16048585484eSchristos /* ... and tell the evdns_base about it. */ 16058585484eSchristos evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", dns_port); 16068585484eSchristos evdns_base_nameserver_ip_add(dns_base, buf); 16078585484eSchristos 16088585484eSchristos memset(&hints, 0, sizeof(hints)); 16098585484eSchristos hints.ai_family = PF_UNSPEC; 16108585484eSchristos hints.ai_socktype = SOCK_STREAM; 16118585484eSchristos hints.ai_flags = EVUTIL_AI_CANONNAME; 16128585484eSchristos /* 0: Request for both.example.com should return both addresses. */ 16138585484eSchristos r = evdns_getaddrinfo(dns_base, "both.example.com", "8000", 16148585484eSchristos &hints, gai_cb, &a_out[0]); 16158585484eSchristos tt_assert(r); 16168585484eSchristos 16178585484eSchristos /* 1: Request for v4only.example.com should return one address. */ 16188585484eSchristos r = evdns_getaddrinfo(dns_base, "v4only.example.com", "8001", 16198585484eSchristos &hints, gai_cb, &a_out[1]); 16208585484eSchristos tt_assert(r); 16218585484eSchristos 16228585484eSchristos /* 2: Request for v6only.example.com should return one address. */ 16238585484eSchristos hints.ai_flags = 0; 16248585484eSchristos r = evdns_getaddrinfo(dns_base, "v6only.example.com", "8002", 16258585484eSchristos &hints, gai_cb, &a_out[2]); 16268585484eSchristos tt_assert(r); 16278585484eSchristos 16288585484eSchristos /* 3: PF_INET request for v4assert.example.com should not generate a 16298585484eSchristos * v6 request. The server will fail the test if it does. */ 16308585484eSchristos hints.ai_family = PF_INET; 16318585484eSchristos r = evdns_getaddrinfo(dns_base, "v4assert.example.com", "8003", 16328585484eSchristos &hints, gai_cb, &a_out[3]); 16338585484eSchristos tt_assert(r); 16348585484eSchristos 16358585484eSchristos /* 4: PF_INET6 request for v6assert.example.com should not generate a 16368585484eSchristos * v4 request. The server will fail the test if it does. */ 16378585484eSchristos hints.ai_family = PF_INET6; 16388585484eSchristos r = evdns_getaddrinfo(dns_base, "v6assert.example.com", "8004", 16398585484eSchristos &hints, gai_cb, &a_out[4]); 16408585484eSchristos tt_assert(r); 16418585484eSchristos 16428585484eSchristos /* 5: PF_INET request for nosuchplace.example.com should give NEXIST. */ 16438585484eSchristos hints.ai_family = PF_INET; 16448585484eSchristos r = evdns_getaddrinfo(dns_base, "nosuchplace.example.com", "8005", 16458585484eSchristos &hints, gai_cb, &a_out[5]); 16468585484eSchristos tt_assert(r); 16478585484eSchristos 16488585484eSchristos /* 6: PF_UNSPEC request for nosuchplace.example.com should give NEXIST. 16498585484eSchristos */ 16508585484eSchristos hints.ai_family = PF_UNSPEC; 16518585484eSchristos r = evdns_getaddrinfo(dns_base, "nosuchplace.example.com", "8006", 16528585484eSchristos &hints, gai_cb, &a_out[6]); 16538585484eSchristos tt_assert(r); 16548585484eSchristos 16558585484eSchristos /* 7: PF_UNSPEC request for v6timeout.example.com should give an ipv4 16568585484eSchristos * address only. */ 16578585484eSchristos hints.ai_family = PF_UNSPEC; 16588585484eSchristos r = evdns_getaddrinfo(dns_base, "v6timeout.example.com", "8007", 16598585484eSchristos &hints, gai_cb, &a_out[7]); 16608585484eSchristos tt_assert(r); 16618585484eSchristos 16628585484eSchristos /* 8: PF_UNSPEC request for v6timeout-nonexist.example.com should give 16638585484eSchristos * a NEXIST */ 16648585484eSchristos hints.ai_family = PF_UNSPEC; 16658585484eSchristos r = evdns_getaddrinfo(dns_base, "v6timeout-nonexist.example.com", 16668585484eSchristos "8008", &hints, gai_cb, &a_out[8]); 16678585484eSchristos tt_assert(r); 16688585484eSchristos 16698585484eSchristos /* 9: AI_ADDRCONFIG should at least not crash. Can't test it more 16708585484eSchristos * without knowing what kind of internet we have. */ 16718585484eSchristos hints.ai_flags |= EVUTIL_AI_ADDRCONFIG; 16728585484eSchristos r = evdns_getaddrinfo(dns_base, "both.example.com", 16738585484eSchristos "8009", &hints, gai_cb, &a_out[9]); 16748585484eSchristos tt_assert(r); 16758585484eSchristos 16768585484eSchristos /* 10: PF_UNSPEC for v4timeout.example.com should give an ipv6 address 16778585484eSchristos * only. */ 16788585484eSchristos hints.ai_family = PF_UNSPEC; 16798585484eSchristos hints.ai_flags = 0; 16808585484eSchristos r = evdns_getaddrinfo(dns_base, "v4timeout.example.com", "8010", 16818585484eSchristos &hints, gai_cb, &a_out[10]); 16828585484eSchristos tt_assert(r); 16838585484eSchristos 16848585484eSchristos /* 11: timeout.example.com: cancel it after 100 msec. */ 16858585484eSchristos r = evdns_getaddrinfo(dns_base, "all-timeout.example.com", "8011", 16868585484eSchristos &hints, gai_cb, &a_out[11]); 16878585484eSchristos tt_assert(r); 16888585484eSchristos { 16898585484eSchristos struct timeval tv; 16908585484eSchristos tv.tv_sec = 0; 16918585484eSchristos tv.tv_usec = 100*1000; /* 100 msec */ 16928585484eSchristos event_base_once(data->base, -1, EV_TIMEOUT, cancel_gai_cb, 16938585484eSchristos r, &tv); 16948585484eSchristos } 16958585484eSchristos 16968585484eSchristos /* XXXXX There are more tests we could do, including: 16978585484eSchristos 16988585484eSchristos - A test to elicit NODATA. 16998585484eSchristos 17008585484eSchristos */ 17018585484eSchristos 17028585484eSchristos n_gai_results_pending = 12; 17038585484eSchristos exit_base_on_no_pending_results = data->base; 17048585484eSchristos 17058585484eSchristos event_base_dispatch(data->base); 17068585484eSchristos 17078585484eSchristos /* 0: both.example.com */ 17088585484eSchristos tt_int_op(a_out[0].err, ==, 0); 17098585484eSchristos tt_assert(a_out[0].ai); 17108585484eSchristos tt_assert(a_out[0].ai->ai_next); 17118585484eSchristos tt_assert(!a_out[0].ai->ai_next->ai_next); 17128585484eSchristos a = ai_find_by_family(a_out[0].ai, PF_INET); 17138585484eSchristos tt_assert(a); 17148585484eSchristos test_ai_eq(a, "80.80.32.32:8000", SOCK_STREAM, IPPROTO_TCP); 17158585484eSchristos a = ai_find_by_family(a_out[0].ai, PF_INET6); 17168585484eSchristos tt_assert(a); 17178585484eSchristos test_ai_eq(a, "[80ff::bbbb]:8000", SOCK_STREAM, IPPROTO_TCP); 17188585484eSchristos tt_assert(a_out[0].ai->ai_canonname); 17198585484eSchristos tt_str_op(a_out[0].ai->ai_canonname, ==, "both-canonical.example.com"); 17208585484eSchristos 17218585484eSchristos /* 1: v4only.example.com */ 17228585484eSchristos tt_int_op(a_out[1].err, ==, 0); 17238585484eSchristos tt_assert(a_out[1].ai); 17248585484eSchristos tt_assert(! a_out[1].ai->ai_next); 17258585484eSchristos test_ai_eq(a_out[1].ai, "18.52.86.120:8001", SOCK_STREAM, IPPROTO_TCP); 17268585484eSchristos tt_assert(a_out[1].ai->ai_canonname == NULL); 17278585484eSchristos 17288585484eSchristos 17298585484eSchristos /* 2: v6only.example.com */ 17308585484eSchristos tt_int_op(a_out[2].err, ==, 0); 17318585484eSchristos tt_assert(a_out[2].ai); 17328585484eSchristos tt_assert(! a_out[2].ai->ai_next); 17338585484eSchristos test_ai_eq(a_out[2].ai, "[b0b::f00d]:8002", SOCK_STREAM, IPPROTO_TCP); 17348585484eSchristos 17358585484eSchristos /* 3: v4assert.example.com */ 17368585484eSchristos tt_int_op(a_out[3].err, ==, 0); 17378585484eSchristos tt_assert(a_out[3].ai); 17388585484eSchristos tt_assert(! a_out[3].ai->ai_next); 17398585484eSchristos test_ai_eq(a_out[3].ai, "18.52.86.120:8003", SOCK_STREAM, IPPROTO_TCP); 17408585484eSchristos 17418585484eSchristos /* 4: v6assert.example.com */ 17428585484eSchristos tt_int_op(a_out[4].err, ==, 0); 17438585484eSchristos tt_assert(a_out[4].ai); 17448585484eSchristos tt_assert(! a_out[4].ai->ai_next); 17458585484eSchristos test_ai_eq(a_out[4].ai, "[b0b::f00d]:8004", SOCK_STREAM, IPPROTO_TCP); 17468585484eSchristos 17478585484eSchristos /* 5: nosuchplace.example.com (inet) */ 17488585484eSchristos tt_int_op(a_out[5].err, ==, EVUTIL_EAI_NONAME); 17498585484eSchristos tt_assert(! a_out[5].ai); 17508585484eSchristos 17518585484eSchristos /* 6: nosuchplace.example.com (unspec) */ 17528585484eSchristos tt_int_op(a_out[6].err, ==, EVUTIL_EAI_NONAME); 17538585484eSchristos tt_assert(! a_out[6].ai); 17548585484eSchristos 17558585484eSchristos /* 7: v6timeout.example.com */ 17568585484eSchristos tt_int_op(a_out[7].err, ==, 0); 17578585484eSchristos tt_assert(a_out[7].ai); 17588585484eSchristos tt_assert(! a_out[7].ai->ai_next); 17598585484eSchristos test_ai_eq(a_out[7].ai, "171.205.239.1:8007", SOCK_STREAM, IPPROTO_TCP); 17608585484eSchristos 17618585484eSchristos /* 8: v6timeout-nonexist.example.com */ 17628585484eSchristos tt_int_op(a_out[8].err, ==, EVUTIL_EAI_NONAME); 17638585484eSchristos tt_assert(! a_out[8].ai); 17648585484eSchristos 17658585484eSchristos /* 9: both (ADDRCONFIG) */ 17668585484eSchristos tt_int_op(a_out[9].err, ==, 0); 17678585484eSchristos tt_assert(a_out[9].ai); 17688585484eSchristos a = ai_find_by_family(a_out[9].ai, PF_INET); 17698585484eSchristos if (a) 17708585484eSchristos test_ai_eq(a, "80.80.32.32:8009", SOCK_STREAM, IPPROTO_TCP); 17718585484eSchristos else 17728585484eSchristos tt_assert(ai_find_by_family(a_out[9].ai, PF_INET6)); 17738585484eSchristos a = ai_find_by_family(a_out[9].ai, PF_INET6); 17748585484eSchristos if (a) 17758585484eSchristos test_ai_eq(a, "[80ff::bbbb]:8009", SOCK_STREAM, IPPROTO_TCP); 17768585484eSchristos else 17778585484eSchristos tt_assert(ai_find_by_family(a_out[9].ai, PF_INET)); 17788585484eSchristos 17798585484eSchristos /* 10: v4timeout.example.com */ 17808585484eSchristos tt_int_op(a_out[10].err, ==, 0); 17818585484eSchristos tt_assert(a_out[10].ai); 17828585484eSchristos tt_assert(! a_out[10].ai->ai_next); 17838585484eSchristos test_ai_eq(a_out[10].ai, "[a0a::ff01]:8010", SOCK_STREAM, IPPROTO_TCP); 17848585484eSchristos 17858585484eSchristos /* 11: cancelled request. */ 17868585484eSchristos tt_int_op(a_out[11].err, ==, EVUTIL_EAI_CANCEL); 17878585484eSchristos tt_assert(a_out[11].ai == NULL); 17888585484eSchristos 17898585484eSchristos end: 17908585484eSchristos if (local_outcome.ai) 17918585484eSchristos evutil_freeaddrinfo(local_outcome.ai); 1792*eabc0478Schristos for (i = 0; i < ARRAY_SIZE(a_out); ++i) { 17938585484eSchristos if (a_out[i].ai) 17948585484eSchristos evutil_freeaddrinfo(a_out[i].ai); 17958585484eSchristos } 17968585484eSchristos if (port) 17978585484eSchristos evdns_close_server_port(port); 17988585484eSchristos if (dns_base) 17998585484eSchristos evdns_base_free(dns_base, 0); 18008585484eSchristos } 18018585484eSchristos 18028585484eSchristos struct gaic_request_status { 18038585484eSchristos int magic; 18048585484eSchristos struct event_base *base; 18058585484eSchristos struct evdns_base *dns_base; 18068585484eSchristos struct evdns_getaddrinfo_request *request; 18078585484eSchristos struct event cancel_event; 18088585484eSchristos int canceled; 18098585484eSchristos }; 18108585484eSchristos 18118585484eSchristos #define GAIC_MAGIC 0x1234abcd 18128585484eSchristos 1813*eabc0478Schristos static int gaic_pending = 0; 1814*eabc0478Schristos static int gaic_freed = 0; 18158585484eSchristos 18168585484eSchristos static void 18178585484eSchristos gaic_cancel_request_cb(evutil_socket_t fd, short what, void *arg) 18188585484eSchristos { 18198585484eSchristos struct gaic_request_status *status = arg; 18208585484eSchristos 18218585484eSchristos tt_assert(status->magic == GAIC_MAGIC); 18228585484eSchristos status->canceled = 1; 18238585484eSchristos evdns_getaddrinfo_cancel(status->request); 18248585484eSchristos return; 18258585484eSchristos end: 18268585484eSchristos event_base_loopexit(status->base, NULL); 18278585484eSchristos } 18288585484eSchristos 18298585484eSchristos static void 18308585484eSchristos gaic_server_cb(struct evdns_server_request *req, void *arg) 18318585484eSchristos { 18328585484eSchristos ev_uint32_t answer = 0x7f000001; 18338585484eSchristos tt_assert(req->nquestions); 18348585484eSchristos evdns_server_request_add_a_reply(req, req->questions[0]->name, 1, 18358585484eSchristos &answer, 100); 18368585484eSchristos evdns_server_request_respond(req, 0); 18378585484eSchristos return; 18388585484eSchristos end: 18398585484eSchristos evdns_server_request_respond(req, DNS_ERR_REFUSED); 18408585484eSchristos } 18418585484eSchristos 18428585484eSchristos 18438585484eSchristos static void 18448585484eSchristos gaic_getaddrinfo_cb(int result, struct evutil_addrinfo *res, void *arg) 18458585484eSchristos { 18468585484eSchristos struct gaic_request_status *status = arg; 18478585484eSchristos struct event_base *base = status->base; 18488585484eSchristos tt_assert(status->magic == GAIC_MAGIC); 18498585484eSchristos 18508585484eSchristos if (result == EVUTIL_EAI_CANCEL) { 18518585484eSchristos tt_assert(status->canceled); 18528585484eSchristos } 18538585484eSchristos event_del(&status->cancel_event); 18548585484eSchristos 18558585484eSchristos memset(status, 0xf0, sizeof(*status)); 18568585484eSchristos free(status); 18578585484eSchristos 18588585484eSchristos end: 1859*eabc0478Schristos if (res) 1860*eabc0478Schristos { 1861*eabc0478Schristos TT_BLATHER(("evutil_freeaddrinfo(%p)", res)); 1862*eabc0478Schristos evutil_freeaddrinfo(res); 1863*eabc0478Schristos ++gaic_freed; 1864*eabc0478Schristos } 1865*eabc0478Schristos if (--gaic_pending <= 0) 18668585484eSchristos event_base_loopexit(base, NULL); 18678585484eSchristos } 18688585484eSchristos 18698585484eSchristos static void 18708585484eSchristos gaic_launch(struct event_base *base, struct evdns_base *dns_base) 18718585484eSchristos { 18728585484eSchristos struct gaic_request_status *status = calloc(1,sizeof(*status)); 18738585484eSchristos struct timeval tv = { 0, 10000 }; 18748585484eSchristos status->magic = GAIC_MAGIC; 18758585484eSchristos status->base = base; 18768585484eSchristos status->dns_base = dns_base; 18778585484eSchristos event_assign(&status->cancel_event, base, -1, 0, gaic_cancel_request_cb, 18788585484eSchristos status); 18798585484eSchristos status->request = evdns_getaddrinfo(dns_base, 18808585484eSchristos "foobar.bazquux.example.com", "80", NULL, gaic_getaddrinfo_cb, 18818585484eSchristos status); 18828585484eSchristos event_add(&status->cancel_event, &tv); 1883*eabc0478Schristos ++gaic_pending; 18848585484eSchristos } 18858585484eSchristos 18868585484eSchristos #ifdef EVENT_SET_MEM_FUNCTIONS_IMPLEMENTED 18878585484eSchristos /* FIXME: We should move this to regress_main.c if anything else needs it.*/ 18888585484eSchristos 18898585484eSchristos /* Trivial replacements for malloc/free/realloc to check for memory leaks. 18908585484eSchristos * Not threadsafe. */ 18918585484eSchristos static int allocated_chunks = 0; 18928585484eSchristos 18938585484eSchristos static void * 18948585484eSchristos cnt_malloc(size_t sz) 18958585484eSchristos { 18968585484eSchristos allocated_chunks += 1; 18978585484eSchristos return malloc(sz); 18988585484eSchristos } 18998585484eSchristos 19008585484eSchristos static void * 19018585484eSchristos cnt_realloc(void *old, size_t sz) 19028585484eSchristos { 19038585484eSchristos if (!old) 19048585484eSchristos allocated_chunks += 1; 19058585484eSchristos if (!sz) 19068585484eSchristos allocated_chunks -= 1; 19078585484eSchristos return realloc(old, sz); 19088585484eSchristos } 19098585484eSchristos 19108585484eSchristos static void 19118585484eSchristos cnt_free(void *ptr) 19128585484eSchristos { 19138585484eSchristos allocated_chunks -= 1; 19148585484eSchristos free(ptr); 19158585484eSchristos } 19168585484eSchristos 19178585484eSchristos struct testleak_env_t { 19188585484eSchristos struct event_base *base; 19198585484eSchristos struct evdns_base *dns_base; 19208585484eSchristos struct evdns_request *req; 19218585484eSchristos struct generic_dns_callback_result r; 19228585484eSchristos }; 19238585484eSchristos 19248585484eSchristos static void * 19258585484eSchristos testleak_setup(const struct testcase_t *testcase) 19268585484eSchristos { 19278585484eSchristos struct testleak_env_t *env; 19288585484eSchristos 19298585484eSchristos allocated_chunks = 0; 19307476e6e4Schristos 19317476e6e4Schristos /* Reset allocation counter, to start allocations from the very beginning. 19327476e6e4Schristos * (this will avoid false-positive negative numbers for allocated_chunks) 19337476e6e4Schristos */ 19347476e6e4Schristos libevent_global_shutdown(); 19357476e6e4Schristos 19368585484eSchristos event_set_mem_functions(cnt_malloc, cnt_realloc, cnt_free); 19377476e6e4Schristos 19388585484eSchristos event_enable_debug_mode(); 19398585484eSchristos 19408585484eSchristos /* not mm_calloc: we don't want to mess with the count. */ 19418585484eSchristos env = calloc(1, sizeof(struct testleak_env_t)); 19428585484eSchristos env->base = event_base_new(); 19438585484eSchristos env->dns_base = evdns_base_new(env->base, 0); 19448585484eSchristos env->req = evdns_base_resolve_ipv4( 19458585484eSchristos env->dns_base, "example.com", DNS_QUERY_NO_SEARCH, 19468585484eSchristos generic_dns_callback, &env->r); 19478585484eSchristos return env; 19488585484eSchristos } 19498585484eSchristos 19508585484eSchristos static int 19518585484eSchristos testleak_cleanup(const struct testcase_t *testcase, void *env_) 19528585484eSchristos { 19538585484eSchristos int ok = 0; 19548585484eSchristos struct testleak_env_t *env = env_; 19558585484eSchristos tt_assert(env); 19568585484eSchristos #ifdef EVENT__DISABLE_DEBUG_MODE 19578585484eSchristos tt_int_op(allocated_chunks, ==, 0); 19588585484eSchristos #else 19597476e6e4Schristos libevent_global_shutdown(); 19607476e6e4Schristos tt_int_op(allocated_chunks, ==, 0); 19618585484eSchristos #endif 19628585484eSchristos ok = 1; 19638585484eSchristos end: 19648585484eSchristos if (env) { 19658585484eSchristos if (env->dns_base) 19668585484eSchristos evdns_base_free(env->dns_base, 0); 19678585484eSchristos if (env->base) 19688585484eSchristos event_base_free(env->base); 19698585484eSchristos free(env); 19708585484eSchristos } 19718585484eSchristos return ok; 19728585484eSchristos } 19738585484eSchristos 19748585484eSchristos static struct testcase_setup_t testleak_funcs = { 19758585484eSchristos testleak_setup, testleak_cleanup 19768585484eSchristos }; 19778585484eSchristos 19788585484eSchristos static void 19798585484eSchristos test_dbg_leak_cancel(void *env_) 19808585484eSchristos { 19818585484eSchristos /* cancel, loop, free/dns, free/base */ 19828585484eSchristos struct testleak_env_t *env = env_; 19838585484eSchristos int send_err_shutdown = 1; 19848585484eSchristos evdns_cancel_request(env->dns_base, env->req); 19858585484eSchristos env->req = 0; 19868585484eSchristos 19878585484eSchristos /* `req` is freed in callback, that's why one loop is required. */ 19888585484eSchristos event_base_loop(env->base, EVLOOP_NONBLOCK); 19898585484eSchristos 19908585484eSchristos /* send_err_shutdown means nothing as soon as our request is 19918585484eSchristos * already canceled */ 19928585484eSchristos evdns_base_free(env->dns_base, send_err_shutdown); 19938585484eSchristos env->dns_base = 0; 19948585484eSchristos event_base_free(env->base); 19958585484eSchristos env->base = 0; 19968585484eSchristos } 19978585484eSchristos 19988585484eSchristos static void 1999b8ecfcfeSchristos dbg_leak_resume(void *env_, int cancel, int send_err_shutdown) 2000b8ecfcfeSchristos { 2001b8ecfcfeSchristos /* cancel, loop, free/dns, free/base */ 2002b8ecfcfeSchristos struct testleak_env_t *env = env_; 2003b8ecfcfeSchristos if (cancel) { 2004b8ecfcfeSchristos evdns_cancel_request(env->dns_base, env->req); 2005b8ecfcfeSchristos tt_assert(!evdns_base_resume(env->dns_base)); 2006b8ecfcfeSchristos } else { 2007b8ecfcfeSchristos /* TODO: No nameservers, request can't be processed, must be errored */ 2008b8ecfcfeSchristos tt_assert(!evdns_base_resume(env->dns_base)); 2009b8ecfcfeSchristos } 2010b8ecfcfeSchristos 2011*eabc0478Schristos event_base_loop(env->base, EVLOOP_NONBLOCK); 2012b8ecfcfeSchristos /** 2013*eabc0478Schristos * Because we don't cancel request, and want our callback to recieve 2014*eabc0478Schristos * DNS_ERR_SHUTDOWN, we use deferred callback, and there was: 2015b8ecfcfeSchristos * - one extra malloc(), 2016b8ecfcfeSchristos * @see reply_schedule_callback() 2017b8ecfcfeSchristos * - and one missing free 2018b8ecfcfeSchristos * @see request_finished() (req->handle->pending_cb = 1) 2019*eabc0478Schristos * than we don't need to count in testleak_cleanup(), but we can clean them 2020*eabc0478Schristos * if we will run loop once again, but *after* evdns base freed. 2021b8ecfcfeSchristos */ 2022*eabc0478Schristos evdns_base_free(env->dns_base, send_err_shutdown); 2023*eabc0478Schristos env->dns_base = 0; 2024b8ecfcfeSchristos event_base_loop(env->base, EVLOOP_NONBLOCK); 2025b8ecfcfeSchristos 2026b8ecfcfeSchristos end: 2027b8ecfcfeSchristos event_base_free(env->base); 2028b8ecfcfeSchristos env->base = 0; 2029b8ecfcfeSchristos } 2030b8ecfcfeSchristos 2031b8ecfcfeSchristos #define IMPL_DBG_LEAK_RESUME(name, cancel, send_err_shutdown) \ 2032b8ecfcfeSchristos static void \ 2033b8ecfcfeSchristos test_dbg_leak_##name##_(void *env_) \ 2034b8ecfcfeSchristos { \ 2035b8ecfcfeSchristos dbg_leak_resume(env_, cancel, send_err_shutdown); \ 2036b8ecfcfeSchristos } 2037b8ecfcfeSchristos IMPL_DBG_LEAK_RESUME(resume, 0, 0) 2038b8ecfcfeSchristos IMPL_DBG_LEAK_RESUME(cancel_and_resume, 1, 0) 2039b8ecfcfeSchristos IMPL_DBG_LEAK_RESUME(resume_send_err, 0, 1) 2040b8ecfcfeSchristos IMPL_DBG_LEAK_RESUME(cancel_and_resume_send_err, 1, 1) 2041b8ecfcfeSchristos 2042b8ecfcfeSchristos static void 20438585484eSchristos test_dbg_leak_shutdown(void *env_) 20448585484eSchristos { 20458585484eSchristos /* free/dns, loop, free/base */ 20468585484eSchristos struct testleak_env_t *env = env_; 20478585484eSchristos int send_err_shutdown = 1; 20488585484eSchristos 20498585484eSchristos /* `req` is freed both with `send_err_shutdown` and without it, 20508585484eSchristos * the only difference is `evdns_callback` call */ 20518585484eSchristos env->req = 0; 20528585484eSchristos 20538585484eSchristos evdns_base_free(env->dns_base, send_err_shutdown); 20548585484eSchristos env->dns_base = 0; 20558585484eSchristos 20568585484eSchristos /* `req` is freed in callback, that's why one loop is required */ 20578585484eSchristos event_base_loop(env->base, EVLOOP_NONBLOCK); 20588585484eSchristos event_base_free(env->base); 20598585484eSchristos env->base = 0; 20608585484eSchristos } 20618585484eSchristos #endif 20628585484eSchristos 20638585484eSchristos static void 20648585484eSchristos test_getaddrinfo_async_cancel_stress(void *ptr) 20658585484eSchristos { 20668585484eSchristos struct event_base *base; 20678585484eSchristos struct evdns_base *dns_base = NULL; 20688585484eSchristos struct evdns_server_port *server = NULL; 20698585484eSchristos evutil_socket_t fd = -1; 20708585484eSchristos struct sockaddr_in sin; 20718585484eSchristos struct sockaddr_storage ss; 20728585484eSchristos ev_socklen_t slen; 2073*eabc0478Schristos unsigned i; 20748585484eSchristos 20758585484eSchristos base = event_base_new(); 20768585484eSchristos dns_base = evdns_base_new(base, 0); 20778585484eSchristos 20788585484eSchristos memset(&sin, 0, sizeof(sin)); 20798585484eSchristos sin.sin_family = AF_INET; 20808585484eSchristos sin.sin_port = 0; 20818585484eSchristos sin.sin_addr.s_addr = htonl(0x7f000001); 20828585484eSchristos if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 20838585484eSchristos tt_abort_perror("socket"); 20848585484eSchristos } 20858585484eSchristos evutil_make_socket_nonblocking(fd); 20868585484eSchristos if (bind(fd, (struct sockaddr*)&sin, sizeof(sin))<0) { 20878585484eSchristos tt_abort_perror("bind"); 20888585484eSchristos } 20898585484eSchristos server = evdns_add_server_port_with_base(base, fd, 0, gaic_server_cb, 20908585484eSchristos base); 20918585484eSchristos 20928585484eSchristos memset(&ss, 0, sizeof(ss)); 20938585484eSchristos slen = sizeof(ss); 20948585484eSchristos if (getsockname(fd, (struct sockaddr*)&ss, &slen)<0) { 20958585484eSchristos tt_abort_perror("getsockname"); 20968585484eSchristos } 20978585484eSchristos evdns_base_nameserver_sockaddr_add(dns_base, 20988585484eSchristos (struct sockaddr*)&ss, slen, 0); 20998585484eSchristos 21008585484eSchristos for (i = 0; i < 1000; ++i) { 21018585484eSchristos gaic_launch(base, dns_base); 21028585484eSchristos } 21038585484eSchristos 21048585484eSchristos event_base_dispatch(base); 21058585484eSchristos 2106*eabc0478Schristos // at least some was canceled via external event 2107*eabc0478Schristos tt_int_op(gaic_freed, !=, 1000); 2108*eabc0478Schristos 21098585484eSchristos end: 21108585484eSchristos if (dns_base) 21118585484eSchristos evdns_base_free(dns_base, 1); 21128585484eSchristos if (server) 21138585484eSchristos evdns_close_server_port(server); 21147476e6e4Schristos if (base) 21157476e6e4Schristos event_base_free(base); 21168585484eSchristos if (fd >= 0) 21178585484eSchristos evutil_closesocket(fd); 21188585484eSchristos } 21198585484eSchristos 2120*eabc0478Schristos static void 2121*eabc0478Schristos dns_client_fail_requests_test(void *arg) 2122*eabc0478Schristos { 2123*eabc0478Schristos struct basic_test_data *data = arg; 2124*eabc0478Schristos struct event_base *base = data->base; 2125*eabc0478Schristos int limit_inflight = data->setup_data && !strcmp(data->setup_data, "limit-inflight"); 2126*eabc0478Schristos struct evdns_base *dns = NULL; 2127*eabc0478Schristos struct evdns_server_port *dns_port = NULL; 2128*eabc0478Schristos ev_uint16_t portnum = 0; 2129*eabc0478Schristos char buf[64]; 2130*eabc0478Schristos 2131*eabc0478Schristos struct generic_dns_callback_result r[20]; 2132*eabc0478Schristos unsigned i; 2133*eabc0478Schristos 2134*eabc0478Schristos dns_port = regress_get_dnsserver(base, &portnum, NULL, 2135*eabc0478Schristos regress_dns_server_cb, reissue_table); 2136*eabc0478Schristos tt_assert(dns_port); 2137*eabc0478Schristos 2138*eabc0478Schristos evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum); 2139*eabc0478Schristos 2140*eabc0478Schristos dns = evdns_base_new(base, EVDNS_BASE_DISABLE_WHEN_INACTIVE); 2141*eabc0478Schristos tt_assert(!evdns_base_nameserver_ip_add(dns, buf)); 2142*eabc0478Schristos 2143*eabc0478Schristos if (limit_inflight) 2144*eabc0478Schristos tt_assert(!evdns_base_set_option(dns, "max-inflight:", "11")); 2145*eabc0478Schristos 2146*eabc0478Schristos for (i = 0; i < 20; ++i) 2147*eabc0478Schristos evdns_base_resolve_ipv4(dns, "foof.example.com", 0, generic_dns_callback, &r[i]); 2148*eabc0478Schristos 2149*eabc0478Schristos n_replies_left = 20; 2150*eabc0478Schristos exit_base = base; 2151*eabc0478Schristos 2152*eabc0478Schristos evdns_base_free(dns, 1 /** fail requests */); 2153*eabc0478Schristos /** run defered callbacks, to trigger UAF */ 2154*eabc0478Schristos event_base_dispatch(base); 2155*eabc0478Schristos 2156*eabc0478Schristos tt_int_op(n_replies_left, ==, 0); 2157*eabc0478Schristos for (i = 0; i < 20; ++i) 2158*eabc0478Schristos tt_int_op(r[i].result, ==, DNS_ERR_SHUTDOWN); 2159*eabc0478Schristos 2160*eabc0478Schristos end: 2161*eabc0478Schristos evdns_close_server_port(dns_port); 2162*eabc0478Schristos } 2163*eabc0478Schristos 2164*eabc0478Schristos static void 2165*eabc0478Schristos getaddrinfo_cb(int err, struct evutil_addrinfo *res, void *ptr) 2166*eabc0478Schristos { 2167*eabc0478Schristos generic_dns_callback(err, 0, 0, 0, NULL, ptr); 2168*eabc0478Schristos } 2169*eabc0478Schristos static void 2170*eabc0478Schristos dns_client_fail_requests_getaddrinfo_test(void *arg) 2171*eabc0478Schristos { 2172*eabc0478Schristos struct basic_test_data *data = arg; 2173*eabc0478Schristos struct event_base *base = data->base; 2174*eabc0478Schristos struct evdns_base *dns = NULL; 2175*eabc0478Schristos struct evdns_server_port *dns_port = NULL; 2176*eabc0478Schristos ev_uint16_t portnum = 0; 2177*eabc0478Schristos char buf[64]; 2178*eabc0478Schristos 2179*eabc0478Schristos struct generic_dns_callback_result r[20]; 2180*eabc0478Schristos int i; 2181*eabc0478Schristos 2182*eabc0478Schristos dns_port = regress_get_dnsserver(base, &portnum, NULL, 2183*eabc0478Schristos regress_dns_server_cb, reissue_table); 2184*eabc0478Schristos tt_assert(dns_port); 2185*eabc0478Schristos 2186*eabc0478Schristos evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum); 2187*eabc0478Schristos 2188*eabc0478Schristos dns = evdns_base_new(base, EVDNS_BASE_DISABLE_WHEN_INACTIVE); 2189*eabc0478Schristos tt_assert(!evdns_base_nameserver_ip_add(dns, buf)); 2190*eabc0478Schristos 2191*eabc0478Schristos for (i = 0; i < 20; ++i) 2192*eabc0478Schristos tt_assert(evdns_getaddrinfo(dns, "foof.example.com", "80", NULL, getaddrinfo_cb, &r[i])); 2193*eabc0478Schristos 2194*eabc0478Schristos n_replies_left = 20; 2195*eabc0478Schristos exit_base = base; 2196*eabc0478Schristos 2197*eabc0478Schristos evdns_base_free(dns, 1 /** fail requests */); 2198*eabc0478Schristos /** run defered callbacks, to trigger UAF */ 2199*eabc0478Schristos event_base_dispatch(base); 2200*eabc0478Schristos 2201*eabc0478Schristos tt_int_op(n_replies_left, ==, 0); 2202*eabc0478Schristos for (i = 0; i < 20; ++i) 2203*eabc0478Schristos tt_int_op(r[i].result, ==, EVUTIL_EAI_FAIL); 2204*eabc0478Schristos 2205*eabc0478Schristos end: 2206*eabc0478Schristos evdns_close_server_port(dns_port); 2207*eabc0478Schristos } 2208*eabc0478Schristos 2209*eabc0478Schristos #ifdef EVTHREAD_USE_PTHREADS_IMPLEMENTED 2210*eabc0478Schristos struct race_param 2211*eabc0478Schristos { 2212*eabc0478Schristos void *lock; 2213*eabc0478Schristos void *reqs_cmpl_cond; 2214*eabc0478Schristos int bw_threads; 2215*eabc0478Schristos void *bw_threads_exited_cond; 2216*eabc0478Schristos volatile int stopping; 2217*eabc0478Schristos void *base; 2218*eabc0478Schristos void *dns; 2219*eabc0478Schristos 2220*eabc0478Schristos int locked; 2221*eabc0478Schristos }; 2222*eabc0478Schristos static void * 2223*eabc0478Schristos race_base_run(void *arg) 2224*eabc0478Schristos { 2225*eabc0478Schristos struct race_param *rp = (struct race_param *)arg; 2226*eabc0478Schristos event_base_loop(rp->base, EVLOOP_NO_EXIT_ON_EMPTY); 2227*eabc0478Schristos THREAD_RETURN(); 2228*eabc0478Schristos } 2229*eabc0478Schristos static void * 2230*eabc0478Schristos race_busywait_run(void *arg) 2231*eabc0478Schristos { 2232*eabc0478Schristos struct race_param *rp = (struct race_param *)arg; 2233*eabc0478Schristos struct sockaddr_storage ss; 2234*eabc0478Schristos while (!rp->stopping) 2235*eabc0478Schristos evdns_base_get_nameserver_addr(rp->dns, 0, (struct sockaddr *)&ss, sizeof(ss)); 2236*eabc0478Schristos EVLOCK_LOCK(rp->lock, 0); 2237*eabc0478Schristos if (--rp->bw_threads == 0) 2238*eabc0478Schristos EVTHREAD_COND_SIGNAL(rp->bw_threads_exited_cond); 2239*eabc0478Schristos EVLOCK_UNLOCK(rp->lock, 0); 2240*eabc0478Schristos THREAD_RETURN(); 2241*eabc0478Schristos } 2242*eabc0478Schristos static void 2243*eabc0478Schristos race_gai_cb(int result, struct evutil_addrinfo *res, void *arg) 2244*eabc0478Schristos { 2245*eabc0478Schristos struct race_param *rp = arg; 2246*eabc0478Schristos (void)result; 2247*eabc0478Schristos (void)res; 2248*eabc0478Schristos 2249*eabc0478Schristos --n_replies_left; 2250*eabc0478Schristos if (n_replies_left == 0) { 2251*eabc0478Schristos EVLOCK_LOCK(rp->lock, 0); 2252*eabc0478Schristos EVTHREAD_COND_SIGNAL(rp->reqs_cmpl_cond); 2253*eabc0478Schristos EVLOCK_UNLOCK(rp->lock, 0); 2254*eabc0478Schristos } 2255*eabc0478Schristos } 2256*eabc0478Schristos static void 2257*eabc0478Schristos getaddrinfo_race_gotresolve_test(void *arg) 2258*eabc0478Schristos { 2259*eabc0478Schristos struct race_param rp; 2260*eabc0478Schristos struct evdns_server_port *dns_port = NULL; 2261*eabc0478Schristos ev_uint16_t portnum = 0; 2262*eabc0478Schristos char buf[64]; 2263*eabc0478Schristos int i; 2264*eabc0478Schristos 2265*eabc0478Schristos // Some stress is needed to yield inside getaddrinfo between resolve_ipv4 and resolve_ipv6 2266*eabc0478Schristos int n_reqs = 16384; 2267*eabc0478Schristos #ifdef _SC_NPROCESSORS_ONLN 2268*eabc0478Schristos int n_threads = sysconf(_SC_NPROCESSORS_ONLN) + 1; 2269*eabc0478Schristos #else 2270*eabc0478Schristos int n_threads = 17; 2271*eabc0478Schristos #endif 2272*eabc0478Schristos THREAD_T thread[n_threads]; 2273*eabc0478Schristos struct timeval tv; 2274*eabc0478Schristos 2275*eabc0478Schristos (void)arg; 2276*eabc0478Schristos 2277*eabc0478Schristos evthread_use_pthreads(); 2278*eabc0478Schristos 2279*eabc0478Schristos rp.base = event_base_new(); 2280*eabc0478Schristos tt_assert(rp.base); 2281*eabc0478Schristos if (evthread_make_base_notifiable(rp.base) < 0) 2282*eabc0478Schristos tt_abort_msg("Couldn't make base notifiable!"); 2283*eabc0478Schristos 2284*eabc0478Schristos dns_port = regress_get_dnsserver(rp.base, &portnum, NULL, 2285*eabc0478Schristos regress_dns_server_cb, reissue_table); 2286*eabc0478Schristos tt_assert(dns_port); 2287*eabc0478Schristos 2288*eabc0478Schristos evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum); 2289*eabc0478Schristos 2290*eabc0478Schristos rp.dns = evdns_base_new(rp.base, 0); 2291*eabc0478Schristos tt_assert(!evdns_base_nameserver_ip_add(rp.dns, buf)); 2292*eabc0478Schristos 2293*eabc0478Schristos n_replies_left = n_reqs; 2294*eabc0478Schristos 2295*eabc0478Schristos EVTHREAD_ALLOC_LOCK(rp.lock, 0); 2296*eabc0478Schristos EVTHREAD_ALLOC_COND(rp.reqs_cmpl_cond); 2297*eabc0478Schristos EVTHREAD_ALLOC_COND(rp.bw_threads_exited_cond); 2298*eabc0478Schristos tt_assert(rp.lock); 2299*eabc0478Schristos tt_assert(rp.reqs_cmpl_cond); 2300*eabc0478Schristos tt_assert(rp.bw_threads_exited_cond); 2301*eabc0478Schristos rp.bw_threads = 0; 2302*eabc0478Schristos rp.stopping = 0; 2303*eabc0478Schristos 2304*eabc0478Schristos // Run resolver thread 2305*eabc0478Schristos THREAD_START(thread[0], race_base_run, &rp); 2306*eabc0478Schristos // Run busy-wait threads used to force yield this thread 2307*eabc0478Schristos for (i = 1; i < n_threads; i++) { 2308*eabc0478Schristos rp.bw_threads++; 2309*eabc0478Schristos THREAD_START(thread[i], race_busywait_run, &rp); 2310*eabc0478Schristos } 2311*eabc0478Schristos 2312*eabc0478Schristos EVLOCK_LOCK(rp.lock, 0); 2313*eabc0478Schristos rp.locked = 1; 2314*eabc0478Schristos 2315*eabc0478Schristos for (i = 0; i < n_reqs; ++i) { 2316*eabc0478Schristos tt_assert(evdns_getaddrinfo(rp.dns, "foof.example.com", "80", NULL, race_gai_cb, &rp)); 2317*eabc0478Schristos // This magic along with busy-wait threads make this thread yield frequently 2318*eabc0478Schristos if (i % 100 == 0) { 2319*eabc0478Schristos tv.tv_sec = 0; 2320*eabc0478Schristos tv.tv_usec = 10000; 2321*eabc0478Schristos evutil_usleep_(&tv); 2322*eabc0478Schristos } 2323*eabc0478Schristos } 2324*eabc0478Schristos 2325*eabc0478Schristos exit_base = rp.base; 2326*eabc0478Schristos 2327*eabc0478Schristos // Wait for some time 2328*eabc0478Schristos tv.tv_sec = 5; 2329*eabc0478Schristos tv.tv_usec = 0; 2330*eabc0478Schristos EVTHREAD_COND_WAIT_TIMED(rp.reqs_cmpl_cond, rp.lock, &tv); 2331*eabc0478Schristos 2332*eabc0478Schristos // Stop busy-wait threads 2333*eabc0478Schristos tv.tv_sec = 1; 2334*eabc0478Schristos tv.tv_usec = 0; 2335*eabc0478Schristos rp.stopping = 1; 2336*eabc0478Schristos tt_assert(EVTHREAD_COND_WAIT_TIMED(rp.bw_threads_exited_cond, rp.lock, &tv) == 0); 2337*eabc0478Schristos 2338*eabc0478Schristos EVLOCK_UNLOCK(rp.lock, 0); 2339*eabc0478Schristos rp.locked = 0; 2340*eabc0478Schristos 2341*eabc0478Schristos evdns_base_free(rp.dns, 1 /** fail requests */); 2342*eabc0478Schristos 2343*eabc0478Schristos tt_int_op(n_replies_left, ==, 0); 2344*eabc0478Schristos 2345*eabc0478Schristos end: 2346*eabc0478Schristos if (rp.locked) 2347*eabc0478Schristos EVLOCK_UNLOCK(rp.lock, 0); 2348*eabc0478Schristos EVTHREAD_FREE_LOCK(rp.lock, 0); 2349*eabc0478Schristos EVTHREAD_FREE_COND(rp.reqs_cmpl_cond); 2350*eabc0478Schristos EVTHREAD_FREE_COND(rp.bw_threads_exited_cond); 2351*eabc0478Schristos evdns_close_server_port(dns_port); 2352*eabc0478Schristos event_base_loopbreak(rp.base); 2353*eabc0478Schristos event_base_free(rp.base); 2354*eabc0478Schristos } 2355*eabc0478Schristos #endif 2356*eabc0478Schristos 2357*eabc0478Schristos static void 2358*eabc0478Schristos test_set_so_rcvbuf_so_sndbuf(void *arg) 2359*eabc0478Schristos { 2360*eabc0478Schristos struct basic_test_data *data = arg; 2361*eabc0478Schristos struct evdns_base *dns_base; 2362*eabc0478Schristos 2363*eabc0478Schristos dns_base = evdns_base_new(data->base, 0); 2364*eabc0478Schristos tt_assert(dns_base); 2365*eabc0478Schristos 2366*eabc0478Schristos tt_assert(!evdns_base_set_option(dns_base, "so-rcvbuf", "10240")); 2367*eabc0478Schristos tt_assert(!evdns_base_set_option(dns_base, "so-sndbuf", "10240")); 2368*eabc0478Schristos 2369*eabc0478Schristos /* actually check SO_RCVBUF/SO_SNDBUF not fails */ 2370*eabc0478Schristos tt_assert(!evdns_base_nameserver_ip_add(dns_base, "127.0.0.1")); 2371*eabc0478Schristos 2372*eabc0478Schristos end: 2373*eabc0478Schristos if (dns_base) 2374*eabc0478Schristos evdns_base_free(dns_base, 0); 2375*eabc0478Schristos } 2376*eabc0478Schristos 2377*eabc0478Schristos static void 2378*eabc0478Schristos test_set_option(void *arg) 2379*eabc0478Schristos { 2380*eabc0478Schristos #define SUCCESS 0 2381*eabc0478Schristos #define FAIL -1 2382*eabc0478Schristos struct basic_test_data *data = arg; 2383*eabc0478Schristos struct evdns_base *dns_base; 2384*eabc0478Schristos size_t i; 2385*eabc0478Schristos /* Option names are allowed to have ':' at the end. 2386*eabc0478Schristos * So all test option names come in pairs. 2387*eabc0478Schristos */ 2388*eabc0478Schristos const char *int_options[] = { 2389*eabc0478Schristos "ndots", "ndots:", 2390*eabc0478Schristos "max-timeouts", "max-timeouts:", 2391*eabc0478Schristos "max-inflight", "max-inflight:", 2392*eabc0478Schristos "attempts", "attempts:", 2393*eabc0478Schristos "randomize-case", "randomize-case:", 2394*eabc0478Schristos "so-rcvbuf", "so-rcvbuf:", 2395*eabc0478Schristos "so-sndbuf", "so-sndbuf:", 2396*eabc0478Schristos }; 2397*eabc0478Schristos const char *timeval_options[] = { 2398*eabc0478Schristos "timeout", "timeout:", 2399*eabc0478Schristos "getaddrinfo-allow-skew", "getaddrinfo-allow-skew:", 2400*eabc0478Schristos "initial-probe-timeout", "initial-probe-timeout:", 2401*eabc0478Schristos }; 2402*eabc0478Schristos const char *addr_port_options[] = { 2403*eabc0478Schristos "bind-to", "bind-to:", 2404*eabc0478Schristos }; 2405*eabc0478Schristos 2406*eabc0478Schristos dns_base = evdns_base_new(data->base, 0); 2407*eabc0478Schristos tt_assert(dns_base); 2408*eabc0478Schristos 2409*eabc0478Schristos for (i = 0; i < ARRAY_SIZE(int_options); ++i) { 2410*eabc0478Schristos tt_assert(SUCCESS == evdns_base_set_option(dns_base, int_options[i], "0")); 2411*eabc0478Schristos tt_assert(SUCCESS == evdns_base_set_option(dns_base, int_options[i], "1")); 2412*eabc0478Schristos tt_assert(SUCCESS == evdns_base_set_option(dns_base, int_options[i], "10000")); 2413*eabc0478Schristos tt_assert(FAIL == evdns_base_set_option(dns_base, int_options[i], "foo")); 2414*eabc0478Schristos tt_assert(FAIL == evdns_base_set_option(dns_base, int_options[i], "3.14")); 2415*eabc0478Schristos } 2416*eabc0478Schristos 2417*eabc0478Schristos for (i = 0; i < ARRAY_SIZE(timeval_options); ++i) { 2418*eabc0478Schristos tt_assert(SUCCESS == evdns_base_set_option(dns_base, timeval_options[i], "1")); 2419*eabc0478Schristos tt_assert(SUCCESS == evdns_base_set_option(dns_base, timeval_options[i], "0.001")); 2420*eabc0478Schristos tt_assert(SUCCESS == evdns_base_set_option(dns_base, timeval_options[i], "3.14")); 2421*eabc0478Schristos tt_assert(SUCCESS == evdns_base_set_option(dns_base, timeval_options[i], "10000")); 2422*eabc0478Schristos tt_assert(FAIL == evdns_base_set_option(dns_base, timeval_options[i], "0")); 2423*eabc0478Schristos tt_assert(FAIL == evdns_base_set_option(dns_base, timeval_options[i], "foo")); 2424*eabc0478Schristos } 2425*eabc0478Schristos 2426*eabc0478Schristos for (i = 0; i < ARRAY_SIZE(addr_port_options); ++i) { 2427*eabc0478Schristos tt_assert(SUCCESS == evdns_base_set_option(dns_base, addr_port_options[i], "8.8.8.8:80")); 2428*eabc0478Schristos tt_assert(SUCCESS == evdns_base_set_option(dns_base, addr_port_options[i], "1.2.3.4")); 2429*eabc0478Schristos tt_assert(SUCCESS == evdns_base_set_option(dns_base, addr_port_options[i], "::1:82")); 2430*eabc0478Schristos tt_assert(SUCCESS == evdns_base_set_option(dns_base, addr_port_options[i], "3::4")); 2431*eabc0478Schristos tt_assert(FAIL == evdns_base_set_option(dns_base, addr_port_options[i], "3.14")); 2432*eabc0478Schristos tt_assert(FAIL == evdns_base_set_option(dns_base, addr_port_options[i], "foo")); 2433*eabc0478Schristos } 2434*eabc0478Schristos 2435*eabc0478Schristos #undef SUCCESS 2436*eabc0478Schristos #undef FAIL 2437*eabc0478Schristos end: 2438*eabc0478Schristos if (dns_base) 2439*eabc0478Schristos evdns_base_free(dns_base, 0); 2440*eabc0478Schristos } 24418585484eSchristos 24428585484eSchristos #define DNS_LEGACY(name, flags) \ 24438585484eSchristos { #name, run_legacy_test_fn, flags|TT_LEGACY, &legacy_setup, \ 24448585484eSchristos dns_##name } 24458585484eSchristos 24468585484eSchristos struct testcase_t dns_testcases[] = { 24478585484eSchristos DNS_LEGACY(server, TT_FORK|TT_NEED_BASE), 24488585484eSchristos DNS_LEGACY(gethostbyname, TT_FORK|TT_NEED_BASE|TT_NEED_DNS|TT_OFF_BY_DEFAULT), 24498585484eSchristos DNS_LEGACY(gethostbyname6, TT_FORK|TT_NEED_BASE|TT_NEED_DNS|TT_OFF_BY_DEFAULT), 24508585484eSchristos DNS_LEGACY(gethostbyaddr, TT_FORK|TT_NEED_BASE|TT_NEED_DNS|TT_OFF_BY_DEFAULT), 24518585484eSchristos { "resolve_reverse", dns_resolve_reverse, TT_FORK|TT_OFF_BY_DEFAULT, NULL, NULL }, 2452*eabc0478Schristos { "search_empty", dns_search_empty_test, TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, 24538585484eSchristos { "search", dns_search_test, TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, 2454*eabc0478Schristos { "search_lower", dns_search_lower_test, TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, 24558585484eSchristos { "search_cancel", dns_search_cancel_test, 24568585484eSchristos TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, 2457b8ecfcfeSchristos { "retry", dns_retry_test, TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, NULL }, 24587476e6e4Schristos { "retry_disable_when_inactive", dns_retry_disable_when_inactive_test, 24597476e6e4Schristos TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, NULL }, 2460b8ecfcfeSchristos { "reissue", dns_reissue_test, TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, NULL }, 24617476e6e4Schristos { "reissue_disable_when_inactive", dns_reissue_disable_when_inactive_test, 24627476e6e4Schristos TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, NULL }, 24638585484eSchristos { "inflight", dns_inflight_test, TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, 24648585484eSchristos { "bufferevent_connect_hostname", test_bufferevent_connect_hostname, 24658585484eSchristos TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, 2466*eabc0478Schristos #ifdef EVENT__HAVE_SETRLIMIT 2467*eabc0478Schristos { "bufferevent_connect_hostname_emfile", test_bufferevent_connect_hostname, 2468*eabc0478Schristos TT_FORK|TT_NEED_BASE, &basic_setup, (char*)"emfile" }, 2469*eabc0478Schristos #endif 24707476e6e4Schristos { "disable_when_inactive", dns_disable_when_inactive_test, 24717476e6e4Schristos TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, 24727476e6e4Schristos { "disable_when_inactive_no_ns", dns_disable_when_inactive_no_ns_test, 2473*eabc0478Schristos TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, NULL }, 2474*eabc0478Schristos 2475*eabc0478Schristos { "initialize_nameservers", dns_initialize_nameservers_test, 24767476e6e4Schristos TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, 2477*eabc0478Schristos #ifndef _WIN32 2478*eabc0478Schristos { "nameservers_no_default", dns_nameservers_no_default_test, 2479*eabc0478Schristos TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, 2480*eabc0478Schristos #endif 24818585484eSchristos 24828585484eSchristos { "getaddrinfo_async", test_getaddrinfo_async, 24838585484eSchristos TT_FORK|TT_NEED_BASE, &basic_setup, (char*)"" }, 24848585484eSchristos { "getaddrinfo_cancel_stress", test_getaddrinfo_async_cancel_stress, 24858585484eSchristos TT_FORK, NULL, NULL }, 24868585484eSchristos 24878585484eSchristos #ifdef EVENT_SET_MEM_FUNCTIONS_IMPLEMENTED 24888585484eSchristos { "leak_shutdown", test_dbg_leak_shutdown, TT_FORK, &testleak_funcs, NULL }, 24898585484eSchristos { "leak_cancel", test_dbg_leak_cancel, TT_FORK, &testleak_funcs, NULL }, 2490b8ecfcfeSchristos 2491b8ecfcfeSchristos { "leak_resume", test_dbg_leak_resume_, TT_FORK, &testleak_funcs, NULL }, 2492b8ecfcfeSchristos { "leak_cancel_and_resume", test_dbg_leak_cancel_and_resume_, 2493b8ecfcfeSchristos TT_FORK, &testleak_funcs, NULL }, 2494b8ecfcfeSchristos { "leak_resume_send_err", test_dbg_leak_resume_send_err_, 2495b8ecfcfeSchristos TT_FORK, &testleak_funcs, NULL }, 2496b8ecfcfeSchristos { "leak_cancel_and_resume_send_err", test_dbg_leak_cancel_and_resume_send_err_, 2497b8ecfcfeSchristos TT_FORK, &testleak_funcs, NULL }, 24988585484eSchristos #endif 24998585484eSchristos 2500*eabc0478Schristos { "client_fail_requests", dns_client_fail_requests_test, 2501*eabc0478Schristos TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, NULL }, 2502*eabc0478Schristos { "client_fail_waiting_requests", dns_client_fail_requests_test, 2503*eabc0478Schristos TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, (char*)"limit-inflight" }, 2504*eabc0478Schristos { "client_fail_requests_getaddrinfo", 2505*eabc0478Schristos dns_client_fail_requests_getaddrinfo_test, 2506*eabc0478Schristos TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, NULL }, 2507*eabc0478Schristos #ifdef EVTHREAD_USE_PTHREADS_IMPLEMENTED 2508*eabc0478Schristos { "getaddrinfo_race_gotresolve", 2509*eabc0478Schristos getaddrinfo_race_gotresolve_test, 2510*eabc0478Schristos TT_FORK|TT_OFF_BY_DEFAULT, NULL, NULL }, 2511*eabc0478Schristos #endif 2512*eabc0478Schristos 2513*eabc0478Schristos { "set_SO_RCVBUF_SO_SNDBUF", test_set_so_rcvbuf_so_sndbuf, 2514*eabc0478Schristos TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, 2515*eabc0478Schristos { "set_options", test_set_option, 2516*eabc0478Schristos TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, 2517*eabc0478Schristos 25188585484eSchristos END_OF_TESTCASES 25198585484eSchristos }; 25208585484eSchristos 2521