1 /* MIT License
2 *
3 * Copyright (c) The c-ares project and its contributors
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 *
24 * SPDX-License-Identifier: MIT
25 */
26 #include "ares_setup.h"
27 #include "ares.h"
28 #include "ares_nameser.h"
29 #include "ares-test.h"
30 #include "ares-test-ai.h"
31 #include "dns-proto.h"
32 #include "ares_dns.h"
33
34 extern "C" {
35 // Remove command-line defines of package variables for the test project...
36 #undef PACKAGE_NAME
37 #undef PACKAGE_BUGREPORT
38 #undef PACKAGE_STRING
39 #undef PACKAGE_TARNAME
40 // ... so we can include the library's config without symbol redefinitions.
41 #include "ares_setup.h"
42 #include "ares_inet_net_pton.h"
43 #include "ares_data.h"
44 #include "str/ares_strsplit.h"
45 #include "ares_private.h"
46 }
47
48
49 #ifdef HAVE_NETDB_H
50 #include <netdb.h>
51 #endif
52 #ifdef HAVE_NETINET_TCP_H
53 #include <netinet/tcp.h>
54 #endif
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <string.h>
58
59 #include <functional>
60 #include <sstream>
61 #include <algorithm>
62 #include <chrono>
63
64 #ifdef WIN32
65 #define BYTE_CAST (char *)
66 #define mkdir_(d, p) mkdir(d)
67 #else
68 #define BYTE_CAST
69 #define mkdir_(d, p) mkdir(d, p)
70 #endif
71
72 namespace ares {
73 namespace test {
74
75 bool verbose = false;
76 static constexpr unsigned short dynamic_port = 0;
77 unsigned short mock_port = dynamic_port;
78
79 const std::vector<int> both_families = {AF_INET, AF_INET6};
80 const std::vector<int> ipv4_family = {AF_INET};
81 const std::vector<int> ipv6_family = {AF_INET6};
82
83 const std::vector<std::pair<int, bool>> both_families_both_modes = {
84 std::make_pair<int, bool>(AF_INET, false),
85 std::make_pair<int, bool>(AF_INET, true),
86 std::make_pair<int, bool>(AF_INET6, false),
87 std::make_pair<int, bool>(AF_INET6, true)
88 };
89 const std::vector<std::pair<int, bool>> ipv4_family_both_modes = {
90 std::make_pair<int, bool>(AF_INET, false),
91 std::make_pair<int, bool>(AF_INET, true)
92 };
93 const std::vector<std::pair<int, bool>> ipv6_family_both_modes = {
94 std::make_pair<int, bool>(AF_INET6, false),
95 std::make_pair<int, bool>(AF_INET6, true)
96 };
97
98
99 const std::vector<std::tuple<ares_evsys_t, int, bool>> all_evsys_ipv4_family_both_modes = {
100 #ifdef _WIN32
101 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_WIN32, AF_INET, false),
102 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_WIN32, AF_INET, true),
103 #endif
104 #ifdef HAVE_KQUEUE
105 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_KQUEUE, AF_INET, false),
106 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_KQUEUE, AF_INET, true),
107 #endif
108 #ifdef HAVE_EPOLL
109 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_EPOLL, AF_INET, false),
110 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_EPOLL, AF_INET, true),
111 #endif
112 #ifdef HAVE_POLL
113 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_POLL, AF_INET, false),
114 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_POLL, AF_INET, true),
115 #endif
116 #ifdef HAVE_PIPE
117 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_SELECT, AF_INET, false),
118 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_SELECT, AF_INET, true),
119 #endif
120 };
121
122 const std::vector<std::tuple<ares_evsys_t, int, bool>> all_evsys_ipv6_family_both_modes = {
123 #ifdef _WIN32
124 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_WIN32, AF_INET6, false),
125 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_WIN32, AF_INET6, true),
126 #endif
127 #ifdef HAVE_KQUEUE
128 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_KQUEUE, AF_INET6, false),
129 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_KQUEUE, AF_INET6, true),
130 #endif
131 #ifdef HAVE_EPOLL
132 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_EPOLL, AF_INET6, false),
133 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_EPOLL, AF_INET6, true),
134 #endif
135 #ifdef HAVE_POLL
136 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_POLL, AF_INET6, false),
137 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_POLL, AF_INET6, true),
138 #endif
139 #ifdef HAVE_PIPE
140 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_SELECT, AF_INET6, false),
141 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_SELECT, AF_INET6, true),
142 #endif
143 };
144
145 const std::vector<std::tuple<ares_evsys_t, int, bool>> all_evsys_both_families_both_modes = {
146 #ifdef _WIN32
147 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_WIN32, AF_INET, false),
148 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_WIN32, AF_INET, true),
149 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_WIN32, AF_INET6, false),
150 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_WIN32, AF_INET6, true),
151 #endif
152 #ifdef HAVE_KQUEUE
153 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_KQUEUE, AF_INET, false),
154 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_KQUEUE, AF_INET, true),
155 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_KQUEUE, AF_INET6, false),
156 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_KQUEUE, AF_INET6, true),
157 #endif
158 #ifdef HAVE_EPOLL
159 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_EPOLL, AF_INET, false),
160 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_EPOLL, AF_INET, true),
161 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_EPOLL, AF_INET6, false),
162 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_EPOLL, AF_INET6, true),
163 #endif
164 #ifdef HAVE_POLL
165 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_POLL, AF_INET, false),
166 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_POLL, AF_INET, true),
167 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_POLL, AF_INET6, false),
168 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_POLL, AF_INET6, true),
169 #endif
170 #ifdef HAVE_PIPE
171 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_SELECT, AF_INET, false),
172 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_SELECT, AF_INET, true),
173 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_SELECT, AF_INET6, false),
174 std::make_tuple<ares_evsys_t, int, bool>(ARES_EVSYS_SELECT, AF_INET6, true),
175 #endif
176 };
177
178
179 std::vector<std::tuple<ares_evsys_t, int, bool>> evsys_families_modes = all_evsys_both_families_both_modes;
180
181
182 const std::vector<std::tuple<ares_evsys_t, int>> all_evsys_ipv4_family = {
183 #ifdef _WIN32
184 std::make_tuple<ares_evsys_t, int>(ARES_EVSYS_WIN32, AF_INET),
185 #endif
186 #ifdef HAVE_KQUEUE
187 std::make_tuple<ares_evsys_t, int>(ARES_EVSYS_KQUEUE, AF_INET),
188 #endif
189 #ifdef HAVE_EPOLL
190 std::make_tuple<ares_evsys_t, int>(ARES_EVSYS_EPOLL, AF_INET),
191 #endif
192 #ifdef HAVE_POLL
193 std::make_tuple<ares_evsys_t, int>(ARES_EVSYS_POLL, AF_INET),
194 #endif
195 #ifdef HAVE_PIPE
196 std::make_tuple<ares_evsys_t, int>(ARES_EVSYS_SELECT, AF_INET),
197 #endif
198 };
199
200 const std::vector<std::tuple<ares_evsys_t, int>> all_evsys_ipv6_family = {
201 #ifdef _WIN32
202 std::make_tuple<ares_evsys_t, int>(ARES_EVSYS_WIN32, AF_INET6),
203 #endif
204 #ifdef HAVE_KQUEUE
205 std::make_tuple<ares_evsys_t, int>(ARES_EVSYS_KQUEUE, AF_INET6),
206 #endif
207 #ifdef HAVE_EPOLL
208 std::make_tuple<ares_evsys_t, int>(ARES_EVSYS_EPOLL, AF_INET6),
209 #endif
210 #ifdef HAVE_POLL
211 std::make_tuple<ares_evsys_t, int>(ARES_EVSYS_POLL, AF_INET6),
212 #endif
213 #ifdef HAVE_PIPE
214 std::make_tuple<ares_evsys_t, int>(ARES_EVSYS_SELECT, AF_INET6),
215 #endif
216 };
217
218 const std::vector<std::tuple<ares_evsys_t, int>> all_evsys_both_families = {
219 #ifdef _WIN32
220 std::make_tuple<ares_evsys_t, int>(ARES_EVSYS_WIN32, AF_INET),
221 std::make_tuple<ares_evsys_t, int>(ARES_EVSYS_WIN32, AF_INET6),
222 #endif
223 #ifdef HAVE_KQUEUE
224 std::make_tuple<ares_evsys_t, int>(ARES_EVSYS_KQUEUE, AF_INET),
225 std::make_tuple<ares_evsys_t, int>(ARES_EVSYS_KQUEUE, AF_INET6),
226 #endif
227 #ifdef HAVE_EPOLL
228 std::make_tuple<ares_evsys_t, int>(ARES_EVSYS_EPOLL, AF_INET),
229 std::make_tuple<ares_evsys_t, int>(ARES_EVSYS_EPOLL, AF_INET6),
230 #endif
231 #ifdef HAVE_POLL
232 std::make_tuple<ares_evsys_t, int>(ARES_EVSYS_POLL, AF_INET),
233 std::make_tuple<ares_evsys_t, int>(ARES_EVSYS_POLL, AF_INET6),
234 #endif
235 #ifdef HAVE_PIPE
236 std::make_tuple<ares_evsys_t, int>(ARES_EVSYS_SELECT, AF_INET),
237 std::make_tuple<ares_evsys_t, int>(ARES_EVSYS_SELECT, AF_INET6),
238 #endif
239 };
240
241
242
243 std::vector<std::tuple<ares_evsys_t, int>> evsys_families = all_evsys_both_families;
244
245
246 // Which parameters to use in tests
247 std::vector<int> families = both_families;
248 std::vector<std::pair<int, bool>> families_modes = both_families_both_modes;
249
250 unsigned long long LibraryTest::fails_ = 0;
251 std::map<size_t, int> LibraryTest::size_fails_;
252 std::mutex LibraryTest::lock_;
253 bool LibraryTest::failsend_ = false;
254
ares_sleep_time(unsigned int ms)255 void ares_sleep_time(unsigned int ms)
256 {
257 auto duration = std::chrono::milliseconds(ms);
258 auto start_time = std::chrono::high_resolution_clock::now();
259 auto wake_time = start_time + duration;
260 std::this_thread::sleep_until(wake_time);
261 auto end_time = std::chrono::high_resolution_clock::now();
262 if (verbose) std::cerr << "sleep requested " << ms << "ms, slept for " << std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time).count() << "ms" << std::endl;
263 }
264
ProcessWork(ares_channel_t * channel,std::function<std::set<ares_socket_t> ()> get_extrafds,std::function<void (ares_socket_t)> process_extra,unsigned int cancel_ms)265 void ProcessWork(ares_channel_t *channel,
266 std::function<std::set<ares_socket_t>()> get_extrafds,
267 std::function<void(ares_socket_t)> process_extra,
268 unsigned int cancel_ms) {
269 int nfds, count;
270 fd_set readers, writers;
271
272 auto tv_begin = std::chrono::high_resolution_clock::now();
273 auto tv_cancel = tv_begin;
274
275 if (cancel_ms) {
276 if (verbose) std::cerr << "ares_cancel will be called after " << cancel_ms << "ms" << std::endl;
277 tv_cancel += std::chrono::milliseconds(cancel_ms);
278 }
279
280 while (true) {
281 struct timeval tv;
282 struct timeval *tv_select;
283
284 // Retrieve the set of file descriptors that the library wants us to monitor.
285 FD_ZERO(&readers);
286 FD_ZERO(&writers);
287 nfds = ares_fds(channel, &readers, &writers);
288 if (nfds == 0) // no work left to do in the library
289 return;
290
291 // Add in the extra FDs if present.
292 std::set<ares_socket_t> extrafds = get_extrafds();
293 for (ares_socket_t extrafd : extrafds) {
294 FD_SET(extrafd, &readers);
295 if (extrafd >= (ares_socket_t)nfds) {
296 nfds = (int)extrafd + 1;
297 }
298 }
299
300 /* If ares_timeout returns NULL, it means there are no requests in queue,
301 * so we can break out */
302 tv_select = ares_timeout(channel, NULL, &tv);
303 if (tv_select == NULL)
304 return;
305
306 if (cancel_ms) {
307 auto tv_now = std::chrono::high_resolution_clock::now();
308 auto remaining_ms = std::chrono::duration_cast<std::chrono::milliseconds>(tv_cancel - tv_now).count();
309
310 if (remaining_ms <= 0) {
311 if (verbose) std::cerr << "Issuing ares_cancel()" << std::endl;
312 ares_cancel(channel);
313 cancel_ms = 0; /* Disable issuing cancel again */
314 } else {
315 struct timeval tv_remaining;
316
317 tv_remaining.tv_sec = remaining_ms / 1000;
318 tv_remaining.tv_usec = (int)(remaining_ms % 1000);
319
320 /* Recalculate proper timeout since we also have a cancel to wait on */
321 tv_select = ares_timeout(channel, &tv_remaining, &tv);
322 }
323 }
324
325 count = select(nfds, &readers, &writers, nullptr, tv_select);
326 if (count < 0) {
327 fprintf(stderr, "select() failed, errno %d\n", errno);
328 return;
329 }
330
331 // Let the library process any activity.
332 ares_process(channel, &readers, &writers);
333
334 // Let the provided callback process any activity on the extra FD.
335 for (ares_socket_t extrafd : extrafds) {
336 if (FD_ISSET(extrafd, &readers)) {
337 process_extra(extrafd);
338 }
339 }
340 }
341 }
342
343
SetFailSend()344 void LibraryTest::SetFailSend() {
345 failsend_ = true;
346 }
347
348 // static
ares_sendv_fail(ares_socket_t socket,const struct iovec * vec,int len,void * user_data)349 ares_ssize_t LibraryTest::ares_sendv_fail(ares_socket_t socket, const struct iovec *vec, int len, void *user_data)
350 {
351 (void)user_data;
352
353 if (failsend_) {
354 #ifdef USE_WINSOCK
355 WSASetLastError(WSAECONNREFUSED);
356 #else
357 errno = ECONNREFUSED;
358 #endif
359 failsend_ = false;
360 return -1;
361 }
362
363 return send(socket, (const char *)vec[0].iov_base, vec[0].iov_len, 0);
364 }
365
366
SetAllocFail(int nth)367 void LibraryTest::SetAllocFail(int nth) {
368 lock_.lock();
369 assert(nth > 0);
370 assert(nth <= (int)(8 * sizeof(fails_)));
371 fails_ |= (1LL << (nth - 1));
372 lock_.unlock();
373 }
374
375 // static
SetAllocSizeFail(size_t size)376 void LibraryTest::SetAllocSizeFail(size_t size) {
377 lock_.lock();
378 size_fails_[size]++;
379 lock_.unlock();
380 }
381
382 // static
ClearFails()383 void LibraryTest::ClearFails() {
384 lock_.lock();
385 fails_ = 0;
386 size_fails_.clear();
387 lock_.unlock();
388 }
389
390
391 // static
ShouldAllocFail(size_t size)392 bool LibraryTest::ShouldAllocFail(size_t size) {
393 lock_.lock();
394 bool fail = (fails_ & 0x01);
395 fails_ >>= 1;
396 if (size_fails_[size] > 0) {
397 size_fails_[size]--;
398 fail = true;
399 }
400 lock_.unlock();
401 return fail;
402 }
403
404 // static
amalloc(size_t size)405 void* LibraryTest::amalloc(size_t size) {
406 if (ShouldAllocFail(size) || size == 0) {
407 if (verbose) std::cerr << "Failing malloc(" << size << ") request" << std::endl;
408 return nullptr;
409 } else {
410 return malloc(size);
411 }
412 }
413
414 // static
arealloc(void * ptr,size_t size)415 void* LibraryTest::arealloc(void *ptr, size_t size) {
416 if (ShouldAllocFail(size)) {
417 if (verbose) std::cerr << "Failing realloc(" << ptr << ", " << size << ") request" << std::endl;
418 return nullptr;
419 } else {
420 return realloc(ptr, size);
421 }
422 }
423
424 // static
afree(void * ptr)425 void LibraryTest::afree(void *ptr) {
426 free(ptr);
427 }
428
NoExtraFDs()429 std::set<ares_socket_t> NoExtraFDs() {
430 return std::set<ares_socket_t>();
431 }
432
Process(unsigned int cancel_ms)433 void DefaultChannelTest::Process(unsigned int cancel_ms) {
434 ProcessWork(channel_, NoExtraFDs, nullptr, cancel_ms);
435 }
436
Process(unsigned int cancel_ms)437 void FileChannelTest::Process(unsigned int cancel_ms) {
438 ProcessWork(channel_, NoExtraFDs, nullptr, cancel_ms);
439 }
440
Process(unsigned int cancel_ms)441 void DefaultChannelModeTest::Process(unsigned int cancel_ms) {
442 ProcessWork(channel_, NoExtraFDs, nullptr, cancel_ms);
443 }
444
MockServer(int family,unsigned short port)445 MockServer::MockServer(int family, unsigned short port)
446 : udpport_(port), tcpport_(port), qid_(-1) {
447 reply_ = nullptr;
448 // Create a TCP socket to receive data on.
449 tcp_data_ = NULL;
450 tcp_data_len_ = 0;
451 tcpfd_ = socket(family, SOCK_STREAM, 0);
452 EXPECT_NE(ARES_SOCKET_BAD, tcpfd_);
453 int optval = 1;
454 setsockopt(tcpfd_, SOL_SOCKET, SO_REUSEADDR,
455 BYTE_CAST &optval , sizeof(int));
456 // Send TCP data right away.
457 setsockopt(tcpfd_, IPPROTO_TCP, TCP_NODELAY,
458 BYTE_CAST &optval , sizeof(int));
459 #if defined(SO_NOSIGPIPE)
460 setsockopt(tcpfd_, SOL_SOCKET, SO_NOSIGPIPE, (void *)&optval, sizeof(optval));
461 #endif
462
463 /* Test system enable TCP FastOpen */
464 #if defined(TCP_FASTOPEN)
465 # ifdef __linux__
466 int qlen = 32;
467 setsockopt(tcpfd_, IPPROTO_TCP, TCP_FASTOPEN, &qlen, sizeof(qlen));
468 # else
469 int on = 1;
470 setsockopt(tcpfd_, IPPROTO_TCP, TCP_FASTOPEN, BYTE_CAST &on, sizeof(on));
471 # endif
472 #endif
473
474 // Create a UDP socket to receive data on.
475 udpfd_ = socket(family, SOCK_DGRAM, 0);
476 EXPECT_NE(ARES_SOCKET_BAD, udpfd_);
477 #if defined(SO_NOSIGPIPE)
478 setsockopt(udpfd_, SOL_SOCKET, SO_NOSIGPIPE, (void *)&optval, sizeof(optval));
479 #endif
480
481 // Bind the sockets to the given port.
482 if (family == AF_INET) {
483 struct sockaddr_in addr;
484 memset(&addr, 0, sizeof(addr));
485 addr.sin_family = AF_INET;
486 addr.sin_addr.s_addr = htonl(INADDR_ANY);
487 addr.sin_port = htons(tcpport_);
488 int tcprc = bind(tcpfd_, (struct sockaddr*)&addr, sizeof(addr));
489 EXPECT_EQ(0, tcprc) << "Failed to bind AF_INET to TCP port " << tcpport_;
490 addr.sin_port = htons(udpport_);
491 int udprc = bind(udpfd_, (struct sockaddr*)&addr, sizeof(addr));
492 EXPECT_EQ(0, udprc) << "Failed to bind AF_INET to UDP port " << udpport_;
493 // retrieve system-assigned port
494 if (udpport_ == dynamic_port) {
495 ares_socklen_t len = sizeof(addr);
496 auto result = getsockname(udpfd_, (struct sockaddr*)&addr, &len);
497 EXPECT_EQ(0, result);
498 udpport_ = ntohs(addr.sin_port);
499 EXPECT_NE(dynamic_port, udpport_);
500 }
501 if (tcpport_ == dynamic_port) {
502 ares_socklen_t len = sizeof(addr);
503 auto result = getsockname(tcpfd_, (struct sockaddr*)&addr, &len);
504 EXPECT_EQ(0, result);
505 tcpport_ = ntohs(addr.sin_port);
506 EXPECT_NE(dynamic_port, tcpport_);
507 }
508 } else {
509 EXPECT_EQ(AF_INET6, family);
510 struct sockaddr_in6 addr;
511 memset(&addr, 0, sizeof(addr));
512 addr.sin6_family = AF_INET6;
513 memset(&addr.sin6_addr, 0, sizeof(addr.sin6_addr)); // in6addr_any
514 addr.sin6_port = htons(tcpport_);
515 int tcprc = bind(tcpfd_, (struct sockaddr*)&addr, sizeof(addr));
516 EXPECT_EQ(0, tcprc) << "Failed to bind AF_INET6 to TCP port " << tcpport_;
517 addr.sin6_port = htons(udpport_);
518 int udprc = bind(udpfd_, (struct sockaddr*)&addr, sizeof(addr));
519 EXPECT_EQ(0, udprc) << "Failed to bind AF_INET6 to UDP port " << udpport_;
520 // retrieve system-assigned port
521 if (udpport_ == dynamic_port) {
522 ares_socklen_t len = sizeof(addr);
523 auto result = getsockname(udpfd_, (struct sockaddr*)&addr, &len);
524 EXPECT_EQ(0, result);
525 udpport_ = ntohs(addr.sin6_port);
526 EXPECT_NE(dynamic_port, udpport_);
527 }
528 if (tcpport_ == dynamic_port) {
529 ares_socklen_t len = sizeof(addr);
530 auto result = getsockname(tcpfd_, (struct sockaddr*)&addr, &len);
531 EXPECT_EQ(0, result);
532 tcpport_ = ntohs(addr.sin6_port);
533 EXPECT_NE(dynamic_port, tcpport_);
534 }
535 }
536 if (verbose) std::cerr << "Configured "
537 << (family == AF_INET ? "IPv4" : "IPv6")
538 << " mock server with TCP socket " << tcpfd_
539 << " on port " << tcpport_
540 << " and UDP socket " << udpfd_
541 << " on port " << udpport_ << std::endl;
542
543 // For TCP, also need to listen for connections.
544 EXPECT_EQ(0, listen(tcpfd_, 5)) << "Failed to listen for TCP connections";
545 }
546
~MockServer()547 MockServer::~MockServer() {
548 for (ares_socket_t fd : connfds_) {
549 sclose(fd);
550 }
551 sclose(tcpfd_);
552 sclose(udpfd_);
553 free(tcp_data_);
554 }
555
getaddrport(struct sockaddr_storage * addr)556 static unsigned short getaddrport(struct sockaddr_storage *addr)
557 {
558 if (addr->ss_family == AF_INET)
559 return ntohs(((struct sockaddr_in *)(void *)addr)->sin_port);
560 if (addr->ss_family == AF_INET6)
561 return ntohs(((struct sockaddr_in6 *)(void *)addr)->sin6_port);
562
563 /* TCP should use getpeername() to get the port, getting this from recvfrom
564 * won't work */
565 return 0;
566 }
567
ProcessPacket(ares_socket_t fd,struct sockaddr_storage * addr,ares_socklen_t addrlen,byte * data,int len)568 void MockServer::ProcessPacket(ares_socket_t fd, struct sockaddr_storage *addr, ares_socklen_t addrlen,
569 byte *data, int len) {
570
571 // Assume the packet is a well-formed DNS request and extract the request
572 // details.
573 if (len < NS_HFIXEDSZ) {
574 std::cerr << "Packet too short (" << len << ")" << std::endl;
575 return;
576 }
577 int qid = DNS_HEADER_QID(data);
578 if (DNS_HEADER_QR(data) != 0) {
579 std::cerr << "Not a request" << std::endl;
580 return;
581 }
582 if (DNS_HEADER_OPCODE(data) != O_QUERY) {
583 std::cerr << "Not a query (opcode " << DNS_HEADER_OPCODE(data)
584 << ")" << std::endl;
585 return;
586 }
587 if (DNS_HEADER_QDCOUNT(data) != 1) {
588 std::cerr << "Unexpected question count (" << DNS_HEADER_QDCOUNT(data)
589 << ")" << std::endl;
590 return;
591 }
592 byte* question = data + NS_HFIXEDSZ;
593 int qlen = len - NS_HFIXEDSZ;
594
595 char *name = nullptr;
596 long enclen;
597 ares_expand_name(question, data, len, &name, &enclen);
598 if (!name) {
599 std::cerr << "Failed to retrieve name" << std::endl;
600 return;
601 }
602 if (enclen > qlen) {
603 std::cerr << "(error, encoded name len " << enclen << "bigger than remaining data " << qlen << " bytes)" << std::endl;
604 ares_free_string(name);
605 return;
606 }
607 qlen -= (int)enclen;
608 question += enclen;
609
610 if (qlen < 4) {
611 std::cerr << "Unexpected question size (" << qlen
612 << " bytes after name)" << std::endl;
613 ares_free_string(name);
614 return;
615 }
616 if (DNS_QUESTION_CLASS(question) != C_IN) {
617 std::cerr << "Unexpected question class (" << DNS_QUESTION_CLASS(question)
618 << ")" << std::endl;
619 ares_free_string(name);
620 return;
621 }
622 int rrtype = DNS_QUESTION_TYPE(question);
623
624 std::vector<byte> req(data, data + len);
625 std::string reqstr = PacketToString(req);
626 if (verbose) {
627 std::cerr << "received " << (fd == udpfd_ ? "UDP" : "TCP") << " request " << reqstr
628 << " on port " << (fd == udpfd_ ? udpport_ : tcpport_)
629 << ":" << getaddrport(addr) << std::endl;
630 std::cerr << "ProcessRequest(" << qid << ", '" << name
631 << "', " << RRTypeToString(rrtype) << ")" << std::endl;
632 }
633 ProcessRequest(fd, addr, addrlen, req, reqstr, qid, name, rrtype);
634 ares_free_string(name);
635 }
636
ProcessFD(ares_socket_t fd)637 void MockServer::ProcessFD(ares_socket_t fd) {
638 if (fd != tcpfd_ && fd != udpfd_ && connfds_.find(fd) == connfds_.end()) {
639 // Not one of our FDs.
640 return;
641 }
642 if (fd == tcpfd_) {
643 ares_socket_t connfd = accept(tcpfd_, NULL, NULL);
644 if (connfd == ARES_SOCKET_BAD) {
645 std::cerr << "Error accepting connection on fd " << fd << std::endl;
646 } else {
647 connfds_.insert(connfd);
648 }
649 return;
650 }
651
652 // Activity on a data-bearing file descriptor.
653 struct sockaddr_storage addr;
654 socklen_t addrlen = sizeof(addr);
655 memset(&addr, 0, sizeof(addr));
656 byte buffer[2048];
657 ares_ssize_t len = (ares_ssize_t)recvfrom(fd, BYTE_CAST buffer, sizeof(buffer), 0,
658 (struct sockaddr *)&addr, &addrlen);
659
660 if (fd != udpfd_) {
661 if (len <= 0) {
662 connfds_.erase(std::find(connfds_.begin(), connfds_.end(), fd));
663 sclose(fd);
664 free(tcp_data_);
665 tcp_data_ = NULL;
666 tcp_data_len_ = 0;
667 return;
668 }
669 tcp_data_ = (unsigned char *)realloc(tcp_data_, tcp_data_len_ + (size_t)len);
670 memcpy(tcp_data_ + tcp_data_len_, buffer, (size_t)len);
671 tcp_data_len_ += (size_t)len;
672
673 /* TCP might aggregate the various requests into a single packet, so we
674 * need to split */
675 while (tcp_data_len_ > 2) {
676 size_t tcplen = ((size_t)tcp_data_[0] << 8) + (size_t)tcp_data_[1];
677 if (tcp_data_len_ - 2 < tcplen)
678 break;
679
680 ProcessPacket(fd, &addr, addrlen, tcp_data_ + 2, (int)tcplen);
681
682 /* strip off processed data if connection not terminated */
683 if (tcp_data_ != NULL) {
684 memmove(tcp_data_, tcp_data_ + tcplen + 2, tcp_data_len_ - 2 - tcplen);
685 tcp_data_len_ -= 2 + tcplen;
686 }
687 }
688 } else {
689 /* UDP is always a single packet */
690 ProcessPacket(fd, &addr, addrlen, buffer, (int)len);
691 }
692
693 }
694
fds() const695 std::set<ares_socket_t> MockServer::fds() const {
696 std::set<ares_socket_t> result = connfds_;
697 result.insert(tcpfd_);
698 result.insert(udpfd_);
699 return result;
700 }
701
ProcessRequest(ares_socket_t fd,struct sockaddr_storage * addr,ares_socklen_t addrlen,const std::vector<byte> & req,const std::string & reqstr,int qid,const char * name,int rrtype)702 void MockServer::ProcessRequest(ares_socket_t fd, struct sockaddr_storage* addr,
703 ares_socklen_t addrlen, const std::vector<byte> &req,
704 const std::string &reqstr,
705 int qid, const char *name, int rrtype) {
706
707 /* DNS 0x20 will mix case, do case-insensitive matching of name in request */
708 char lower_name[256];
709 int flags = 0;
710
711 arestest_strtolower(lower_name, name, sizeof(lower_name));
712
713 // Before processing, let gMock know the request is happening.
714 OnRequest(lower_name, rrtype);
715
716 // If we are expecting a specific request then check it matches here.
717 if (expected_request_.length() > 0) {
718 ASSERT_EQ(expected_request_, reqstr);
719 }
720
721 if (reply_ != nullptr) {
722 ares_dns_record_t *dnsrec = NULL;
723 /* We will *attempt* to parse the request string. It may be malformed that
724 * will lead to a parse failure. If so, we just ignore it. We want to
725 * pass this parsed data structure to the reply generator in case it needs
726 * to extract metadata (such as a DNS client cookie) from the original
727 * request. If we can't parse it, oh well, we'll just pass NULL, most
728 * replies don't need anything from the request other than the name which
729 * is passed separately. */
730 ares_dns_parse(req.data(), req.size(), 0, &dnsrec);
731 exact_reply_ = reply_->data(name, dnsrec);
732 ares_dns_record_destroy(dnsrec);
733 }
734
735 if (exact_reply_.size() == 0) {
736 return;
737 }
738
739 // Make a local copy of the current pending reply.
740 std::vector<byte> reply = exact_reply_;
741
742 if (qid_ >= 0) {
743 // Use the explicitly specified query ID.
744 qid = qid_;
745 }
746 if (reply.size() >= 2) {
747 // Overwrite the query ID if space to do so.
748 reply[0] = (byte)((qid >> 8) & 0xff);
749 reply[1] = (byte)(qid & 0xff);
750 }
751 if (verbose) {
752 std::cerr << "sending reply " << PacketToString(reply)
753 << " on port " << ((fd == udpfd_) ? udpport_ : tcpport_)
754 << ":" << getaddrport(addr) << std::endl;
755 }
756
757 // Prefix with 2-byte length if TCP.
758 if (fd != udpfd_) {
759 int len = (int)reply.size();
760 std::vector<byte> vlen = {(byte)((len & 0xFF00) >> 8), (byte)(len & 0xFF)};
761 reply.insert(reply.begin(), vlen.begin(), vlen.end());
762 // Also, don't bother with the destination address.
763 addr = nullptr;
764 addrlen = 0;
765 }
766
767 #ifdef MSG_NOSIGNAL
768 flags |= MSG_NOSIGNAL;
769 #endif
770
771 ares_ssize_t rc = (ares_ssize_t)sendto(fd, BYTE_CAST reply.data(), (SEND_TYPE_ARG3)reply.size(), flags,
772 (struct sockaddr *)addr, addrlen);
773 if (rc < static_cast<ares_ssize_t>(reply.size())) {
774 std::cerr << "Failed to send full reply, rc=" << rc << std::endl;
775 }
776
777 }
778
779 // static
BuildServers(int count,int family,unsigned short base_port)780 MockChannelOptsTest::NiceMockServers MockChannelOptsTest::BuildServers(int count, int family, unsigned short base_port) {
781 NiceMockServers servers;
782 assert(count > 0);
783 for (unsigned short ii = 0; ii < count; ii++) {
784 unsigned short port = base_port == dynamic_port ? dynamic_port : base_port + ii;
785 std::unique_ptr<NiceMockServer> server(new NiceMockServer(family, port));
786 servers.push_back(std::move(server));
787 }
788 return servers;
789 }
790
MockChannelOptsTest(int count,int family,bool force_tcp,bool honor_sysconfig,struct ares_options * givenopts,int optmask)791 MockChannelOptsTest::MockChannelOptsTest(int count,
792 int family,
793 bool force_tcp,
794 bool honor_sysconfig,
795 struct ares_options* givenopts,
796 int optmask)
797 : servers_(BuildServers(count, family, mock_port)),
798 server_(*servers_[0].get()), channel_(nullptr) {
799 // Set up channel options.
800 const char *domains[3] = {"first.com", "second.org", "third.gov"};
801 struct ares_options opts;
802 if (givenopts) {
803 memcpy(&opts, givenopts, sizeof(opts));
804 } else {
805 memset(&opts, 0, sizeof(opts));
806 }
807
808 /* Honor items from resolv.conf except the dns server itself */
809 if (!honor_sysconfig) {
810 if (!(optmask & (ARES_OPT_TIMEOUTMS|ARES_OPT_TIMEOUT))) {
811 // Reduce timeouts significantly to shorten test times.
812 opts.timeout = 250;
813 optmask |= ARES_OPT_TIMEOUTMS;
814 }
815 // If not already overridden, set 3 retries.
816 if (!(optmask & ARES_OPT_TRIES)) {
817 opts.tries = 3;
818 optmask |= ARES_OPT_TRIES;
819 }
820
821 // If not already overridden, set search domains.
822 if (!(optmask & ARES_OPT_DOMAINS)) {
823 opts.ndomains = 3;
824 opts.domains = (char**)domains;
825 optmask |= ARES_OPT_DOMAINS;
826 }
827
828 /* Tests expect ndots=1 in general, the system config may not default to this
829 * so we don't want to inherit that. */
830 if (!(optmask & ARES_OPT_NDOTS)) {
831 opts.ndots = 1;
832 optmask |= ARES_OPT_NDOTS;
833 }
834 }
835
836 if (force_tcp) {
837 opts.flags |= ARES_FLAG_USEVC;
838 optmask |= ARES_OPT_FLAGS;
839 }
840
841 /* Disable the query cache for tests unless explicitly enabled. As of
842 * c-ares 1.31.0, the query cache is enabled by default so we have to set
843 * the option and set the TTL to 0 to effectively disable it. */
844 if (!(optmask & ARES_OPT_QUERY_CACHE)) {
845 opts.qcache_max_ttl = 0;
846 optmask |= ARES_OPT_QUERY_CACHE;
847 }
848
849 /* Enable DNS0x20 by default. Need to also turn on default flag of EDNS */
850 if (!(optmask & ARES_OPT_FLAGS)) {
851 optmask |= ARES_OPT_FLAGS;
852 opts.flags = ARES_FLAG_DNS0x20|ARES_FLAG_EDNS;
853 }
854
855 EXPECT_EQ(ARES_SUCCESS, ares_init_options(&channel_, &opts, optmask));
856 EXPECT_NE(nullptr, channel_);
857
858 // Set up servers after construction so we can set individual ports
859 struct ares_addr_port_node* prev = nullptr;
860 struct ares_addr_port_node* first = nullptr;
861 for (const auto& server : servers_) {
862 struct ares_addr_port_node* node = (struct ares_addr_port_node*)malloc(sizeof(*node));
863 if (prev) {
864 prev->next = node;
865 } else {
866 first = node;
867 }
868 node->next = nullptr;
869 node->family = family;
870 node->udp_port = server->udpport();
871 node->tcp_port = server->tcpport();
872 if (family == AF_INET) {
873 node->addr.addr4.s_addr = htonl(0x7F000001);
874 } else {
875 memset(&node->addr.addr6, 0, sizeof(node->addr.addr6));
876 node->addr.addr6._S6_un._S6_u8[15] = 1;
877 }
878 prev = node;
879 }
880 EXPECT_EQ(ARES_SUCCESS, ares_set_servers_ports(channel_, first));
881
882 while (first) {
883 prev = first;
884 first = first->next;
885 free(prev);
886 }
887 if (verbose) {
888 std::cerr << "Configured library with servers:";
889 std::cerr << GetNameServers(channel_);
890 std::cerr << std::endl;
891 }
892 }
893
~MockChannelOptsTest()894 MockChannelOptsTest::~MockChannelOptsTest() {
895 if (channel_) {
896 ares_destroy(channel_);
897 }
898 channel_ = nullptr;
899 }
900
fds() const901 std::set<ares_socket_t> MockChannelOptsTest::fds() const {
902 std::set<ares_socket_t> fds;
903 for (const auto& server : servers_) {
904 std::set<ares_socket_t> serverfds = server->fds();
905 fds.insert(serverfds.begin(), serverfds.end());
906 }
907 return fds;
908 }
909
ProcessFD(ares_socket_t fd)910 void MockChannelOptsTest::ProcessFD(ares_socket_t fd) {
911 for (auto& server : servers_) {
912 server->ProcessFD(fd);
913 }
914 }
915
ProcessAltChannel(ares_channel_t * chan,unsigned int cancel_ms)916 void MockChannelOptsTest::ProcessAltChannel(ares_channel_t *chan, unsigned int cancel_ms) {
917 using namespace std::placeholders;
918 ProcessWork(chan,
919 std::bind(&MockChannelOptsTest::fds, this),
920 std::bind(&MockChannelOptsTest::ProcessFD, this, _1),
921 cancel_ms);
922 }
923
Process(unsigned int cancel_ms)924 void MockChannelOptsTest::Process(unsigned int cancel_ms) {
925 ProcessAltChannel(channel_, cancel_ms);
926 }
927
Process(unsigned int cancel_ms)928 void MockEventThreadOptsTest::Process(unsigned int cancel_ms) {
929 std::set<ares_socket_t> fds;
930
931 auto tv_begin = std::chrono::high_resolution_clock::now();
932 auto tv_cancel = tv_begin;
933
934 if (cancel_ms) {
935 if (verbose) std::cerr << "ares_cancel will be called after " << cancel_ms << "ms" << std::endl;
936 tv_cancel += std::chrono::milliseconds(cancel_ms);
937 }
938
939 while (ares_queue_active_queries(channel_)) {
940 //if (verbose) std::cerr << "pending queries: " << ares_queue_active_queries(channel_) << std::endl;
941
942 int nfds = 0;
943 fd_set readers;
944
945 struct timeval tv;
946
947 /* c-ares is using its own event thread, so we only need to monitor the
948 * extrafds passed in */
949 FD_ZERO(&readers);
950 fds = MockEventThreadOptsTest::fds();
951 for (ares_socket_t fd : fds) {
952 FD_SET(fd, &readers);
953 if (fd >= (ares_socket_t)nfds) {
954 nfds = (int)fd + 1;
955 }
956 }
957
958 /* We just always wait 20ms then recheck if we're done. Not doing any
959 * complex signaling. */
960 tv.tv_sec = 0;
961 tv.tv_usec = 20000;
962
963 if (cancel_ms) {
964 auto tv_now = std::chrono::high_resolution_clock::now();
965 auto remaining_ms = std::chrono::duration_cast<std::chrono::milliseconds>(tv_cancel - tv_now).count();
966
967 if (remaining_ms <= 0) {
968 if (verbose) std::cerr << "Issuing ares_cancel()" << std::endl;
969 ares_cancel(channel_);
970 cancel_ms = 0; /* Disable issuing cancel again */
971 } else {
972 tv.tv_sec = remaining_ms / 1000;
973 tv.tv_usec = (int)(remaining_ms % 1000);
974 }
975 }
976
977 if (select(nfds, &readers, nullptr, nullptr, &tv) < 0) {
978 fprintf(stderr, "select() failed, errno %d\n", errno);
979 return;
980 }
981
982 // Let the provided callback process any activity on the extra FD.
983 for (ares_socket_t fd : fds) {
984 if (FD_ISSET(fd, &readers)) {
985 ProcessFD(fd);
986 }
987 }
988 }
989
990 //if (verbose) std::cerr << "pending queries at process end: " << ares_queue_active_queries(channel_) << std::endl;
991 }
992
operator <<(std::ostream & os,const HostResult & result)993 std::ostream& operator<<(std::ostream& os, const HostResult& result) {
994 os << '{';
995 if (result.done_) {
996 os << StatusToString(result.status_);
997 if (result.host_.addrtype_ != -1) {
998 os << " " << result.host_;
999 } else {
1000 os << ", (no hostent)";
1001 }
1002 } else {
1003 os << "(incomplete)";
1004 }
1005 os << '}';
1006 return os;
1007 }
1008
HostEnt(const struct hostent * hostent)1009 HostEnt::HostEnt(const struct hostent *hostent) : addrtype_(-1) {
1010 if (!hostent)
1011 return;
1012
1013 if (hostent->h_name) {
1014 // DNS 0x20 may mix case, output as all lower for checks as the mixed case
1015 // is really more of an internal thing
1016 char lowername[256];
1017 arestest_strtolower(lowername, hostent->h_name, sizeof(lowername));
1018 name_ = lowername;
1019 }
1020
1021 if (hostent->h_aliases) {
1022 char** palias = hostent->h_aliases;
1023 while (*palias != nullptr) {
1024 aliases_.push_back(*palias);
1025 palias++;
1026 }
1027 }
1028
1029 addrtype_ = hostent->h_addrtype;
1030
1031 if (hostent->h_addr_list) {
1032 char** paddr = hostent->h_addr_list;
1033 while (*paddr != nullptr) {
1034 std::string addr = AddressToString(*paddr, hostent->h_length);
1035 addrs_.push_back(addr);
1036 paddr++;
1037 }
1038 }
1039 }
1040
operator <<(std::ostream & os,const HostEnt & host)1041 std::ostream& operator<<(std::ostream& os, const HostEnt& host) {
1042 os << "{'";
1043 if (host.name_.length() > 0) {
1044 os << host.name_;
1045 }
1046 os << "' aliases=[";
1047 for (size_t ii = 0; ii < host.aliases_.size(); ii++) {
1048 if (ii > 0) os << ", ";
1049 os << host.aliases_[ii];
1050 }
1051 os << "] ";
1052 os << "addrs=[";
1053 for (size_t ii = 0; ii < host.addrs_.size(); ii++) {
1054 if (ii > 0) os << ", ";
1055 os << host.addrs_[ii];
1056 }
1057 os << "]";
1058 os << '}';
1059 return os;
1060 }
1061
HostCallback(void * data,int status,int timeouts,struct hostent * hostent)1062 void HostCallback(void *data, int status, int timeouts,
1063 struct hostent *hostent) {
1064 EXPECT_NE(nullptr, data);
1065 if (data == nullptr)
1066 return;
1067
1068 HostResult* result = reinterpret_cast<HostResult*>(data);
1069 result->done_ = true;
1070 result->status_ = status;
1071 result->timeouts_ = timeouts;
1072 if (hostent)
1073 result->host_ = HostEnt(hostent);
1074 if (verbose) std::cerr << "HostCallback(" << *result << ")" << std::endl;
1075 }
1076
operator <<(std::ostream & os,const AresDnsRecord & dnsrec)1077 std::ostream& operator<<(std::ostream& os, const AresDnsRecord& dnsrec) {
1078 os << "{'";
1079 /* XXX: Todo */
1080 os << '}';
1081 return os;
1082 }
1083
operator <<(std::ostream & os,const QueryResult & result)1084 std::ostream& operator<<(std::ostream& os, const QueryResult& result) {
1085 os << '{';
1086 if (result.done_) {
1087 os << StatusToString(result.status_);
1088 if (result.dnsrec_.dnsrec_ != nullptr) {
1089 os << " " << result.dnsrec_;
1090 } else {
1091 os << ", (no dnsrec)";
1092 }
1093 } else {
1094 os << "(incomplete)";
1095 }
1096 os << '}';
1097 return os;
1098 }
1099
QueryCallback(void * data,ares_status_t status,size_t timeouts,const ares_dns_record_t * dnsrec)1100 void QueryCallback(void *data, ares_status_t status, size_t timeouts,
1101 const ares_dns_record_t *dnsrec) {
1102 EXPECT_NE(nullptr, data);
1103 if (data == nullptr)
1104 return;
1105
1106 QueryResult* result = reinterpret_cast<QueryResult*>(data);
1107 result->done_ = true;
1108 result->status_ = status;
1109 result->timeouts_ = timeouts;
1110 if (dnsrec)
1111 result->dnsrec_.SetDnsRecord(dnsrec);
1112 if (verbose) std::cerr << "QueryCallback(" << *result << ")" << std::endl;
1113 }
1114
operator <<(std::ostream & os,const AddrInfoResult & result)1115 std::ostream& operator<<(std::ostream& os, const AddrInfoResult& result) {
1116 os << '{';
1117 if (result.done_ && result.ai_) {
1118 os << StatusToString(result.status_) << " " << result.ai_;
1119 } else {
1120 os << "(incomplete)";
1121 }
1122 os << '}';
1123 return os;
1124 }
1125
operator <<(std::ostream & os,const AddrInfo & ai)1126 std::ostream& operator<<(std::ostream& os, const AddrInfo& ai) {
1127 os << '{';
1128 if (ai == nullptr) {
1129 os << "nullptr}";
1130 return os;
1131 }
1132
1133 struct ares_addrinfo_cname *next_cname = ai->cnames;
1134 while(next_cname) {
1135 if(next_cname->alias) {
1136 os << next_cname->alias << "->";
1137 }
1138 if(next_cname->name) {
1139 os << next_cname->name;
1140 }
1141
1142 next_cname = next_cname->next;
1143
1144 if (next_cname != NULL)
1145 os << ", ";
1146 else
1147 os << " ";
1148 }
1149
1150 struct ares_addrinfo_node *next = ai->nodes;
1151 while(next) {
1152 //if(next->ai_canonname) {
1153 //os << "'" << next->ai_canonname << "' ";
1154 //}
1155 unsigned short port = 0;
1156 os << "addr=[";
1157 if(next->ai_family == AF_INET) {
1158 sockaddr_in* sin = (sockaddr_in *)((void *)next->ai_addr);
1159 port = ntohs(sin->sin_port);
1160 os << AddressToString(&sin->sin_addr, 4);
1161 }
1162 else if (next->ai_family == AF_INET6) {
1163 sockaddr_in6* sin = (sockaddr_in6*)((void *)next->ai_addr);
1164 port = ntohs(sin->sin6_port);
1165 os << "[" << AddressToString(&sin->sin6_addr, 16) << "]";
1166 }
1167 else
1168 os << "unknown family";
1169 if(port) {
1170 os << ":" << port;
1171 }
1172 os << "]";
1173 next = next->ai_next;
1174 if (next != NULL)
1175 os << ", ";
1176 }
1177 os << '}';
1178 return os;
1179 }
1180
AddrInfoCallback(void * data,int status,int timeouts,struct ares_addrinfo * ai)1181 void AddrInfoCallback(void *data, int status, int timeouts,
1182 struct ares_addrinfo *ai) {
1183 EXPECT_NE(nullptr, data);
1184 AddrInfoResult* result = reinterpret_cast<AddrInfoResult*>(data);
1185 result->done_ = true;
1186 result->status_ = status;
1187 result->timeouts_= timeouts;
1188 if (ai)
1189 result->ai_ = AddrInfo(ai);
1190 if (verbose) std::cerr << "AddrInfoCallback(" << *result << ")" << std::endl;
1191 }
1192
operator <<(std::ostream & os,const SearchResult & result)1193 std::ostream& operator<<(std::ostream& os, const SearchResult& result) {
1194 os << '{';
1195 if (result.done_) {
1196 os << StatusToString(result.status_) << " " << PacketToString(result.data_);
1197 } else {
1198 os << "(incomplete)";
1199 }
1200 os << '}';
1201 return os;
1202 }
1203
SearchCallback(void * data,int status,int timeouts,unsigned char * abuf,int alen)1204 void SearchCallback(void *data, int status, int timeouts,
1205 unsigned char *abuf, int alen) {
1206 EXPECT_NE(nullptr, data);
1207 SearchResult* result = reinterpret_cast<SearchResult*>(data);
1208 result->done_ = true;
1209 result->status_ = status;
1210 result->timeouts_ = timeouts;
1211 result->data_.assign(abuf, abuf + alen);
1212 if (verbose) std::cerr << "SearchCallback(" << *result << ")" << std::endl;
1213 }
1214
SearchCallbackDnsRec(void * data,ares_status_t status,size_t timeouts,const ares_dns_record_t * dnsrec)1215 void SearchCallbackDnsRec(void *data, ares_status_t status, size_t timeouts,
1216 const ares_dns_record_t *dnsrec) {
1217 EXPECT_NE(nullptr, data);
1218 SearchResult* result = reinterpret_cast<SearchResult*>(data);
1219 unsigned char *abuf = NULL;
1220 size_t alen = 0;
1221 result->done_ = true;
1222 result->status_ = (int)status;
1223 result->timeouts_ = (int)timeouts;
1224 if (dnsrec != NULL) {
1225 ares_dns_write(dnsrec, &abuf, &alen);
1226 }
1227 result->data_.assign(abuf, abuf + alen);
1228 ares_free_string(abuf);
1229 if (verbose) std::cerr << "SearchCallbackDnsRec(" << *result << ")" << std::endl;
1230 }
1231
operator <<(std::ostream & os,const NameInfoResult & result)1232 std::ostream& operator<<(std::ostream& os, const NameInfoResult& result) {
1233 os << '{';
1234 if (result.done_) {
1235 os << StatusToString(result.status_) << " " << result.node_ << " " << result.service_;
1236 } else {
1237 os << "(incomplete)";
1238 }
1239 os << '}';
1240 return os;
1241 }
1242
NameInfoCallback(void * data,int status,int timeouts,char * node,char * service)1243 void NameInfoCallback(void *data, int status, int timeouts,
1244 char *node, char *service) {
1245 EXPECT_NE(nullptr, data);
1246 NameInfoResult* result = reinterpret_cast<NameInfoResult*>(data);
1247 result->done_ = true;
1248 result->status_ = status;
1249 result->timeouts_ = timeouts;
1250 result->node_ = std::string(node ? node : "");
1251 result->service_ = std::string(service ? service : "");
1252 if (verbose) std::cerr << "NameInfoCallback(" << *result << ")" << std::endl;
1253 }
1254
GetNameServers(ares_channel_t * channel)1255 std::string GetNameServers(ares_channel_t *channel) {
1256 char *csv = ares_get_servers_csv(channel);
1257 EXPECT_NE((char *)NULL, csv);
1258
1259 std::string servers(csv);
1260
1261 ares_free_string(csv);
1262 return servers;
1263 }
1264
TransientDir(const std::string & dirname)1265 TransientDir::TransientDir(const std::string& dirname) : dirname_(dirname) {
1266 if (mkdir_(dirname_.c_str(), 0755) != 0) {
1267 std::cerr << "Failed to create subdirectory '" << dirname_ << "'" << std::endl;
1268 }
1269 }
1270
~TransientDir()1271 TransientDir::~TransientDir() {
1272 rmdir(dirname_.c_str());
1273 }
1274
TransientFile(const std::string & filename,const std::string & contents)1275 TransientFile::TransientFile(const std::string& filename,
1276 const std::string& contents)
1277 : filename_(filename) {
1278 FILE *f = fopen(filename.c_str(), "w");
1279 if (f == nullptr) {
1280 std::cerr << "Error: failed to create '" << filename << "'" << std::endl;
1281 return;
1282 }
1283 size_t rc = (size_t)fwrite(contents.data(), 1, contents.size(), f);
1284 if (rc != contents.size()) {
1285 std::cerr << "Error: failed to write contents of '" << filename << "'" << std::endl;
1286 }
1287 fclose(f);
1288 }
1289
~TransientFile()1290 TransientFile::~TransientFile() {
1291 unlink(filename_.c_str());
1292 }
1293
TempNam(const char * dir,const char * prefix)1294 std::string TempNam(const char *dir, const char *prefix) {
1295 char *p = tempnam(dir, prefix);
1296 std::string result(p);
1297 free(p);
1298 return result;
1299 }
1300
TempFile(const std::string & contents)1301 TempFile::TempFile(const std::string& contents)
1302 : TransientFile(TempNam(nullptr, "ares"), contents) {
1303
1304 }
1305
VirtualizeIO(ares_channel_t * c)1306 VirtualizeIO::VirtualizeIO(ares_channel_t *c)
1307 : channel_(c)
1308 {
1309 ares_set_socket_functions(channel_, &default_functions, 0);
1310 }
1311
~VirtualizeIO()1312 VirtualizeIO::~VirtualizeIO() {
1313 ares_set_socket_functions(channel_, 0, 0);
1314 }
1315
1316 } // namespace test
1317 } // namespace ares
1318