• 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 "async_wrap-inl.h"
23 #include "base_object-inl.h"
24 #include "base64-inl.h"
25 #include "cares_wrap.h"
26 #include "env-inl.h"
27 #include "memory_tracker-inl.h"
28 #include "node.h"
29 #include "node_errors.h"
30 #include "req_wrap-inl.h"
31 #include "util-inl.h"
32 #include "v8.h"
33 #include "uv.h"
34 
35 #include <cerrno>
36 #include <cstring>
37 #include <memory>
38 #include <vector>
39 #include <unordered_set>
40 
41 #ifndef T_CAA
42 # define T_CAA    257 /* Certification Authority Authorization */
43 #endif
44 
45 // OpenBSD does not define these
46 #ifndef AI_ALL
47 # define AI_ALL 0
48 #endif
49 #ifndef AI_V4MAPPED
50 # define AI_V4MAPPED 0
51 #endif
52 
53 
54 namespace node {
55 namespace cares_wrap {
56 
57 using v8::Array;
58 using v8::Context;
59 using v8::EscapableHandleScope;
60 using v8::FunctionCallbackInfo;
61 using v8::FunctionTemplate;
62 using v8::HandleScope;
63 using v8::Int32;
64 using v8::Integer;
65 using v8::Isolate;
66 using v8::Just;
67 using v8::Local;
68 using v8::Maybe;
69 using v8::Nothing;
70 using v8::Null;
71 using v8::Object;
72 using v8::String;
73 using v8::Value;
74 
75 namespace {
76 
77 Mutex ares_library_mutex;
78 
cares_get_16bit(const unsigned char * p)79 inline uint16_t cares_get_16bit(const unsigned char* p) {
80   return static_cast<uint32_t>(p[0] << 8U) | (static_cast<uint32_t>(p[1]));
81 }
82 
ares_poll_cb(uv_poll_t * watcher,int status,int events)83 void ares_poll_cb(uv_poll_t* watcher, int status, int events) {
84   NodeAresTask* task = ContainerOf(&NodeAresTask::poll_watcher, watcher);
85   ChannelWrap* channel = task->channel;
86 
87   /* Reset the idle timer */
88   uv_timer_again(channel->timer_handle());
89 
90   if (status < 0) {
91     /* An error happened. Just pretend that the socket is both readable and */
92     /* writable. */
93     ares_process_fd(channel->cares_channel(), task->sock, task->sock);
94     return;
95   }
96 
97   /* Process DNS responses */
98   ares_process_fd(channel->cares_channel(),
99                   events & UV_READABLE ? task->sock : ARES_SOCKET_BAD,
100                   events & UV_WRITABLE ? task->sock : ARES_SOCKET_BAD);
101 }
102 
103 
ares_poll_close_cb(uv_poll_t * watcher)104 void ares_poll_close_cb(uv_poll_t* watcher) {
105   std::unique_ptr<NodeAresTask> free_me(
106         ContainerOf(&NodeAresTask::poll_watcher, watcher));
107 }
108 
109 
110 /* Callback from ares when socket operation is started */
ares_sockstate_cb(void * data,ares_socket_t sock,int read,int write)111 void ares_sockstate_cb(void* data, ares_socket_t sock, int read, int write) {
112   ChannelWrap* channel = static_cast<ChannelWrap*>(data);
113   NodeAresTask* task;
114 
115   NodeAresTask lookup_task;
116   lookup_task.sock = sock;
117   auto it = channel->task_list()->find(&lookup_task);
118 
119   task = (it == channel->task_list()->end()) ? nullptr : *it;
120 
121   if (read || write) {
122     if (!task) {
123       /* New socket */
124       channel->StartTimer();
125 
126       task = NodeAresTask::Create(channel, sock);
127       if (task == nullptr) {
128         /* This should never happen unless we're out of memory or something */
129         /* is seriously wrong. The socket won't be polled, but the query will */
130         /* eventually time out. */
131         return;
132       }
133 
134       channel->task_list()->insert(task);
135     }
136 
137     /* This should never fail. If it fails anyway, the query will eventually */
138     /* time out. */
139     uv_poll_start(&task->poll_watcher,
140                   (read ? UV_READABLE : 0) | (write ? UV_WRITABLE : 0),
141                   ares_poll_cb);
142 
143   } else {
144     /* read == 0 and write == 0 this is c-ares's way of notifying us that */
145     /* the socket is now closed. We must free the data associated with */
146     /* socket. */
147     CHECK(task &&
148           "When an ares socket is closed we should have a handle for it");
149 
150     channel->task_list()->erase(it);
151     channel->env()->CloseHandle(&task->poll_watcher, ares_poll_close_cb);
152 
153     if (channel->task_list()->empty()) {
154       channel->CloseTimer();
155     }
156   }
157 }
158 
HostentToNames(Environment * env,struct hostent * host)159 Local<Array> HostentToNames(Environment* env, struct hostent* host) {
160   EscapableHandleScope scope(env->isolate());
161 
162   std::vector<Local<Value>> names;
163 
164   for (uint32_t i = 0; host->h_aliases[i] != nullptr; ++i)
165     names.emplace_back(OneByteString(env->isolate(), host->h_aliases[i]));
166 
167   Local<Array> ret = Array::New(env->isolate(), names.data(), names.size());
168 
169   return scope.Escape(ret);
170 }
171 
HostentToNames(Environment * env,struct hostent * host,Local<Array> names)172 Local<Array> HostentToNames(Environment* env,
173                             struct hostent* host,
174                             Local<Array> names) {
175   size_t offset = names->Length();
176 
177   for (uint32_t i = 0; host->h_aliases[i] != nullptr; ++i) {
178     names->Set(
179         env->context(),
180         i + offset,
181         OneByteString(env->isolate(), host->h_aliases[i])).Check();
182   }
183 
184   return names;
185 }
186 
187 template <typename T>
AddrTTLToArray(Environment * env,const T * addrttls,size_t naddrttls)188 Local<Array> AddrTTLToArray(
189     Environment* env,
190     const T* addrttls,
191     size_t naddrttls) {
192   MaybeStackBuffer<Local<Value>, 8> ttls(naddrttls);
193   for (size_t i = 0; i < naddrttls; i++)
194     ttls[i] = Integer::NewFromUnsigned(env->isolate(), addrttls[i].ttl);
195 
196   return Array::New(env->isolate(), ttls.out(), naddrttls);
197 }
198 
ParseGeneralReply(Environment * env,const unsigned char * buf,int len,int * type,Local<Array> ret,void * addrttls=nullptr,int * naddrttls=nullptr)199 int ParseGeneralReply(
200     Environment* env,
201     const unsigned char* buf,
202     int len,
203     int* type,
204     Local<Array> ret,
205     void* addrttls = nullptr,
206     int* naddrttls = nullptr) {
207   HandleScope handle_scope(env->isolate());
208   hostent* host;
209 
210   int status;
211   switch (*type) {
212     case ns_t_a:
213     case ns_t_cname:
214     case ns_t_cname_or_a:
215       status = ares_parse_a_reply(buf,
216                                   len,
217                                   &host,
218                                   static_cast<ares_addrttl*>(addrttls),
219                                   naddrttls);
220       break;
221     case ns_t_aaaa:
222       status = ares_parse_aaaa_reply(buf,
223                                      len,
224                                      &host,
225                                      static_cast<ares_addr6ttl*>(addrttls),
226                                      naddrttls);
227       break;
228     case ns_t_ns:
229       status = ares_parse_ns_reply(buf, len, &host);
230       break;
231     case ns_t_ptr:
232       status = ares_parse_ptr_reply(buf, len, nullptr, 0, AF_INET, &host);
233       break;
234     default:
235       CHECK(0 && "Bad NS type");
236       break;
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   std::unique_ptr<GetAddrInfoReqWrap> req_wrap {
1432       static_cast<GetAddrInfoReqWrap*>(req->data)};
1433   Environment* env = req_wrap->env();
1434 
1435   HandleScope handle_scope(env->isolate());
1436   Context::Scope context_scope(env->context());
1437 
1438   Local<Value> argv[] = {
1439     Integer::New(env->isolate(), status),
1440     Null(env->isolate())
1441   };
1442 
1443   uint64_t n = 0;
1444   const bool verbatim = req_wrap->verbatim();
1445 
1446   if (status == 0) {
1447     Local<Array> results = Array::New(env->isolate());
1448 
1449     auto add = [&] (bool want_ipv4, bool want_ipv6) -> Maybe<bool> {
1450       for (auto p = res; p != nullptr; p = p->ai_next) {
1451         CHECK_EQ(p->ai_socktype, SOCK_STREAM);
1452 
1453         const char* addr;
1454         if (want_ipv4 && p->ai_family == AF_INET) {
1455           addr = reinterpret_cast<char*>(
1456               &(reinterpret_cast<struct sockaddr_in*>(p->ai_addr)->sin_addr));
1457         } else if (want_ipv6 && p->ai_family == AF_INET6) {
1458           addr = reinterpret_cast<char*>(
1459               &(reinterpret_cast<struct sockaddr_in6*>(p->ai_addr)->sin6_addr));
1460         } else {
1461           continue;
1462         }
1463 
1464         char ip[INET6_ADDRSTRLEN];
1465         if (uv_inet_ntop(p->ai_family, addr, ip, sizeof(ip)))
1466           continue;
1467 
1468         Local<String> s = OneByteString(env->isolate(), ip);
1469         if (results->Set(env->context(), n, s).IsNothing())
1470           return Nothing<bool>();
1471         n++;
1472       }
1473       return Just(true);
1474     };
1475 
1476     if (add(true, verbatim).IsNothing())
1477       return;
1478     if (verbatim == false) {
1479       if (add(false, true).IsNothing())
1480         return;
1481     }
1482 
1483     // No responses were found to return
1484     if (n == 0) {
1485       argv[0] = Integer::New(env->isolate(), UV_EAI_NODATA);
1486     }
1487 
1488     argv[1] = results;
1489   }
1490 
1491   uv_freeaddrinfo(res);
1492 
1493   TRACE_EVENT_NESTABLE_ASYNC_END2(
1494       TRACING_CATEGORY_NODE2(dns, native), "lookup", req_wrap.get(),
1495       "count", n, "verbatim", verbatim);
1496 
1497   // Make the callback into JavaScript
1498   req_wrap->MakeCallback(env->oncomplete_string(), arraysize(argv), argv);
1499 }
1500 
1501 
AfterGetNameInfo(uv_getnameinfo_t * req,int status,const char * hostname,const char * service)1502 void AfterGetNameInfo(uv_getnameinfo_t* req,
1503                       int status,
1504                       const char* hostname,
1505                       const char* service) {
1506   std::unique_ptr<GetNameInfoReqWrap> req_wrap {
1507       static_cast<GetNameInfoReqWrap*>(req->data)};
1508   Environment* env = req_wrap->env();
1509 
1510   HandleScope handle_scope(env->isolate());
1511   Context::Scope context_scope(env->context());
1512 
1513   Local<Value> argv[] = {
1514     Integer::New(env->isolate(), status),
1515     Null(env->isolate()),
1516     Null(env->isolate())
1517   };
1518 
1519   if (status == 0) {
1520     // Success
1521     Local<String> js_hostname = OneByteString(env->isolate(), hostname);
1522     Local<String> js_service = OneByteString(env->isolate(), service);
1523     argv[1] = js_hostname;
1524     argv[2] = js_service;
1525   }
1526 
1527   TRACE_EVENT_NESTABLE_ASYNC_END2(
1528       TRACING_CATEGORY_NODE2(dns, native), "lookupService", req_wrap.get(),
1529       "hostname", TRACE_STR_COPY(hostname),
1530       "service", TRACE_STR_COPY(service));
1531 
1532   // Make the callback into JavaScript
1533   req_wrap->MakeCallback(env->oncomplete_string(), arraysize(argv), argv);
1534 }
1535 
1536 using ParseIPResult =
1537     decltype(static_cast<ares_addr_port_node*>(nullptr)->addr);
1538 
ParseIP(const char * ip,ParseIPResult * result=nullptr)1539 int ParseIP(const char* ip, ParseIPResult* result = nullptr) {
1540   ParseIPResult tmp;
1541   if (result == nullptr) result = &tmp;
1542   if (0 == uv_inet_pton(AF_INET, ip, result)) return 4;
1543   if (0 == uv_inet_pton(AF_INET6, ip, result)) return 6;
1544   return 0;
1545 }
1546 
CanonicalizeIP(const FunctionCallbackInfo<Value> & args)1547 void CanonicalizeIP(const FunctionCallbackInfo<Value>& args) {
1548   Isolate* isolate = args.GetIsolate();
1549   node::Utf8Value ip(isolate, args[0]);
1550 
1551   ParseIPResult result;
1552   const int rc = ParseIP(*ip, &result);
1553   if (rc == 0) return;
1554 
1555   char canonical_ip[INET6_ADDRSTRLEN];
1556   const int af = (rc == 4 ? AF_INET : AF_INET6);
1557   CHECK_EQ(0, uv_inet_ntop(af, &result, canonical_ip, sizeof(canonical_ip)));
1558   Local<String> val = String::NewFromUtf8(isolate, canonical_ip)
1559       .ToLocalChecked();
1560   args.GetReturnValue().Set(val);
1561 }
1562 
GetAddrInfo(const FunctionCallbackInfo<Value> & args)1563 void GetAddrInfo(const FunctionCallbackInfo<Value>& args) {
1564   Environment* env = Environment::GetCurrent(args);
1565 
1566   CHECK(args[0]->IsObject());
1567   CHECK(args[1]->IsString());
1568   CHECK(args[2]->IsInt32());
1569   CHECK(args[4]->IsBoolean());
1570   Local<Object> req_wrap_obj = args[0].As<Object>();
1571   node::Utf8Value hostname(env->isolate(), args[1]);
1572 
1573   int32_t flags = 0;
1574   if (args[3]->IsInt32()) {
1575     flags = args[3].As<Int32>()->Value();
1576   }
1577 
1578   int family;
1579 
1580   switch (args[2].As<Int32>()->Value()) {
1581     case 0:
1582       family = AF_UNSPEC;
1583       break;
1584     case 4:
1585       family = AF_INET;
1586       break;
1587     case 6:
1588       family = AF_INET6;
1589       break;
1590     default:
1591       CHECK(0 && "bad address family");
1592   }
1593 
1594   auto req_wrap = std::make_unique<GetAddrInfoReqWrap>(env,
1595                                                        req_wrap_obj,
1596                                                        args[4]->IsTrue());
1597 
1598   struct addrinfo hints;
1599   memset(&hints, 0, sizeof(hints));
1600   hints.ai_family = family;
1601   hints.ai_socktype = SOCK_STREAM;
1602   hints.ai_flags = flags;
1603 
1604   TRACE_EVENT_NESTABLE_ASYNC_BEGIN2(
1605       TRACING_CATEGORY_NODE2(dns, native), "lookup", req_wrap.get(),
1606       "hostname", TRACE_STR_COPY(*hostname),
1607       "family",
1608       family == AF_INET ? "ipv4" : family == AF_INET6 ? "ipv6" : "unspec");
1609 
1610   int err = req_wrap->Dispatch(uv_getaddrinfo,
1611                                AfterGetAddrInfo,
1612                                *hostname,
1613                                nullptr,
1614                                &hints);
1615   if (err == 0)
1616     // Release ownership of the pointer allowing the ownership to be transferred
1617     USE(req_wrap.release());
1618 
1619   args.GetReturnValue().Set(err);
1620 }
1621 
1622 
GetNameInfo(const FunctionCallbackInfo<Value> & args)1623 void GetNameInfo(const FunctionCallbackInfo<Value>& args) {
1624   Environment* env = Environment::GetCurrent(args);
1625 
1626   CHECK(args[0]->IsObject());
1627   CHECK(args[1]->IsString());
1628   CHECK(args[2]->IsUint32());
1629   Local<Object> req_wrap_obj = args[0].As<Object>();
1630   node::Utf8Value ip(env->isolate(), args[1]);
1631   const unsigned port = args[2]->Uint32Value(env->context()).FromJust();
1632   struct sockaddr_storage addr;
1633 
1634   CHECK(uv_ip4_addr(*ip, port, reinterpret_cast<sockaddr_in*>(&addr)) == 0 ||
1635         uv_ip6_addr(*ip, port, reinterpret_cast<sockaddr_in6*>(&addr)) == 0);
1636 
1637   auto req_wrap = std::make_unique<GetNameInfoReqWrap>(env, req_wrap_obj);
1638 
1639   TRACE_EVENT_NESTABLE_ASYNC_BEGIN2(
1640       TRACING_CATEGORY_NODE2(dns, native), "lookupService", req_wrap.get(),
1641       "ip", TRACE_STR_COPY(*ip), "port", port);
1642 
1643   int err = req_wrap->Dispatch(uv_getnameinfo,
1644                                AfterGetNameInfo,
1645                                reinterpret_cast<struct sockaddr*>(&addr),
1646                                NI_NAMEREQD);
1647   if (err == 0)
1648     // Release ownership of the pointer allowing the ownership to be transferred
1649     USE(req_wrap.release());
1650 
1651   args.GetReturnValue().Set(err);
1652 }
1653 
1654 
GetServers(const FunctionCallbackInfo<Value> & args)1655 void GetServers(const FunctionCallbackInfo<Value>& args) {
1656   Environment* env = Environment::GetCurrent(args);
1657   ChannelWrap* channel;
1658   ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
1659 
1660   Local<Array> server_array = Array::New(env->isolate());
1661 
1662   ares_addr_port_node* servers;
1663 
1664   int r = ares_get_servers_ports(channel->cares_channel(), &servers);
1665   CHECK_EQ(r, ARES_SUCCESS);
1666   auto cleanup = OnScopeLeave([&]() { ares_free_data(servers); });
1667 
1668   ares_addr_port_node* cur = servers;
1669 
1670   for (uint32_t i = 0; cur != nullptr; ++i, cur = cur->next) {
1671     char ip[INET6_ADDRSTRLEN];
1672 
1673     const void* caddr = static_cast<const void*>(&cur->addr);
1674     int err = uv_inet_ntop(cur->family, caddr, ip, sizeof(ip));
1675     CHECK_EQ(err, 0);
1676 
1677     Local<Value> ret[] = {
1678       OneByteString(env->isolate(), ip),
1679       Integer::New(env->isolate(), cur->udp_port)
1680     };
1681 
1682     if (server_array->Set(env->context(), i,
1683                           Array::New(env->isolate(), ret, arraysize(ret)))
1684           .IsNothing()) {
1685       return;
1686     }
1687   }
1688 
1689   args.GetReturnValue().Set(server_array);
1690 }
1691 
1692 
SetServers(const FunctionCallbackInfo<Value> & args)1693 void SetServers(const FunctionCallbackInfo<Value>& args) {
1694   Environment* env = Environment::GetCurrent(args);
1695   ChannelWrap* channel;
1696   ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
1697 
1698   if (channel->active_query_count()) {
1699     return args.GetReturnValue().Set(DNS_ESETSRVPENDING);
1700   }
1701 
1702   CHECK(args[0]->IsArray());
1703 
1704   Local<Array> arr = Local<Array>::Cast(args[0]);
1705 
1706   uint32_t len = arr->Length();
1707 
1708   if (len == 0) {
1709     int rv = ares_set_servers(channel->cares_channel(), nullptr);
1710     return args.GetReturnValue().Set(rv);
1711   }
1712 
1713   std::vector<ares_addr_port_node> servers(len);
1714   ares_addr_port_node* last = nullptr;
1715 
1716   int err;
1717 
1718   for (uint32_t i = 0; i < len; i++) {
1719     CHECK(arr->Get(env->context(), i).ToLocalChecked()->IsArray());
1720 
1721     Local<Array> elm =
1722         Local<Array>::Cast(arr->Get(env->context(), i).ToLocalChecked());
1723 
1724     CHECK(elm->Get(env->context(),
1725                    0).ToLocalChecked()->Int32Value(env->context()).FromJust());
1726     CHECK(elm->Get(env->context(), 1).ToLocalChecked()->IsString());
1727     CHECK(elm->Get(env->context(),
1728                    2).ToLocalChecked()->Int32Value(env->context()).FromJust());
1729 
1730     int fam = elm->Get(env->context(), 0)
1731         .ToLocalChecked()->Int32Value(env->context()).FromJust();
1732     node::Utf8Value ip(env->isolate(),
1733                        elm->Get(env->context(), 1).ToLocalChecked());
1734     int port = elm->Get(env->context(), 2)
1735         .ToLocalChecked()->Int32Value(env->context()).FromJust();
1736 
1737     ares_addr_port_node* cur = &servers[i];
1738 
1739     cur->tcp_port = cur->udp_port = port;
1740     switch (fam) {
1741       case 4:
1742         cur->family = AF_INET;
1743         err = uv_inet_pton(AF_INET, *ip, &cur->addr);
1744         break;
1745       case 6:
1746         cur->family = AF_INET6;
1747         err = uv_inet_pton(AF_INET6, *ip, &cur->addr);
1748         break;
1749       default:
1750         CHECK(0 && "Bad address family.");
1751     }
1752 
1753     if (err)
1754       break;
1755 
1756     cur->next = nullptr;
1757 
1758     if (last != nullptr)
1759       last->next = cur;
1760 
1761     last = cur;
1762   }
1763 
1764   if (err == 0)
1765     err = ares_set_servers_ports(channel->cares_channel(), &servers[0]);
1766   else
1767     err = ARES_EBADSTR;
1768 
1769   if (err == ARES_SUCCESS)
1770     channel->set_is_servers_default(false);
1771 
1772   args.GetReturnValue().Set(err);
1773 }
1774 
SetLocalAddress(const FunctionCallbackInfo<Value> & args)1775 void SetLocalAddress(const FunctionCallbackInfo<Value>& args) {
1776   Environment* env = Environment::GetCurrent(args);
1777   ChannelWrap* channel;
1778   ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
1779 
1780   CHECK_EQ(args.Length(), 2);
1781   CHECK(args[0]->IsString());
1782 
1783   Isolate* isolate = args.GetIsolate();
1784   node::Utf8Value ip0(isolate, args[0]);
1785 
1786   unsigned char addr0[sizeof(struct in6_addr)];
1787   unsigned char addr1[sizeof(struct in6_addr)];
1788   int type0 = 0;
1789 
1790   // This function accepts 2 arguments.  The first may be either an IPv4
1791   // address or an IPv6 address.  If present, the second argument must be the
1792   // other type of address.  Otherwise, the unspecified type of IP is set
1793   // to 0 (any).
1794 
1795   if (uv_inet_pton(AF_INET, *ip0, &addr0) == 0) {
1796     ares_set_local_ip4(channel->cares_channel(), ReadUint32BE(addr0));
1797     type0 = 4;
1798   } else if (uv_inet_pton(AF_INET6, *ip0, &addr0) == 0) {
1799     ares_set_local_ip6(channel->cares_channel(), addr0);
1800     type0 = 6;
1801   } else {
1802     THROW_ERR_INVALID_ARG_VALUE(env, "Invalid IP address.");
1803     return;
1804   }
1805 
1806   if (!args[1]->IsUndefined()) {
1807     CHECK(args[1]->IsString());
1808     node::Utf8Value ip1(isolate, args[1]);
1809 
1810     if (uv_inet_pton(AF_INET, *ip1, &addr1) == 0) {
1811       if (type0 == 4) {
1812         THROW_ERR_INVALID_ARG_VALUE(env, "Cannot specify two IPv4 addresses.");
1813         return;
1814       } else {
1815         ares_set_local_ip4(channel->cares_channel(), ReadUint32BE(addr1));
1816       }
1817     } else if (uv_inet_pton(AF_INET6, *ip1, &addr1) == 0) {
1818       if (type0 == 6) {
1819         THROW_ERR_INVALID_ARG_VALUE(env, "Cannot specify two IPv6 addresses.");
1820         return;
1821       } else {
1822         ares_set_local_ip6(channel->cares_channel(), addr1);
1823       }
1824     } else {
1825       THROW_ERR_INVALID_ARG_VALUE(env, "Invalid IP address.");
1826       return;
1827     }
1828   } else {
1829     // No second arg specified
1830     if (type0 == 4) {
1831       memset(&addr1, 0, sizeof(addr1));
1832       ares_set_local_ip6(channel->cares_channel(), addr1);
1833     } else {
1834       ares_set_local_ip4(channel->cares_channel(), 0);
1835     }
1836   }
1837 }
1838 
Cancel(const FunctionCallbackInfo<Value> & args)1839 void Cancel(const FunctionCallbackInfo<Value>& args) {
1840   ChannelWrap* channel;
1841   ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
1842 
1843   TRACE_EVENT_INSTANT0(TRACING_CATEGORY_NODE2(dns, native),
1844       "cancel", TRACE_EVENT_SCOPE_THREAD);
1845 
1846   ares_cancel(channel->cares_channel());
1847 }
1848 
1849 const char EMSG_ESETSRVPENDING[] = "There are pending queries.";
StrError(const FunctionCallbackInfo<Value> & args)1850 void StrError(const FunctionCallbackInfo<Value>& args) {
1851   Environment* env = Environment::GetCurrent(args);
1852   int code = args[0]->Int32Value(env->context()).FromJust();
1853   const char* errmsg = (code == DNS_ESETSRVPENDING) ?
1854     EMSG_ESETSRVPENDING :
1855     ares_strerror(code);
1856   args.GetReturnValue().Set(OneByteString(env->isolate(), errmsg));
1857 }
1858 
1859 }  // namespace
1860 
safe_free_hostent(struct hostent * host)1861 inline void safe_free_hostent(struct hostent* host) {
1862   int idx;
1863 
1864   if (host->h_addr_list != nullptr) {
1865     idx = 0;
1866     while (host->h_addr_list[idx]) {
1867       free(host->h_addr_list[idx++]);
1868     }
1869     free(host->h_addr_list);
1870     host->h_addr_list = nullptr;
1871   }
1872 
1873   if (host->h_aliases != nullptr) {
1874     idx = 0;
1875     while (host->h_aliases[idx]) {
1876       free(host->h_aliases[idx++]);
1877     }
1878     free(host->h_aliases);
1879     host->h_aliases = nullptr;
1880   }
1881 
1882   free(host->h_name);
1883   free(host);
1884 }
1885 
Initialize(Local<Object> target,Local<Value> unused,Local<Context> context,void * priv)1886 void Initialize(Local<Object> target,
1887                 Local<Value> unused,
1888                 Local<Context> context,
1889                 void* priv) {
1890   Environment* env = Environment::GetCurrent(context);
1891 
1892   env->SetMethod(target, "getaddrinfo", GetAddrInfo);
1893   env->SetMethod(target, "getnameinfo", GetNameInfo);
1894   env->SetMethodNoSideEffect(target, "canonicalizeIP", CanonicalizeIP);
1895 
1896   env->SetMethod(target, "strerror", StrError);
1897 
1898   target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(), "AF_INET"),
1899               Integer::New(env->isolate(), AF_INET)).Check();
1900   target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(), "AF_INET6"),
1901               Integer::New(env->isolate(), AF_INET6)).Check();
1902   target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(),
1903                                                     "AF_UNSPEC"),
1904               Integer::New(env->isolate(), AF_UNSPEC)).Check();
1905   target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(),
1906                                                     "AI_ADDRCONFIG"),
1907               Integer::New(env->isolate(), AI_ADDRCONFIG)).Check();
1908   target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(),
1909                                                     "AI_ALL"),
1910               Integer::New(env->isolate(), AI_ALL)).Check();
1911   target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(),
1912                                                     "AI_V4MAPPED"),
1913               Integer::New(env->isolate(), AI_V4MAPPED)).Check();
1914 
1915   Local<FunctionTemplate> aiw =
1916       BaseObject::MakeLazilyInitializedJSTemplate(env);
1917   aiw->Inherit(AsyncWrap::GetConstructorTemplate(env));
1918   env->SetConstructorFunction(target, "GetAddrInfoReqWrap", aiw);
1919 
1920   Local<FunctionTemplate> niw =
1921       BaseObject::MakeLazilyInitializedJSTemplate(env);
1922   niw->Inherit(AsyncWrap::GetConstructorTemplate(env));
1923   env->SetConstructorFunction(target, "GetNameInfoReqWrap", niw);
1924 
1925   Local<FunctionTemplate> qrw =
1926       BaseObject::MakeLazilyInitializedJSTemplate(env);
1927   qrw->Inherit(AsyncWrap::GetConstructorTemplate(env));
1928   env->SetConstructorFunction(target, "QueryReqWrap", qrw);
1929 
1930   Local<FunctionTemplate> channel_wrap =
1931       env->NewFunctionTemplate(ChannelWrap::New);
1932   channel_wrap->InstanceTemplate()->SetInternalFieldCount(
1933       ChannelWrap::kInternalFieldCount);
1934   channel_wrap->Inherit(AsyncWrap::GetConstructorTemplate(env));
1935 
1936   env->SetProtoMethod(channel_wrap, "queryAny", Query<QueryAnyWrap>);
1937   env->SetProtoMethod(channel_wrap, "queryA", Query<QueryAWrap>);
1938   env->SetProtoMethod(channel_wrap, "queryAaaa", Query<QueryAaaaWrap>);
1939   env->SetProtoMethod(channel_wrap, "queryCaa", Query<QueryCaaWrap>);
1940   env->SetProtoMethod(channel_wrap, "queryCname", Query<QueryCnameWrap>);
1941   env->SetProtoMethod(channel_wrap, "queryMx", Query<QueryMxWrap>);
1942   env->SetProtoMethod(channel_wrap, "queryNs", Query<QueryNsWrap>);
1943   env->SetProtoMethod(channel_wrap, "queryTxt", Query<QueryTxtWrap>);
1944   env->SetProtoMethod(channel_wrap, "querySrv", Query<QuerySrvWrap>);
1945   env->SetProtoMethod(channel_wrap, "queryPtr", Query<QueryPtrWrap>);
1946   env->SetProtoMethod(channel_wrap, "queryNaptr", Query<QueryNaptrWrap>);
1947   env->SetProtoMethod(channel_wrap, "querySoa", Query<QuerySoaWrap>);
1948   env->SetProtoMethod(channel_wrap, "getHostByAddr", Query<GetHostByAddrWrap>);
1949 
1950   env->SetProtoMethodNoSideEffect(channel_wrap, "getServers", GetServers);
1951   env->SetProtoMethod(channel_wrap, "setServers", SetServers);
1952   env->SetProtoMethod(channel_wrap, "setLocalAddress", SetLocalAddress);
1953   env->SetProtoMethod(channel_wrap, "cancel", Cancel);
1954 
1955   env->SetConstructorFunction(target, "ChannelWrap", channel_wrap);
1956 }
1957 
1958 }  // namespace cares_wrap
1959 }  // namespace node
1960 
1961 NODE_MODULE_CONTEXT_AWARE_INTERNAL(cares_wrap, node::cares_wrap::Initialize)
1962