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