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