• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright Joyent, Inc. and other Node contributors.
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a
4 // copy of this software and associated documentation files (the
5 // "Software"), to deal in the Software without restriction, including
6 // without limitation the rights to use, copy, modify, merge, publish,
7 // distribute, sublicense, and/or sell copies of the Software, and to permit
8 // persons to whom the Software is furnished to do so, subject to the
9 // following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included
12 // in all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17 // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18 // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 // USE OR OTHER DEALINGS IN THE SOFTWARE.
21 
22 #define CARES_STATICLIB
23 #include "ares.h"
24 #include "async_wrap-inl.h"
25 #include "env-inl.h"
26 #include "memory_tracker-inl.h"
27 #include "node.h"
28 #include "req_wrap-inl.h"
29 #include "util-inl.h"
30 #include "uv.h"
31 
32 #include <cerrno>
33 #include <cstring>
34 #include <memory>
35 #include <vector>
36 #include <unordered_set>
37 
38 #ifdef __POSIX__
39 # include <netdb.h>
40 #endif  // __POSIX__
41 
42 #if defined(__ANDROID__) || \
43     defined(__MINGW32__) || \
44     defined(__OpenBSD__) || \
45     defined(_MSC_VER)
46 
47 # include <nameser.h>
48 #else
49 # include <arpa/nameser.h>
50 #endif
51 
52 #if defined(__OpenBSD__)
53 # define AI_V4MAPPED 0
54 #endif
55 
56 namespace node {
57 namespace cares_wrap {
58 
59 using v8::Array;
60 using v8::Context;
61 using v8::EscapableHandleScope;
62 using v8::FunctionCallbackInfo;
63 using v8::FunctionTemplate;
64 using v8::HandleScope;
65 using v8::Int32;
66 using v8::Integer;
67 using v8::Isolate;
68 using v8::Local;
69 using v8::NewStringType;
70 using v8::Null;
71 using v8::Object;
72 using v8::String;
73 using v8::Value;
74 
75 namespace {
76 
77 Mutex ares_library_mutex;
78 
cares_get_16bit(const unsigned char * p)79 inline uint16_t cares_get_16bit(const unsigned char* p) {
80   return static_cast<uint32_t>(p[0] << 8U) | (static_cast<uint32_t>(p[1]));
81 }
82 
cares_get_32bit(const unsigned char * p)83 inline uint32_t cares_get_32bit(const unsigned char* p) {
84   return static_cast<uint32_t>(p[0] << 24U) |
85          static_cast<uint32_t>(p[1] << 16U) |
86          static_cast<uint32_t>(p[2] << 8U) |
87          static_cast<uint32_t>(p[3]);
88 }
89 
90 const int ns_t_cname_or_a = -1;
91 
92 #define DNS_ESETSRVPENDING -1000
ToErrorCodeString(int status)93 inline const char* ToErrorCodeString(int status) {
94   switch (status) {
95 #define V(code) case ARES_##code: return #code;
96     V(EADDRGETNETWORKPARAMS)
97     V(EBADFAMILY)
98     V(EBADFLAGS)
99     V(EBADHINTS)
100     V(EBADNAME)
101     V(EBADQUERY)
102     V(EBADRESP)
103     V(EBADSTR)
104     V(ECANCELLED)
105     V(ECONNREFUSED)
106     V(EDESTRUCTION)
107     V(EFILE)
108     V(EFORMERR)
109     V(ELOADIPHLPAPI)
110     V(ENODATA)
111     V(ENOMEM)
112     V(ENONAME)
113     V(ENOTFOUND)
114     V(ENOTIMP)
115     V(ENOTINITIALIZED)
116     V(EOF)
117     V(EREFUSED)
118     V(ESERVFAIL)
119     V(ETIMEOUT)
120 #undef V
121   }
122 
123   return "UNKNOWN_ARES_ERROR";
124 }
125 
126 class ChannelWrap;
127 
128 struct node_ares_task : public MemoryRetainer {
129   ChannelWrap* channel;
130   ares_socket_t sock;
131   uv_poll_t poll_watcher;
132 
133   inline void MemoryInfo(MemoryTracker* tracker) const override;
134   SET_MEMORY_INFO_NAME(node_ares_task)
135   SET_SELF_SIZE(node_ares_task)
136 };
137 
138 struct TaskHash {
operator ()node::cares_wrap::__anon75d25ba00111::TaskHash139   size_t operator()(node_ares_task* a) const {
140     return std::hash<ares_socket_t>()(a->sock);
141   }
142 };
143 
144 struct TaskEqual {
operator ()node::cares_wrap::__anon75d25ba00111::TaskEqual145   inline bool operator()(node_ares_task* a, node_ares_task* b) const {
146     return a->sock == b->sock;
147   }
148 };
149 
150 using node_ares_task_list =
151     std::unordered_set<node_ares_task*, TaskHash, TaskEqual>;
152 
153 class ChannelWrap : public AsyncWrap {
154  public:
155   ChannelWrap(Environment* env, Local<Object> object, int timeout);
156   ~ChannelWrap() override;
157 
158   static void New(const FunctionCallbackInfo<Value>& args);
159 
160   void Setup();
161   void EnsureServers();
162   void StartTimer();
163   void CloseTimer();
164 
165   void ModifyActivityQueryCount(int count);
166 
timer_handle()167   inline uv_timer_t* timer_handle() { return timer_handle_; }
cares_channel()168   inline ares_channel cares_channel() { return channel_; }
set_query_last_ok(bool ok)169   inline void set_query_last_ok(bool ok) { query_last_ok_ = ok; }
set_is_servers_default(bool is_default)170   inline void set_is_servers_default(bool is_default) {
171     is_servers_default_ = is_default;
172   }
active_query_count()173   inline int active_query_count() { return active_query_count_; }
task_list()174   inline node_ares_task_list* task_list() { return &task_list_; }
175 
MemoryInfo(MemoryTracker * tracker) const176   void MemoryInfo(MemoryTracker* tracker) const override {
177     if (timer_handle_ != nullptr)
178       tracker->TrackField("timer_handle", *timer_handle_);
179     tracker->TrackField("task_list", task_list_, "node_ares_task_list");
180   }
181 
182   SET_MEMORY_INFO_NAME(ChannelWrap)
183   SET_SELF_SIZE(ChannelWrap)
184 
185   static void AresTimeout(uv_timer_t* handle);
186 
187  private:
188   uv_timer_t* timer_handle_;
189   ares_channel channel_;
190   bool query_last_ok_;
191   bool is_servers_default_;
192   bool library_inited_;
193   int timeout_;
194   int active_query_count_;
195   node_ares_task_list task_list_;
196 };
197 
ChannelWrap(Environment * env,Local<Object> object,int timeout)198 ChannelWrap::ChannelWrap(Environment* env,
199                          Local<Object> object,
200                          int timeout)
201   : AsyncWrap(env, object, PROVIDER_DNSCHANNEL),
202     timer_handle_(nullptr),
203     channel_(nullptr),
204     query_last_ok_(true),
205     is_servers_default_(true),
206     library_inited_(false),
207     timeout_(timeout),
208     active_query_count_(0) {
209   MakeWeak();
210 
211   Setup();
212 }
213 
New(const FunctionCallbackInfo<Value> & args)214 void ChannelWrap::New(const FunctionCallbackInfo<Value>& args) {
215   CHECK(args.IsConstructCall());
216   CHECK_EQ(args.Length(), 1);
217   CHECK(args[0]->IsInt32());
218   const int timeout = args[0].As<Int32>()->Value();
219   Environment* env = Environment::GetCurrent(args);
220   new ChannelWrap(env, args.This(), timeout);
221 }
222 
223 class GetAddrInfoReqWrap : public ReqWrap<uv_getaddrinfo_t> {
224  public:
225   GetAddrInfoReqWrap(Environment* env,
226                      Local<Object> req_wrap_obj,
227                      bool verbatim);
228 
229   SET_NO_MEMORY_INFO()
SET_MEMORY_INFO_NAME(GetAddrInfoReqWrap)230   SET_MEMORY_INFO_NAME(GetAddrInfoReqWrap)
231   SET_SELF_SIZE(GetAddrInfoReqWrap)
232 
233   bool verbatim() const { return verbatim_; }
234 
235  private:
236   const bool verbatim_;
237 };
238 
GetAddrInfoReqWrap(Environment * env,Local<Object> req_wrap_obj,bool verbatim)239 GetAddrInfoReqWrap::GetAddrInfoReqWrap(Environment* env,
240                                        Local<Object> req_wrap_obj,
241                                        bool verbatim)
242     : ReqWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_GETADDRINFOREQWRAP)
243     , verbatim_(verbatim) {
244 }
245 
246 
247 class GetNameInfoReqWrap : public ReqWrap<uv_getnameinfo_t> {
248  public:
249   GetNameInfoReqWrap(Environment* env, Local<Object> req_wrap_obj);
250 
251   SET_NO_MEMORY_INFO()
252   SET_MEMORY_INFO_NAME(GetNameInfoReqWrap)
253   SET_SELF_SIZE(GetNameInfoReqWrap)
254 };
255 
GetNameInfoReqWrap(Environment * env,Local<Object> req_wrap_obj)256 GetNameInfoReqWrap::GetNameInfoReqWrap(Environment* env,
257                                        Local<Object> req_wrap_obj)
258     : ReqWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_GETNAMEINFOREQWRAP) {
259 }
260 
261 
262 /* This is called once per second by loop->timer. It is used to constantly */
263 /* call back into c-ares for possibly processing timeouts. */
AresTimeout(uv_timer_t * handle)264 void ChannelWrap::AresTimeout(uv_timer_t* handle) {
265   ChannelWrap* channel = static_cast<ChannelWrap*>(handle->data);
266   CHECK_EQ(channel->timer_handle(), handle);
267   CHECK_EQ(false, channel->task_list()->empty());
268   ares_process_fd(channel->cares_channel(), ARES_SOCKET_BAD, ARES_SOCKET_BAD);
269 }
270 
271 
ares_poll_cb(uv_poll_t * watcher,int status,int events)272 void ares_poll_cb(uv_poll_t* watcher, int status, int events) {
273   node_ares_task* task = ContainerOf(&node_ares_task::poll_watcher, watcher);
274   ChannelWrap* channel = task->channel;
275 
276   /* Reset the idle timer */
277   uv_timer_again(channel->timer_handle());
278 
279   if (status < 0) {
280     /* An error happened. Just pretend that the socket is both readable and */
281     /* writable. */
282     ares_process_fd(channel->cares_channel(), task->sock, task->sock);
283     return;
284   }
285 
286   /* Process DNS responses */
287   ares_process_fd(channel->cares_channel(),
288                   events & UV_READABLE ? task->sock : ARES_SOCKET_BAD,
289                   events & UV_WRITABLE ? task->sock : ARES_SOCKET_BAD);
290 }
291 
292 
ares_poll_close_cb(uv_poll_t * watcher)293 void ares_poll_close_cb(uv_poll_t* watcher) {
294   node_ares_task* task = ContainerOf(&node_ares_task::poll_watcher, watcher);
295   delete task;
296 }
297 
MemoryInfo(MemoryTracker * tracker) const298 void node_ares_task::MemoryInfo(MemoryTracker* tracker) const {
299   tracker->TrackField("channel", channel);
300 }
301 
302 /* Allocates and returns a new node_ares_task */
ares_task_create(ChannelWrap * channel,ares_socket_t sock)303 node_ares_task* ares_task_create(ChannelWrap* channel, ares_socket_t sock) {
304   auto task = new node_ares_task();
305 
306   task->channel = channel;
307   task->sock = sock;
308 
309   if (uv_poll_init_socket(channel->env()->event_loop(),
310                           &task->poll_watcher, sock) < 0) {
311     /* This should never happen. */
312     delete task;
313     return nullptr;
314   }
315 
316   return task;
317 }
318 
319 
320 /* Callback from ares when socket operation is started */
ares_sockstate_cb(void * data,ares_socket_t sock,int read,int write)321 void ares_sockstate_cb(void* data,
322                        ares_socket_t sock,
323                        int read,
324                        int write) {
325   ChannelWrap* channel = static_cast<ChannelWrap*>(data);
326   node_ares_task* task;
327 
328   node_ares_task lookup_task;
329   lookup_task.sock = sock;
330   auto it = channel->task_list()->find(&lookup_task);
331 
332   task = (it == channel->task_list()->end()) ? nullptr : *it;
333 
334   if (read || write) {
335     if (!task) {
336       /* New socket */
337       channel->StartTimer();
338 
339       task = ares_task_create(channel, sock);
340       if (task == nullptr) {
341         /* This should never happen unless we're out of memory or something */
342         /* is seriously wrong. The socket won't be polled, but the query will */
343         /* eventually time out. */
344         return;
345       }
346 
347       channel->task_list()->insert(task);
348     }
349 
350     /* This should never fail. If it fails anyway, the query will eventually */
351     /* time out. */
352     uv_poll_start(&task->poll_watcher,
353                   (read ? UV_READABLE : 0) | (write ? UV_WRITABLE : 0),
354                   ares_poll_cb);
355 
356   } else {
357     /* read == 0 and write == 0 this is c-ares's way of notifying us that */
358     /* the socket is now closed. We must free the data associated with */
359     /* socket. */
360     CHECK(task &&
361           "When an ares socket is closed we should have a handle for it");
362 
363     channel->task_list()->erase(it);
364     channel->env()->CloseHandle(&task->poll_watcher, ares_poll_close_cb);
365 
366     if (channel->task_list()->empty()) {
367       channel->CloseTimer();
368     }
369   }
370 }
371 
372 
HostentToNames(Environment * env,struct hostent * host,Local<Array> append_to=Local<Array> ())373 Local<Array> HostentToNames(Environment* env,
374                             struct hostent* host,
375                             Local<Array> append_to = Local<Array>()) {
376   EscapableHandleScope scope(env->isolate());
377   auto context = env->context();
378   bool append = !append_to.IsEmpty();
379   Local<Array> names = append ? append_to : Array::New(env->isolate());
380   size_t offset = names->Length();
381 
382   for (uint32_t i = 0; host->h_aliases[i] != nullptr; ++i) {
383     Local<String> address = OneByteString(env->isolate(), host->h_aliases[i]);
384     names->Set(context, i + offset, address).Check();
385   }
386 
387   return append ? names : scope.Escape(names);
388 }
389 
safe_free_hostent(struct hostent * host)390 void safe_free_hostent(struct hostent* host) {
391   int idx;
392 
393   if (host->h_addr_list != nullptr) {
394     idx = 0;
395     while (host->h_addr_list[idx]) {
396       free(host->h_addr_list[idx++]);
397     }
398     free(host->h_addr_list);
399     host->h_addr_list = nullptr;
400   }
401 
402   if (host->h_aliases != nullptr) {
403     idx = 0;
404     while (host->h_aliases[idx]) {
405       free(host->h_aliases[idx++]);
406     }
407     free(host->h_aliases);
408     host->h_aliases = nullptr;
409   }
410 
411   free(host->h_name);
412   free(host);
413 }
414 
cares_wrap_hostent_cpy(struct hostent * dest,const struct hostent * src)415 void cares_wrap_hostent_cpy(struct hostent* dest, const struct hostent* src) {
416   dest->h_addr_list = nullptr;
417   dest->h_addrtype = 0;
418   dest->h_aliases = nullptr;
419   dest->h_length = 0;
420   dest->h_name = nullptr;
421 
422   /* copy `h_name` */
423   size_t name_size = strlen(src->h_name) + 1;
424   dest->h_name = node::Malloc<char>(name_size);
425   memcpy(dest->h_name, src->h_name, name_size);
426 
427   /* copy `h_aliases` */
428   size_t alias_count;
429   for (alias_count = 0;
430       src->h_aliases[alias_count] != nullptr;
431       alias_count++) {
432   }
433 
434   dest->h_aliases = node::Malloc<char*>(alias_count + 1);
435   for (size_t i = 0; i < alias_count; i++) {
436     const size_t cur_alias_size = strlen(src->h_aliases[i]) + 1;
437     dest->h_aliases[i] = node::Malloc(cur_alias_size);
438     memcpy(dest->h_aliases[i], src->h_aliases[i], cur_alias_size);
439   }
440   dest->h_aliases[alias_count] = nullptr;
441 
442   /* copy `h_addr_list` */
443   size_t list_count;
444   for (list_count = 0;
445       src->h_addr_list[list_count] != nullptr;
446       list_count++) {
447   }
448 
449   dest->h_addr_list = node::Malloc<char*>(list_count + 1);
450   for (size_t i = 0; i < list_count; i++) {
451     dest->h_addr_list[i] = node::Malloc(src->h_length);
452     memcpy(dest->h_addr_list[i], src->h_addr_list[i], src->h_length);
453   }
454   dest->h_addr_list[list_count] = nullptr;
455 
456   /* work after work */
457   dest->h_length = src->h_length;
458   dest->h_addrtype = src->h_addrtype;
459 }
460 
461 class QueryWrap;
462 
Setup()463 void ChannelWrap::Setup() {
464   struct ares_options options;
465   memset(&options, 0, sizeof(options));
466   options.flags = ARES_FLAG_NOCHECKRESP;
467   options.sock_state_cb = ares_sockstate_cb;
468   options.sock_state_cb_data = this;
469   options.timeout = timeout_;
470 
471   int r;
472   if (!library_inited_) {
473     Mutex::ScopedLock lock(ares_library_mutex);
474     // Multiple calls to ares_library_init() increase a reference counter,
475     // so this is a no-op except for the first call to it.
476     r = ares_library_init(ARES_LIB_INIT_ALL);
477     if (r != ARES_SUCCESS)
478       return env()->ThrowError(ToErrorCodeString(r));
479   }
480 
481   /* We do the call to ares_init_option for caller. */
482   const int optmask =
483       ARES_OPT_FLAGS | ARES_OPT_TIMEOUTMS | ARES_OPT_SOCK_STATE_CB;
484   r = ares_init_options(&channel_, &options, optmask);
485 
486   if (r != ARES_SUCCESS) {
487     Mutex::ScopedLock lock(ares_library_mutex);
488     ares_library_cleanup();
489     return env()->ThrowError(ToErrorCodeString(r));
490   }
491 
492   library_inited_ = true;
493 }
494 
StartTimer()495 void ChannelWrap::StartTimer() {
496   if (timer_handle_ == nullptr) {
497     timer_handle_ = new uv_timer_t();
498     timer_handle_->data = static_cast<void*>(this);
499     uv_timer_init(env()->event_loop(), timer_handle_);
500   } else if (uv_is_active(reinterpret_cast<uv_handle_t*>(timer_handle_))) {
501     return;
502   }
503   int timeout = timeout_;
504   if (timeout == 0) timeout = 1;
505   if (timeout < 0 || timeout > 1000) timeout = 1000;
506   uv_timer_start(timer_handle_, AresTimeout, timeout, timeout);
507 }
508 
CloseTimer()509 void ChannelWrap::CloseTimer() {
510   if (timer_handle_ == nullptr)
511     return;
512 
513   env()->CloseHandle(timer_handle_, [](uv_timer_t* handle) { delete handle; });
514   timer_handle_ = nullptr;
515 }
516 
~ChannelWrap()517 ChannelWrap::~ChannelWrap() {
518   ares_destroy(channel_);
519 
520   if (library_inited_) {
521     Mutex::ScopedLock lock(ares_library_mutex);
522     // This decreases the reference counter increased by ares_library_init().
523     ares_library_cleanup();
524   }
525 
526   CloseTimer();
527 }
528 
529 
ModifyActivityQueryCount(int count)530 void ChannelWrap::ModifyActivityQueryCount(int count) {
531   active_query_count_ += count;
532   CHECK_GE(active_query_count_, 0);
533 }
534 
535 
536 /**
537  * This function is to check whether current servers are fallback servers
538  * when cares initialized.
539  *
540  * The fallback servers of cares is [ "127.0.0.1" ] with no user additional
541  * setting.
542  */
EnsureServers()543 void ChannelWrap::EnsureServers() {
544   /* if last query is OK or servers are set by user self, do not check */
545   if (query_last_ok_ || !is_servers_default_) {
546     return;
547   }
548 
549   ares_addr_port_node* servers = nullptr;
550 
551   ares_get_servers_ports(channel_, &servers);
552 
553   /* if no server or multi-servers, ignore */
554   if (servers == nullptr) return;
555   if (servers->next != nullptr) {
556     ares_free_data(servers);
557     is_servers_default_ = false;
558     return;
559   }
560 
561   /* if the only server is not 127.0.0.1, ignore */
562   if (servers[0].family != AF_INET ||
563       servers[0].addr.addr4.s_addr != htonl(INADDR_LOOPBACK) ||
564       servers[0].tcp_port != 0 ||
565       servers[0].udp_port != 0) {
566     ares_free_data(servers);
567     is_servers_default_ = false;
568     return;
569   }
570 
571   ares_free_data(servers);
572   servers = nullptr;
573 
574   /* destroy channel and reset channel */
575   ares_destroy(channel_);
576 
577   CloseTimer();
578   Setup();
579 }
580 
581 
582 class QueryWrap : public AsyncWrap {
583  public:
QueryWrap(ChannelWrap * channel,Local<Object> req_wrap_obj,const char * name)584   QueryWrap(ChannelWrap* channel, Local<Object> req_wrap_obj, const char* name)
585       : AsyncWrap(channel->env(), req_wrap_obj, AsyncWrap::PROVIDER_QUERYWRAP),
586         channel_(channel),
587         trace_name_(name) {
588   }
589 
~QueryWrap()590   ~QueryWrap() override {
591     CHECK_EQ(false, persistent().IsEmpty());
592 
593     // Let Callback() know that this object no longer exists.
594     if (callback_ptr_ != nullptr)
595       *callback_ptr_ = nullptr;
596   }
597 
598   // Subclasses should implement the appropriate Send method.
Send(const char * name)599   virtual int Send(const char* name) {
600     UNREACHABLE();
601     return 0;
602   }
603 
Send(const char * name,int family)604   virtual int Send(const char* name, int family) {
605     UNREACHABLE();
606     return 0;
607   }
608 
609  protected:
AresQuery(const char * name,int dnsclass,int type)610   void AresQuery(const char* name,
611                  int dnsclass,
612                  int type) {
613     channel_->EnsureServers();
614     TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(
615       TRACING_CATEGORY_NODE2(dns, native), trace_name_, this,
616       "name", TRACE_STR_COPY(name));
617     ares_query(channel_->cares_channel(), name, dnsclass, type, Callback,
618                MakeCallbackPointer());
619   }
620 
621   struct ResponseData {
622     int status;
623     bool is_host;
624     DeleteFnPtr<hostent, safe_free_hostent> host;
625     MallocedBuffer<unsigned char> buf;
626   };
627 
AfterResponse()628   void AfterResponse() {
629     CHECK(response_data_);
630 
631     const int status = response_data_->status;
632 
633     if (status != ARES_SUCCESS) {
634       ParseError(status);
635     } else if (!response_data_->is_host) {
636       Parse(response_data_->buf.data, response_data_->buf.size);
637     } else {
638       Parse(response_data_->host.get());
639     }
640   }
641 
MakeCallbackPointer()642   void* MakeCallbackPointer() {
643     CHECK_NULL(callback_ptr_);
644     callback_ptr_ = new QueryWrap*(this);
645     return callback_ptr_;
646   }
647 
FromCallbackPointer(void * arg)648   static QueryWrap* FromCallbackPointer(void* arg) {
649     std::unique_ptr<QueryWrap*> wrap_ptr { static_cast<QueryWrap**>(arg) };
650     QueryWrap* wrap = *wrap_ptr.get();
651     if (wrap == nullptr) return nullptr;
652     wrap->callback_ptr_ = nullptr;
653     return wrap;
654   }
655 
Callback(void * arg,int status,int timeouts,unsigned char * answer_buf,int answer_len)656   static void Callback(void* arg, int status, int timeouts,
657                        unsigned char* answer_buf, int answer_len) {
658     QueryWrap* wrap = FromCallbackPointer(arg);
659     if (wrap == nullptr) return;
660 
661     unsigned char* buf_copy = nullptr;
662     if (status == ARES_SUCCESS) {
663       buf_copy = node::Malloc<unsigned char>(answer_len);
664       memcpy(buf_copy, answer_buf, answer_len);
665     }
666 
667     wrap->response_data_ = std::make_unique<ResponseData>();
668     ResponseData* data = wrap->response_data_.get();
669     data->status = status;
670     data->is_host = false;
671     data->buf = MallocedBuffer<unsigned char>(buf_copy, answer_len);
672 
673     wrap->QueueResponseCallback(status);
674   }
675 
Callback(void * arg,int status,int timeouts,struct hostent * host)676   static void Callback(void* arg, int status, int timeouts,
677                        struct hostent* host) {
678     QueryWrap* wrap = FromCallbackPointer(arg);
679     if (wrap == nullptr) return;
680 
681     struct hostent* host_copy = nullptr;
682     if (status == ARES_SUCCESS) {
683       host_copy = node::Malloc<hostent>(1);
684       cares_wrap_hostent_cpy(host_copy, host);
685     }
686 
687     wrap->response_data_ = std::make_unique<ResponseData>();
688     ResponseData* data = wrap->response_data_.get();
689     data->status = status;
690     data->host.reset(host_copy);
691     data->is_host = true;
692 
693     wrap->QueueResponseCallback(status);
694   }
695 
QueueResponseCallback(int status)696   void QueueResponseCallback(int status) {
697     BaseObjectPtr<QueryWrap> strong_ref{this};
698     env()->SetImmediate([this, strong_ref](Environment*) {
699       AfterResponse();
700 
701       // Delete once strong_ref goes out of scope.
702       Detach();
703     });
704 
705     channel_->set_query_last_ok(status != ARES_ECONNREFUSED);
706     channel_->ModifyActivityQueryCount(-1);
707   }
708 
CallOnComplete(Local<Value> answer,Local<Value> extra=Local<Value> ())709   void CallOnComplete(Local<Value> answer,
710                       Local<Value> extra = Local<Value>()) {
711     HandleScope handle_scope(env()->isolate());
712     Context::Scope context_scope(env()->context());
713     Local<Value> argv[] = {
714       Integer::New(env()->isolate(), 0),
715       answer,
716       extra
717     };
718     const int argc = arraysize(argv) - extra.IsEmpty();
719     TRACE_EVENT_NESTABLE_ASYNC_END0(
720         TRACING_CATEGORY_NODE2(dns, native), trace_name_, this);
721 
722     MakeCallback(env()->oncomplete_string(), argc, argv);
723   }
724 
ParseError(int status)725   void ParseError(int status) {
726     CHECK_NE(status, ARES_SUCCESS);
727     HandleScope handle_scope(env()->isolate());
728     Context::Scope context_scope(env()->context());
729     const char* code = ToErrorCodeString(status);
730     Local<Value> arg = OneByteString(env()->isolate(), code);
731     TRACE_EVENT_NESTABLE_ASYNC_END1(
732         TRACING_CATEGORY_NODE2(dns, native), trace_name_, this,
733         "error", status);
734     MakeCallback(env()->oncomplete_string(), 1, &arg);
735   }
736 
737   // Subclasses should implement the appropriate Parse method.
Parse(unsigned char * buf,int len)738   virtual void Parse(unsigned char* buf, int len) {
739     UNREACHABLE();
740   }
741 
Parse(struct hostent * host)742   virtual void Parse(struct hostent* host) {
743     UNREACHABLE();
744   }
745 
746   BaseObjectPtr<ChannelWrap> channel_;
747 
748  private:
749   std::unique_ptr<ResponseData> response_data_;
750   const char* trace_name_;
751   // Pointer to pointer to 'this' that can be reset from the destructor,
752   // in order to let Callback() know that 'this' no longer exists.
753   QueryWrap** callback_ptr_ = nullptr;
754 };
755 
756 
757 template <typename T>
AddrTTLToArray(Environment * env,const T * addrttls,size_t naddrttls)758 Local<Array> AddrTTLToArray(Environment* env,
759                             const T* addrttls,
760                             size_t naddrttls) {
761   auto isolate = env->isolate();
762 
763   MaybeStackBuffer<Local<Value>, 8> ttls(naddrttls);
764   for (size_t i = 0; i < naddrttls; i++)
765     ttls[i] = Integer::NewFromUnsigned(isolate, addrttls[i].ttl);
766 
767   return Array::New(isolate, ttls.out(), naddrttls);
768 }
769 
770 
ParseGeneralReply(Environment * env,const unsigned char * buf,int len,int * type,Local<Array> ret,void * addrttls=nullptr,int * naddrttls=nullptr)771 int ParseGeneralReply(Environment* env,
772                       const unsigned char* buf,
773                       int len,
774                       int* type,
775                       Local<Array> ret,
776                       void* addrttls = nullptr,
777                       int* naddrttls = nullptr) {
778   HandleScope handle_scope(env->isolate());
779   auto context = env->context();
780   hostent* host;
781 
782   int status;
783   switch (*type) {
784     case ns_t_a:
785     case ns_t_cname:
786     case ns_t_cname_or_a:
787       status = ares_parse_a_reply(buf,
788                                   len,
789                                   &host,
790                                   static_cast<ares_addrttl*>(addrttls),
791                                   naddrttls);
792       break;
793     case ns_t_aaaa:
794       status = ares_parse_aaaa_reply(buf,
795                                      len,
796                                      &host,
797                                      static_cast<ares_addr6ttl*>(addrttls),
798                                      naddrttls);
799       break;
800     case ns_t_ns:
801       status = ares_parse_ns_reply(buf, len, &host);
802       break;
803     case ns_t_ptr:
804       status = ares_parse_ptr_reply(buf, len, nullptr, 0, AF_INET, &host);
805       break;
806     default:
807       CHECK(0 && "Bad NS type");
808       break;
809   }
810 
811   if (status != ARES_SUCCESS)
812     return status;
813 
814   /* If it's `CNAME`, return the CNAME value;
815    * And if it's `CNAME_OR_A` and it has value in `h_name` and `h_aliases[0]`,
816    * we consider it's a CNAME record, otherwise we consider it's an A record. */
817   if ((*type == ns_t_cname_or_a && host->h_name && host->h_aliases[0]) ||
818       *type == ns_t_cname) {
819     // A cname lookup always returns a single record but we follow the
820     // common API here.
821     *type = ns_t_cname;
822     ret->Set(context,
823              ret->Length(),
824              OneByteString(env->isolate(), host->h_name)).Check();
825     ares_free_hostent(host);
826     return ARES_SUCCESS;
827   }
828 
829   if (*type == ns_t_cname_or_a)
830     *type = ns_t_a;
831 
832   if (*type == ns_t_ns) {
833     HostentToNames(env, host, ret);
834   } else if (*type == ns_t_ptr) {
835     uint32_t offset = ret->Length();
836     for (uint32_t i = 0; host->h_aliases[i] != nullptr; i++) {
837       auto alias = OneByteString(env->isolate(), host->h_aliases[i]);
838       ret->Set(context, i + offset, alias).Check();
839     }
840   } else {
841     uint32_t offset = ret->Length();
842     char ip[INET6_ADDRSTRLEN];
843     for (uint32_t i = 0; host->h_addr_list[i] != nullptr; ++i) {
844       uv_inet_ntop(host->h_addrtype, host->h_addr_list[i], ip, sizeof(ip));
845       auto address = OneByteString(env->isolate(), ip);
846       ret->Set(context, i + offset, address).Check();
847     }
848   }
849 
850   ares_free_hostent(host);
851 
852   return ARES_SUCCESS;
853 }
854 
855 
ParseMxReply(Environment * env,const unsigned char * buf,int len,Local<Array> ret,bool need_type=false)856 int ParseMxReply(Environment* env,
857                  const unsigned char* buf,
858                  int len,
859                  Local<Array> ret,
860                  bool need_type = false) {
861   HandleScope handle_scope(env->isolate());
862   auto context = env->context();
863 
864   struct ares_mx_reply* mx_start;
865   int status = ares_parse_mx_reply(buf, len, &mx_start);
866   if (status != ARES_SUCCESS) {
867     return status;
868   }
869 
870   uint32_t offset = ret->Length();
871   ares_mx_reply* current = mx_start;
872   for (uint32_t i = 0; current != nullptr; ++i, current = current->next) {
873     Local<Object> mx_record = Object::New(env->isolate());
874     mx_record->Set(context,
875                    env->exchange_string(),
876                    OneByteString(env->isolate(), current->host)).Check();
877     mx_record->Set(context,
878                    env->priority_string(),
879                    Integer::New(env->isolate(), current->priority)).Check();
880     if (need_type)
881       mx_record->Set(context,
882                      env->type_string(),
883                      env->dns_mx_string()).Check();
884 
885     ret->Set(context, i + offset, mx_record).Check();
886   }
887 
888   ares_free_data(mx_start);
889   return ARES_SUCCESS;
890 }
891 
ParseTxtReply(Environment * env,const unsigned char * buf,int len,Local<Array> ret,bool need_type=false)892 int ParseTxtReply(Environment* env,
893                   const unsigned char* buf,
894                   int len,
895                   Local<Array> ret,
896                   bool need_type = false) {
897   HandleScope handle_scope(env->isolate());
898   auto context = env->context();
899 
900   struct ares_txt_ext* txt_out;
901 
902   int status = ares_parse_txt_reply_ext(buf, len, &txt_out);
903   if (status != ARES_SUCCESS) {
904     return status;
905   }
906 
907   Local<Array> txt_chunk;
908 
909   struct ares_txt_ext* current = txt_out;
910   uint32_t i = 0, j;
911   uint32_t offset = ret->Length();
912   for (j = 0; current != nullptr; current = current->next) {
913     Local<String> txt =
914         OneByteString(env->isolate(), current->txt, current->length);
915 
916     // New record found - write out the current chunk
917     if (current->record_start) {
918       if (!txt_chunk.IsEmpty()) {
919         if (need_type) {
920           Local<Object> elem = Object::New(env->isolate());
921           elem->Set(context, env->entries_string(), txt_chunk).Check();
922           elem->Set(context,
923                     env->type_string(),
924                     env->dns_txt_string()).Check();
925           ret->Set(context, offset + i++, elem).Check();
926         } else {
927           ret->Set(context, offset + i++, txt_chunk).Check();
928         }
929       }
930 
931       txt_chunk = Array::New(env->isolate());
932       j = 0;
933     }
934 
935     txt_chunk->Set(context, j++, txt).Check();
936   }
937 
938   // Push last chunk if it isn't empty
939   if (!txt_chunk.IsEmpty()) {
940     if (need_type) {
941       Local<Object> elem = Object::New(env->isolate());
942       elem->Set(context, env->entries_string(), txt_chunk).Check();
943       elem->Set(context,
944                 env->type_string(),
945                 env->dns_txt_string()).Check();
946       ret->Set(context, offset + i, elem).Check();
947     } else {
948       ret->Set(context, offset + i, txt_chunk).Check();
949     }
950   }
951 
952   ares_free_data(txt_out);
953   return ARES_SUCCESS;
954 }
955 
956 
ParseSrvReply(Environment * env,const unsigned char * buf,int len,Local<Array> ret,bool need_type=false)957 int ParseSrvReply(Environment* env,
958                   const unsigned char* buf,
959                   int len,
960                   Local<Array> ret,
961                   bool need_type = false) {
962   HandleScope handle_scope(env->isolate());
963   auto context = env->context();
964 
965   struct ares_srv_reply* srv_start;
966   int status = ares_parse_srv_reply(buf, len, &srv_start);
967   if (status != ARES_SUCCESS) {
968     return status;
969   }
970 
971   ares_srv_reply* current = srv_start;
972   int offset = ret->Length();
973   for (uint32_t i = 0; current != nullptr; ++i, current = current->next) {
974     Local<Object> srv_record = Object::New(env->isolate());
975     srv_record->Set(context,
976                     env->name_string(),
977                     OneByteString(env->isolate(), current->host)).Check();
978     srv_record->Set(context,
979                     env->port_string(),
980                     Integer::New(env->isolate(), current->port)).Check();
981     srv_record->Set(context,
982                     env->priority_string(),
983                     Integer::New(env->isolate(), current->priority)).Check();
984     srv_record->Set(context,
985                     env->weight_string(),
986                     Integer::New(env->isolate(), current->weight)).Check();
987     if (need_type)
988       srv_record->Set(context,
989                       env->type_string(),
990                       env->dns_srv_string()).Check();
991 
992     ret->Set(context, i + offset, srv_record).Check();
993   }
994 
995   ares_free_data(srv_start);
996   return ARES_SUCCESS;
997 }
998 
999 
ParseNaptrReply(Environment * env,const unsigned char * buf,int len,Local<Array> ret,bool need_type=false)1000 int ParseNaptrReply(Environment* env,
1001                     const unsigned char* buf,
1002                     int len,
1003                     Local<Array> ret,
1004                     bool need_type = false) {
1005   HandleScope handle_scope(env->isolate());
1006   auto context = env->context();
1007 
1008   ares_naptr_reply* naptr_start;
1009   int status = ares_parse_naptr_reply(buf, len, &naptr_start);
1010 
1011   if (status != ARES_SUCCESS) {
1012     return status;
1013   }
1014 
1015   ares_naptr_reply* current = naptr_start;
1016   int offset = ret->Length();
1017   for (uint32_t i = 0; current != nullptr; ++i, current = current->next) {
1018     Local<Object> naptr_record = Object::New(env->isolate());
1019     naptr_record->Set(context,
1020                       env->flags_string(),
1021                       OneByteString(env->isolate(), current->flags)).Check();
1022     naptr_record->Set(context,
1023                       env->service_string(),
1024                       OneByteString(env->isolate(),
1025                                     current->service)).Check();
1026     naptr_record->Set(context,
1027                       env->regexp_string(),
1028                       OneByteString(env->isolate(),
1029                                     current->regexp)).Check();
1030     naptr_record->Set(context,
1031                       env->replacement_string(),
1032                       OneByteString(env->isolate(),
1033                                     current->replacement)).Check();
1034     naptr_record->Set(context,
1035                       env->order_string(),
1036                       Integer::New(env->isolate(), current->order)).Check();
1037     naptr_record->Set(context,
1038                       env->preference_string(),
1039                       Integer::New(env->isolate(),
1040                                    current->preference)).Check();
1041     if (need_type)
1042       naptr_record->Set(context,
1043                         env->type_string(),
1044                         env->dns_naptr_string()).Check();
1045 
1046     ret->Set(context, i + offset, naptr_record).Check();
1047   }
1048 
1049   ares_free_data(naptr_start);
1050   return ARES_SUCCESS;
1051 }
1052 
1053 
ParseSoaReply(Environment * env,unsigned char * buf,int len,Local<Object> * ret)1054 int ParseSoaReply(Environment* env,
1055                   unsigned char* buf,
1056                   int len,
1057                   Local<Object>* ret) {
1058   EscapableHandleScope handle_scope(env->isolate());
1059   auto context = env->context();
1060 
1061   // Manage memory using standardard smart pointer std::unique_tr
1062   struct AresDeleter {
1063     void operator()(char* ptr) const noexcept { ares_free_string(ptr); }
1064   };
1065   using ares_unique_ptr = std::unique_ptr<char[], AresDeleter>;
1066 
1067   // Can't use ares_parse_soa_reply() here which can only parse single record
1068   const unsigned int ancount = cares_get_16bit(buf + 6);
1069   unsigned char* ptr = buf + NS_HFIXEDSZ;
1070   char* name_temp = nullptr;
1071   long temp_len;  // NOLINT(runtime/int)
1072   int status = ares_expand_name(ptr, buf, len, &name_temp, &temp_len);
1073   if (status != ARES_SUCCESS) {
1074     // returns EBADRESP in case of invalid input
1075     return status == ARES_EBADNAME ? ARES_EBADRESP : status;
1076   }
1077 
1078   const ares_unique_ptr name(name_temp);
1079 
1080   if (ptr + temp_len + NS_QFIXEDSZ > buf + len) {
1081     return ARES_EBADRESP;
1082   }
1083   ptr += temp_len + NS_QFIXEDSZ;
1084 
1085   for (unsigned int i = 0; i < ancount; i++) {
1086     char* rr_name_temp = nullptr;
1087     long rr_temp_len;  // NOLINT(runtime/int)
1088     int status2 = ares_expand_name(ptr, buf, len, &rr_name_temp, &rr_temp_len);
1089 
1090     if (status2 != ARES_SUCCESS)
1091       return status2 == ARES_EBADNAME ? ARES_EBADRESP : status2;
1092 
1093     const ares_unique_ptr rr_name(rr_name_temp);
1094 
1095     ptr += rr_temp_len;
1096     if (ptr + NS_RRFIXEDSZ > buf + len) {
1097       return ARES_EBADRESP;
1098     }
1099 
1100     const int rr_type = cares_get_16bit(ptr);
1101     const int rr_len = cares_get_16bit(ptr + 8);
1102     ptr += NS_RRFIXEDSZ;
1103 
1104     // only need SOA
1105     if (rr_type == ns_t_soa) {
1106       char* nsname_temp = nullptr;
1107       long nsname_temp_len;  // NOLINT(runtime/int)
1108 
1109       int status3 = ares_expand_name(ptr, buf, len,
1110                                      &nsname_temp,
1111                                      &nsname_temp_len);
1112       if (status3 != ARES_SUCCESS) {
1113         return status3 == ARES_EBADNAME ? ARES_EBADRESP : status3;
1114       }
1115       const ares_unique_ptr nsname(nsname_temp);
1116       ptr += nsname_temp_len;
1117 
1118       char* hostmaster_temp = nullptr;
1119       long hostmaster_temp_len;  // NOLINT(runtime/int)
1120       int status4 = ares_expand_name(ptr, buf, len,
1121                                      &hostmaster_temp,
1122                                      &hostmaster_temp_len);
1123       if (status4 != ARES_SUCCESS) {
1124         return status4 == ARES_EBADNAME ? ARES_EBADRESP : status4;
1125       }
1126       const ares_unique_ptr hostmaster(hostmaster_temp);
1127       ptr += hostmaster_temp_len;
1128 
1129       if (ptr + 5 * 4 > buf + len) {
1130         return ARES_EBADRESP;
1131       }
1132 
1133       const unsigned int serial = cares_get_32bit(ptr + 0 * 4);
1134       const unsigned int refresh = cares_get_32bit(ptr + 1 * 4);
1135       const unsigned int retry = cares_get_32bit(ptr + 2 * 4);
1136       const unsigned int expire = cares_get_32bit(ptr + 3 * 4);
1137       const unsigned int minttl = cares_get_32bit(ptr + 4 * 4);
1138 
1139       Local<Object> soa_record = Object::New(env->isolate());
1140       soa_record->Set(context,
1141                       env->nsname_string(),
1142                       OneByteString(env->isolate(), nsname.get())).Check();
1143       soa_record->Set(context,
1144                       env->hostmaster_string(),
1145                       OneByteString(env->isolate(),
1146                                     hostmaster.get())).Check();
1147       soa_record->Set(context,
1148                       env->serial_string(),
1149                       Integer::NewFromUnsigned(env->isolate(), serial)).Check();
1150       soa_record->Set(context,
1151                       env->refresh_string(),
1152                       Integer::New(env->isolate(), refresh)).Check();
1153       soa_record->Set(context,
1154                       env->retry_string(),
1155                       Integer::New(env->isolate(), retry)).Check();
1156       soa_record->Set(context,
1157                       env->expire_string(),
1158                       Integer::New(env->isolate(), expire)).Check();
1159       soa_record->Set(context,
1160                       env->minttl_string(),
1161                       Integer::NewFromUnsigned(env->isolate(), minttl)).Check();
1162       soa_record->Set(context,
1163                       env->type_string(),
1164                       env->dns_soa_string()).Check();
1165 
1166 
1167       *ret = handle_scope.Escape(soa_record);
1168       break;
1169     }
1170 
1171     ptr += rr_len;
1172   }
1173 
1174   return ARES_SUCCESS;
1175 }
1176 
1177 
1178 class QueryAnyWrap: public QueryWrap {
1179  public:
QueryAnyWrap(ChannelWrap * channel,Local<Object> req_wrap_obj)1180   QueryAnyWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1181     : QueryWrap(channel, req_wrap_obj, "resolveAny") {
1182   }
1183 
Send(const char * name)1184   int Send(const char* name) override {
1185     AresQuery(name, ns_c_in, ns_t_any);
1186     return 0;
1187   }
1188 
1189   SET_NO_MEMORY_INFO()
1190   SET_MEMORY_INFO_NAME(QueryAnyWrap)
1191   SET_SELF_SIZE(QueryAnyWrap)
1192 
1193  protected:
Parse(unsigned char * buf,int len)1194   void Parse(unsigned char* buf, int len) override {
1195     HandleScope handle_scope(env()->isolate());
1196     auto context = env()->context();
1197     Context::Scope context_scope(context);
1198 
1199     Local<Array> ret = Array::New(env()->isolate());
1200     int type, status, old_count;
1201 
1202     /* Parse A records or CNAME records */
1203     ares_addrttl addrttls[256];
1204     int naddrttls = arraysize(addrttls);
1205 
1206     type = ns_t_cname_or_a;
1207     status = ParseGeneralReply(env(),
1208                                buf,
1209                                len,
1210                                &type,
1211                                ret,
1212                                addrttls,
1213                                &naddrttls);
1214     uint32_t a_count = ret->Length();
1215     if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1216       ParseError(status);
1217       return;
1218     }
1219 
1220     if (type == ns_t_a) {
1221       CHECK_EQ(static_cast<uint32_t>(naddrttls), a_count);
1222       for (uint32_t i = 0; i < a_count; i++) {
1223         Local<Object> obj = Object::New(env()->isolate());
1224         obj->Set(context,
1225                  env()->address_string(),
1226                  ret->Get(context, i).ToLocalChecked()).Check();
1227         obj->Set(context,
1228                  env()->ttl_string(),
1229                  Integer::NewFromUnsigned(
1230                    env()->isolate(), addrttls[i].ttl)).Check();
1231         obj->Set(context,
1232                  env()->type_string(),
1233                  env()->dns_a_string()).Check();
1234         ret->Set(context, i, obj).Check();
1235       }
1236     } else {
1237       for (uint32_t i = 0; i < a_count; i++) {
1238         Local<Object> obj = Object::New(env()->isolate());
1239         obj->Set(context,
1240                  env()->value_string(),
1241                  ret->Get(context, i).ToLocalChecked()).Check();
1242         obj->Set(context,
1243                  env()->type_string(),
1244                  env()->dns_cname_string()).Check();
1245         ret->Set(context, i, obj).Check();
1246       }
1247     }
1248 
1249     /* Parse AAAA records */
1250     ares_addr6ttl addr6ttls[256];
1251     int naddr6ttls = arraysize(addr6ttls);
1252 
1253     type = ns_t_aaaa;
1254     status = ParseGeneralReply(env(),
1255                                buf,
1256                                len,
1257                                &type,
1258                                ret,
1259                                addr6ttls,
1260                                &naddr6ttls);
1261     uint32_t aaaa_count = ret->Length() - a_count;
1262     if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1263       ParseError(status);
1264       return;
1265     }
1266 
1267     CHECK_EQ(aaaa_count, static_cast<uint32_t>(naddr6ttls));
1268     CHECK_EQ(ret->Length(), a_count + aaaa_count);
1269     for (uint32_t i = a_count; i < ret->Length(); i++) {
1270       Local<Object> obj = Object::New(env()->isolate());
1271       obj->Set(context,
1272                env()->address_string(),
1273                ret->Get(context, i).ToLocalChecked()).Check();
1274       obj->Set(context,
1275                env()->ttl_string(),
1276                Integer::NewFromUnsigned(
1277                  env()->isolate(), addr6ttls[i - a_count].ttl)).Check();
1278       obj->Set(context,
1279                env()->type_string(),
1280                env()->dns_aaaa_string()).Check();
1281       ret->Set(context, i, obj).Check();
1282     }
1283 
1284     /* Parse MX records */
1285     status = ParseMxReply(env(), buf, len, ret, true);
1286     if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1287       ParseError(status);
1288       return;
1289     }
1290 
1291     /* Parse NS records */
1292     type = ns_t_ns;
1293     old_count = ret->Length();
1294     status = ParseGeneralReply(env(), buf, len, &type, ret);
1295     if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1296       ParseError(status);
1297       return;
1298     }
1299     for (uint32_t i = old_count; i < ret->Length(); i++) {
1300       Local<Object> obj = Object::New(env()->isolate());
1301       obj->Set(context,
1302                env()->value_string(),
1303                ret->Get(context, i).ToLocalChecked()).Check();
1304       obj->Set(context,
1305                env()->type_string(),
1306                env()->dns_ns_string()).Check();
1307       ret->Set(context, i, obj).Check();
1308     }
1309 
1310     /* Parse TXT records */
1311     status = ParseTxtReply(env(), buf, len, ret, true);
1312     if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1313       ParseError(status);
1314       return;
1315     }
1316 
1317     /* Parse SRV records */
1318     status = ParseSrvReply(env(), buf, len, ret, true);
1319     if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1320       return;
1321     }
1322 
1323     /* Parse PTR records */
1324     type = ns_t_ptr;
1325     old_count = ret->Length();
1326     status = ParseGeneralReply(env(), buf, len, &type, ret);
1327     for (uint32_t i = old_count; i < ret->Length(); i++) {
1328       Local<Object> obj = Object::New(env()->isolate());
1329       obj->Set(context,
1330                env()->value_string(),
1331                ret->Get(context, i).ToLocalChecked()).Check();
1332       obj->Set(context,
1333                env()->type_string(),
1334                env()->dns_ptr_string()).Check();
1335       ret->Set(context, i, obj).Check();
1336     }
1337 
1338     /* Parse NAPTR records */
1339     status = ParseNaptrReply(env(), buf, len, ret, true);
1340     if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1341       ParseError(status);
1342       return;
1343     }
1344 
1345     /* Parse SOA records */
1346     Local<Object> soa_record = Local<Object>();
1347     status = ParseSoaReply(env(), buf, len, &soa_record);
1348     if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1349       ParseError(status);
1350       return;
1351     }
1352     if (!soa_record.IsEmpty())
1353       ret->Set(context, ret->Length(), soa_record).Check();
1354 
1355     CallOnComplete(ret);
1356   }
1357 };
1358 
1359 
1360 class QueryAWrap: public QueryWrap {
1361  public:
QueryAWrap(ChannelWrap * channel,Local<Object> req_wrap_obj)1362   QueryAWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1363       : QueryWrap(channel, req_wrap_obj, "resolve4") {
1364   }
1365 
Send(const char * name)1366   int Send(const char* name) override {
1367     AresQuery(name, ns_c_in, ns_t_a);
1368     return 0;
1369   }
1370 
1371   SET_NO_MEMORY_INFO()
1372   SET_MEMORY_INFO_NAME(QueryAWrap)
1373   SET_SELF_SIZE(QueryAWrap)
1374 
1375  protected:
Parse(unsigned char * buf,int len)1376   void Parse(unsigned char* buf, int len) override {
1377     HandleScope handle_scope(env()->isolate());
1378     Context::Scope context_scope(env()->context());
1379 
1380     ares_addrttl addrttls[256];
1381     int naddrttls = arraysize(addrttls), status;
1382     Local<Array> ret = Array::New(env()->isolate());
1383 
1384     int type = ns_t_a;
1385     status = ParseGeneralReply(env(),
1386                                buf,
1387                                len,
1388                                &type,
1389                                ret,
1390                                addrttls,
1391                                &naddrttls);
1392     if (status != ARES_SUCCESS) {
1393       ParseError(status);
1394       return;
1395     }
1396 
1397     Local<Array> ttls = AddrTTLToArray<ares_addrttl>(env(),
1398                                                      addrttls,
1399                                                      naddrttls);
1400 
1401     CallOnComplete(ret, ttls);
1402   }
1403 };
1404 
1405 
1406 class QueryAaaaWrap: public QueryWrap {
1407  public:
QueryAaaaWrap(ChannelWrap * channel,Local<Object> req_wrap_obj)1408   QueryAaaaWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1409       : QueryWrap(channel, req_wrap_obj, "resolve6") {
1410   }
1411 
Send(const char * name)1412   int Send(const char* name) override {
1413     AresQuery(name, ns_c_in, ns_t_aaaa);
1414     return 0;
1415   }
1416 
1417   SET_NO_MEMORY_INFO()
1418   SET_MEMORY_INFO_NAME(QueryAaaaWrap)
1419   SET_SELF_SIZE(QueryAaaaWrap)
1420 
1421  protected:
Parse(unsigned char * buf,int len)1422   void Parse(unsigned char* buf, int len) override {
1423     HandleScope handle_scope(env()->isolate());
1424     Context::Scope context_scope(env()->context());
1425 
1426     ares_addr6ttl addrttls[256];
1427     int naddrttls = arraysize(addrttls), status;
1428     Local<Array> ret = Array::New(env()->isolate());
1429 
1430     int type = ns_t_aaaa;
1431     status = ParseGeneralReply(env(),
1432                                buf,
1433                                len,
1434                                &type,
1435                                ret,
1436                                addrttls,
1437                                &naddrttls);
1438     if (status != ARES_SUCCESS) {
1439       ParseError(status);
1440       return;
1441     }
1442 
1443     Local<Array> ttls = AddrTTLToArray<ares_addr6ttl>(env(),
1444                                                       addrttls,
1445                                                       naddrttls);
1446 
1447     CallOnComplete(ret, ttls);
1448   }
1449 };
1450 
1451 
1452 class QueryCnameWrap: public QueryWrap {
1453  public:
QueryCnameWrap(ChannelWrap * channel,Local<Object> req_wrap_obj)1454   QueryCnameWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1455       : QueryWrap(channel, req_wrap_obj, "resolveCname") {
1456   }
1457 
Send(const char * name)1458   int Send(const char* name) override {
1459     AresQuery(name, ns_c_in, ns_t_cname);
1460     return 0;
1461   }
1462 
1463   SET_NO_MEMORY_INFO()
1464   SET_MEMORY_INFO_NAME(QueryCnameWrap)
1465   SET_SELF_SIZE(QueryCnameWrap)
1466 
1467  protected:
Parse(unsigned char * buf,int len)1468   void Parse(unsigned char* buf, int len) override {
1469     HandleScope handle_scope(env()->isolate());
1470     Context::Scope context_scope(env()->context());
1471 
1472     Local<Array> ret = Array::New(env()->isolate());
1473     int type = ns_t_cname;
1474     int status = ParseGeneralReply(env(), buf, len, &type, ret);
1475     if (status != ARES_SUCCESS) {
1476       ParseError(status);
1477       return;
1478     }
1479 
1480     this->CallOnComplete(ret);
1481   }
1482 };
1483 
1484 
1485 class QueryMxWrap: public QueryWrap {
1486  public:
QueryMxWrap(ChannelWrap * channel,Local<Object> req_wrap_obj)1487   QueryMxWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1488       : QueryWrap(channel, req_wrap_obj, "resolveMx") {
1489   }
1490 
Send(const char * name)1491   int Send(const char* name) override {
1492     AresQuery(name, ns_c_in, ns_t_mx);
1493     return 0;
1494   }
1495 
1496   SET_NO_MEMORY_INFO()
1497   SET_MEMORY_INFO_NAME(QueryMxWrap)
1498   SET_SELF_SIZE(QueryMxWrap)
1499 
1500  protected:
Parse(unsigned char * buf,int len)1501   void Parse(unsigned char* buf, int len) override {
1502     HandleScope handle_scope(env()->isolate());
1503     Context::Scope context_scope(env()->context());
1504 
1505     Local<Array> mx_records = Array::New(env()->isolate());
1506     int status = ParseMxReply(env(), buf, len, mx_records);
1507 
1508     if (status != ARES_SUCCESS) {
1509       ParseError(status);
1510       return;
1511     }
1512 
1513     this->CallOnComplete(mx_records);
1514   }
1515 };
1516 
1517 
1518 class QueryNsWrap: public QueryWrap {
1519  public:
QueryNsWrap(ChannelWrap * channel,Local<Object> req_wrap_obj)1520   QueryNsWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1521       : QueryWrap(channel, req_wrap_obj, "resolveNs") {
1522   }
1523 
Send(const char * name)1524   int Send(const char* name) override {
1525     AresQuery(name, ns_c_in, ns_t_ns);
1526     return 0;
1527   }
1528 
1529   SET_NO_MEMORY_INFO()
1530   SET_MEMORY_INFO_NAME(QueryNsWrap)
1531   SET_SELF_SIZE(QueryNsWrap)
1532 
1533  protected:
Parse(unsigned char * buf,int len)1534   void Parse(unsigned char* buf, int len) override {
1535     HandleScope handle_scope(env()->isolate());
1536     Context::Scope context_scope(env()->context());
1537 
1538     int type = ns_t_ns;
1539     Local<Array> names = Array::New(env()->isolate());
1540     int status = ParseGeneralReply(env(), buf, len, &type, names);
1541     if (status != ARES_SUCCESS) {
1542       ParseError(status);
1543       return;
1544     }
1545 
1546     this->CallOnComplete(names);
1547   }
1548 };
1549 
1550 
1551 class QueryTxtWrap: public QueryWrap {
1552  public:
QueryTxtWrap(ChannelWrap * channel,Local<Object> req_wrap_obj)1553   QueryTxtWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1554       : QueryWrap(channel, req_wrap_obj, "resolveTxt") {
1555   }
1556 
Send(const char * name)1557   int Send(const char* name) override {
1558     AresQuery(name, ns_c_in, ns_t_txt);
1559     return 0;
1560   }
1561 
1562   SET_NO_MEMORY_INFO()
1563   SET_MEMORY_INFO_NAME(QueryTxtWrap)
1564   SET_SELF_SIZE(QueryTxtWrap)
1565 
1566  protected:
Parse(unsigned char * buf,int len)1567   void Parse(unsigned char* buf, int len) override {
1568     HandleScope handle_scope(env()->isolate());
1569     Context::Scope context_scope(env()->context());
1570 
1571     Local<Array> txt_records = Array::New(env()->isolate());
1572     int status = ParseTxtReply(env(), buf, len, txt_records);
1573     if (status != ARES_SUCCESS) {
1574       ParseError(status);
1575       return;
1576     }
1577 
1578     this->CallOnComplete(txt_records);
1579   }
1580 };
1581 
1582 
1583 class QuerySrvWrap: public QueryWrap {
1584  public:
QuerySrvWrap(ChannelWrap * channel,Local<Object> req_wrap_obj)1585   explicit QuerySrvWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1586       : QueryWrap(channel, req_wrap_obj, "resolveSrv") {
1587   }
1588 
Send(const char * name)1589   int Send(const char* name) override {
1590     AresQuery(name, ns_c_in, ns_t_srv);
1591     return 0;
1592   }
1593 
1594   SET_NO_MEMORY_INFO()
1595   SET_MEMORY_INFO_NAME(QuerySrvWrap)
1596   SET_SELF_SIZE(QuerySrvWrap)
1597 
1598  protected:
Parse(unsigned char * buf,int len)1599   void Parse(unsigned char* buf, int len) override {
1600     HandleScope handle_scope(env()->isolate());
1601     Context::Scope context_scope(env()->context());
1602 
1603     Local<Array> srv_records = Array::New(env()->isolate());
1604     int status = ParseSrvReply(env(), buf, len, srv_records);
1605     if (status != ARES_SUCCESS) {
1606       ParseError(status);
1607       return;
1608     }
1609 
1610     this->CallOnComplete(srv_records);
1611   }
1612 };
1613 
1614 class QueryPtrWrap: public QueryWrap {
1615  public:
QueryPtrWrap(ChannelWrap * channel,Local<Object> req_wrap_obj)1616   explicit QueryPtrWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1617       : QueryWrap(channel, req_wrap_obj, "resolvePtr") {
1618   }
1619 
Send(const char * name)1620   int Send(const char* name) override {
1621     AresQuery(name, ns_c_in, ns_t_ptr);
1622     return 0;
1623   }
1624 
1625   SET_NO_MEMORY_INFO()
1626   SET_MEMORY_INFO_NAME(QueryPtrWrap)
1627   SET_SELF_SIZE(QueryPtrWrap)
1628 
1629  protected:
Parse(unsigned char * buf,int len)1630   void Parse(unsigned char* buf, int len) override {
1631     HandleScope handle_scope(env()->isolate());
1632     Context::Scope context_scope(env()->context());
1633 
1634     int type = ns_t_ptr;
1635     Local<Array> aliases = Array::New(env()->isolate());
1636 
1637     int status = ParseGeneralReply(env(), buf, len, &type, aliases);
1638     if (status != ARES_SUCCESS) {
1639       ParseError(status);
1640       return;
1641     }
1642 
1643     this->CallOnComplete(aliases);
1644   }
1645 };
1646 
1647 class QueryNaptrWrap: public QueryWrap {
1648  public:
QueryNaptrWrap(ChannelWrap * channel,Local<Object> req_wrap_obj)1649   explicit QueryNaptrWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1650       : QueryWrap(channel, req_wrap_obj, "resolveNaptr") {
1651   }
1652 
Send(const char * name)1653   int Send(const char* name) override {
1654     AresQuery(name, ns_c_in, ns_t_naptr);
1655     return 0;
1656   }
1657 
1658   SET_NO_MEMORY_INFO()
1659   SET_MEMORY_INFO_NAME(QueryNaptrWrap)
1660   SET_SELF_SIZE(QueryNaptrWrap)
1661 
1662  protected:
Parse(unsigned char * buf,int len)1663   void Parse(unsigned char* buf, int len) override {
1664     HandleScope handle_scope(env()->isolate());
1665     Context::Scope context_scope(env()->context());
1666 
1667     Local<Array> naptr_records = Array::New(env()->isolate());
1668     int status = ParseNaptrReply(env(), buf, len, naptr_records);
1669     if (status != ARES_SUCCESS) {
1670       ParseError(status);
1671       return;
1672     }
1673 
1674     this->CallOnComplete(naptr_records);
1675   }
1676 };
1677 
1678 
1679 class QuerySoaWrap: public QueryWrap {
1680  public:
QuerySoaWrap(ChannelWrap * channel,Local<Object> req_wrap_obj)1681   QuerySoaWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1682       : QueryWrap(channel, req_wrap_obj, "resolveSoa") {
1683   }
1684 
Send(const char * name)1685   int Send(const char* name) override {
1686     AresQuery(name, ns_c_in, ns_t_soa);
1687     return 0;
1688   }
1689 
1690   SET_NO_MEMORY_INFO()
1691   SET_MEMORY_INFO_NAME(QuerySoaWrap)
1692   SET_SELF_SIZE(QuerySoaWrap)
1693 
1694  protected:
Parse(unsigned char * buf,int len)1695   void Parse(unsigned char* buf, int len) override {
1696     HandleScope handle_scope(env()->isolate());
1697     auto context = env()->context();
1698     Context::Scope context_scope(context);
1699 
1700     ares_soa_reply* soa_out;
1701     int status = ares_parse_soa_reply(buf, len, &soa_out);
1702 
1703     if (status != ARES_SUCCESS) {
1704       ParseError(status);
1705       return;
1706     }
1707 
1708     Local<Object> soa_record = Object::New(env()->isolate());
1709 
1710     soa_record->Set(context,
1711                     env()->nsname_string(),
1712                     OneByteString(env()->isolate(),
1713                                   soa_out->nsname)).Check();
1714     soa_record->Set(context,
1715                     env()->hostmaster_string(),
1716                     OneByteString(env()->isolate(),
1717                                   soa_out->hostmaster)).Check();
1718     soa_record->Set(context,
1719                     env()->serial_string(),
1720                     Integer::NewFromUnsigned(
1721                       env()->isolate(), soa_out->serial)).Check();
1722     soa_record->Set(context,
1723                     env()->refresh_string(),
1724                     Integer::New(env()->isolate(),
1725                                  soa_out->refresh)).Check();
1726     soa_record->Set(context,
1727                     env()->retry_string(),
1728                     Integer::New(env()->isolate(), soa_out->retry)).Check();
1729     soa_record->Set(context,
1730                     env()->expire_string(),
1731                     Integer::New(env()->isolate(), soa_out->expire)).Check();
1732     soa_record->Set(context,
1733                     env()->minttl_string(),
1734                     Integer::NewFromUnsigned(
1735                       env()->isolate(), soa_out->minttl)).Check();
1736 
1737     ares_free_data(soa_out);
1738 
1739     this->CallOnComplete(soa_record);
1740   }
1741 };
1742 
1743 
1744 class GetHostByAddrWrap: public QueryWrap {
1745  public:
GetHostByAddrWrap(ChannelWrap * channel,Local<Object> req_wrap_obj)1746   explicit GetHostByAddrWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1747       : QueryWrap(channel, req_wrap_obj, "reverse") {
1748   }
1749 
Send(const char * name)1750   int Send(const char* name) override {
1751     int length, family;
1752     char address_buffer[sizeof(struct in6_addr)];
1753 
1754     if (uv_inet_pton(AF_INET, name, &address_buffer) == 0) {
1755       length = sizeof(struct in_addr);
1756       family = AF_INET;
1757     } else if (uv_inet_pton(AF_INET6, name, &address_buffer) == 0) {
1758       length = sizeof(struct in6_addr);
1759       family = AF_INET6;
1760     } else {
1761       return UV_EINVAL;  // So errnoException() reports a proper error.
1762     }
1763 
1764     TRACE_EVENT_NESTABLE_ASYNC_BEGIN2(
1765         TRACING_CATEGORY_NODE2(dns, native), "reverse", this,
1766         "name", TRACE_STR_COPY(name),
1767         "family", family == AF_INET ? "ipv4" : "ipv6");
1768 
1769     ares_gethostbyaddr(channel_->cares_channel(),
1770                        address_buffer,
1771                        length,
1772                        family,
1773                        Callback,
1774                        MakeCallbackPointer());
1775     return 0;
1776   }
1777 
1778   SET_NO_MEMORY_INFO()
1779   SET_MEMORY_INFO_NAME(GetHostByAddrWrap)
1780   SET_SELF_SIZE(GetHostByAddrWrap)
1781 
1782  protected:
Parse(struct hostent * host)1783   void Parse(struct hostent* host) override {
1784     HandleScope handle_scope(env()->isolate());
1785     Context::Scope context_scope(env()->context());
1786     this->CallOnComplete(HostentToNames(env(), host));
1787   }
1788 };
1789 
1790 
1791 template <class Wrap>
Query(const FunctionCallbackInfo<Value> & args)1792 static void Query(const FunctionCallbackInfo<Value>& args) {
1793   Environment* env = Environment::GetCurrent(args);
1794   ChannelWrap* channel;
1795   ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
1796 
1797   CHECK_EQ(false, args.IsConstructCall());
1798   CHECK(args[0]->IsObject());
1799   CHECK(args[1]->IsString());
1800 
1801   Local<Object> req_wrap_obj = args[0].As<Object>();
1802   Local<String> string = args[1].As<String>();
1803   auto wrap = std::make_unique<Wrap>(channel, req_wrap_obj);
1804 
1805   node::Utf8Value name(env->isolate(), string);
1806   channel->ModifyActivityQueryCount(1);
1807   int err = wrap->Send(*name);
1808   if (err) {
1809     channel->ModifyActivityQueryCount(-1);
1810   } else {
1811     // Release ownership of the pointer allowing the ownership to be transferred
1812     USE(wrap.release());
1813   }
1814 
1815   args.GetReturnValue().Set(err);
1816 }
1817 
1818 
AfterGetAddrInfo(uv_getaddrinfo_t * req,int status,struct addrinfo * res)1819 void AfterGetAddrInfo(uv_getaddrinfo_t* req, int status, struct addrinfo* res) {
1820   std::unique_ptr<GetAddrInfoReqWrap> req_wrap {
1821       static_cast<GetAddrInfoReqWrap*>(req->data)};
1822   Environment* env = req_wrap->env();
1823 
1824   HandleScope handle_scope(env->isolate());
1825   Context::Scope context_scope(env->context());
1826 
1827   Local<Value> argv[] = {
1828     Integer::New(env->isolate(), status),
1829     Null(env->isolate())
1830   };
1831 
1832   uint64_t n = 0;
1833   const bool verbatim = req_wrap->verbatim();
1834 
1835   if (status == 0) {
1836     Local<Array> results = Array::New(env->isolate());
1837 
1838     auto add = [&] (bool want_ipv4, bool want_ipv6) {
1839       for (auto p = res; p != nullptr; p = p->ai_next) {
1840         CHECK_EQ(p->ai_socktype, SOCK_STREAM);
1841 
1842         const char* addr;
1843         if (want_ipv4 && p->ai_family == AF_INET) {
1844           addr = reinterpret_cast<char*>(
1845               &(reinterpret_cast<struct sockaddr_in*>(p->ai_addr)->sin_addr));
1846         } else if (want_ipv6 && p->ai_family == AF_INET6) {
1847           addr = reinterpret_cast<char*>(
1848               &(reinterpret_cast<struct sockaddr_in6*>(p->ai_addr)->sin6_addr));
1849         } else {
1850           continue;
1851         }
1852 
1853         char ip[INET6_ADDRSTRLEN];
1854         if (uv_inet_ntop(p->ai_family, addr, ip, sizeof(ip)))
1855           continue;
1856 
1857         Local<String> s = OneByteString(env->isolate(), ip);
1858         results->Set(env->context(), n, s).Check();
1859         n++;
1860       }
1861     };
1862 
1863     add(true, verbatim);
1864     if (verbatim == false)
1865       add(false, true);
1866 
1867     // No responses were found to return
1868     if (n == 0) {
1869       argv[0] = Integer::New(env->isolate(), UV_EAI_NODATA);
1870     }
1871 
1872     argv[1] = results;
1873   }
1874 
1875   uv_freeaddrinfo(res);
1876 
1877   TRACE_EVENT_NESTABLE_ASYNC_END2(
1878       TRACING_CATEGORY_NODE2(dns, native), "lookup", req_wrap.get(),
1879       "count", n, "verbatim", verbatim);
1880 
1881   // Make the callback into JavaScript
1882   req_wrap->MakeCallback(env->oncomplete_string(), arraysize(argv), argv);
1883 }
1884 
1885 
AfterGetNameInfo(uv_getnameinfo_t * req,int status,const char * hostname,const char * service)1886 void AfterGetNameInfo(uv_getnameinfo_t* req,
1887                       int status,
1888                       const char* hostname,
1889                       const char* service) {
1890   std::unique_ptr<GetNameInfoReqWrap> req_wrap {
1891       static_cast<GetNameInfoReqWrap*>(req->data)};
1892   Environment* env = req_wrap->env();
1893 
1894   HandleScope handle_scope(env->isolate());
1895   Context::Scope context_scope(env->context());
1896 
1897   Local<Value> argv[] = {
1898     Integer::New(env->isolate(), status),
1899     Null(env->isolate()),
1900     Null(env->isolate())
1901   };
1902 
1903   if (status == 0) {
1904     // Success
1905     Local<String> js_hostname = OneByteString(env->isolate(), hostname);
1906     Local<String> js_service = OneByteString(env->isolate(), service);
1907     argv[1] = js_hostname;
1908     argv[2] = js_service;
1909   }
1910 
1911   TRACE_EVENT_NESTABLE_ASYNC_END2(
1912       TRACING_CATEGORY_NODE2(dns, native), "lookupService", req_wrap.get(),
1913       "hostname", TRACE_STR_COPY(hostname),
1914       "service", TRACE_STR_COPY(service));
1915 
1916   // Make the callback into JavaScript
1917   req_wrap->MakeCallback(env->oncomplete_string(), arraysize(argv), argv);
1918 }
1919 
1920 using ParseIPResult =
1921     decltype(static_cast<ares_addr_port_node*>(nullptr)->addr);
1922 
ParseIP(const char * ip,ParseIPResult * result=nullptr)1923 int ParseIP(const char* ip, ParseIPResult* result = nullptr) {
1924   ParseIPResult tmp;
1925   if (result == nullptr) result = &tmp;
1926   if (0 == uv_inet_pton(AF_INET, ip, result)) return 4;
1927   if (0 == uv_inet_pton(AF_INET6, ip, result)) return 6;
1928   return 0;
1929 }
1930 
CanonicalizeIP(const FunctionCallbackInfo<Value> & args)1931 void CanonicalizeIP(const FunctionCallbackInfo<Value>& args) {
1932   Isolate* isolate = args.GetIsolate();
1933   node::Utf8Value ip(isolate, args[0]);
1934 
1935   ParseIPResult result;
1936   const int rc = ParseIP(*ip, &result);
1937   if (rc == 0) return;
1938 
1939   char canonical_ip[INET6_ADDRSTRLEN];
1940   const int af = (rc == 4 ? AF_INET : AF_INET6);
1941   CHECK_EQ(0, uv_inet_ntop(af, &result, canonical_ip, sizeof(canonical_ip)));
1942   Local<String> val = String::NewFromUtf8(isolate, canonical_ip,
1943       NewStringType::kNormal).ToLocalChecked();
1944   args.GetReturnValue().Set(val);
1945 }
1946 
GetAddrInfo(const FunctionCallbackInfo<Value> & args)1947 void GetAddrInfo(const FunctionCallbackInfo<Value>& args) {
1948   Environment* env = Environment::GetCurrent(args);
1949 
1950   CHECK(args[0]->IsObject());
1951   CHECK(args[1]->IsString());
1952   CHECK(args[2]->IsInt32());
1953   CHECK(args[4]->IsBoolean());
1954   Local<Object> req_wrap_obj = args[0].As<Object>();
1955   node::Utf8Value hostname(env->isolate(), args[1]);
1956 
1957   int32_t flags = 0;
1958   if (args[3]->IsInt32()) {
1959     flags = args[3].As<Int32>()->Value();
1960   }
1961 
1962   int family;
1963 
1964   switch (args[2].As<Int32>()->Value()) {
1965     case 0:
1966       family = AF_UNSPEC;
1967       break;
1968     case 4:
1969       family = AF_INET;
1970       break;
1971     case 6:
1972       family = AF_INET6;
1973       break;
1974     default:
1975       CHECK(0 && "bad address family");
1976   }
1977 
1978   auto req_wrap = std::make_unique<GetAddrInfoReqWrap>(env,
1979                                                        req_wrap_obj,
1980                                                        args[4]->IsTrue());
1981 
1982   struct addrinfo hints;
1983   memset(&hints, 0, sizeof(hints));
1984   hints.ai_family = family;
1985   hints.ai_socktype = SOCK_STREAM;
1986   hints.ai_flags = flags;
1987 
1988   TRACE_EVENT_NESTABLE_ASYNC_BEGIN2(
1989       TRACING_CATEGORY_NODE2(dns, native), "lookup", req_wrap.get(),
1990       "hostname", TRACE_STR_COPY(*hostname),
1991       "family",
1992       family == AF_INET ? "ipv4" : family == AF_INET6 ? "ipv6" : "unspec");
1993 
1994   int err = req_wrap->Dispatch(uv_getaddrinfo,
1995                                AfterGetAddrInfo,
1996                                *hostname,
1997                                nullptr,
1998                                &hints);
1999   if (err == 0)
2000     // Release ownership of the pointer allowing the ownership to be transferred
2001     USE(req_wrap.release());
2002 
2003   args.GetReturnValue().Set(err);
2004 }
2005 
2006 
GetNameInfo(const FunctionCallbackInfo<Value> & args)2007 void GetNameInfo(const FunctionCallbackInfo<Value>& args) {
2008   Environment* env = Environment::GetCurrent(args);
2009 
2010   CHECK(args[0]->IsObject());
2011   CHECK(args[1]->IsString());
2012   CHECK(args[2]->IsUint32());
2013   Local<Object> req_wrap_obj = args[0].As<Object>();
2014   node::Utf8Value ip(env->isolate(), args[1]);
2015   const unsigned port = args[2]->Uint32Value(env->context()).FromJust();
2016   struct sockaddr_storage addr;
2017 
2018   CHECK(uv_ip4_addr(*ip, port, reinterpret_cast<sockaddr_in*>(&addr)) == 0 ||
2019         uv_ip6_addr(*ip, port, reinterpret_cast<sockaddr_in6*>(&addr)) == 0);
2020 
2021   auto req_wrap = std::make_unique<GetNameInfoReqWrap>(env, req_wrap_obj);
2022 
2023   TRACE_EVENT_NESTABLE_ASYNC_BEGIN2(
2024       TRACING_CATEGORY_NODE2(dns, native), "lookupService", req_wrap.get(),
2025       "ip", TRACE_STR_COPY(*ip), "port", port);
2026 
2027   int err = req_wrap->Dispatch(uv_getnameinfo,
2028                                AfterGetNameInfo,
2029                                reinterpret_cast<struct sockaddr*>(&addr),
2030                                NI_NAMEREQD);
2031   if (err == 0)
2032     // Release ownership of the pointer allowing the ownership to be transferred
2033     USE(req_wrap.release());
2034 
2035   args.GetReturnValue().Set(err);
2036 }
2037 
2038 
GetServers(const FunctionCallbackInfo<Value> & args)2039 void GetServers(const FunctionCallbackInfo<Value>& args) {
2040   Environment* env = Environment::GetCurrent(args);
2041   ChannelWrap* channel;
2042   ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
2043 
2044   Local<Array> server_array = Array::New(env->isolate());
2045 
2046   ares_addr_port_node* servers;
2047 
2048   int r = ares_get_servers_ports(channel->cares_channel(), &servers);
2049   CHECK_EQ(r, ARES_SUCCESS);
2050   auto cleanup = OnScopeLeave([&]() { ares_free_data(servers); });
2051 
2052   ares_addr_port_node* cur = servers;
2053 
2054   for (uint32_t i = 0; cur != nullptr; ++i, cur = cur->next) {
2055     char ip[INET6_ADDRSTRLEN];
2056 
2057     const void* caddr = static_cast<const void*>(&cur->addr);
2058     int err = uv_inet_ntop(cur->family, caddr, ip, sizeof(ip));
2059     CHECK_EQ(err, 0);
2060 
2061     Local<Value> ret[] = {
2062       OneByteString(env->isolate(), ip),
2063       Integer::New(env->isolate(), cur->udp_port)
2064     };
2065 
2066     if (server_array->Set(env->context(), i,
2067                           Array::New(env->isolate(), ret, arraysize(ret)))
2068           .IsNothing()) {
2069       return;
2070     }
2071   }
2072 
2073   args.GetReturnValue().Set(server_array);
2074 }
2075 
2076 
SetServers(const FunctionCallbackInfo<Value> & args)2077 void SetServers(const FunctionCallbackInfo<Value>& args) {
2078   Environment* env = Environment::GetCurrent(args);
2079   ChannelWrap* channel;
2080   ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
2081 
2082   if (channel->active_query_count()) {
2083     return args.GetReturnValue().Set(DNS_ESETSRVPENDING);
2084   }
2085 
2086   CHECK(args[0]->IsArray());
2087 
2088   Local<Array> arr = Local<Array>::Cast(args[0]);
2089 
2090   uint32_t len = arr->Length();
2091 
2092   if (len == 0) {
2093     int rv = ares_set_servers(channel->cares_channel(), nullptr);
2094     return args.GetReturnValue().Set(rv);
2095   }
2096 
2097   std::vector<ares_addr_port_node> servers(len);
2098   ares_addr_port_node* last = nullptr;
2099 
2100   int err;
2101 
2102   for (uint32_t i = 0; i < len; i++) {
2103     CHECK(arr->Get(env->context(), i).ToLocalChecked()->IsArray());
2104 
2105     Local<Array> elm =
2106         Local<Array>::Cast(arr->Get(env->context(), i).ToLocalChecked());
2107 
2108     CHECK(elm->Get(env->context(),
2109                    0).ToLocalChecked()->Int32Value(env->context()).FromJust());
2110     CHECK(elm->Get(env->context(), 1).ToLocalChecked()->IsString());
2111     CHECK(elm->Get(env->context(),
2112                    2).ToLocalChecked()->Int32Value(env->context()).FromJust());
2113 
2114     int fam = elm->Get(env->context(), 0)
2115         .ToLocalChecked()->Int32Value(env->context()).FromJust();
2116     node::Utf8Value ip(env->isolate(),
2117                        elm->Get(env->context(), 1).ToLocalChecked());
2118     int port = elm->Get(env->context(), 2)
2119         .ToLocalChecked()->Int32Value(env->context()).FromJust();
2120 
2121     ares_addr_port_node* cur = &servers[i];
2122 
2123     cur->tcp_port = cur->udp_port = port;
2124     switch (fam) {
2125       case 4:
2126         cur->family = AF_INET;
2127         err = uv_inet_pton(AF_INET, *ip, &cur->addr);
2128         break;
2129       case 6:
2130         cur->family = AF_INET6;
2131         err = uv_inet_pton(AF_INET6, *ip, &cur->addr);
2132         break;
2133       default:
2134         CHECK(0 && "Bad address family.");
2135     }
2136 
2137     if (err)
2138       break;
2139 
2140     cur->next = nullptr;
2141 
2142     if (last != nullptr)
2143       last->next = cur;
2144 
2145     last = cur;
2146   }
2147 
2148   if (err == 0)
2149     err = ares_set_servers_ports(channel->cares_channel(), &servers[0]);
2150   else
2151     err = ARES_EBADSTR;
2152 
2153   if (err == ARES_SUCCESS)
2154     channel->set_is_servers_default(false);
2155 
2156   args.GetReturnValue().Set(err);
2157 }
2158 
Cancel(const FunctionCallbackInfo<Value> & args)2159 void Cancel(const FunctionCallbackInfo<Value>& args) {
2160   ChannelWrap* channel;
2161   ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
2162 
2163   TRACE_EVENT_INSTANT0(TRACING_CATEGORY_NODE2(dns, native),
2164       "cancel", TRACE_EVENT_SCOPE_THREAD);
2165 
2166   ares_cancel(channel->cares_channel());
2167 }
2168 
2169 const char EMSG_ESETSRVPENDING[] = "There are pending queries.";
StrError(const FunctionCallbackInfo<Value> & args)2170 void StrError(const FunctionCallbackInfo<Value>& args) {
2171   Environment* env = Environment::GetCurrent(args);
2172   int code = args[0]->Int32Value(env->context()).FromJust();
2173   const char* errmsg = (code == DNS_ESETSRVPENDING) ?
2174     EMSG_ESETSRVPENDING :
2175     ares_strerror(code);
2176   args.GetReturnValue().Set(OneByteString(env->isolate(), errmsg));
2177 }
2178 
2179 
Initialize(Local<Object> target,Local<Value> unused,Local<Context> context,void * priv)2180 void Initialize(Local<Object> target,
2181                 Local<Value> unused,
2182                 Local<Context> context,
2183                 void* priv) {
2184   Environment* env = Environment::GetCurrent(context);
2185 
2186   env->SetMethod(target, "getaddrinfo", GetAddrInfo);
2187   env->SetMethod(target, "getnameinfo", GetNameInfo);
2188   env->SetMethodNoSideEffect(target, "canonicalizeIP", CanonicalizeIP);
2189 
2190   env->SetMethod(target, "strerror", StrError);
2191 
2192   target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(), "AF_INET"),
2193               Integer::New(env->isolate(), AF_INET)).Check();
2194   target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(), "AF_INET6"),
2195               Integer::New(env->isolate(), AF_INET6)).Check();
2196   target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(),
2197                                                     "AF_UNSPEC"),
2198               Integer::New(env->isolate(), AF_UNSPEC)).Check();
2199   target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(),
2200                                                     "AI_ADDRCONFIG"),
2201               Integer::New(env->isolate(), AI_ADDRCONFIG)).Check();
2202   target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(),
2203                                                     "AI_ALL"),
2204               Integer::New(env->isolate(), AI_ALL)).Check();
2205   target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(),
2206                                                     "AI_V4MAPPED"),
2207               Integer::New(env->isolate(), AI_V4MAPPED)).Check();
2208 
2209   Local<FunctionTemplate> aiw =
2210       BaseObject::MakeLazilyInitializedJSTemplate(env);
2211   aiw->Inherit(AsyncWrap::GetConstructorTemplate(env));
2212   Local<String> addrInfoWrapString =
2213       FIXED_ONE_BYTE_STRING(env->isolate(), "GetAddrInfoReqWrap");
2214   aiw->SetClassName(addrInfoWrapString);
2215   target->Set(env->context(),
2216               addrInfoWrapString,
2217               aiw->GetFunction(context).ToLocalChecked()).Check();
2218 
2219   Local<FunctionTemplate> niw =
2220       BaseObject::MakeLazilyInitializedJSTemplate(env);
2221   niw->Inherit(AsyncWrap::GetConstructorTemplate(env));
2222   Local<String> nameInfoWrapString =
2223       FIXED_ONE_BYTE_STRING(env->isolate(), "GetNameInfoReqWrap");
2224   niw->SetClassName(nameInfoWrapString);
2225   target->Set(env->context(),
2226               nameInfoWrapString,
2227               niw->GetFunction(context).ToLocalChecked()).Check();
2228 
2229   Local<FunctionTemplate> qrw =
2230       BaseObject::MakeLazilyInitializedJSTemplate(env);
2231   qrw->Inherit(AsyncWrap::GetConstructorTemplate(env));
2232   Local<String> queryWrapString =
2233       FIXED_ONE_BYTE_STRING(env->isolate(), "QueryReqWrap");
2234   qrw->SetClassName(queryWrapString);
2235   target->Set(env->context(),
2236               queryWrapString,
2237               qrw->GetFunction(context).ToLocalChecked()).Check();
2238 
2239   Local<FunctionTemplate> channel_wrap =
2240       env->NewFunctionTemplate(ChannelWrap::New);
2241   channel_wrap->InstanceTemplate()->SetInternalFieldCount(
2242       ChannelWrap::kInternalFieldCount);
2243   channel_wrap->Inherit(AsyncWrap::GetConstructorTemplate(env));
2244 
2245   env->SetProtoMethod(channel_wrap, "queryAny", Query<QueryAnyWrap>);
2246   env->SetProtoMethod(channel_wrap, "queryA", Query<QueryAWrap>);
2247   env->SetProtoMethod(channel_wrap, "queryAaaa", Query<QueryAaaaWrap>);
2248   env->SetProtoMethod(channel_wrap, "queryCname", Query<QueryCnameWrap>);
2249   env->SetProtoMethod(channel_wrap, "queryMx", Query<QueryMxWrap>);
2250   env->SetProtoMethod(channel_wrap, "queryNs", Query<QueryNsWrap>);
2251   env->SetProtoMethod(channel_wrap, "queryTxt", Query<QueryTxtWrap>);
2252   env->SetProtoMethod(channel_wrap, "querySrv", Query<QuerySrvWrap>);
2253   env->SetProtoMethod(channel_wrap, "queryPtr", Query<QueryPtrWrap>);
2254   env->SetProtoMethod(channel_wrap, "queryNaptr", Query<QueryNaptrWrap>);
2255   env->SetProtoMethod(channel_wrap, "querySoa", Query<QuerySoaWrap>);
2256   env->SetProtoMethod(channel_wrap, "getHostByAddr", Query<GetHostByAddrWrap>);
2257 
2258   env->SetProtoMethodNoSideEffect(channel_wrap, "getServers", GetServers);
2259   env->SetProtoMethod(channel_wrap, "setServers", SetServers);
2260   env->SetProtoMethod(channel_wrap, "cancel", Cancel);
2261 
2262   Local<String> channelWrapString =
2263       FIXED_ONE_BYTE_STRING(env->isolate(), "ChannelWrap");
2264   channel_wrap->SetClassName(channelWrapString);
2265   target->Set(env->context(), channelWrapString,
2266               channel_wrap->GetFunction(context).ToLocalChecked()).Check();
2267 }
2268 
2269 }  // anonymous namespace
2270 }  // namespace cares_wrap
2271 }  // namespace node
2272 
2273 NODE_MODULE_CONTEXT_AWARE_INTERNAL(cares_wrap, node::cares_wrap::Initialize)
2274