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