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