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