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