1 #include "ares_setup.h"
2 #include "ares.h"
3 #include "ares_nameser.h"
4 #include "ares-test.h"
5 #include "ares-test-ai.h"
6 #include "dns-proto.h"
7
8 // Include ares internal files for DNS protocol details
9 #include "ares_dns.h"
10
11 #ifdef HAVE_NETDB_H
12 #include <netdb.h>
13 #endif
14 #ifdef HAVE_NETINET_TCP_H
15 #include <netinet/tcp.h>
16 #endif
17 #include <stdio.h>
18 #include <stdlib.h>
19
20 #include <functional>
21 #include <sstream>
22
23 #ifdef WIN32
24 #define BYTE_CAST (char *)
25 #define mkdir_(d, p) mkdir(d)
26 #else
27 #define BYTE_CAST
28 #define mkdir_(d, p) mkdir(d, p)
29 #endif
30
31 namespace ares {
32 namespace test {
33
34 bool verbose = false;
35 static constexpr int dynamic_port = 0;
36 int mock_port = dynamic_port;
37
38 const std::vector<int> both_families = {AF_INET, AF_INET6};
39 const std::vector<int> ipv4_family = {AF_INET};
40 const std::vector<int> ipv6_family = {AF_INET6};
41
42 const std::vector<std::pair<int, bool>> both_families_both_modes = {
43 std::make_pair<int, bool>(AF_INET, false),
44 std::make_pair<int, bool>(AF_INET, true),
45 std::make_pair<int, bool>(AF_INET6, false),
46 std::make_pair<int, bool>(AF_INET6, true)
47 };
48 const std::vector<std::pair<int, bool>> ipv4_family_both_modes = {
49 std::make_pair<int, bool>(AF_INET, false),
50 std::make_pair<int, bool>(AF_INET, true)
51 };
52 const std::vector<std::pair<int, bool>> ipv6_family_both_modes = {
53 std::make_pair<int, bool>(AF_INET6, false),
54 std::make_pair<int, bool>(AF_INET6, true)
55 };
56
57 // Which parameters to use in tests
58 std::vector<int> families = both_families;
59 std::vector<std::pair<int, bool>> families_modes = both_families_both_modes;
60
61 unsigned long long LibraryTest::fails_ = 0;
62 std::map<size_t, int> LibraryTest::size_fails_;
63
ProcessWork(ares_channel channel,std::function<std::set<int> ()> get_extrafds,std::function<void (int)> process_extra)64 void ProcessWork(ares_channel channel,
65 std::function<std::set<int>()> get_extrafds,
66 std::function<void(int)> process_extra) {
67 int nfds, count;
68 fd_set readers, writers;
69 struct timeval tv;
70 while (true) {
71 // Retrieve the set of file descriptors that the library wants us to monitor.
72 FD_ZERO(&readers);
73 FD_ZERO(&writers);
74 nfds = ares_fds(channel, &readers, &writers);
75 if (nfds == 0) // no work left to do in the library
76 return;
77
78 // Add in the extra FDs if present.
79 std::set<int> extrafds = get_extrafds();
80 for (int extrafd : extrafds) {
81 FD_SET(extrafd, &readers);
82 if (extrafd >= nfds) {
83 nfds = extrafd + 1;
84 }
85 }
86
87 // Wait for activity or timeout.
88 tv.tv_sec = 0;
89 tv.tv_usec = 100000; // 100ms
90 count = select(nfds, &readers, &writers, nullptr, &tv);
91 if (count < 0) {
92 fprintf(stderr, "select() failed, errno %d\n", errno);
93 return;
94 }
95
96 // Let the library process any activity.
97 ares_process(channel, &readers, &writers);
98
99 // Let the provided callback process any activity on the extra FD.
100 for (int extrafd : extrafds) {
101 if (FD_ISSET(extrafd, &readers)) {
102 process_extra(extrafd);
103 }
104 }
105 }
106 }
107
108 // static
SetAllocFail(int nth)109 void LibraryTest::SetAllocFail(int nth) {
110 assert(nth > 0);
111 assert(nth <= (int)(8 * sizeof(fails_)));
112 fails_ |= (1LL << (nth - 1));
113 }
114
115 // static
SetAllocSizeFail(size_t size)116 void LibraryTest::SetAllocSizeFail(size_t size) {
117 size_fails_[size]++;
118 }
119
120 // static
ClearFails()121 void LibraryTest::ClearFails() {
122 fails_ = 0;
123 size_fails_.clear();
124 }
125
126
127 // static
ShouldAllocFail(size_t size)128 bool LibraryTest::ShouldAllocFail(size_t size) {
129 bool fail = (fails_ & 0x01);
130 fails_ >>= 1;
131 if (size_fails_[size] > 0) {
132 size_fails_[size]--;
133 fail = true;
134 }
135 return fail;
136 }
137
138 // static
amalloc(size_t size)139 void* LibraryTest::amalloc(size_t size) {
140 if (ShouldAllocFail(size) || size == 0) {
141 if (verbose) std::cerr << "Failing malloc(" << size << ") request" << std::endl;
142 return nullptr;
143 } else {
144 return malloc(size);
145 }
146 }
147
148 // static
arealloc(void * ptr,size_t size)149 void* LibraryTest::arealloc(void *ptr, size_t size) {
150 if (ShouldAllocFail(size)) {
151 if (verbose) std::cerr << "Failing realloc(" << ptr << ", " << size << ") request" << std::endl;
152 return nullptr;
153 } else {
154 return realloc(ptr, size);
155 }
156 }
157
158 // static
afree(void * ptr)159 void LibraryTest::afree(void *ptr) {
160 free(ptr);
161 }
162
NoExtraFDs()163 std::set<int> NoExtraFDs() {
164 return std::set<int>();
165 }
166
Process()167 void DefaultChannelTest::Process() {
168 ProcessWork(channel_, NoExtraFDs, nullptr);
169 }
170
Process()171 void DefaultChannelModeTest::Process() {
172 ProcessWork(channel_, NoExtraFDs, nullptr);
173 }
174
MockServer(int family,int port)175 MockServer::MockServer(int family, int port)
176 : udpport_(port), tcpport_(port), qid_(-1) {
177 // Create a TCP socket to receive data on.
178 tcpfd_ = socket(family, SOCK_STREAM, 0);
179 EXPECT_NE(-1, tcpfd_);
180 int optval = 1;
181 setsockopt(tcpfd_, SOL_SOCKET, SO_REUSEADDR,
182 BYTE_CAST &optval , sizeof(int));
183 // Send TCP data right away.
184 setsockopt(tcpfd_, IPPROTO_TCP, TCP_NODELAY,
185 BYTE_CAST &optval , sizeof(int));
186
187 // Create a UDP socket to receive data on.
188 udpfd_ = socket(family, SOCK_DGRAM, 0);
189 EXPECT_NE(-1, udpfd_);
190
191 // Bind the sockets to the given port.
192 if (family == AF_INET) {
193 struct sockaddr_in addr;
194 memset(&addr, 0, sizeof(addr));
195 addr.sin_family = AF_INET;
196 addr.sin_addr.s_addr = htonl(INADDR_ANY);
197 addr.sin_port = htons(tcpport_);
198 int tcprc = bind(tcpfd_, (struct sockaddr*)&addr, sizeof(addr));
199 EXPECT_EQ(0, tcprc) << "Failed to bind AF_INET to TCP port " << tcpport_;
200 addr.sin_port = htons(udpport_);
201 int udprc = bind(udpfd_, (struct sockaddr*)&addr, sizeof(addr));
202 EXPECT_EQ(0, udprc) << "Failed to bind AF_INET to UDP port " << udpport_;
203 // retrieve system-assigned port
204 if (udpport_ == dynamic_port) {
205 ares_socklen_t len = sizeof(addr);
206 auto result = getsockname(udpfd_, (struct sockaddr*)&addr, &len);
207 EXPECT_EQ(0, result);
208 udpport_ = ntohs(addr.sin_port);
209 EXPECT_NE(dynamic_port, udpport_);
210 }
211 if (tcpport_ == dynamic_port) {
212 ares_socklen_t len = sizeof(addr);
213 auto result = getsockname(tcpfd_, (struct sockaddr*)&addr, &len);
214 EXPECT_EQ(0, result);
215 tcpport_ = ntohs(addr.sin_port);
216 EXPECT_NE(dynamic_port, tcpport_);
217 }
218 } else {
219 EXPECT_EQ(AF_INET6, family);
220 struct sockaddr_in6 addr;
221 memset(&addr, 0, sizeof(addr));
222 addr.sin6_family = AF_INET6;
223 memset(&addr.sin6_addr, 0, sizeof(addr.sin6_addr)); // in6addr_any
224 addr.sin6_port = htons(tcpport_);
225 int tcprc = bind(tcpfd_, (struct sockaddr*)&addr, sizeof(addr));
226 EXPECT_EQ(0, tcprc) << "Failed to bind AF_INET6 to TCP port " << tcpport_;
227 addr.sin6_port = htons(udpport_);
228 int udprc = bind(udpfd_, (struct sockaddr*)&addr, sizeof(addr));
229 EXPECT_EQ(0, udprc) << "Failed to bind AF_INET6 to UDP port " << udpport_;
230 // retrieve system-assigned port
231 if (udpport_ == dynamic_port) {
232 ares_socklen_t len = sizeof(addr);
233 auto result = getsockname(udpfd_, (struct sockaddr*)&addr, &len);
234 EXPECT_EQ(0, result);
235 udpport_ = ntohs(addr.sin6_port);
236 EXPECT_NE(dynamic_port, udpport_);
237 }
238 if (tcpport_ == dynamic_port) {
239 ares_socklen_t len = sizeof(addr);
240 auto result = getsockname(tcpfd_, (struct sockaddr*)&addr, &len);
241 EXPECT_EQ(0, result);
242 tcpport_ = ntohs(addr.sin6_port);
243 EXPECT_NE(dynamic_port, tcpport_);
244 }
245 }
246 if (verbose) std::cerr << "Configured "
247 << (family == AF_INET ? "IPv4" : "IPv6")
248 << " mock server with TCP socket " << tcpfd_
249 << " on port " << tcpport_
250 << " and UDP socket " << udpfd_
251 << " on port " << udpport_ << std::endl;
252
253 // For TCP, also need to listen for connections.
254 EXPECT_EQ(0, listen(tcpfd_, 5)) << "Failed to listen for TCP connections";
255 }
256
~MockServer()257 MockServer::~MockServer() {
258 for (int fd : connfds_) {
259 sclose(fd);
260 }
261 sclose(tcpfd_);
262 sclose(udpfd_);
263 }
264
ProcessPacket(int fd,struct sockaddr_storage * addr,socklen_t addrlen,byte * data,int len)265 void MockServer::ProcessPacket(int fd, struct sockaddr_storage *addr, socklen_t addrlen,
266 byte *data, int len) {
267
268 // Assume the packet is a well-formed DNS request and extract the request
269 // details.
270 if (len < NS_HFIXEDSZ) {
271 std::cerr << "Packet too short (" << len << ")" << std::endl;
272 return;
273 }
274 int qid = DNS_HEADER_QID(data);
275 if (DNS_HEADER_QR(data) != 0) {
276 std::cerr << "Not a request" << std::endl;
277 return;
278 }
279 if (DNS_HEADER_OPCODE(data) != O_QUERY) {
280 std::cerr << "Not a query (opcode " << DNS_HEADER_OPCODE(data)
281 << ")" << std::endl;
282 return;
283 }
284 if (DNS_HEADER_QDCOUNT(data) != 1) {
285 std::cerr << "Unexpected question count (" << DNS_HEADER_QDCOUNT(data)
286 << ")" << std::endl;
287 return;
288 }
289 byte* question = data + 12;
290 int qlen = len - 12;
291
292 char *name = nullptr;
293 long enclen;
294 ares_expand_name(question, data, len, &name, &enclen);
295 if (!name) {
296 std::cerr << "Failed to retrieve name" << std::endl;
297 return;
298 }
299 qlen -= enclen;
300 question += enclen;
301 std::string namestr(name);
302 ares_free_string(name);
303
304 if (qlen < 4) {
305 std::cerr << "Unexpected question size (" << qlen
306 << " bytes after name)" << std::endl;
307 return;
308 }
309 if (DNS_QUESTION_CLASS(question) != C_IN) {
310 std::cerr << "Unexpected question class (" << DNS_QUESTION_CLASS(question)
311 << ")" << std::endl;
312 return;
313 }
314 int rrtype = DNS_QUESTION_TYPE(question);
315
316 if (verbose) {
317 std::vector<byte> req(data, data + len);
318 std::cerr << "received " << (fd == udpfd_ ? "UDP" : "TCP") << " request " << PacketToString(req)
319 << " on port " << (fd == udpfd_ ? udpport_ : tcpport_) << std::endl;
320 std::cerr << "ProcessRequest(" << qid << ", '" << namestr
321 << "', " << RRTypeToString(rrtype) << ")" << std::endl;
322 }
323 ProcessRequest(fd, addr, addrlen, qid, namestr, rrtype);
324
325 }
326
ProcessFD(int fd)327 void MockServer::ProcessFD(int fd) {
328 if (fd != tcpfd_ && fd != udpfd_ && connfds_.find(fd) == connfds_.end()) {
329 // Not one of our FDs.
330 return;
331 }
332 if (fd == tcpfd_) {
333 int connfd = accept(tcpfd_, NULL, NULL);
334 if (connfd < 0) {
335 std::cerr << "Error accepting connection on fd " << fd << std::endl;
336 } else {
337 connfds_.insert(connfd);
338 }
339 return;
340 }
341
342 // Activity on a data-bearing file descriptor.
343 struct sockaddr_storage addr;
344 socklen_t addrlen = sizeof(addr);
345 byte buffer[2048];
346 int len = recvfrom(fd, BYTE_CAST buffer, sizeof(buffer), 0,
347 (struct sockaddr *)&addr, &addrlen);
348 byte* data = buffer;
349
350 if (fd != udpfd_) {
351 if (len == 0) {
352 connfds_.erase(std::find(connfds_.begin(), connfds_.end(), fd));
353 sclose(fd);
354 return;
355 }
356 if (len < 2) {
357 std::cerr << "Packet too short (" << len << ")" << std::endl;
358 return;
359 }
360 /* TCP might aggregate the various requests into a single packet, so we
361 * need to split */
362 while (len) {
363 int tcplen = (data[0] << 8) + data[1];
364 data += 2;
365 len -= 2;
366 if (tcplen > len) {
367 std::cerr << "Warning: TCP length " << tcplen
368 << " doesn't match remaining data length " << len << std::endl;
369 }
370 int process_len = (tcplen > len)?len:tcplen;
371 ProcessPacket(fd, &addr, addrlen, data, process_len);
372 len -= process_len;
373 data += process_len;
374 }
375 } else {
376 /* UDP is always a single packet */
377 ProcessPacket(fd, &addr, addrlen, data, len);
378 }
379
380 }
381
fds() const382 std::set<int> MockServer::fds() const {
383 std::set<int> result = connfds_;
384 result.insert(tcpfd_);
385 result.insert(udpfd_);
386 return result;
387 }
388
ProcessRequest(int fd,struct sockaddr_storage * addr,int addrlen,int qid,const std::string & name,int rrtype)389 void MockServer::ProcessRequest(int fd, struct sockaddr_storage* addr, int addrlen,
390 int qid, const std::string& name, int rrtype) {
391 // Before processing, let gMock know the request is happening.
392 OnRequest(name, rrtype);
393
394 if (reply_.size() == 0) {
395 return;
396 }
397
398 // Make a local copy of the current pending reply.
399 std::vector<byte> reply = reply_;
400
401 if (qid_ >= 0) {
402 // Use the explicitly specified query ID.
403 qid = qid_;
404 }
405 if (reply.size() >= 2) {
406 // Overwrite the query ID if space to do so.
407 reply[0] = (byte)((qid >> 8) & 0xff);
408 reply[1] = (byte)(qid & 0xff);
409 }
410 if (verbose) std::cerr << "sending reply " << PacketToString(reply)
411 << " on port " << ((fd == udpfd_) ? udpport_ : tcpport_) << std::endl;
412
413 // Prefix with 2-byte length if TCP.
414 if (fd != udpfd_) {
415 int len = reply.size();
416 std::vector<byte> vlen = {(byte)((len & 0xFF00) >> 8), (byte)(len & 0xFF)};
417 reply.insert(reply.begin(), vlen.begin(), vlen.end());
418 // Also, don't bother with the destination address.
419 addr = nullptr;
420 addrlen = 0;
421 }
422
423 int rc = sendto(fd, BYTE_CAST reply.data(), reply.size(), 0,
424 (struct sockaddr *)addr, addrlen);
425 if (rc < static_cast<int>(reply.size())) {
426 std::cerr << "Failed to send full reply, rc=" << rc << std::endl;
427 }
428 }
429
430 // static
BuildServers(int count,int family,int base_port)431 MockChannelOptsTest::NiceMockServers MockChannelOptsTest::BuildServers(int count, int family, int base_port) {
432 NiceMockServers servers;
433 assert(count > 0);
434 for (int ii = 0; ii < count; ii++) {
435 int port = base_port == dynamic_port ? dynamic_port : base_port + ii;
436 std::unique_ptr<NiceMockServer> server(new NiceMockServer(family, port));
437 servers.push_back(std::move(server));
438 }
439 return servers;
440 }
441
MockChannelOptsTest(int count,int family,bool force_tcp,struct ares_options * givenopts,int optmask)442 MockChannelOptsTest::MockChannelOptsTest(int count,
443 int family,
444 bool force_tcp,
445 struct ares_options* givenopts,
446 int optmask)
447 : servers_(BuildServers(count, family, mock_port)),
448 server_(*servers_[0].get()), channel_(nullptr) {
449 // Set up channel options.
450 struct ares_options opts;
451 if (givenopts) {
452 memcpy(&opts, givenopts, sizeof(opts));
453 } else {
454 memset(&opts, 0, sizeof(opts));
455 }
456
457 // Point the library at the first mock server by default (overridden below).
458 opts.udp_port = server_.udpport();
459 optmask |= ARES_OPT_UDP_PORT;
460 opts.tcp_port = server_.tcpport();
461 optmask |= ARES_OPT_TCP_PORT;
462
463 // If not already overridden, set short-ish timeouts.
464 if (!(optmask & (ARES_OPT_TIMEOUTMS|ARES_OPT_TIMEOUT))) {
465 opts.timeout = 1500;
466 optmask |= ARES_OPT_TIMEOUTMS;
467 }
468 // If not already overridden, set 3 retries.
469 if (!(optmask & ARES_OPT_TRIES)) {
470 opts.tries = 3;
471 optmask |= ARES_OPT_TRIES;
472 }
473 // If not already overridden, set search domains.
474 const char *domains[3] = {"first.com", "second.org", "third.gov"};
475 if (!(optmask & ARES_OPT_DOMAINS)) {
476 opts.ndomains = 3;
477 opts.domains = (char**)domains;
478 optmask |= ARES_OPT_DOMAINS;
479 }
480 if (force_tcp) {
481 opts.flags |= ARES_FLAG_USEVC;
482 optmask |= ARES_OPT_FLAGS;
483 }
484
485 EXPECT_EQ(ARES_SUCCESS, ares_init_options(&channel_, &opts, optmask));
486 EXPECT_NE(nullptr, channel_);
487
488 // Set up servers after construction so we can set individual ports
489 struct ares_addr_port_node* prev = nullptr;
490 struct ares_addr_port_node* first = nullptr;
491 for (const auto& server : servers_) {
492 struct ares_addr_port_node* node = (struct ares_addr_port_node*)malloc(sizeof(*node));
493 if (prev) {
494 prev->next = node;
495 } else {
496 first = node;
497 }
498 node->next = nullptr;
499 node->family = family;
500 node->udp_port = server->udpport();
501 node->tcp_port = server->tcpport();
502 if (family == AF_INET) {
503 node->addr.addr4.s_addr = htonl(0x7F000001);
504 } else {
505 memset(&node->addr.addr6, 0, sizeof(node->addr.addr6));
506 node->addr.addr6._S6_un._S6_u8[15] = 1;
507 }
508 prev = node;
509 }
510 EXPECT_EQ(ARES_SUCCESS, ares_set_servers_ports(channel_, first));
511
512 while (first) {
513 prev = first;
514 first = first->next;
515 free(prev);
516 }
517 if (verbose) {
518 std::cerr << "Configured library with servers:";
519 std::vector<std::string> servers = GetNameServers(channel_);
520 for (const auto& server : servers) {
521 std::cerr << " " << server;
522 }
523 std::cerr << std::endl;
524 }
525 }
526
~MockChannelOptsTest()527 MockChannelOptsTest::~MockChannelOptsTest() {
528 if (channel_) {
529 ares_destroy(channel_);
530 }
531 channel_ = nullptr;
532 }
533
fds() const534 std::set<int> MockChannelOptsTest::fds() const {
535 std::set<int> fds;
536 for (const auto& server : servers_) {
537 std::set<int> serverfds = server->fds();
538 fds.insert(serverfds.begin(), serverfds.end());
539 }
540 return fds;
541 }
542
ProcessFD(int fd)543 void MockChannelOptsTest::ProcessFD(int fd) {
544 for (auto& server : servers_) {
545 server->ProcessFD(fd);
546 }
547 }
548
Process()549 void MockChannelOptsTest::Process() {
550 using namespace std::placeholders;
551 ProcessWork(channel_,
552 std::bind(&MockChannelOptsTest::fds, this),
553 std::bind(&MockChannelOptsTest::ProcessFD, this, _1));
554 }
555
operator <<(std::ostream & os,const HostResult & result)556 std::ostream& operator<<(std::ostream& os, const HostResult& result) {
557 os << '{';
558 if (result.done_) {
559 os << StatusToString(result.status_);
560 if (result.host_.addrtype_ != -1) {
561 os << " " << result.host_;
562 } else {
563 os << ", (no hostent)";
564 }
565 } else {
566 os << "(incomplete)";
567 }
568 os << '}';
569 return os;
570 }
571
HostEnt(const struct hostent * hostent)572 HostEnt::HostEnt(const struct hostent *hostent) : addrtype_(-1) {
573 if (!hostent)
574 return;
575
576 if (hostent->h_name)
577 name_ = hostent->h_name;
578
579 if (hostent->h_aliases) {
580 char** palias = hostent->h_aliases;
581 while (*palias != nullptr) {
582 aliases_.push_back(*palias);
583 palias++;
584 }
585 }
586
587 addrtype_ = hostent->h_addrtype;
588
589 if (hostent->h_addr_list) {
590 char** paddr = hostent->h_addr_list;
591 while (*paddr != nullptr) {
592 std::string addr = AddressToString(*paddr, hostent->h_length);
593 addrs_.push_back(addr);
594 paddr++;
595 }
596 }
597 }
598
operator <<(std::ostream & os,const HostEnt & host)599 std::ostream& operator<<(std::ostream& os, const HostEnt& host) {
600 os << "{'";
601 if (host.name_.length() > 0) {
602 os << host.name_;
603 }
604 os << "' aliases=[";
605 for (size_t ii = 0; ii < host.aliases_.size(); ii++) {
606 if (ii > 0) os << ", ";
607 os << host.aliases_[ii];
608 }
609 os << "] ";
610 os << "addrs=[";
611 for (size_t ii = 0; ii < host.addrs_.size(); ii++) {
612 if (ii > 0) os << ", ";
613 os << host.addrs_[ii];
614 }
615 os << "]";
616 os << '}';
617 return os;
618 }
619
HostCallback(void * data,int status,int timeouts,struct hostent * hostent)620 void HostCallback(void *data, int status, int timeouts,
621 struct hostent *hostent) {
622 EXPECT_NE(nullptr, data);
623 if (data == nullptr)
624 return;
625
626 HostResult* result = reinterpret_cast<HostResult*>(data);
627 result->done_ = true;
628 result->status_ = status;
629 result->timeouts_ = timeouts;
630 if (hostent)
631 result->host_ = HostEnt(hostent);
632 if (verbose) std::cerr << "HostCallback(" << *result << ")" << std::endl;
633 }
634
operator <<(std::ostream & os,const AddrInfoResult & result)635 std::ostream& operator<<(std::ostream& os, const AddrInfoResult& result) {
636 os << '{';
637 if (result.done_ && result.ai_) {
638 os << StatusToString(result.status_) << " " << result.ai_;
639 } else {
640 os << "(incomplete)";
641 }
642 os << '}';
643 return os;
644 }
645
operator <<(std::ostream & os,const AddrInfo & ai)646 std::ostream& operator<<(std::ostream& os, const AddrInfo& ai) {
647 os << '{';
648 if (ai == nullptr) {
649 os << "nullptr}";
650 return os;
651 }
652
653 struct ares_addrinfo_cname *next_cname = ai->cnames;
654 while(next_cname) {
655 if(next_cname->alias) {
656 os << next_cname->alias << "->";
657 }
658 if(next_cname->name) {
659 os << next_cname->name;
660 }
661 if((next_cname = next_cname->next))
662 os << ", ";
663 else
664 os << " ";
665 }
666
667 struct ares_addrinfo_node *next = ai->nodes;
668 while(next) {
669 //if(next->ai_canonname) {
670 //os << "'" << next->ai_canonname << "' ";
671 //}
672 unsigned short port = 0;
673 os << "addr=[";
674 if(next->ai_family == AF_INET) {
675 sockaddr_in* sin = (sockaddr_in*)next->ai_addr;
676 port = ntohs(sin->sin_port);
677 os << AddressToString(&sin->sin_addr, 4);
678 }
679 else if (next->ai_family == AF_INET6) {
680 sockaddr_in6* sin = (sockaddr_in6*)next->ai_addr;
681 port = ntohs(sin->sin6_port);
682 os << "[" << AddressToString(&sin->sin6_addr, 16) << "]";
683 }
684 else
685 os << "unknown family";
686 if(port) {
687 os << ":" << port;
688 }
689 os << "]";
690 if((next = next->ai_next))
691 os << ", ";
692 }
693 os << '}';
694 return os;
695 }
696
AddrInfoCallback(void * data,int status,int timeouts,struct ares_addrinfo * ai)697 void AddrInfoCallback(void *data, int status, int timeouts,
698 struct ares_addrinfo *ai) {
699 EXPECT_NE(nullptr, data);
700 AddrInfoResult* result = reinterpret_cast<AddrInfoResult*>(data);
701 result->done_ = true;
702 result->status_ = status;
703 result->timeouts_= timeouts;
704 result->ai_ = AddrInfo(ai);
705 if (verbose) std::cerr << "AddrInfoCallback(" << *result << ")" << std::endl;
706 }
707
operator <<(std::ostream & os,const SearchResult & result)708 std::ostream& operator<<(std::ostream& os, const SearchResult& result) {
709 os << '{';
710 if (result.done_) {
711 os << StatusToString(result.status_) << " " << PacketToString(result.data_);
712 } else {
713 os << "(incomplete)";
714 }
715 os << '}';
716 return os;
717 }
718
SearchCallback(void * data,int status,int timeouts,unsigned char * abuf,int alen)719 void SearchCallback(void *data, int status, int timeouts,
720 unsigned char *abuf, int alen) {
721 EXPECT_NE(nullptr, data);
722 SearchResult* result = reinterpret_cast<SearchResult*>(data);
723 result->done_ = true;
724 result->status_ = status;
725 result->timeouts_ = timeouts;
726 result->data_.assign(abuf, abuf + alen);
727 if (verbose) std::cerr << "SearchCallback(" << *result << ")" << std::endl;
728 }
729
operator <<(std::ostream & os,const NameInfoResult & result)730 std::ostream& operator<<(std::ostream& os, const NameInfoResult& result) {
731 os << '{';
732 if (result.done_) {
733 os << StatusToString(result.status_) << " " << result.node_ << " " << result.service_;
734 } else {
735 os << "(incomplete)";
736 }
737 os << '}';
738 return os;
739 }
740
NameInfoCallback(void * data,int status,int timeouts,char * node,char * service)741 void NameInfoCallback(void *data, int status, int timeouts,
742 char *node, char *service) {
743 EXPECT_NE(nullptr, data);
744 NameInfoResult* result = reinterpret_cast<NameInfoResult*>(data);
745 result->done_ = true;
746 result->status_ = status;
747 result->timeouts_ = timeouts;
748 result->node_ = std::string(node ? node : "");
749 result->service_ = std::string(service ? service : "");
750 if (verbose) std::cerr << "NameInfoCallback(" << *result << ")" << std::endl;
751 }
752
GetNameServers(ares_channel channel)753 std::vector<std::string> GetNameServers(ares_channel channel) {
754 struct ares_addr_port_node* servers = nullptr;
755 EXPECT_EQ(ARES_SUCCESS, ares_get_servers_ports(channel, &servers));
756 struct ares_addr_port_node* server = servers;
757 std::vector<std::string> results;
758 while (server) {
759 std::stringstream ss;
760 switch (server->family) {
761 case AF_INET:
762 ss << AddressToString((char*)&server->addr.addr4, 4);
763 break;
764 case AF_INET6:
765 if (server->udp_port != 0) {
766 ss << '[';
767 }
768 ss << AddressToString((char*)&server->addr.addr6, 16);
769 if (server->udp_port != 0) {
770 ss << ']';
771 }
772 break;
773 default:
774 results.push_back("<unknown family>");
775 break;
776 }
777 if (server->udp_port != 0) {
778 ss << ":" << server->udp_port;
779 }
780 results.push_back(ss.str());
781 server = server->next;
782 }
783 if (servers) ares_free_data(servers);
784 return results;
785 }
786
TransientDir(const std::string & dirname)787 TransientDir::TransientDir(const std::string& dirname) : dirname_(dirname) {
788 if (mkdir_(dirname_.c_str(), 0755) != 0) {
789 std::cerr << "Failed to create subdirectory '" << dirname_ << "'" << std::endl;
790 }
791 }
792
~TransientDir()793 TransientDir::~TransientDir() {
794 rmdir(dirname_.c_str());
795 }
796
TransientFile(const std::string & filename,const std::string & contents)797 TransientFile::TransientFile(const std::string& filename,
798 const std::string& contents)
799 : filename_(filename) {
800 FILE *f = fopen(filename.c_str(), "w");
801 if (f == nullptr) {
802 std::cerr << "Error: failed to create '" << filename << "'" << std::endl;
803 return;
804 }
805 int rc = fwrite(contents.data(), 1, contents.size(), f);
806 if (rc != (int)contents.size()) {
807 std::cerr << "Error: failed to write contents of '" << filename << "'" << std::endl;
808 }
809 fclose(f);
810 }
811
~TransientFile()812 TransientFile::~TransientFile() {
813 unlink(filename_.c_str());
814 }
815
TempNam(const char * dir,const char * prefix)816 std::string TempNam(const char *dir, const char *prefix) {
817 char *p = tempnam(dir, prefix);
818 std::string result(p);
819 free(p);
820 return result;
821 }
822
TempFile(const std::string & contents)823 TempFile::TempFile(const std::string& contents)
824 : TransientFile(TempNam(nullptr, "ares"), contents) {
825
826 }
827
VirtualizeIO(ares_channel c)828 VirtualizeIO::VirtualizeIO(ares_channel c)
829 : channel_(c)
830 {
831 ares_set_socket_functions(channel_, &default_functions, 0);
832 }
833
~VirtualizeIO()834 VirtualizeIO::~VirtualizeIO() {
835 ares_set_socket_functions(channel_, 0, 0);
836 }
837
838 } // namespace test
839 } // namespace ares
840