GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/cares_wrap.cc Lines: 155 1237 12.5 %
Date: 2021-02-19 04:08:54 Branches: 37 678 5.5 %

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

624
        if (want_ipv4 && p->ai_family == AF_INET) {
1916
156
          addr = reinterpret_cast<char*>(
1917
312
              &(reinterpret_cast<struct sockaddr_in*>(p->ai_addr)->sin_addr));
1918

468
        } else if (want_ipv6 && p->ai_family == AF_INET6) {
1919
156
          addr = reinterpret_cast<char*>(
1920
312
              &(reinterpret_cast<struct sockaddr_in6*>(p->ai_addr)->sin6_addr));
1921
        } else {
1922
624
          continue;
1923
        }
1924
1925
        char ip[INET6_ADDRSTRLEN];
1926
312
        if (uv_inet_ntop(p->ai_family, addr, ip, sizeof(ip)))
1927
          continue;
1928
1929
624
        Local<String> s = OneByteString(env->isolate(), ip);
1930
1248
        results->Set(env->context(), n, s).Check();
1931
312
        n++;
1932
      }
1933
39
    };
1934
1935
13
    add(true, verbatim);
1936
13
    if (verbatim == false)
1937
13
      add(false, true);
1938
1939
    // No responses were found to return
1940
13
    if (n == 0) {
1941
      argv[0] = Integer::New(env->isolate(), UV_EAI_NODATA);
1942
    }
1943
1944
13
    argv[1] = results;
1945
  }
1946
1947
13
  uv_freeaddrinfo(res);
1948
1949
  TRACE_EVENT_NESTABLE_ASYNC_END2(
1950
13
      TRACING_CATEGORY_NODE2(dns, native), "lookup", req_wrap.get(),
1951
13
      "count", n, "verbatim", verbatim);
1952
2
1953
28
  // Make the callback into JavaScript
1954
26
  req_wrap->MakeCallback(env->oncomplete_string(), arraysize(argv), argv);
1955
13
}
1956
1957
1958
void AfterGetNameInfo(uv_getnameinfo_t* req,
1959
                      int status,
1960
                      const char* hostname,
1961
                      const char* service) {
1962
  std::unique_ptr<GetNameInfoReqWrap> req_wrap {
1963
      static_cast<GetNameInfoReqWrap*>(req->data)};
1964
  Environment* env = req_wrap->env();
1965
1966
  HandleScope handle_scope(env->isolate());
1967
  Context::Scope context_scope(env->context());
1968
1969
  Local<Value> argv[] = {
1970
    Integer::New(env->isolate(), status),
1971
    Null(env->isolate()),
1972
    Null(env->isolate())
1973
  };
1974
1975
  if (status == 0) {
1976
    // Success
1977
    Local<String> js_hostname = OneByteString(env->isolate(), hostname);
1978
    Local<String> js_service = OneByteString(env->isolate(), service);
1979
    argv[1] = js_hostname;
1980
    argv[2] = js_service;
1981
  }
1982
1983
  TRACE_EVENT_NESTABLE_ASYNC_END2(
1984
      TRACING_CATEGORY_NODE2(dns, native), "lookupService", req_wrap.get(),
1985
      "hostname", TRACE_STR_COPY(hostname),
1986
      "service", TRACE_STR_COPY(service));
1987
1988
  // Make the callback into JavaScript
1989
  req_wrap->MakeCallback(env->oncomplete_string(), arraysize(argv), argv);
1990
}
1991
1992
using ParseIPResult =
1993
    decltype(static_cast<ares_addr_port_node*>(nullptr)->addr);
1994
1995
int ParseIP(const char* ip, ParseIPResult* result = nullptr) {
1996
  ParseIPResult tmp;
1997
  if (result == nullptr) result = &tmp;
1998
  if (0 == uv_inet_pton(AF_INET, ip, result)) return 4;
1999
  if (0 == uv_inet_pton(AF_INET6, ip, result)) return 6;
2000
  return 0;
2001
}
2002
2003
void CanonicalizeIP(const FunctionCallbackInfo<Value>& args) {
2004
  Isolate* isolate = args.GetIsolate();
2005
  node::Utf8Value ip(isolate, args[0]);
2006
2007
  ParseIPResult result;
2008
  const int rc = ParseIP(*ip, &result);
2009
  if (rc == 0) return;
2010
2011
  char canonical_ip[INET6_ADDRSTRLEN];
2012
  const int af = (rc == 4 ? AF_INET : AF_INET6);
2013
  CHECK_EQ(0, uv_inet_ntop(af, &result, canonical_ip, sizeof(canonical_ip)));
2014
  Local<String> val = String::NewFromUtf8(isolate, canonical_ip)
2015
      .ToLocalChecked();
2016
  args.GetReturnValue().Set(val);
2017
}
2018
2019
13
void GetAddrInfo(const FunctionCallbackInfo<Value>& args) {
2020
13
  Environment* env = Environment::GetCurrent(args);
2021
2022
26
  CHECK(args[0]->IsObject());
2023
39
  CHECK(args[1]->IsString());
2024
26
  CHECK(args[2]->IsInt32());
2025
26
  CHECK(args[4]->IsBoolean());
2026
26
  Local<Object> req_wrap_obj = args[0].As<Object>();
2027
26
  node::Utf8Value hostname(env->isolate(), args[1]);
2028
2029
13
  int32_t flags = 0;
2030
26
  if (args[3]->IsInt32()) {
2031
39
    flags = args[3].As<Int32>()->Value();
2032
  }
2033
2034
  int family;
2035
2036

39
  switch (args[2].As<Int32>()->Value()) {
2037
    case 0:
2038
13
      family = AF_UNSPEC;
2039
13
      break;
2040
    case 4:
2041
      family = AF_INET;
2042
      break;
2043
    case 6:
2044
      family = AF_INET6;
2045
      break;
2046
    default:
2047
      CHECK(0 && "bad address family");
2048
  }
2049
2050
  auto req_wrap = std::make_unique<GetAddrInfoReqWrap>(env,
2051
                                                       req_wrap_obj,
2052
39
                                                       args[4]->IsTrue());
2053
2054
  struct addrinfo hints;
2055
13
  memset(&hints, 0, sizeof(hints));
2056
13
  hints.ai_family = family;
2057
13
  hints.ai_socktype = SOCK_STREAM;
2058
13
  hints.ai_flags = flags;
2059
2060
  TRACE_EVENT_NESTABLE_ASYNC_BEGIN2(
2061
13
      TRACING_CATEGORY_NODE2(dns, native), "lookup", req_wrap.get(),
2062
13
      "hostname", TRACE_STR_COPY(*hostname),
2063
2
      "family",
2064
28
      family == AF_INET ? "ipv4" : family == AF_INET6 ? "ipv6" : "unspec");
2065
13
2066
13
  int err = req_wrap->Dispatch(uv_getaddrinfo,
2067
                               AfterGetAddrInfo,
2068
                               *hostname,
2069
                               nullptr,
2070
13
                               &hints);
2071
13
  if (err == 0)
2072
    // Release ownership of the pointer allowing the ownership to be transferred
2073
13
    USE(req_wrap.release());
2074
2075
26
  args.GetReturnValue().Set(err);
2076
13
}
2077
2078
2079
void GetNameInfo(const FunctionCallbackInfo<Value>& args) {
2080
  Environment* env = Environment::GetCurrent(args);
2081
2082
  CHECK(args[0]->IsObject());
2083
  CHECK(args[1]->IsString());
2084
  CHECK(args[2]->IsUint32());
2085
  Local<Object> req_wrap_obj = args[0].As<Object>();
2086
  node::Utf8Value ip(env->isolate(), args[1]);
2087
  const unsigned port = args[2]->Uint32Value(env->context()).FromJust();
2088
  struct sockaddr_storage addr;
2089
2090
  CHECK(uv_ip4_addr(*ip, port, reinterpret_cast<sockaddr_in*>(&addr)) == 0 ||
2091
        uv_ip6_addr(*ip, port, reinterpret_cast<sockaddr_in6*>(&addr)) == 0);
2092
2093
  auto req_wrap = std::make_unique<GetNameInfoReqWrap>(env, req_wrap_obj);
2094
2095
  TRACE_EVENT_NESTABLE_ASYNC_BEGIN2(
2096
      TRACING_CATEGORY_NODE2(dns, native), "lookupService", req_wrap.get(),
2097
      "ip", TRACE_STR_COPY(*ip), "port", port);
2098
2099
  int err = req_wrap->Dispatch(uv_getnameinfo,
2100
                               AfterGetNameInfo,
2101
                               reinterpret_cast<struct sockaddr*>(&addr),
2102
                               NI_NAMEREQD);
2103
  if (err == 0)
2104
    // Release ownership of the pointer allowing the ownership to be transferred
2105
    USE(req_wrap.release());
2106
2107
  args.GetReturnValue().Set(err);
2108
}
2109
2110
2111
void GetServers(const FunctionCallbackInfo<Value>& args) {
2112
  Environment* env = Environment::GetCurrent(args);
2113
  ChannelWrap* channel;
2114
  ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
2115
2116
  Local<Array> server_array = Array::New(env->isolate());
2117
2118
  ares_addr_port_node* servers;
2119
2120
  int r = ares_get_servers_ports(channel->cares_channel(), &servers);
2121
  CHECK_EQ(r, ARES_SUCCESS);
2122
  auto cleanup = OnScopeLeave([&]() { ares_free_data(servers); });
2123
2124
  ares_addr_port_node* cur = servers;
2125
2126
  for (uint32_t i = 0; cur != nullptr; ++i, cur = cur->next) {
2127
    char ip[INET6_ADDRSTRLEN];
2128
2129
    const void* caddr = static_cast<const void*>(&cur->addr);
2130
    int err = uv_inet_ntop(cur->family, caddr, ip, sizeof(ip));
2131
    CHECK_EQ(err, 0);
2132
2133
    Local<Value> ret[] = {
2134
      OneByteString(env->isolate(), ip),
2135
      Integer::New(env->isolate(), cur->udp_port)
2136
    };
2137
2138
    if (server_array->Set(env->context(), i,
2139
                          Array::New(env->isolate(), ret, arraysize(ret)))
2140
          .IsNothing()) {
2141
      return;
2142
    }
2143
  }
2144
2145
  args.GetReturnValue().Set(server_array);
2146
}
2147
2148
2149
void SetServers(const FunctionCallbackInfo<Value>& args) {
2150
  Environment* env = Environment::GetCurrent(args);
2151
  ChannelWrap* channel;
2152
  ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
2153
2154
  if (channel->active_query_count()) {
2155
    return args.GetReturnValue().Set(DNS_ESETSRVPENDING);
2156
  }
2157
2158
  CHECK(args[0]->IsArray());
2159
2160
  Local<Array> arr = Local<Array>::Cast(args[0]);
2161
2162
  uint32_t len = arr->Length();
2163
2164
  if (len == 0) {
2165
    int rv = ares_set_servers(channel->cares_channel(), nullptr);
2166
    return args.GetReturnValue().Set(rv);
2167
  }
2168
2169
  std::vector<ares_addr_port_node> servers(len);
2170
  ares_addr_port_node* last = nullptr;
2171
2172
  int err;
2173
2174
  for (uint32_t i = 0; i < len; i++) {
2175
    CHECK(arr->Get(env->context(), i).ToLocalChecked()->IsArray());
2176
2177
    Local<Array> elm =
2178
        Local<Array>::Cast(arr->Get(env->context(), i).ToLocalChecked());
2179
2180
    CHECK(elm->Get(env->context(),
2181
                   0).ToLocalChecked()->Int32Value(env->context()).FromJust());
2182
    CHECK(elm->Get(env->context(), 1).ToLocalChecked()->IsString());
2183
    CHECK(elm->Get(env->context(),
2184
                   2).ToLocalChecked()->Int32Value(env->context()).FromJust());
2185
2186
    int fam = elm->Get(env->context(), 0)
2187
        .ToLocalChecked()->Int32Value(env->context()).FromJust();
2188
    node::Utf8Value ip(env->isolate(),
2189
                       elm->Get(env->context(), 1).ToLocalChecked());
2190
    int port = elm->Get(env->context(), 2)
2191
        .ToLocalChecked()->Int32Value(env->context()).FromJust();
2192
2193
    ares_addr_port_node* cur = &servers[i];
2194
2195
    cur->tcp_port = cur->udp_port = port;
2196
    switch (fam) {
2197
      case 4:
2198
        cur->family = AF_INET;
2199
        err = uv_inet_pton(AF_INET, *ip, &cur->addr);
2200
        break;
2201
      case 6:
2202
        cur->family = AF_INET6;
2203
        err = uv_inet_pton(AF_INET6, *ip, &cur->addr);
2204
        break;
2205
      default:
2206
        CHECK(0 && "Bad address family.");
2207
    }
2208
2209
    if (err)
2210
      break;
2211
2212
    cur->next = nullptr;
2213
2214
    if (last != nullptr)
2215
      last->next = cur;
2216
2217
    last = cur;
2218
  }
2219
2220
  if (err == 0)
2221
    err = ares_set_servers_ports(channel->cares_channel(), &servers[0]);
2222
  else
2223
    err = ARES_EBADSTR;
2224
2225
  if (err == ARES_SUCCESS)
2226
    channel->set_is_servers_default(false);
2227
2228
  args.GetReturnValue().Set(err);
2229
}
2230
2231
void SetLocalAddress(const FunctionCallbackInfo<Value>& args) {
2232
  Environment* env = Environment::GetCurrent(args);
2233
  ChannelWrap* channel;
2234
  ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
2235
2236
  CHECK_EQ(args.Length(), 2);
2237
  CHECK(args[0]->IsString());
2238
2239
  Isolate* isolate = args.GetIsolate();
2240
  node::Utf8Value ip0(isolate, args[0]);
2241
2242
  unsigned char addr0[sizeof(struct in6_addr)];
2243
  unsigned char addr1[sizeof(struct in6_addr)];
2244
  int type0 = 0;
2245
2246
  // This function accepts 2 arguments.  The first may be either an IPv4
2247
  // address or an IPv6 address.  If present, the second argument must be the
2248
  // other type of address.  Otherwise, the unspecified type of IP is set
2249
  // to 0 (any).
2250
2251
  if (uv_inet_pton(AF_INET, *ip0, &addr0) == 0) {
2252
    ares_set_local_ip4(channel->cares_channel(), ReadUint32BE(addr0));
2253
    type0 = 4;
2254
  } else if (uv_inet_pton(AF_INET6, *ip0, &addr0) == 0) {
2255
    ares_set_local_ip6(channel->cares_channel(), addr0);
2256
    type0 = 6;
2257
  } else {
2258
    THROW_ERR_INVALID_ARG_VALUE(env, "Invalid IP address.");
2259
    return;
2260
  }
2261
2262
  if (!args[1]->IsUndefined()) {
2263
    CHECK(args[1]->IsString());
2264
    node::Utf8Value ip1(isolate, args[1]);
2265
2266
    if (uv_inet_pton(AF_INET, *ip1, &addr1) == 0) {
2267
      if (type0 == 4) {
2268
        THROW_ERR_INVALID_ARG_VALUE(env, "Cannot specify two IPv4 addresses.");
2269
        return;
2270
      } else {
2271
        ares_set_local_ip4(channel->cares_channel(), ReadUint32BE(addr1));
2272
      }
2273
    } else if (uv_inet_pton(AF_INET6, *ip1, &addr1) == 0) {
2274
      if (type0 == 6) {
2275
        THROW_ERR_INVALID_ARG_VALUE(env, "Cannot specify two IPv6 addresses.");
2276
        return;
2277
      } else {
2278
        ares_set_local_ip6(channel->cares_channel(), addr1);
2279
      }
2280
    } else {
2281
      THROW_ERR_INVALID_ARG_VALUE(env, "Invalid IP address.");
2282
      return;
2283
    }
2284
  } else {
2285
    // No second arg specifed
2286
    if (type0 == 4) {
2287
      memset(&addr1, 0, sizeof(addr1));
2288
      ares_set_local_ip6(channel->cares_channel(), addr1);
2289
    } else {
2290
      ares_set_local_ip4(channel->cares_channel(), 0);
2291
    }
2292
  }
2293
}
2294
2295
void Cancel(const FunctionCallbackInfo<Value>& args) {
2296
  ChannelWrap* channel;
2297
  ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
2298
2299
  TRACE_EVENT_INSTANT0(TRACING_CATEGORY_NODE2(dns, native),
2300
      "cancel", TRACE_EVENT_SCOPE_THREAD);
2301
2302
  ares_cancel(channel->cares_channel());
2303
}
2304
2305
const char EMSG_ESETSRVPENDING[] = "There are pending queries.";
2306
void StrError(const FunctionCallbackInfo<Value>& args) {
2307
  Environment* env = Environment::GetCurrent(args);
2308
  int code = args[0]->Int32Value(env->context()).FromJust();
2309
  const char* errmsg = (code == DNS_ESETSRVPENDING) ?
2310
    EMSG_ESETSRVPENDING :
2311
    ares_strerror(code);
2312
  args.GetReturnValue().Set(OneByteString(env->isolate(), errmsg));
2313
}
2314
2315
2316
2
void Initialize(Local<Object> target,
2317
                Local<Value> unused,
2318
                Local<Context> context,
2319
                void* priv) {
2320
2
  Environment* env = Environment::GetCurrent(context);
2321
2322
2
  env->SetMethod(target, "getaddrinfo", GetAddrInfo);
2323
2
  env->SetMethod(target, "getnameinfo", GetNameInfo);
2324
2
  env->SetMethodNoSideEffect(target, "canonicalizeIP", CanonicalizeIP);
2325
2326
2
  env->SetMethod(target, "strerror", StrError);
2327
2328
4
  target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(), "AF_INET"),
2329
10
              Integer::New(env->isolate(), AF_INET)).Check();
2330
4
  target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(), "AF_INET6"),
2331
10
              Integer::New(env->isolate(), AF_INET6)).Check();
2332
4
  target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(),
2333
                                                    "AF_UNSPEC"),
2334
10
              Integer::New(env->isolate(), AF_UNSPEC)).Check();
2335
4
  target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(),
2336
                                                    "AI_ADDRCONFIG"),
2337
10
              Integer::New(env->isolate(), AI_ADDRCONFIG)).Check();
2338
4
  target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(),
2339
                                                    "AI_ALL"),
2340
10
              Integer::New(env->isolate(), AI_ALL)).Check();
2341
4
  target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(),
2342
                                                    "AI_V4MAPPED"),
2343
10
              Integer::New(env->isolate(), AI_V4MAPPED)).Check();
2344
2345
  Local<FunctionTemplate> aiw =
2346
2
      BaseObject::MakeLazilyInitializedJSTemplate(env);
2347
4
  aiw->Inherit(AsyncWrap::GetConstructorTemplate(env));
2348
2
  env->SetConstructorFunction(target, "GetAddrInfoReqWrap", aiw);
2349
2350
  Local<FunctionTemplate> niw =
2351
2
      BaseObject::MakeLazilyInitializedJSTemplate(env);
2352
4
  niw->Inherit(AsyncWrap::GetConstructorTemplate(env));
2353
2
  env->SetConstructorFunction(target, "GetNameInfoReqWrap", niw);
2354
2355
  Local<FunctionTemplate> qrw =
2356
2
      BaseObject::MakeLazilyInitializedJSTemplate(env);
2357
4
  qrw->Inherit(AsyncWrap::GetConstructorTemplate(env));
2358
2
  env->SetConstructorFunction(target, "QueryReqWrap", qrw);
2359
2360
  Local<FunctionTemplate> channel_wrap =
2361
2
      env->NewFunctionTemplate(ChannelWrap::New);
2362
6
  channel_wrap->InstanceTemplate()->SetInternalFieldCount(
2363
2
      ChannelWrap::kInternalFieldCount);
2364
4
  channel_wrap->Inherit(AsyncWrap::GetConstructorTemplate(env));
2365
2366
2
  env->SetProtoMethod(channel_wrap, "queryAny", Query<QueryAnyWrap>);
2367
2
  env->SetProtoMethod(channel_wrap, "queryA", Query<QueryAWrap>);
2368
2
  env->SetProtoMethod(channel_wrap, "queryAaaa", Query<QueryAaaaWrap>);
2369
2
  env->SetProtoMethod(channel_wrap, "queryCaa", Query<QueryCaaWrap>);
2370
2
  env->SetProtoMethod(channel_wrap, "queryCname", Query<QueryCnameWrap>);
2371
2
  env->SetProtoMethod(channel_wrap, "queryMx", Query<QueryMxWrap>);
2372
2
  env->SetProtoMethod(channel_wrap, "queryNs", Query<QueryNsWrap>);
2373
2
  env->SetProtoMethod(channel_wrap, "queryTxt", Query<QueryTxtWrap>);
2374
2
  env->SetProtoMethod(channel_wrap, "querySrv", Query<QuerySrvWrap>);
2375
2
  env->SetProtoMethod(channel_wrap, "queryPtr", Query<QueryPtrWrap>);
2376
2
  env->SetProtoMethod(channel_wrap, "queryNaptr", Query<QueryNaptrWrap>);
2377
2
  env->SetProtoMethod(channel_wrap, "querySoa", Query<QuerySoaWrap>);
2378
2
  env->SetProtoMethod(channel_wrap, "getHostByAddr", Query<GetHostByAddrWrap>);
2379
2380
2
  env->SetProtoMethodNoSideEffect(channel_wrap, "getServers", GetServers);
2381
2
  env->SetProtoMethod(channel_wrap, "setServers", SetServers);
2382
2
  env->SetProtoMethod(channel_wrap, "setLocalAddress", SetLocalAddress);
2383
2
  env->SetProtoMethod(channel_wrap, "cancel", Cancel);
2384
2385
2
  env->SetConstructorFunction(target, "ChannelWrap", channel_wrap);
2386
2
}
2387
2388
}  // anonymous namespace
2389
}  // namespace cares_wrap
2390
}  // namespace node
2391
2392

481
NODE_MODULE_CONTEXT_AWARE_INTERNAL(cares_wrap, node::cares_wrap::Initialize)