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