1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/ipc/chromium/src/third_party/libevent/test/regress_dns.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1855 @@ 1.4 +/* 1.5 + * Copyright (c) 2003-2007 Niels Provos <provos@citi.umich.edu> 1.6 + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson 1.7 + * 1.8 + * Redistribution and use in source and binary forms, with or without 1.9 + * modification, are permitted provided that the following conditions 1.10 + * are met: 1.11 + * 1. Redistributions of source code must retain the above copyright 1.12 + * notice, this list of conditions and the following disclaimer. 1.13 + * 2. Redistributions in binary form must reproduce the above copyright 1.14 + * notice, this list of conditions and the following disclaimer in the 1.15 + * documentation and/or other materials provided with the distribution. 1.16 + * 3. The name of the author may not be used to endorse or promote products 1.17 + * derived from this software without specific prior written permission. 1.18 + * 1.19 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1.20 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1.21 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1.22 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1.23 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 1.24 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.25 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.26 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.27 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 1.28 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.29 + */ 1.30 + 1.31 +#ifdef WIN32 1.32 +#include <winsock2.h> 1.33 +#include <windows.h> 1.34 +#include <ws2tcpip.h> 1.35 +#endif 1.36 + 1.37 +#include "event2/event-config.h" 1.38 + 1.39 +#include <sys/types.h> 1.40 +#include <sys/stat.h> 1.41 +#ifdef _EVENT_HAVE_SYS_TIME_H 1.42 +#include <sys/time.h> 1.43 +#endif 1.44 +#include <sys/queue.h> 1.45 +#ifndef WIN32 1.46 +#include <sys/socket.h> 1.47 +#include <signal.h> 1.48 +#include <netinet/in.h> 1.49 +#include <arpa/inet.h> 1.50 +#include <unistd.h> 1.51 +#endif 1.52 +#ifdef _EVENT_HAVE_NETINET_IN6_H 1.53 +#include <netinet/in6.h> 1.54 +#endif 1.55 +#ifdef HAVE_NETDB_H 1.56 +#include <netdb.h> 1.57 +#endif 1.58 +#include <fcntl.h> 1.59 +#include <stdlib.h> 1.60 +#include <stdio.h> 1.61 +#include <string.h> 1.62 +#include <errno.h> 1.63 + 1.64 +#include "event2/dns.h" 1.65 +#include "event2/dns_compat.h" 1.66 +#include "event2/dns_struct.h" 1.67 +#include "event2/event.h" 1.68 +#include "event2/event_compat.h" 1.69 +#include "event2/event_struct.h" 1.70 +#include "event2/util.h" 1.71 +#include "event2/listener.h" 1.72 +#include "event2/bufferevent.h" 1.73 +#include "log-internal.h" 1.74 +#include "regress.h" 1.75 +#include "regress_testutils.h" 1.76 + 1.77 +#include "../util-internal.h" 1.78 + 1.79 +static int dns_ok = 0; 1.80 +static int dns_got_cancel = 0; 1.81 +static int dns_err = 0; 1.82 + 1.83 + 1.84 +static void 1.85 +dns_gethostbyname_cb(int result, char type, int count, int ttl, 1.86 + void *addresses, void *arg) 1.87 +{ 1.88 + dns_ok = dns_err = 0; 1.89 + 1.90 + if (result == DNS_ERR_TIMEOUT) { 1.91 + printf("[Timed out] "); 1.92 + dns_err = result; 1.93 + goto out; 1.94 + } 1.95 + 1.96 + if (result != DNS_ERR_NONE) { 1.97 + printf("[Error code %d] ", result); 1.98 + goto out; 1.99 + } 1.100 + 1.101 + TT_BLATHER(("type: %d, count: %d, ttl: %d: ", type, count, ttl)); 1.102 + 1.103 + switch (type) { 1.104 + case DNS_IPv6_AAAA: { 1.105 +#if defined(_EVENT_HAVE_STRUCT_IN6_ADDR) && defined(_EVENT_HAVE_INET_NTOP) && defined(INET6_ADDRSTRLEN) 1.106 + struct in6_addr *in6_addrs = addresses; 1.107 + char buf[INET6_ADDRSTRLEN+1]; 1.108 + int i; 1.109 + /* a resolution that's not valid does not help */ 1.110 + if (ttl < 0) 1.111 + goto out; 1.112 + for (i = 0; i < count; ++i) { 1.113 + const char *b = evutil_inet_ntop(AF_INET6, &in6_addrs[i], buf,sizeof(buf)); 1.114 + if (b) 1.115 + TT_BLATHER(("%s ", b)); 1.116 + else 1.117 + TT_BLATHER(("%s ", strerror(errno))); 1.118 + } 1.119 +#endif 1.120 + break; 1.121 + } 1.122 + case DNS_IPv4_A: { 1.123 + struct in_addr *in_addrs = addresses; 1.124 + int i; 1.125 + /* a resolution that's not valid does not help */ 1.126 + if (ttl < 0) 1.127 + goto out; 1.128 + for (i = 0; i < count; ++i) 1.129 + TT_BLATHER(("%s ", inet_ntoa(in_addrs[i]))); 1.130 + break; 1.131 + } 1.132 + case DNS_PTR: 1.133 + /* may get at most one PTR */ 1.134 + if (count != 1) 1.135 + goto out; 1.136 + 1.137 + TT_BLATHER(("%s ", *(char **)addresses)); 1.138 + break; 1.139 + default: 1.140 + goto out; 1.141 + } 1.142 + 1.143 + dns_ok = type; 1.144 + 1.145 +out: 1.146 + if (arg == NULL) 1.147 + event_loopexit(NULL); 1.148 + else 1.149 + event_base_loopexit((struct event_base *)arg, NULL); 1.150 +} 1.151 + 1.152 +static void 1.153 +dns_gethostbyname(void) 1.154 +{ 1.155 + dns_ok = 0; 1.156 + evdns_resolve_ipv4("www.monkey.org", 0, dns_gethostbyname_cb, NULL); 1.157 + event_dispatch(); 1.158 + 1.159 + tt_int_op(dns_ok, ==, DNS_IPv4_A); 1.160 + test_ok = dns_ok; 1.161 +end: 1.162 + ; 1.163 +} 1.164 + 1.165 +static void 1.166 +dns_gethostbyname6(void) 1.167 +{ 1.168 + dns_ok = 0; 1.169 + evdns_resolve_ipv6("www.ietf.org", 0, dns_gethostbyname_cb, NULL); 1.170 + event_dispatch(); 1.171 + 1.172 + if (!dns_ok && dns_err == DNS_ERR_TIMEOUT) { 1.173 + tt_skip(); 1.174 + } 1.175 + 1.176 + tt_int_op(dns_ok, ==, DNS_IPv6_AAAA); 1.177 + test_ok = 1; 1.178 +end: 1.179 + ; 1.180 +} 1.181 + 1.182 +static void 1.183 +dns_gethostbyaddr(void) 1.184 +{ 1.185 + struct in_addr in; 1.186 + in.s_addr = htonl(0x7f000001ul); /* 127.0.0.1 */ 1.187 + dns_ok = 0; 1.188 + evdns_resolve_reverse(&in, 0, dns_gethostbyname_cb, NULL); 1.189 + event_dispatch(); 1.190 + 1.191 + tt_int_op(dns_ok, ==, DNS_PTR); 1.192 + test_ok = dns_ok; 1.193 +end: 1.194 + ; 1.195 +} 1.196 + 1.197 +static void 1.198 +dns_resolve_reverse(void *ptr) 1.199 +{ 1.200 + struct in_addr in; 1.201 + struct event_base *base = event_base_new(); 1.202 + struct evdns_base *dns = evdns_base_new(base, 1/* init name servers */); 1.203 + struct evdns_request *req = NULL; 1.204 + 1.205 + tt_assert(base); 1.206 + tt_assert(dns); 1.207 + in.s_addr = htonl(0x7f000001ul); /* 127.0.0.1 */ 1.208 + dns_ok = 0; 1.209 + 1.210 + req = evdns_base_resolve_reverse( 1.211 + dns, &in, 0, dns_gethostbyname_cb, base); 1.212 + tt_assert(req); 1.213 + 1.214 + event_base_dispatch(base); 1.215 + 1.216 + tt_int_op(dns_ok, ==, DNS_PTR); 1.217 + 1.218 +end: 1.219 + if (dns) 1.220 + evdns_base_free(dns, 0); 1.221 + if (base) 1.222 + event_base_free(base); 1.223 +} 1.224 + 1.225 +static int n_server_responses = 0; 1.226 + 1.227 +static void 1.228 +dns_server_request_cb(struct evdns_server_request *req, void *data) 1.229 +{ 1.230 + int i, r; 1.231 + const char TEST_ARPA[] = "11.11.168.192.in-addr.arpa"; 1.232 + const char TEST_IN6[] = 1.233 + "f.e.f.e." "0.0.0.0." "0.0.0.0." "1.1.1.1." 1.234 + "a.a.a.a." "0.0.0.0." "0.0.0.0." "0.f.f.f.ip6.arpa"; 1.235 + 1.236 + for (i = 0; i < req->nquestions; ++i) { 1.237 + const int qtype = req->questions[i]->type; 1.238 + const int qclass = req->questions[i]->dns_question_class; 1.239 + const char *qname = req->questions[i]->name; 1.240 + 1.241 + struct in_addr ans; 1.242 + ans.s_addr = htonl(0xc0a80b0bUL); /* 192.168.11.11 */ 1.243 + if (qtype == EVDNS_TYPE_A && 1.244 + qclass == EVDNS_CLASS_INET && 1.245 + !evutil_ascii_strcasecmp(qname, "zz.example.com")) { 1.246 + r = evdns_server_request_add_a_reply(req, qname, 1.247 + 1, &ans.s_addr, 12345); 1.248 + if (r<0) 1.249 + dns_ok = 0; 1.250 + } else if (qtype == EVDNS_TYPE_AAAA && 1.251 + qclass == EVDNS_CLASS_INET && 1.252 + !evutil_ascii_strcasecmp(qname, "zz.example.com")) { 1.253 + char addr6[17] = "abcdefghijklmnop"; 1.254 + r = evdns_server_request_add_aaaa_reply(req, 1.255 + qname, 1, addr6, 123); 1.256 + if (r<0) 1.257 + dns_ok = 0; 1.258 + } else if (qtype == EVDNS_TYPE_PTR && 1.259 + qclass == EVDNS_CLASS_INET && 1.260 + !evutil_ascii_strcasecmp(qname, TEST_ARPA)) { 1.261 + r = evdns_server_request_add_ptr_reply(req, NULL, 1.262 + qname, "ZZ.EXAMPLE.COM", 54321); 1.263 + if (r<0) 1.264 + dns_ok = 0; 1.265 + } else if (qtype == EVDNS_TYPE_PTR && 1.266 + qclass == EVDNS_CLASS_INET && 1.267 + !evutil_ascii_strcasecmp(qname, TEST_IN6)){ 1.268 + r = evdns_server_request_add_ptr_reply(req, NULL, 1.269 + qname, 1.270 + "ZZ-INET6.EXAMPLE.COM", 54322); 1.271 + if (r<0) 1.272 + dns_ok = 0; 1.273 + } else if (qtype == EVDNS_TYPE_A && 1.274 + qclass == EVDNS_CLASS_INET && 1.275 + !evutil_ascii_strcasecmp(qname, "drop.example.com")) { 1.276 + if (evdns_server_request_drop(req)<0) 1.277 + dns_ok = 0; 1.278 + return; 1.279 + } else { 1.280 + printf("Unexpected question %d %d \"%s\" ", 1.281 + qtype, qclass, qname); 1.282 + dns_ok = 0; 1.283 + } 1.284 + } 1.285 + r = evdns_server_request_respond(req, 0); 1.286 + if (r<0) { 1.287 + printf("Couldn't send reply. "); 1.288 + dns_ok = 0; 1.289 + } 1.290 +} 1.291 + 1.292 +static void 1.293 +dns_server_gethostbyname_cb(int result, char type, int count, int ttl, 1.294 + void *addresses, void *arg) 1.295 +{ 1.296 + if (result == DNS_ERR_CANCEL) { 1.297 + if (arg != (void*)(char*)90909) { 1.298 + printf("Unexpected cancelation"); 1.299 + dns_ok = 0; 1.300 + } 1.301 + dns_got_cancel = 1; 1.302 + goto out; 1.303 + } 1.304 + if (result != DNS_ERR_NONE) { 1.305 + printf("Unexpected result %d. ", result); 1.306 + dns_ok = 0; 1.307 + goto out; 1.308 + } 1.309 + if (count != 1) { 1.310 + printf("Unexpected answer count %d. ", count); 1.311 + dns_ok = 0; 1.312 + goto out; 1.313 + } 1.314 + switch (type) { 1.315 + case DNS_IPv4_A: { 1.316 + struct in_addr *in_addrs = addresses; 1.317 + if (in_addrs[0].s_addr != htonl(0xc0a80b0bUL) || ttl != 12345) { 1.318 + printf("Bad IPv4 response \"%s\" %d. ", 1.319 + inet_ntoa(in_addrs[0]), ttl); 1.320 + dns_ok = 0; 1.321 + goto out; 1.322 + } 1.323 + break; 1.324 + } 1.325 + case DNS_IPv6_AAAA: { 1.326 +#if defined (_EVENT_HAVE_STRUCT_IN6_ADDR) && defined(_EVENT_HAVE_INET_NTOP) && defined(INET6_ADDRSTRLEN) 1.327 + struct in6_addr *in6_addrs = addresses; 1.328 + char buf[INET6_ADDRSTRLEN+1]; 1.329 + if (memcmp(&in6_addrs[0].s6_addr, "abcdefghijklmnop", 16) 1.330 + || ttl != 123) { 1.331 + const char *b = evutil_inet_ntop(AF_INET6, &in6_addrs[0],buf,sizeof(buf)); 1.332 + printf("Bad IPv6 response \"%s\" %d. ", b, ttl); 1.333 + dns_ok = 0; 1.334 + goto out; 1.335 + } 1.336 +#endif 1.337 + break; 1.338 + } 1.339 + case DNS_PTR: { 1.340 + char **addrs = addresses; 1.341 + if (arg != (void*)6) { 1.342 + if (strcmp(addrs[0], "ZZ.EXAMPLE.COM") || 1.343 + ttl != 54321) { 1.344 + printf("Bad PTR response \"%s\" %d. ", 1.345 + addrs[0], ttl); 1.346 + dns_ok = 0; 1.347 + goto out; 1.348 + } 1.349 + } else { 1.350 + if (strcmp(addrs[0], "ZZ-INET6.EXAMPLE.COM") || 1.351 + ttl != 54322) { 1.352 + printf("Bad ipv6 PTR response \"%s\" %d. ", 1.353 + addrs[0], ttl); 1.354 + dns_ok = 0; 1.355 + goto out; 1.356 + } 1.357 + } 1.358 + break; 1.359 + } 1.360 + default: 1.361 + printf("Bad response type %d. ", type); 1.362 + dns_ok = 0; 1.363 + } 1.364 + out: 1.365 + if (++n_server_responses == 3) { 1.366 + event_loopexit(NULL); 1.367 + } 1.368 +} 1.369 + 1.370 +static void 1.371 +dns_server(void) 1.372 +{ 1.373 + evutil_socket_t sock=-1; 1.374 + struct sockaddr_in my_addr; 1.375 + struct sockaddr_storage ss; 1.376 + ev_socklen_t slen; 1.377 + struct evdns_server_port *port=NULL; 1.378 + struct in_addr resolve_addr; 1.379 + struct in6_addr resolve_addr6; 1.380 + struct evdns_base *base=NULL; 1.381 + struct evdns_request *req=NULL; 1.382 + 1.383 + dns_ok = 1; 1.384 + 1.385 + base = evdns_base_new(NULL, 0); 1.386 + 1.387 + /* Now configure a nameserver port. */ 1.388 + sock = socket(AF_INET, SOCK_DGRAM, 0); 1.389 + if (sock<0) { 1.390 + tt_abort_perror("socket"); 1.391 + } 1.392 + 1.393 + evutil_make_socket_nonblocking(sock); 1.394 + 1.395 + memset(&my_addr, 0, sizeof(my_addr)); 1.396 + my_addr.sin_family = AF_INET; 1.397 + my_addr.sin_port = 0; /* kernel picks */ 1.398 + my_addr.sin_addr.s_addr = htonl(0x7f000001UL); 1.399 + if (bind(sock, (struct sockaddr*)&my_addr, sizeof(my_addr)) < 0) { 1.400 + tt_abort_perror("bind"); 1.401 + } 1.402 + slen = sizeof(ss); 1.403 + if (getsockname(sock, (struct sockaddr*)&ss, &slen) < 0) { 1.404 + tt_abort_perror("getsockname"); 1.405 + } 1.406 + 1.407 + port = evdns_add_server_port(sock, 0, dns_server_request_cb, NULL); 1.408 + 1.409 + /* Add ourself as the only nameserver, and make sure we really are 1.410 + * the only nameserver. */ 1.411 + evdns_base_nameserver_sockaddr_add(base, (struct sockaddr*)&ss, slen, 0); 1.412 + tt_int_op(evdns_base_count_nameservers(base), ==, 1); 1.413 + 1.414 + /* Send some queries. */ 1.415 + evdns_base_resolve_ipv4(base, "zz.example.com", DNS_QUERY_NO_SEARCH, 1.416 + dns_server_gethostbyname_cb, NULL); 1.417 + evdns_base_resolve_ipv6(base, "zz.example.com", DNS_QUERY_NO_SEARCH, 1.418 + dns_server_gethostbyname_cb, NULL); 1.419 + resolve_addr.s_addr = htonl(0xc0a80b0bUL); /* 192.168.11.11 */ 1.420 + evdns_base_resolve_reverse(base, &resolve_addr, 0, 1.421 + dns_server_gethostbyname_cb, NULL); 1.422 + memcpy(resolve_addr6.s6_addr, 1.423 + "\xff\xf0\x00\x00\x00\x00\xaa\xaa" 1.424 + "\x11\x11\x00\x00\x00\x00\xef\xef", 16); 1.425 + evdns_base_resolve_reverse_ipv6(base, &resolve_addr6, 0, 1.426 + dns_server_gethostbyname_cb, (void*)6); 1.427 + 1.428 + req = evdns_base_resolve_ipv4(base, 1.429 + "drop.example.com", DNS_QUERY_NO_SEARCH, 1.430 + dns_server_gethostbyname_cb, (void*)(char*)90909); 1.431 + 1.432 + evdns_cancel_request(base, req); 1.433 + 1.434 + event_dispatch(); 1.435 + 1.436 + tt_assert(dns_got_cancel); 1.437 + test_ok = dns_ok; 1.438 + 1.439 +end: 1.440 + if (port) 1.441 + evdns_close_server_port(port); 1.442 + if (sock >= 0) 1.443 + evutil_closesocket(sock); 1.444 + if (base) 1.445 + evdns_base_free(base, 0); 1.446 +} 1.447 + 1.448 +static int n_replies_left; 1.449 +static struct event_base *exit_base; 1.450 + 1.451 +struct generic_dns_callback_result { 1.452 + int result; 1.453 + char type; 1.454 + int count; 1.455 + int ttl; 1.456 + size_t addrs_len; 1.457 + void *addrs; 1.458 + char addrs_buf[256]; 1.459 +}; 1.460 + 1.461 +static void 1.462 +generic_dns_callback(int result, char type, int count, int ttl, void *addresses, 1.463 + void *arg) 1.464 +{ 1.465 + size_t len; 1.466 + struct generic_dns_callback_result *res = arg; 1.467 + res->result = result; 1.468 + res->type = type; 1.469 + res->count = count; 1.470 + res->ttl = ttl; 1.471 + 1.472 + if (type == DNS_IPv4_A) 1.473 + len = count * 4; 1.474 + else if (type == DNS_IPv6_AAAA) 1.475 + len = count * 16; 1.476 + else if (type == DNS_PTR) 1.477 + len = strlen(addresses)+1; 1.478 + else { 1.479 + res->addrs_len = len = 0; 1.480 + res->addrs = NULL; 1.481 + } 1.482 + if (len) { 1.483 + res->addrs_len = len; 1.484 + if (len > 256) 1.485 + len = 256; 1.486 + memcpy(res->addrs_buf, addresses, len); 1.487 + res->addrs = res->addrs_buf; 1.488 + } 1.489 + 1.490 + if (--n_replies_left == 0) 1.491 + event_base_loopexit(exit_base, NULL); 1.492 +} 1.493 + 1.494 +static struct regress_dns_server_table search_table[] = { 1.495 + { "host.a.example.com", "err", "3", 0 }, 1.496 + { "host.b.example.com", "err", "3", 0 }, 1.497 + { "host.c.example.com", "A", "11.22.33.44", 0 }, 1.498 + { "host2.a.example.com", "err", "3", 0 }, 1.499 + { "host2.b.example.com", "A", "200.100.0.100", 0 }, 1.500 + { "host2.c.example.com", "err", "3", 0 }, 1.501 + { "hostn.a.example.com", "errsoa", "0", 0 }, 1.502 + { "hostn.b.example.com", "errsoa", "3", 0 }, 1.503 + { "hostn.c.example.com", "err", "0", 0 }, 1.504 + 1.505 + { "host", "err", "3", 0 }, 1.506 + { "host2", "err", "3", 0 }, 1.507 + { "*", "err", "3", 0 }, 1.508 + { NULL, NULL, NULL, 0 } 1.509 +}; 1.510 + 1.511 +static void 1.512 +dns_search_test(void *arg) 1.513 +{ 1.514 + struct basic_test_data *data = arg; 1.515 + struct event_base *base = data->base; 1.516 + struct evdns_base *dns = NULL; 1.517 + ev_uint16_t portnum = 0; 1.518 + char buf[64]; 1.519 + 1.520 + struct generic_dns_callback_result r[8]; 1.521 + 1.522 + tt_assert(regress_dnsserver(base, &portnum, search_table)); 1.523 + evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum); 1.524 + 1.525 + dns = evdns_base_new(base, 0); 1.526 + tt_assert(!evdns_base_nameserver_ip_add(dns, buf)); 1.527 + 1.528 + evdns_base_search_add(dns, "a.example.com"); 1.529 + evdns_base_search_add(dns, "b.example.com"); 1.530 + evdns_base_search_add(dns, "c.example.com"); 1.531 + 1.532 + n_replies_left = sizeof(r)/sizeof(r[0]); 1.533 + exit_base = base; 1.534 + 1.535 + evdns_base_resolve_ipv4(dns, "host", 0, generic_dns_callback, &r[0]); 1.536 + evdns_base_resolve_ipv4(dns, "host2", 0, generic_dns_callback, &r[1]); 1.537 + evdns_base_resolve_ipv4(dns, "host", DNS_NO_SEARCH, generic_dns_callback, &r[2]); 1.538 + evdns_base_resolve_ipv4(dns, "host2", DNS_NO_SEARCH, generic_dns_callback, &r[3]); 1.539 + evdns_base_resolve_ipv4(dns, "host3", 0, generic_dns_callback, &r[4]); 1.540 + evdns_base_resolve_ipv4(dns, "hostn.a.example.com", DNS_NO_SEARCH, generic_dns_callback, &r[5]); 1.541 + evdns_base_resolve_ipv4(dns, "hostn.b.example.com", DNS_NO_SEARCH, generic_dns_callback, &r[6]); 1.542 + evdns_base_resolve_ipv4(dns, "hostn.c.example.com", DNS_NO_SEARCH, generic_dns_callback, &r[7]); 1.543 + 1.544 + event_base_dispatch(base); 1.545 + 1.546 + tt_int_op(r[0].type, ==, DNS_IPv4_A); 1.547 + tt_int_op(r[0].count, ==, 1); 1.548 + tt_int_op(((ev_uint32_t*)r[0].addrs)[0], ==, htonl(0x0b16212c)); 1.549 + tt_int_op(r[1].type, ==, DNS_IPv4_A); 1.550 + tt_int_op(r[1].count, ==, 1); 1.551 + tt_int_op(((ev_uint32_t*)r[1].addrs)[0], ==, htonl(0xc8640064)); 1.552 + tt_int_op(r[2].result, ==, DNS_ERR_NOTEXIST); 1.553 + tt_int_op(r[3].result, ==, DNS_ERR_NOTEXIST); 1.554 + tt_int_op(r[4].result, ==, DNS_ERR_NOTEXIST); 1.555 + tt_int_op(r[5].result, ==, DNS_ERR_NODATA); 1.556 + tt_int_op(r[5].ttl, ==, 42); 1.557 + tt_int_op(r[6].result, ==, DNS_ERR_NOTEXIST); 1.558 + tt_int_op(r[6].ttl, ==, 42); 1.559 + tt_int_op(r[7].result, ==, DNS_ERR_NODATA); 1.560 + tt_int_op(r[7].ttl, ==, 0); 1.561 + 1.562 +end: 1.563 + if (dns) 1.564 + evdns_base_free(dns, 0); 1.565 + 1.566 + regress_clean_dnsserver(); 1.567 +} 1.568 + 1.569 +static int request_count = 0; 1.570 +static struct evdns_request *current_req = NULL; 1.571 + 1.572 +static void 1.573 +search_cancel_server_cb(struct evdns_server_request *req, void *data) 1.574 +{ 1.575 + const char *question; 1.576 + 1.577 + if (req->nquestions != 1) 1.578 + TT_DIE(("Only handling one question at a time; got %d", 1.579 + req->nquestions)); 1.580 + 1.581 + question = req->questions[0]->name; 1.582 + 1.583 + TT_BLATHER(("got question, %s", question)); 1.584 + 1.585 + tt_assert(request_count > 0); 1.586 + tt_assert(!evdns_server_request_respond(req, 3)); 1.587 + 1.588 + if (!--request_count) 1.589 + evdns_cancel_request(NULL, current_req); 1.590 + 1.591 +end: 1.592 + ; 1.593 +} 1.594 + 1.595 +static void 1.596 +dns_search_cancel_test(void *arg) 1.597 +{ 1.598 + struct basic_test_data *data = arg; 1.599 + struct event_base *base = data->base; 1.600 + struct evdns_base *dns = NULL; 1.601 + struct evdns_server_port *port = NULL; 1.602 + ev_uint16_t portnum = 0; 1.603 + struct generic_dns_callback_result r1; 1.604 + char buf[64]; 1.605 + 1.606 + port = regress_get_dnsserver(base, &portnum, NULL, 1.607 + search_cancel_server_cb, NULL); 1.608 + tt_assert(port); 1.609 + evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum); 1.610 + 1.611 + dns = evdns_base_new(base, 0); 1.612 + tt_assert(!evdns_base_nameserver_ip_add(dns, buf)); 1.613 + 1.614 + evdns_base_search_add(dns, "a.example.com"); 1.615 + evdns_base_search_add(dns, "b.example.com"); 1.616 + evdns_base_search_add(dns, "c.example.com"); 1.617 + evdns_base_search_add(dns, "d.example.com"); 1.618 + 1.619 + exit_base = base; 1.620 + request_count = 3; 1.621 + n_replies_left = 1; 1.622 + 1.623 + current_req = evdns_base_resolve_ipv4(dns, "host", 0, 1.624 + generic_dns_callback, &r1); 1.625 + event_base_dispatch(base); 1.626 + 1.627 + tt_int_op(r1.result, ==, DNS_ERR_CANCEL); 1.628 + 1.629 +end: 1.630 + if (port) 1.631 + evdns_close_server_port(port); 1.632 + if (dns) 1.633 + evdns_base_free(dns, 0); 1.634 +} 1.635 + 1.636 +static void 1.637 +fail_server_cb(struct evdns_server_request *req, void *data) 1.638 +{ 1.639 + const char *question; 1.640 + int *count = data; 1.641 + struct in_addr in; 1.642 + 1.643 + /* Drop the first N requests that we get. */ 1.644 + if (*count > 0) { 1.645 + --*count; 1.646 + tt_want(! evdns_server_request_drop(req)); 1.647 + return; 1.648 + } 1.649 + 1.650 + if (req->nquestions != 1) 1.651 + TT_DIE(("Only handling one question at a time; got %d", 1.652 + req->nquestions)); 1.653 + 1.654 + question = req->questions[0]->name; 1.655 + 1.656 + if (!evutil_ascii_strcasecmp(question, "google.com")) { 1.657 + /* Detect a probe, and get out of the loop. */ 1.658 + event_base_loopexit(exit_base, NULL); 1.659 + } 1.660 + 1.661 + evutil_inet_pton(AF_INET, "16.32.64.128", &in); 1.662 + evdns_server_request_add_a_reply(req, question, 1, &in.s_addr, 1.663 + 100); 1.664 + tt_assert(! evdns_server_request_respond(req, 0)) 1.665 + return; 1.666 +end: 1.667 + tt_want(! evdns_server_request_drop(req)); 1.668 +} 1.669 + 1.670 +static void 1.671 +dns_retry_test(void *arg) 1.672 +{ 1.673 + struct basic_test_data *data = arg; 1.674 + struct event_base *base = data->base; 1.675 + struct evdns_server_port *port = NULL; 1.676 + struct evdns_base *dns = NULL; 1.677 + int drop_count = 2; 1.678 + ev_uint16_t portnum = 0; 1.679 + char buf[64]; 1.680 + 1.681 + struct generic_dns_callback_result r1; 1.682 + 1.683 + port = regress_get_dnsserver(base, &portnum, NULL, 1.684 + fail_server_cb, &drop_count); 1.685 + tt_assert(port); 1.686 + evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum); 1.687 + 1.688 + dns = evdns_base_new(base, 0); 1.689 + tt_assert(!evdns_base_nameserver_ip_add(dns, buf)); 1.690 + tt_assert(! evdns_base_set_option(dns, "timeout", "0.3")); 1.691 + tt_assert(! evdns_base_set_option(dns, "max-timeouts:", "10")); 1.692 + tt_assert(! evdns_base_set_option(dns, "initial-probe-timeout", "0.5")); 1.693 + 1.694 + evdns_base_resolve_ipv4(dns, "host.example.com", 0, 1.695 + generic_dns_callback, &r1); 1.696 + 1.697 + n_replies_left = 1; 1.698 + exit_base = base; 1.699 + 1.700 + event_base_dispatch(base); 1.701 + 1.702 + tt_int_op(drop_count, ==, 0); 1.703 + 1.704 + tt_int_op(r1.type, ==, DNS_IPv4_A); 1.705 + tt_int_op(r1.count, ==, 1); 1.706 + tt_int_op(((ev_uint32_t*)r1.addrs)[0], ==, htonl(0x10204080)); 1.707 + 1.708 + /* Now try again, but this time have the server get treated as 1.709 + * failed, so we can send it a test probe. */ 1.710 + drop_count = 4; 1.711 + tt_assert(! evdns_base_set_option(dns, "max-timeouts:", "3")); 1.712 + tt_assert(! evdns_base_set_option(dns, "attempts:", "4")); 1.713 + memset(&r1, 0, sizeof(r1)); 1.714 + 1.715 + evdns_base_resolve_ipv4(dns, "host.example.com", 0, 1.716 + generic_dns_callback, &r1); 1.717 + 1.718 + n_replies_left = 2; 1.719 + 1.720 + /* This will run until it answers the "google.com" probe request. */ 1.721 + event_base_dispatch(base); 1.722 + 1.723 + /* We'll treat the server as failed here. */ 1.724 + tt_int_op(r1.result, ==, DNS_ERR_TIMEOUT); 1.725 + 1.726 + /* It should work this time. */ 1.727 + tt_int_op(drop_count, ==, 0); 1.728 + evdns_base_resolve_ipv4(dns, "host.example.com", 0, 1.729 + generic_dns_callback, &r1); 1.730 + 1.731 + event_base_dispatch(base); 1.732 + tt_int_op(r1.result, ==, DNS_ERR_NONE); 1.733 + tt_int_op(r1.type, ==, DNS_IPv4_A); 1.734 + tt_int_op(r1.count, ==, 1); 1.735 + tt_int_op(((ev_uint32_t*)r1.addrs)[0], ==, htonl(0x10204080)); 1.736 + 1.737 +end: 1.738 + if (dns) 1.739 + evdns_base_free(dns, 0); 1.740 + if (port) 1.741 + evdns_close_server_port(port); 1.742 +} 1.743 + 1.744 +static struct regress_dns_server_table internal_error_table[] = { 1.745 + /* Error 4 (NOTIMPL) makes us reissue the request to another server 1.746 + if we can. 1.747 + 1.748 + XXXX we should reissue under a much wider set of circumstances! 1.749 + */ 1.750 + { "foof.example.com", "err", "4", 0 }, 1.751 + { NULL, NULL, NULL, 0 } 1.752 +}; 1.753 + 1.754 +static struct regress_dns_server_table reissue_table[] = { 1.755 + { "foof.example.com", "A", "240.15.240.15", 0 }, 1.756 + { NULL, NULL, NULL, 0 } 1.757 +}; 1.758 + 1.759 +static void 1.760 +dns_reissue_test(void *arg) 1.761 +{ 1.762 + struct basic_test_data *data = arg; 1.763 + struct event_base *base = data->base; 1.764 + struct evdns_server_port *port1 = NULL, *port2 = NULL; 1.765 + struct evdns_base *dns = NULL; 1.766 + struct generic_dns_callback_result r1; 1.767 + ev_uint16_t portnum1 = 0, portnum2=0; 1.768 + char buf1[64], buf2[64]; 1.769 + 1.770 + port1 = regress_get_dnsserver(base, &portnum1, NULL, 1.771 + regress_dns_server_cb, internal_error_table); 1.772 + tt_assert(port1); 1.773 + port2 = regress_get_dnsserver(base, &portnum2, NULL, 1.774 + regress_dns_server_cb, reissue_table); 1.775 + tt_assert(port2); 1.776 + evutil_snprintf(buf1, sizeof(buf1), "127.0.0.1:%d", (int)portnum1); 1.777 + evutil_snprintf(buf2, sizeof(buf2), "127.0.0.1:%d", (int)portnum2); 1.778 + 1.779 + dns = evdns_base_new(base, 0); 1.780 + tt_assert(!evdns_base_nameserver_ip_add(dns, buf1)); 1.781 + tt_assert(! evdns_base_set_option(dns, "timeout:", "0.3")); 1.782 + tt_assert(! evdns_base_set_option(dns, "max-timeouts:", "2")); 1.783 + tt_assert(! evdns_base_set_option(dns, "attempts:", "5")); 1.784 + 1.785 + memset(&r1, 0, sizeof(r1)); 1.786 + evdns_base_resolve_ipv4(dns, "foof.example.com", 0, 1.787 + generic_dns_callback, &r1); 1.788 + 1.789 + /* Add this after, so that we are sure to get a reissue. */ 1.790 + tt_assert(!evdns_base_nameserver_ip_add(dns, buf2)); 1.791 + 1.792 + n_replies_left = 1; 1.793 + exit_base = base; 1.794 + 1.795 + event_base_dispatch(base); 1.796 + tt_int_op(r1.result, ==, DNS_ERR_NONE); 1.797 + tt_int_op(r1.type, ==, DNS_IPv4_A); 1.798 + tt_int_op(r1.count, ==, 1); 1.799 + tt_int_op(((ev_uint32_t*)r1.addrs)[0], ==, htonl(0xf00ff00f)); 1.800 + 1.801 + /* Make sure we dropped at least once. */ 1.802 + tt_int_op(internal_error_table[0].seen, >, 0); 1.803 + 1.804 +end: 1.805 + if (dns) 1.806 + evdns_base_free(dns, 0); 1.807 + if (port1) 1.808 + evdns_close_server_port(port1); 1.809 + if (port2) 1.810 + evdns_close_server_port(port2); 1.811 +} 1.812 + 1.813 +#if 0 1.814 +static void 1.815 +dumb_bytes_fn(char *p, size_t n) 1.816 +{ 1.817 + unsigned i; 1.818 + /* This gets us 6 bits of entropy per transaction ID, which means we 1.819 + * will have probably have collisions and need to pick again. */ 1.820 + for (i=0;i<n;++i) 1.821 + p[i] = (char)(rand() & 7); 1.822 +} 1.823 +#endif 1.824 + 1.825 +static void 1.826 +dns_inflight_test(void *arg) 1.827 +{ 1.828 + struct basic_test_data *data = arg; 1.829 + struct event_base *base = data->base; 1.830 + struct evdns_base *dns = NULL; 1.831 + ev_uint16_t portnum = 0; 1.832 + char buf[64]; 1.833 + 1.834 + struct generic_dns_callback_result r[20]; 1.835 + int i; 1.836 + 1.837 + tt_assert(regress_dnsserver(base, &portnum, reissue_table)); 1.838 + evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum); 1.839 + 1.840 + dns = evdns_base_new(base, 0); 1.841 + tt_assert(!evdns_base_nameserver_ip_add(dns, buf)); 1.842 + tt_assert(! evdns_base_set_option(dns, "max-inflight:", "3")); 1.843 + tt_assert(! evdns_base_set_option(dns, "randomize-case:", "0")); 1.844 + 1.845 + for (i=0;i<20;++i) 1.846 + evdns_base_resolve_ipv4(dns, "foof.example.com", 0, generic_dns_callback, &r[i]); 1.847 + 1.848 + n_replies_left = 20; 1.849 + exit_base = base; 1.850 + 1.851 + event_base_dispatch(base); 1.852 + 1.853 + for (i=0;i<20;++i) { 1.854 + tt_int_op(r[i].type, ==, DNS_IPv4_A); 1.855 + tt_int_op(r[i].count, ==, 1); 1.856 + tt_int_op(((ev_uint32_t*)r[i].addrs)[0], ==, htonl(0xf00ff00f)); 1.857 + } 1.858 + 1.859 +end: 1.860 + if (dns) 1.861 + evdns_base_free(dns, 0); 1.862 + regress_clean_dnsserver(); 1.863 +} 1.864 + 1.865 +/* === Test for bufferevent_socket_connect_hostname */ 1.866 + 1.867 +static int total_connected_or_failed = 0; 1.868 +static int total_n_accepted = 0; 1.869 +static struct event_base *be_connect_hostname_base = NULL; 1.870 + 1.871 +/* Implements a DNS server for the connect_hostname test and the 1.872 + * getaddrinfo_async test */ 1.873 +static void 1.874 +be_getaddrinfo_server_cb(struct evdns_server_request *req, void *data) 1.875 +{ 1.876 + int i; 1.877 + int *n_got_p=data; 1.878 + int added_any=0; 1.879 + ++*n_got_p; 1.880 + 1.881 + for (i=0;i<req->nquestions;++i) { 1.882 + const int qtype = req->questions[i]->type; 1.883 + const int qclass = req->questions[i]->dns_question_class; 1.884 + const char *qname = req->questions[i]->name; 1.885 + struct in_addr ans; 1.886 + struct in6_addr ans6; 1.887 + memset(&ans6, 0, sizeof(ans6)); 1.888 + 1.889 + if (qtype == EVDNS_TYPE_A && 1.890 + qclass == EVDNS_CLASS_INET && 1.891 + !evutil_ascii_strcasecmp(qname, "nobodaddy.example.com")) { 1.892 + ans.s_addr = htonl(0x7f000001); 1.893 + evdns_server_request_add_a_reply(req, qname, 1.894 + 1, &ans.s_addr, 2000); 1.895 + added_any = 1; 1.896 + } else if (!evutil_ascii_strcasecmp(qname, 1.897 + "nosuchplace.example.com")) { 1.898 + /* ok, just say notfound. */ 1.899 + } else if (!evutil_ascii_strcasecmp(qname, 1.900 + "both.example.com")) { 1.901 + if (qtype == EVDNS_TYPE_A) { 1.902 + ans.s_addr = htonl(0x50502020); 1.903 + evdns_server_request_add_a_reply(req, qname, 1.904 + 1, &ans.s_addr, 2000); 1.905 + added_any = 1; 1.906 + } else if (qtype == EVDNS_TYPE_AAAA) { 1.907 + ans6.s6_addr[0] = 0x80; 1.908 + ans6.s6_addr[1] = 0xff; 1.909 + ans6.s6_addr[14] = 0xbb; 1.910 + ans6.s6_addr[15] = 0xbb; 1.911 + evdns_server_request_add_aaaa_reply(req, qname, 1.912 + 1, &ans6.s6_addr, 2000); 1.913 + added_any = 1; 1.914 + } 1.915 + evdns_server_request_add_cname_reply(req, qname, 1.916 + "both-canonical.example.com", 1000); 1.917 + } else if (!evutil_ascii_strcasecmp(qname, 1.918 + "v4only.example.com") || 1.919 + !evutil_ascii_strcasecmp(qname, "v4assert.example.com")) { 1.920 + if (qtype == EVDNS_TYPE_A) { 1.921 + ans.s_addr = htonl(0x12345678); 1.922 + evdns_server_request_add_a_reply(req, qname, 1.923 + 1, &ans.s_addr, 2000); 1.924 + added_any = 1; 1.925 + } else if (!evutil_ascii_strcasecmp(qname, 1.926 + "v4assert.example.com")) { 1.927 + TT_FAIL(("Got an AAAA request for v4assert")); 1.928 + } 1.929 + } else if (!evutil_ascii_strcasecmp(qname, 1.930 + "v6only.example.com") || 1.931 + !evutil_ascii_strcasecmp(qname, "v6assert.example.com")) { 1.932 + if (qtype == EVDNS_TYPE_AAAA) { 1.933 + ans6.s6_addr[0] = 0x0b; 1.934 + ans6.s6_addr[1] = 0x0b; 1.935 + ans6.s6_addr[14] = 0xf0; 1.936 + ans6.s6_addr[15] = 0x0d; 1.937 + evdns_server_request_add_aaaa_reply(req, qname, 1.938 + 1, &ans6.s6_addr, 2000); 1.939 + added_any = 1; 1.940 + } else if (!evutil_ascii_strcasecmp(qname, 1.941 + "v6assert.example.com")) { 1.942 + TT_FAIL(("Got a A request for v6assert")); 1.943 + } 1.944 + } else if (!evutil_ascii_strcasecmp(qname, 1.945 + "v6timeout.example.com")) { 1.946 + if (qtype == EVDNS_TYPE_A) { 1.947 + ans.s_addr = htonl(0xabcdef01); 1.948 + evdns_server_request_add_a_reply(req, qname, 1.949 + 1, &ans.s_addr, 2000); 1.950 + added_any = 1; 1.951 + } else if (qtype == EVDNS_TYPE_AAAA) { 1.952 + /* Let the v6 request time out.*/ 1.953 + evdns_server_request_drop(req); 1.954 + return; 1.955 + } 1.956 + } else if (!evutil_ascii_strcasecmp(qname, 1.957 + "v4timeout.example.com")) { 1.958 + if (qtype == EVDNS_TYPE_AAAA) { 1.959 + ans6.s6_addr[0] = 0x0a; 1.960 + ans6.s6_addr[1] = 0x0a; 1.961 + ans6.s6_addr[14] = 0xff; 1.962 + ans6.s6_addr[15] = 0x01; 1.963 + evdns_server_request_add_aaaa_reply(req, qname, 1.964 + 1, &ans6.s6_addr, 2000); 1.965 + added_any = 1; 1.966 + } else if (qtype == EVDNS_TYPE_A) { 1.967 + /* Let the v4 request time out.*/ 1.968 + evdns_server_request_drop(req); 1.969 + return; 1.970 + } 1.971 + } else if (!evutil_ascii_strcasecmp(qname, 1.972 + "v6timeout-nonexist.example.com")) { 1.973 + if (qtype == EVDNS_TYPE_A) { 1.974 + /* Fall through, give an nexist. */ 1.975 + } else if (qtype == EVDNS_TYPE_AAAA) { 1.976 + /* Let the v6 request time out.*/ 1.977 + evdns_server_request_drop(req); 1.978 + return; 1.979 + } 1.980 + } else if (!evutil_ascii_strcasecmp(qname, 1.981 + "all-timeout.example.com")) { 1.982 + /* drop all requests */ 1.983 + evdns_server_request_drop(req); 1.984 + return; 1.985 + } else { 1.986 + TT_GRIPE(("Got weird request for %s",qname)); 1.987 + } 1.988 + } 1.989 + if (added_any) 1.990 + evdns_server_request_respond(req, 0); 1.991 + else 1.992 + evdns_server_request_respond(req, 3); 1.993 +} 1.994 + 1.995 +/* Implements a listener for connect_hostname test. */ 1.996 +static void 1.997 +nil_accept_cb(struct evconnlistener *l, evutil_socket_t fd, struct sockaddr *s, 1.998 + int socklen, void *arg) 1.999 +{ 1.1000 + int *p = arg; 1.1001 + (*p)++; 1.1002 + ++total_n_accepted; 1.1003 + /* don't do anything with the socket; let it close when we exit() */ 1.1004 + if (total_n_accepted >= 3 && total_connected_or_failed >= 5) 1.1005 + event_base_loopexit(be_connect_hostname_base, 1.1006 + NULL); 1.1007 +} 1.1008 + 1.1009 +struct be_conn_hostname_result { 1.1010 + int dnserr; 1.1011 + int what; 1.1012 +}; 1.1013 + 1.1014 +/* Bufferevent event callback for the connect_hostname test: remembers what 1.1015 + * event we got. */ 1.1016 +static void 1.1017 +be_connect_hostname_event_cb(struct bufferevent *bev, short what, void *ctx) 1.1018 +{ 1.1019 + struct be_conn_hostname_result *got = ctx; 1.1020 + if (!got->what) { 1.1021 + TT_BLATHER(("Got a bufferevent event %d", what)); 1.1022 + got->what = what; 1.1023 + 1.1024 + if ((what & BEV_EVENT_CONNECTED) || (what & BEV_EVENT_ERROR)) { 1.1025 + int r; 1.1026 + if ((r = bufferevent_socket_get_dns_error(bev))) { 1.1027 + got->dnserr = r; 1.1028 + TT_BLATHER(("DNS error %d: %s", r, 1.1029 + evutil_gai_strerror(r))); 1.1030 + } ++total_connected_or_failed; 1.1031 + TT_BLATHER(("Got %d connections or errors.", total_connected_or_failed)); 1.1032 + 1.1033 + if (total_n_accepted >= 3 && total_connected_or_failed >= 5) 1.1034 + event_base_loopexit(be_connect_hostname_base, 1.1035 + NULL); 1.1036 + } 1.1037 + } else { 1.1038 + TT_FAIL(("Two events on one bufferevent. %d,%d", 1.1039 + got->what, (int)what)); 1.1040 + } 1.1041 +} 1.1042 + 1.1043 +static void 1.1044 +test_bufferevent_connect_hostname(void *arg) 1.1045 +{ 1.1046 + struct basic_test_data *data = arg; 1.1047 + struct evconnlistener *listener = NULL; 1.1048 + struct bufferevent *be1=NULL, *be2=NULL, *be3=NULL, *be4=NULL, *be5=NULL; 1.1049 + struct be_conn_hostname_result be1_outcome={0,0}, be2_outcome={0,0}, 1.1050 + be3_outcome={0,0}, be4_outcome={0,0}, be5_outcome={0,0}; 1.1051 + int expect_err5; 1.1052 + struct evdns_base *dns=NULL; 1.1053 + struct evdns_server_port *port=NULL; 1.1054 + struct sockaddr_in sin; 1.1055 + int listener_port=-1; 1.1056 + ev_uint16_t dns_port=0; 1.1057 + int n_accept=0, n_dns=0; 1.1058 + char buf[128]; 1.1059 + 1.1060 + be_connect_hostname_base = data->base; 1.1061 + 1.1062 + /* Bind an address and figure out what port it's on. */ 1.1063 + memset(&sin, 0, sizeof(sin)); 1.1064 + sin.sin_family = AF_INET; 1.1065 + sin.sin_addr.s_addr = htonl(0x7f000001); /* 127.0.0.1 */ 1.1066 + sin.sin_port = 0; 1.1067 + listener = evconnlistener_new_bind(data->base, nil_accept_cb, 1.1068 + &n_accept, 1.1069 + LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_EXEC, 1.1070 + -1, (struct sockaddr *)&sin, sizeof(sin)); 1.1071 + tt_assert(listener); 1.1072 + listener_port = regress_get_socket_port( 1.1073 + evconnlistener_get_fd(listener)); 1.1074 + 1.1075 + port = regress_get_dnsserver(data->base, &dns_port, NULL, 1.1076 + be_getaddrinfo_server_cb, &n_dns); 1.1077 + tt_assert(port); 1.1078 + tt_int_op(dns_port, >=, 0); 1.1079 + 1.1080 + /* Start an evdns_base that uses the server as its resolver. */ 1.1081 + dns = evdns_base_new(data->base, 0); 1.1082 + evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)dns_port); 1.1083 + evdns_base_nameserver_ip_add(dns, buf); 1.1084 + 1.1085 + /* Now, finally, at long last, launch the bufferevents. One should do 1.1086 + * a failing lookup IP, one should do a successful lookup by IP, 1.1087 + * and one should do a successful lookup by hostname. */ 1.1088 + be1 = bufferevent_socket_new(data->base, -1, BEV_OPT_CLOSE_ON_FREE); 1.1089 + be2 = bufferevent_socket_new(data->base, -1, BEV_OPT_CLOSE_ON_FREE); 1.1090 + be3 = bufferevent_socket_new(data->base, -1, BEV_OPT_CLOSE_ON_FREE); 1.1091 + be4 = bufferevent_socket_new(data->base, -1, BEV_OPT_CLOSE_ON_FREE); 1.1092 + be5 = bufferevent_socket_new(data->base, -1, BEV_OPT_CLOSE_ON_FREE); 1.1093 + 1.1094 + bufferevent_setcb(be1, NULL, NULL, be_connect_hostname_event_cb, 1.1095 + &be1_outcome); 1.1096 + bufferevent_setcb(be2, NULL, NULL, be_connect_hostname_event_cb, 1.1097 + &be2_outcome); 1.1098 + bufferevent_setcb(be3, NULL, NULL, be_connect_hostname_event_cb, 1.1099 + &be3_outcome); 1.1100 + bufferevent_setcb(be4, NULL, NULL, be_connect_hostname_event_cb, 1.1101 + &be4_outcome); 1.1102 + bufferevent_setcb(be5, NULL, NULL, be_connect_hostname_event_cb, 1.1103 + &be5_outcome); 1.1104 + 1.1105 + /* Launch an async resolve that will fail. */ 1.1106 + tt_assert(!bufferevent_socket_connect_hostname(be1, dns, AF_INET, 1.1107 + "nosuchplace.example.com", listener_port)); 1.1108 + /* Connect to the IP without resolving. */ 1.1109 + tt_assert(!bufferevent_socket_connect_hostname(be2, dns, AF_INET, 1.1110 + "127.0.0.1", listener_port)); 1.1111 + /* Launch an async resolve that will succeed. */ 1.1112 + tt_assert(!bufferevent_socket_connect_hostname(be3, dns, AF_INET, 1.1113 + "nobodaddy.example.com", listener_port)); 1.1114 + /* Use the blocking resolver. This one will fail if your resolver 1.1115 + * can't resolve localhost to 127.0.0.1 */ 1.1116 + tt_assert(!bufferevent_socket_connect_hostname(be4, NULL, AF_INET, 1.1117 + "localhost", listener_port)); 1.1118 + /* Use the blocking resolver with a nonexistent hostname. */ 1.1119 + tt_assert(!bufferevent_socket_connect_hostname(be5, NULL, AF_INET, 1.1120 + "nonesuch.nowhere.example.com", 80)); 1.1121 + { 1.1122 + /* The blocking resolver will use the system nameserver, which 1.1123 + * might tell us anything. (Yes, some twits even pretend that 1.1124 + * example.com is real.) Let's see what answer to expect. */ 1.1125 + struct evutil_addrinfo hints, *ai = NULL; 1.1126 + memset(&hints, 0, sizeof(hints)); 1.1127 + hints.ai_family = AF_INET; 1.1128 + hints.ai_socktype = SOCK_STREAM; 1.1129 + hints.ai_protocol = IPPROTO_TCP; 1.1130 + expect_err5 = evutil_getaddrinfo( 1.1131 + "nonesuch.nowhere.example.com", "80", &hints, &ai); 1.1132 + } 1.1133 + 1.1134 + event_base_dispatch(data->base); 1.1135 + 1.1136 + tt_int_op(be1_outcome.what, ==, BEV_EVENT_ERROR); 1.1137 + tt_int_op(be1_outcome.dnserr, ==, EVUTIL_EAI_NONAME); 1.1138 + tt_int_op(be2_outcome.what, ==, BEV_EVENT_CONNECTED); 1.1139 + tt_int_op(be2_outcome.dnserr, ==, 0); 1.1140 + tt_int_op(be3_outcome.what, ==, BEV_EVENT_CONNECTED); 1.1141 + tt_int_op(be3_outcome.dnserr, ==, 0); 1.1142 + tt_int_op(be4_outcome.what, ==, BEV_EVENT_CONNECTED); 1.1143 + tt_int_op(be4_outcome.dnserr, ==, 0); 1.1144 + if (expect_err5) { 1.1145 + tt_int_op(be5_outcome.what, ==, BEV_EVENT_ERROR); 1.1146 + tt_int_op(be5_outcome.dnserr, ==, expect_err5); 1.1147 + } 1.1148 + 1.1149 + tt_int_op(n_accept, ==, 3); 1.1150 + tt_int_op(n_dns, ==, 2); 1.1151 + 1.1152 +end: 1.1153 + if (listener) 1.1154 + evconnlistener_free(listener); 1.1155 + if (port) 1.1156 + evdns_close_server_port(port); 1.1157 + if (dns) 1.1158 + evdns_base_free(dns, 0); 1.1159 + if (be1) 1.1160 + bufferevent_free(be1); 1.1161 + if (be2) 1.1162 + bufferevent_free(be2); 1.1163 + if (be3) 1.1164 + bufferevent_free(be3); 1.1165 + if (be4) 1.1166 + bufferevent_free(be4); 1.1167 + if (be5) 1.1168 + bufferevent_free(be5); 1.1169 +} 1.1170 + 1.1171 + 1.1172 +struct gai_outcome { 1.1173 + int err; 1.1174 + struct evutil_addrinfo *ai; 1.1175 +}; 1.1176 + 1.1177 +static int n_gai_results_pending = 0; 1.1178 +static struct event_base *exit_base_on_no_pending_results = NULL; 1.1179 + 1.1180 +static void 1.1181 +gai_cb(int err, struct evutil_addrinfo *res, void *ptr) 1.1182 +{ 1.1183 + struct gai_outcome *go = ptr; 1.1184 + go->err = err; 1.1185 + go->ai = res; 1.1186 + if (--n_gai_results_pending <= 0 && exit_base_on_no_pending_results) 1.1187 + event_base_loopexit(exit_base_on_no_pending_results, NULL); 1.1188 + if (n_gai_results_pending < 900) 1.1189 + TT_BLATHER(("Got an answer; expecting %d more.", 1.1190 + n_gai_results_pending)); 1.1191 +} 1.1192 + 1.1193 +static void 1.1194 +cancel_gai_cb(evutil_socket_t fd, short what, void *ptr) 1.1195 +{ 1.1196 + struct evdns_getaddrinfo_request *r = ptr; 1.1197 + evdns_getaddrinfo_cancel(r); 1.1198 +} 1.1199 + 1.1200 +static void 1.1201 +test_getaddrinfo_async(void *arg) 1.1202 +{ 1.1203 + struct basic_test_data *data = arg; 1.1204 + struct evutil_addrinfo hints, *a; 1.1205 + struct gai_outcome local_outcome; 1.1206 + struct gai_outcome a_out[12]; 1.1207 + int i; 1.1208 + struct evdns_getaddrinfo_request *r; 1.1209 + char buf[128]; 1.1210 + struct evdns_server_port *port = NULL; 1.1211 + ev_uint16_t dns_port = 0; 1.1212 + int n_dns_questions = 0; 1.1213 + 1.1214 + struct evdns_base *dns_base = evdns_base_new(data->base, 0); 1.1215 + tt_assert(dns_base); 1.1216 + 1.1217 + /* for localhost */ 1.1218 + evdns_base_load_hosts(dns_base, NULL); 1.1219 + 1.1220 + memset(a_out, 0, sizeof(a_out)); 1.1221 + memset(&local_outcome, 0, sizeof(local_outcome)); 1.1222 + 1.1223 + n_gai_results_pending = 10000; /* don't think about exiting yet. */ 1.1224 + 1.1225 + /* 1. Try some cases that will never hit the asynchronous resolver. */ 1.1226 + /* 1a. Simple case with a symbolic service name */ 1.1227 + memset(&hints, 0, sizeof(hints)); 1.1228 + hints.ai_family = PF_UNSPEC; 1.1229 + hints.ai_socktype = SOCK_STREAM; 1.1230 + memset(&local_outcome, 0, sizeof(local_outcome)); 1.1231 + r = evdns_getaddrinfo(dns_base, "1.2.3.4", "http", 1.1232 + &hints, gai_cb, &local_outcome); 1.1233 + tt_assert(! r); 1.1234 + if (!local_outcome.err) { 1.1235 + tt_ptr_op(local_outcome.ai,!=,NULL); 1.1236 + test_ai_eq(local_outcome.ai, "1.2.3.4:80", SOCK_STREAM, IPPROTO_TCP); 1.1237 + evutil_freeaddrinfo(local_outcome.ai); 1.1238 + local_outcome.ai = NULL; 1.1239 + } else { 1.1240 + TT_BLATHER(("Apparently we have no getservbyname.")); 1.1241 + } 1.1242 + 1.1243 + /* 1b. EVUTIL_AI_NUMERICHOST is set */ 1.1244 + memset(&hints, 0, sizeof(hints)); 1.1245 + hints.ai_family = PF_UNSPEC; 1.1246 + hints.ai_flags = EVUTIL_AI_NUMERICHOST; 1.1247 + memset(&local_outcome, 0, sizeof(local_outcome)); 1.1248 + r = evdns_getaddrinfo(dns_base, "www.google.com", "80", 1.1249 + &hints, gai_cb, &local_outcome); 1.1250 + tt_ptr_op(r,==,NULL); 1.1251 + tt_int_op(local_outcome.err,==,EVUTIL_EAI_NONAME); 1.1252 + tt_ptr_op(local_outcome.ai,==,NULL); 1.1253 + 1.1254 + /* 1c. We give a numeric address (ipv6) */ 1.1255 + memset(&hints, 0, sizeof(hints)); 1.1256 + memset(&local_outcome, 0, sizeof(local_outcome)); 1.1257 + hints.ai_family = PF_UNSPEC; 1.1258 + hints.ai_protocol = IPPROTO_TCP; 1.1259 + r = evdns_getaddrinfo(dns_base, "f::f", "8008", 1.1260 + &hints, gai_cb, &local_outcome); 1.1261 + tt_assert(!r); 1.1262 + tt_int_op(local_outcome.err,==,0); 1.1263 + tt_assert(local_outcome.ai); 1.1264 + tt_ptr_op(local_outcome.ai->ai_next,==,NULL); 1.1265 + test_ai_eq(local_outcome.ai, "[f::f]:8008", SOCK_STREAM, IPPROTO_TCP); 1.1266 + evutil_freeaddrinfo(local_outcome.ai); 1.1267 + local_outcome.ai = NULL; 1.1268 + 1.1269 + /* 1d. We give a numeric address (ipv4) */ 1.1270 + memset(&hints, 0, sizeof(hints)); 1.1271 + memset(&local_outcome, 0, sizeof(local_outcome)); 1.1272 + hints.ai_family = PF_UNSPEC; 1.1273 + r = evdns_getaddrinfo(dns_base, "5.6.7.8", NULL, 1.1274 + &hints, gai_cb, &local_outcome); 1.1275 + tt_assert(!r); 1.1276 + tt_int_op(local_outcome.err,==,0); 1.1277 + tt_assert(local_outcome.ai); 1.1278 + a = ai_find_by_protocol(local_outcome.ai, IPPROTO_TCP); 1.1279 + tt_assert(a); 1.1280 + test_ai_eq(a, "5.6.7.8", SOCK_STREAM, IPPROTO_TCP); 1.1281 + a = ai_find_by_protocol(local_outcome.ai, IPPROTO_UDP); 1.1282 + tt_assert(a); 1.1283 + test_ai_eq(a, "5.6.7.8", SOCK_DGRAM, IPPROTO_UDP); 1.1284 + evutil_freeaddrinfo(local_outcome.ai); 1.1285 + local_outcome.ai = NULL; 1.1286 + 1.1287 + /* 1e. nodename is NULL (bind) */ 1.1288 + memset(&hints, 0, sizeof(hints)); 1.1289 + memset(&local_outcome, 0, sizeof(local_outcome)); 1.1290 + hints.ai_family = PF_UNSPEC; 1.1291 + hints.ai_socktype = SOCK_DGRAM; 1.1292 + hints.ai_flags = EVUTIL_AI_PASSIVE; 1.1293 + r = evdns_getaddrinfo(dns_base, NULL, "9090", 1.1294 + &hints, gai_cb, &local_outcome); 1.1295 + tt_assert(!r); 1.1296 + tt_int_op(local_outcome.err,==,0); 1.1297 + tt_assert(local_outcome.ai); 1.1298 + /* we should get a v4 address of 0.0.0.0... */ 1.1299 + a = ai_find_by_family(local_outcome.ai, PF_INET); 1.1300 + tt_assert(a); 1.1301 + test_ai_eq(a, "0.0.0.0:9090", SOCK_DGRAM, IPPROTO_UDP); 1.1302 + /* ... and a v6 address of ::0 */ 1.1303 + a = ai_find_by_family(local_outcome.ai, PF_INET6); 1.1304 + tt_assert(a); 1.1305 + test_ai_eq(a, "[::]:9090", SOCK_DGRAM, IPPROTO_UDP); 1.1306 + evutil_freeaddrinfo(local_outcome.ai); 1.1307 + local_outcome.ai = NULL; 1.1308 + 1.1309 + /* 1f. nodename is NULL (connect) */ 1.1310 + memset(&hints, 0, sizeof(hints)); 1.1311 + memset(&local_outcome, 0, sizeof(local_outcome)); 1.1312 + hints.ai_family = PF_UNSPEC; 1.1313 + hints.ai_socktype = SOCK_STREAM; 1.1314 + r = evdns_getaddrinfo(dns_base, NULL, "2", 1.1315 + &hints, gai_cb, &local_outcome); 1.1316 + tt_assert(!r); 1.1317 + tt_int_op(local_outcome.err,==,0); 1.1318 + tt_assert(local_outcome.ai); 1.1319 + /* we should get a v4 address of 127.0.0.1 .... */ 1.1320 + a = ai_find_by_family(local_outcome.ai, PF_INET); 1.1321 + tt_assert(a); 1.1322 + test_ai_eq(a, "127.0.0.1:2", SOCK_STREAM, IPPROTO_TCP); 1.1323 + /* ... and a v6 address of ::1 */ 1.1324 + a = ai_find_by_family(local_outcome.ai, PF_INET6); 1.1325 + tt_assert(a); 1.1326 + test_ai_eq(a, "[::1]:2", SOCK_STREAM, IPPROTO_TCP); 1.1327 + evutil_freeaddrinfo(local_outcome.ai); 1.1328 + local_outcome.ai = NULL; 1.1329 + 1.1330 + /* 1g. We find localhost immediately. (pf_unspec) */ 1.1331 + memset(&hints, 0, sizeof(hints)); 1.1332 + memset(&local_outcome, 0, sizeof(local_outcome)); 1.1333 + hints.ai_family = PF_UNSPEC; 1.1334 + hints.ai_socktype = SOCK_STREAM; 1.1335 + r = evdns_getaddrinfo(dns_base, "LOCALHOST", "80", 1.1336 + &hints, gai_cb, &local_outcome); 1.1337 + tt_assert(!r); 1.1338 + tt_int_op(local_outcome.err,==,0); 1.1339 + tt_assert(local_outcome.ai); 1.1340 + /* we should get a v4 address of 127.0.0.1 .... */ 1.1341 + a = ai_find_by_family(local_outcome.ai, PF_INET); 1.1342 + tt_assert(a); 1.1343 + test_ai_eq(a, "127.0.0.1:80", SOCK_STREAM, IPPROTO_TCP); 1.1344 + /* ... and a v6 address of ::1 */ 1.1345 + a = ai_find_by_family(local_outcome.ai, PF_INET6); 1.1346 + tt_assert(a); 1.1347 + test_ai_eq(a, "[::1]:80", SOCK_STREAM, IPPROTO_TCP); 1.1348 + evutil_freeaddrinfo(local_outcome.ai); 1.1349 + local_outcome.ai = NULL; 1.1350 + 1.1351 + /* 1g. We find localhost immediately. (pf_inet6) */ 1.1352 + memset(&hints, 0, sizeof(hints)); 1.1353 + memset(&local_outcome, 0, sizeof(local_outcome)); 1.1354 + hints.ai_family = PF_INET6; 1.1355 + hints.ai_socktype = SOCK_STREAM; 1.1356 + r = evdns_getaddrinfo(dns_base, "LOCALHOST", "9999", 1.1357 + &hints, gai_cb, &local_outcome); 1.1358 + tt_assert(! r); 1.1359 + tt_int_op(local_outcome.err,==,0); 1.1360 + tt_assert(local_outcome.ai); 1.1361 + a = local_outcome.ai; 1.1362 + test_ai_eq(a, "[::1]:9999", SOCK_STREAM, IPPROTO_TCP); 1.1363 + tt_ptr_op(a->ai_next, ==, NULL); 1.1364 + evutil_freeaddrinfo(local_outcome.ai); 1.1365 + local_outcome.ai = NULL; 1.1366 + 1.1367 + /* 2. Okay, now we can actually test the asynchronous resolver. */ 1.1368 + /* Start a dummy local dns server... */ 1.1369 + port = regress_get_dnsserver(data->base, &dns_port, NULL, 1.1370 + be_getaddrinfo_server_cb, &n_dns_questions); 1.1371 + tt_assert(port); 1.1372 + tt_int_op(dns_port, >=, 0); 1.1373 + /* ... and tell the evdns_base about it. */ 1.1374 + evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", dns_port); 1.1375 + evdns_base_nameserver_ip_add(dns_base, buf); 1.1376 + 1.1377 + memset(&hints, 0, sizeof(hints)); 1.1378 + hints.ai_family = PF_UNSPEC; 1.1379 + hints.ai_socktype = SOCK_STREAM; 1.1380 + hints.ai_flags = EVUTIL_AI_CANONNAME; 1.1381 + /* 0: Request for both.example.com should return both addresses. */ 1.1382 + r = evdns_getaddrinfo(dns_base, "both.example.com", "8000", 1.1383 + &hints, gai_cb, &a_out[0]); 1.1384 + tt_assert(r); 1.1385 + 1.1386 + /* 1: Request for v4only.example.com should return one address. */ 1.1387 + r = evdns_getaddrinfo(dns_base, "v4only.example.com", "8001", 1.1388 + &hints, gai_cb, &a_out[1]); 1.1389 + tt_assert(r); 1.1390 + 1.1391 + /* 2: Request for v6only.example.com should return one address. */ 1.1392 + hints.ai_flags = 0; 1.1393 + r = evdns_getaddrinfo(dns_base, "v6only.example.com", "8002", 1.1394 + &hints, gai_cb, &a_out[2]); 1.1395 + tt_assert(r); 1.1396 + 1.1397 + /* 3: PF_INET request for v4assert.example.com should not generate a 1.1398 + * v6 request. The server will fail the test if it does. */ 1.1399 + hints.ai_family = PF_INET; 1.1400 + r = evdns_getaddrinfo(dns_base, "v4assert.example.com", "8003", 1.1401 + &hints, gai_cb, &a_out[3]); 1.1402 + tt_assert(r); 1.1403 + 1.1404 + /* 4: PF_INET6 request for v6assert.example.com should not generate a 1.1405 + * v4 request. The server will fail the test if it does. */ 1.1406 + hints.ai_family = PF_INET6; 1.1407 + r = evdns_getaddrinfo(dns_base, "v6assert.example.com", "8004", 1.1408 + &hints, gai_cb, &a_out[4]); 1.1409 + tt_assert(r); 1.1410 + 1.1411 + /* 5: PF_INET request for nosuchplace.example.com should give NEXIST. */ 1.1412 + hints.ai_family = PF_INET; 1.1413 + r = evdns_getaddrinfo(dns_base, "nosuchplace.example.com", "8005", 1.1414 + &hints, gai_cb, &a_out[5]); 1.1415 + tt_assert(r); 1.1416 + 1.1417 + /* 6: PF_UNSPEC request for nosuchplace.example.com should give NEXIST. 1.1418 + */ 1.1419 + hints.ai_family = PF_UNSPEC; 1.1420 + r = evdns_getaddrinfo(dns_base, "nosuchplace.example.com", "8006", 1.1421 + &hints, gai_cb, &a_out[6]); 1.1422 + tt_assert(r); 1.1423 + 1.1424 + /* 7: PF_UNSPEC request for v6timeout.example.com should give an ipv4 1.1425 + * address only. */ 1.1426 + hints.ai_family = PF_UNSPEC; 1.1427 + r = evdns_getaddrinfo(dns_base, "v6timeout.example.com", "8007", 1.1428 + &hints, gai_cb, &a_out[7]); 1.1429 + tt_assert(r); 1.1430 + 1.1431 + /* 8: PF_UNSPEC request for v6timeout-nonexist.example.com should give 1.1432 + * a NEXIST */ 1.1433 + hints.ai_family = PF_UNSPEC; 1.1434 + r = evdns_getaddrinfo(dns_base, "v6timeout-nonexist.example.com", 1.1435 + "8008", &hints, gai_cb, &a_out[8]); 1.1436 + tt_assert(r); 1.1437 + 1.1438 + /* 9: AI_ADDRCONFIG should at least not crash. Can't test it more 1.1439 + * without knowing what kind of internet we have. */ 1.1440 + hints.ai_flags |= EVUTIL_AI_ADDRCONFIG; 1.1441 + r = evdns_getaddrinfo(dns_base, "both.example.com", 1.1442 + "8009", &hints, gai_cb, &a_out[9]); 1.1443 + tt_assert(r); 1.1444 + 1.1445 + /* 10: PF_UNSPEC for v4timeout.example.com should give an ipv6 address 1.1446 + * only. */ 1.1447 + hints.ai_family = PF_UNSPEC; 1.1448 + hints.ai_flags = 0; 1.1449 + r = evdns_getaddrinfo(dns_base, "v4timeout.example.com", "8010", 1.1450 + &hints, gai_cb, &a_out[10]); 1.1451 + tt_assert(r); 1.1452 + 1.1453 + /* 11: timeout.example.com: cancel it after 100 msec. */ 1.1454 + r = evdns_getaddrinfo(dns_base, "all-timeout.example.com", "8011", 1.1455 + &hints, gai_cb, &a_out[11]); 1.1456 + tt_assert(r); 1.1457 + { 1.1458 + struct timeval tv; 1.1459 + tv.tv_sec = 0; 1.1460 + tv.tv_usec = 100*1000; /* 100 msec */ 1.1461 + event_base_once(data->base, -1, EV_TIMEOUT, cancel_gai_cb, 1.1462 + r, &tv); 1.1463 + } 1.1464 + 1.1465 + /* XXXXX There are more tests we could do, including: 1.1466 + 1.1467 + - A test to elicit NODATA. 1.1468 + 1.1469 + */ 1.1470 + 1.1471 + n_gai_results_pending = 12; 1.1472 + exit_base_on_no_pending_results = data->base; 1.1473 + 1.1474 + event_base_dispatch(data->base); 1.1475 + 1.1476 + /* 0: both.example.com */ 1.1477 + tt_int_op(a_out[0].err, ==, 0); 1.1478 + tt_assert(a_out[0].ai); 1.1479 + tt_assert(a_out[0].ai->ai_next); 1.1480 + tt_assert(!a_out[0].ai->ai_next->ai_next); 1.1481 + a = ai_find_by_family(a_out[0].ai, PF_INET); 1.1482 + tt_assert(a); 1.1483 + test_ai_eq(a, "80.80.32.32:8000", SOCK_STREAM, IPPROTO_TCP); 1.1484 + a = ai_find_by_family(a_out[0].ai, PF_INET6); 1.1485 + tt_assert(a); 1.1486 + test_ai_eq(a, "[80ff::bbbb]:8000", SOCK_STREAM, IPPROTO_TCP); 1.1487 + tt_assert(a_out[0].ai->ai_canonname); 1.1488 + tt_str_op(a_out[0].ai->ai_canonname, ==, "both-canonical.example.com"); 1.1489 + 1.1490 + /* 1: v4only.example.com */ 1.1491 + tt_int_op(a_out[1].err, ==, 0); 1.1492 + tt_assert(a_out[1].ai); 1.1493 + tt_assert(! a_out[1].ai->ai_next); 1.1494 + test_ai_eq(a_out[1].ai, "18.52.86.120:8001", SOCK_STREAM, IPPROTO_TCP); 1.1495 + tt_assert(a_out[1].ai->ai_canonname == NULL); 1.1496 + 1.1497 + 1.1498 + /* 2: v6only.example.com */ 1.1499 + tt_int_op(a_out[2].err, ==, 0); 1.1500 + tt_assert(a_out[2].ai); 1.1501 + tt_assert(! a_out[2].ai->ai_next); 1.1502 + test_ai_eq(a_out[2].ai, "[b0b::f00d]:8002", SOCK_STREAM, IPPROTO_TCP); 1.1503 + 1.1504 + /* 3: v4assert.example.com */ 1.1505 + tt_int_op(a_out[3].err, ==, 0); 1.1506 + tt_assert(a_out[3].ai); 1.1507 + tt_assert(! a_out[3].ai->ai_next); 1.1508 + test_ai_eq(a_out[3].ai, "18.52.86.120:8003", SOCK_STREAM, IPPROTO_TCP); 1.1509 + 1.1510 + /* 4: v6assert.example.com */ 1.1511 + tt_int_op(a_out[4].err, ==, 0); 1.1512 + tt_assert(a_out[4].ai); 1.1513 + tt_assert(! a_out[4].ai->ai_next); 1.1514 + test_ai_eq(a_out[4].ai, "[b0b::f00d]:8004", SOCK_STREAM, IPPROTO_TCP); 1.1515 + 1.1516 + /* 5: nosuchplace.example.com (inet) */ 1.1517 + tt_int_op(a_out[5].err, ==, EVUTIL_EAI_NONAME); 1.1518 + tt_assert(! a_out[5].ai); 1.1519 + 1.1520 + /* 6: nosuchplace.example.com (unspec) */ 1.1521 + tt_int_op(a_out[6].err, ==, EVUTIL_EAI_NONAME); 1.1522 + tt_assert(! a_out[6].ai); 1.1523 + 1.1524 + /* 7: v6timeout.example.com */ 1.1525 + tt_int_op(a_out[7].err, ==, 0); 1.1526 + tt_assert(a_out[7].ai); 1.1527 + tt_assert(! a_out[7].ai->ai_next); 1.1528 + test_ai_eq(a_out[7].ai, "171.205.239.1:8007", SOCK_STREAM, IPPROTO_TCP); 1.1529 + 1.1530 + /* 8: v6timeout-nonexist.example.com */ 1.1531 + tt_int_op(a_out[8].err, ==, EVUTIL_EAI_NONAME); 1.1532 + tt_assert(! a_out[8].ai); 1.1533 + 1.1534 + /* 9: both (ADDRCONFIG) */ 1.1535 + tt_int_op(a_out[9].err, ==, 0); 1.1536 + tt_assert(a_out[9].ai); 1.1537 + a = ai_find_by_family(a_out[9].ai, PF_INET); 1.1538 + if (a) 1.1539 + test_ai_eq(a, "80.80.32.32:8009", SOCK_STREAM, IPPROTO_TCP); 1.1540 + else 1.1541 + tt_assert(ai_find_by_family(a_out[9].ai, PF_INET6)); 1.1542 + a = ai_find_by_family(a_out[9].ai, PF_INET6); 1.1543 + if (a) 1.1544 + test_ai_eq(a, "[80ff::bbbb]:8009", SOCK_STREAM, IPPROTO_TCP); 1.1545 + else 1.1546 + tt_assert(ai_find_by_family(a_out[9].ai, PF_INET)); 1.1547 + 1.1548 + /* 10: v4timeout.example.com */ 1.1549 + tt_int_op(a_out[10].err, ==, 0); 1.1550 + tt_assert(a_out[10].ai); 1.1551 + tt_assert(! a_out[10].ai->ai_next); 1.1552 + test_ai_eq(a_out[10].ai, "[a0a::ff01]:8010", SOCK_STREAM, IPPROTO_TCP); 1.1553 + 1.1554 + /* 11: cancelled request. */ 1.1555 + tt_int_op(a_out[11].err, ==, EVUTIL_EAI_CANCEL); 1.1556 + tt_assert(a_out[11].ai == NULL); 1.1557 + 1.1558 +end: 1.1559 + if (local_outcome.ai) 1.1560 + evutil_freeaddrinfo(local_outcome.ai); 1.1561 + for (i=0;i<10;++i) { 1.1562 + if (a_out[i].ai) 1.1563 + evutil_freeaddrinfo(a_out[i].ai); 1.1564 + } 1.1565 + if (port) 1.1566 + evdns_close_server_port(port); 1.1567 + if (dns_base) 1.1568 + evdns_base_free(dns_base, 0); 1.1569 +} 1.1570 + 1.1571 +struct gaic_request_status { 1.1572 + int magic; 1.1573 + struct event_base *base; 1.1574 + struct evdns_base *dns_base; 1.1575 + struct evdns_getaddrinfo_request *request; 1.1576 + struct event cancel_event; 1.1577 + int canceled; 1.1578 +}; 1.1579 + 1.1580 +#define GAIC_MAGIC 0x1234abcd 1.1581 + 1.1582 +static int pending = 0; 1.1583 + 1.1584 +static void 1.1585 +gaic_cancel_request_cb(evutil_socket_t fd, short what, void *arg) 1.1586 +{ 1.1587 + struct gaic_request_status *status = arg; 1.1588 + 1.1589 + tt_assert(status->magic == GAIC_MAGIC); 1.1590 + status->canceled = 1; 1.1591 + evdns_getaddrinfo_cancel(status->request); 1.1592 + return; 1.1593 +end: 1.1594 + event_base_loopexit(status->base, NULL); 1.1595 +} 1.1596 + 1.1597 +static void 1.1598 +gaic_server_cb(struct evdns_server_request *req, void *arg) 1.1599 +{ 1.1600 + ev_uint32_t answer = 0x7f000001; 1.1601 + tt_assert(req->nquestions); 1.1602 + evdns_server_request_add_a_reply(req, req->questions[0]->name, 1, 1.1603 + &answer, 100); 1.1604 + evdns_server_request_respond(req, 0); 1.1605 + return; 1.1606 +end: 1.1607 + evdns_server_request_respond(req, DNS_ERR_REFUSED); 1.1608 +} 1.1609 + 1.1610 + 1.1611 +static void 1.1612 +gaic_getaddrinfo_cb(int result, struct evutil_addrinfo *res, void *arg) 1.1613 +{ 1.1614 + struct gaic_request_status *status = arg; 1.1615 + struct event_base *base = status->base; 1.1616 + tt_assert(status->magic == GAIC_MAGIC); 1.1617 + 1.1618 + if (result == EVUTIL_EAI_CANCEL) { 1.1619 + tt_assert(status->canceled); 1.1620 + } 1.1621 + event_del(&status->cancel_event); 1.1622 + 1.1623 + memset(status, 0xf0, sizeof(*status)); 1.1624 + free(status); 1.1625 + 1.1626 +end: 1.1627 + if (--pending <= 0) 1.1628 + event_base_loopexit(base, NULL); 1.1629 +} 1.1630 + 1.1631 +static void 1.1632 +gaic_launch(struct event_base *base, struct evdns_base *dns_base) 1.1633 +{ 1.1634 + struct gaic_request_status *status = calloc(1,sizeof(*status)); 1.1635 + struct timeval tv = { 0, 10000 }; 1.1636 + status->magic = GAIC_MAGIC; 1.1637 + status->base = base; 1.1638 + status->dns_base = dns_base; 1.1639 + event_assign(&status->cancel_event, base, -1, 0, gaic_cancel_request_cb, 1.1640 + status); 1.1641 + status->request = evdns_getaddrinfo(dns_base, 1.1642 + "foobar.bazquux.example.com", "80", NULL, gaic_getaddrinfo_cb, 1.1643 + status); 1.1644 + event_add(&status->cancel_event, &tv); 1.1645 + ++pending; 1.1646 +} 1.1647 + 1.1648 +#ifdef EVENT_SET_MEM_FUNCTIONS_IMPLEMENTED 1.1649 +/* FIXME: We should move this to regress_main.c if anything else needs it.*/ 1.1650 + 1.1651 +/* Trivial replacements for malloc/free/realloc to check for memory leaks. 1.1652 + * Not threadsafe. */ 1.1653 +static int allocated_chunks = 0; 1.1654 + 1.1655 +static void * 1.1656 +cnt_malloc(size_t sz) 1.1657 +{ 1.1658 + allocated_chunks += 1; 1.1659 + return malloc(sz); 1.1660 +} 1.1661 + 1.1662 +static void * 1.1663 +cnt_realloc(void *old, size_t sz) 1.1664 +{ 1.1665 + if (!old) 1.1666 + allocated_chunks += 1; 1.1667 + if (!sz) 1.1668 + allocated_chunks -= 1; 1.1669 + return realloc(old, sz); 1.1670 +} 1.1671 + 1.1672 +static void 1.1673 +cnt_free(void *ptr) 1.1674 +{ 1.1675 + allocated_chunks -= 1; 1.1676 + free(ptr); 1.1677 +} 1.1678 + 1.1679 +struct testleak_env_t { 1.1680 + struct event_base *base; 1.1681 + struct evdns_base *dns_base; 1.1682 + struct evdns_request *req; 1.1683 + struct generic_dns_callback_result r; 1.1684 +}; 1.1685 + 1.1686 +static void * 1.1687 +testleak_setup(const struct testcase_t *testcase) 1.1688 +{ 1.1689 + struct testleak_env_t *env; 1.1690 + 1.1691 + allocated_chunks = 0; 1.1692 + event_set_mem_functions(cnt_malloc, cnt_realloc, cnt_free); 1.1693 + event_enable_debug_mode(); 1.1694 + 1.1695 + /* not mm_calloc: we don't want to mess with the count. */ 1.1696 + env = calloc(1, sizeof(struct testleak_env_t)); 1.1697 + env->base = event_base_new(); 1.1698 + env->dns_base = evdns_base_new(env->base, 0); 1.1699 + env->req = evdns_base_resolve_ipv4( 1.1700 + env->dns_base, "example.com", DNS_QUERY_NO_SEARCH, 1.1701 + generic_dns_callback, &env->r); 1.1702 + return env; 1.1703 +} 1.1704 + 1.1705 +static int 1.1706 +testleak_cleanup(const struct testcase_t *testcase, void *env_) 1.1707 +{ 1.1708 + int ok = 0; 1.1709 + struct testleak_env_t *env = env_; 1.1710 + tt_assert(env); 1.1711 +#ifdef _EVENT_DISABLE_DEBUG_MODE 1.1712 + tt_int_op(allocated_chunks, ==, 0); 1.1713 +#else 1.1714 + /* FIXME: that's `1' because of event_debug_map_HT_GROW */ 1.1715 + tt_int_op(allocated_chunks, ==, 1); 1.1716 +#endif 1.1717 + ok = 1; 1.1718 +end: 1.1719 + if (env) { 1.1720 + if (env->dns_base) 1.1721 + evdns_base_free(env->dns_base, 0); 1.1722 + if (env->base) 1.1723 + event_base_free(env->base); 1.1724 + free(env); 1.1725 + } 1.1726 + return ok; 1.1727 +} 1.1728 + 1.1729 +static struct testcase_setup_t testleak_funcs = { 1.1730 + testleak_setup, testleak_cleanup 1.1731 +}; 1.1732 + 1.1733 +static void 1.1734 +test_dbg_leak_cancel(void *env_) 1.1735 +{ 1.1736 + /* cancel, loop, free/dns, free/base */ 1.1737 + struct testleak_env_t *env = env_; 1.1738 + int send_err_shutdown = 1; 1.1739 + evdns_cancel_request(env->dns_base, env->req); 1.1740 + env->req = 0; 1.1741 + 1.1742 + /* `req` is freed in callback, that's why one loop is required. */ 1.1743 + event_base_loop(env->base, EVLOOP_NONBLOCK); 1.1744 + 1.1745 + /* send_err_shutdown means nothing as soon as our request is 1.1746 + * already canceled */ 1.1747 + evdns_base_free(env->dns_base, send_err_shutdown); 1.1748 + env->dns_base = 0; 1.1749 + event_base_free(env->base); 1.1750 + env->base = 0; 1.1751 +} 1.1752 + 1.1753 +static void 1.1754 +test_dbg_leak_shutdown(void *env_) 1.1755 +{ 1.1756 + /* free/dns, loop, free/base */ 1.1757 + struct testleak_env_t *env = env_; 1.1758 + int send_err_shutdown = 1; 1.1759 + 1.1760 + /* `req` is freed both with `send_err_shutdown` and without it, 1.1761 + * the only difference is `evdns_callback` call */ 1.1762 + env->req = 0; 1.1763 + 1.1764 + evdns_base_free(env->dns_base, send_err_shutdown); 1.1765 + env->dns_base = 0; 1.1766 + 1.1767 + /* `req` is freed in callback, that's why one loop is required */ 1.1768 + event_base_loop(env->base, EVLOOP_NONBLOCK); 1.1769 + event_base_free(env->base); 1.1770 + env->base = 0; 1.1771 +} 1.1772 +#endif 1.1773 + 1.1774 +static void 1.1775 +test_getaddrinfo_async_cancel_stress(void *ptr) 1.1776 +{ 1.1777 + struct event_base *base; 1.1778 + struct evdns_base *dns_base = NULL; 1.1779 + struct evdns_server_port *server = NULL; 1.1780 + evutil_socket_t fd = -1; 1.1781 + struct sockaddr_in sin; 1.1782 + struct sockaddr_storage ss; 1.1783 + ev_socklen_t slen; 1.1784 + int i; 1.1785 + 1.1786 + base = event_base_new(); 1.1787 + dns_base = evdns_base_new(base, 0); 1.1788 + 1.1789 + memset(&sin, 0, sizeof(sin)); 1.1790 + sin.sin_family = AF_INET; 1.1791 + sin.sin_port = 0; 1.1792 + sin.sin_addr.s_addr = htonl(0x7f000001); 1.1793 + if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 1.1794 + tt_abort_perror("socket"); 1.1795 + } 1.1796 + evutil_make_socket_nonblocking(fd); 1.1797 + if (bind(fd, (struct sockaddr*)&sin, sizeof(sin))<0) { 1.1798 + tt_abort_perror("bind"); 1.1799 + } 1.1800 + server = evdns_add_server_port_with_base(base, fd, 0, gaic_server_cb, 1.1801 + base); 1.1802 + 1.1803 + memset(&ss, 0, sizeof(ss)); 1.1804 + slen = sizeof(ss); 1.1805 + if (getsockname(fd, (struct sockaddr*)&ss, &slen)<0) { 1.1806 + tt_abort_perror("getsockname"); 1.1807 + } 1.1808 + evdns_base_nameserver_sockaddr_add(dns_base, 1.1809 + (struct sockaddr*)&ss, slen, 0); 1.1810 + 1.1811 + for (i = 0; i < 1000; ++i) { 1.1812 + gaic_launch(base, dns_base); 1.1813 + } 1.1814 + 1.1815 + event_base_dispatch(base); 1.1816 + 1.1817 +end: 1.1818 + if (dns_base) 1.1819 + evdns_base_free(dns_base, 1); 1.1820 + if (server) 1.1821 + evdns_close_server_port(server); 1.1822 + if (fd >= 0) 1.1823 + evutil_closesocket(fd); 1.1824 +} 1.1825 + 1.1826 + 1.1827 +#define DNS_LEGACY(name, flags) \ 1.1828 + { #name, run_legacy_test_fn, flags|TT_LEGACY, &legacy_setup, \ 1.1829 + dns_##name } 1.1830 + 1.1831 +struct testcase_t dns_testcases[] = { 1.1832 + DNS_LEGACY(server, TT_FORK|TT_NEED_BASE), 1.1833 + DNS_LEGACY(gethostbyname, TT_FORK|TT_NEED_BASE|TT_NEED_DNS), 1.1834 + DNS_LEGACY(gethostbyname6, TT_FORK|TT_NEED_BASE|TT_NEED_DNS), 1.1835 + DNS_LEGACY(gethostbyaddr, TT_FORK|TT_NEED_BASE|TT_NEED_DNS), 1.1836 + { "resolve_reverse", dns_resolve_reverse, TT_FORK, NULL, NULL }, 1.1837 + { "search", dns_search_test, TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, 1.1838 + { "search_cancel", dns_search_cancel_test, 1.1839 + TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, 1.1840 + { "retry", dns_retry_test, TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, 1.1841 + { "reissue", dns_reissue_test, TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, 1.1842 + { "inflight", dns_inflight_test, TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, 1.1843 + { "bufferevent_connect_hostname", test_bufferevent_connect_hostname, 1.1844 + TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, 1.1845 + 1.1846 + { "getaddrinfo_async", test_getaddrinfo_async, 1.1847 + TT_FORK|TT_NEED_BASE, &basic_setup, (char*)"" }, 1.1848 + { "getaddrinfo_cancel_stress", test_getaddrinfo_async_cancel_stress, 1.1849 + TT_FORK, NULL, NULL }, 1.1850 + 1.1851 +#ifdef EVENT_SET_MEM_FUNCTIONS_IMPLEMENTED 1.1852 + { "leak_shutdown", test_dbg_leak_shutdown, TT_FORK, &testleak_funcs, NULL }, 1.1853 + { "leak_cancel", test_dbg_leak_cancel, TT_FORK, &testleak_funcs, NULL }, 1.1854 +#endif 1.1855 + 1.1856 + END_OF_TESTCASES 1.1857 +}; 1.1858 +