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