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: 941 1272 74.0 %
Date: 2021-04-16 04:11:37 Branches: 328 678 48.4 %

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
4770
Mutex ares_library_mutex;
83
84
56
inline uint16_t cares_get_16bit(const unsigned char* p) {
85
56
  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
33
inline const char* ToErrorCodeString(int status) {
92






33
  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
2
    V(EBADRESP)
101
    V(EBADSTR)
102
24
    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
1
    V(ENOTFOUND)
112
    V(ENOTIMP)
113
    V(ENOTINITIALIZED)
114
    V(EOF)
115
    V(EREFUSED)
116
    V(ESERVFAIL)
117
6
    V(ETIMEOUT)
118
#undef V
119
  }
120
121
  return "UNKNOWN_ARES_ERROR";
122
}
123
124
class ChannelWrap;
125
126
203
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
1106
struct TaskHash {
137
87
  size_t operator()(node_ares_task* a) const {
138
87
    return std::hash<ares_socket_t>()(a->sock);
139
  }
140
};
141
142
1106
struct TaskEqual {
143
29
  inline bool operator()(node_ares_task* a, node_ares_task* b) const {
144
29
    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
89
  inline uv_timer_t* timer_handle() { return timer_handle_; }
166
247
  inline ares_channel cares_channel() { return channel_; }
167
50
  inline void set_query_last_ok(bool ok) { query_last_ok_ = ok; }
168
24
  inline void set_is_servers_default(bool is_default) {
169
24
    is_servers_default_ = is_default;
170
24
  }
171
28
  inline int active_query_count() { return active_query_count_; }
172
276
  inline node_ares_task_list* task_list() { return &task_list_; }
173
174
4
  void MemoryInfo(MemoryTracker* tracker) const override {
175
4
    if (timer_handle_ != nullptr)
176
      tracker->TrackField("timer_handle", *timer_handle_);
177
4
    tracker->TrackField("task_list", task_list_, "node_ares_task_list");
178
4
  }
179
180
4
  SET_MEMORY_INFO_NAME(ChannelWrap)
181
4
  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
1106
ChannelWrap::ChannelWrap(Environment* env,
197
                         Local<Object> object,
198
1106
                         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
1106
    active_query_count_(0) {
207
1106
  MakeWeak();
208
209
1106
  Setup();
210
1106
}
211
212
1106
void ChannelWrap::New(const FunctionCallbackInfo<Value>& args) {
213
1106
  CHECK(args.IsConstructCall());
214
1106
  CHECK_EQ(args.Length(), 1);
215
2212
  CHECK(args[0]->IsInt32());
216
3318
  const int timeout = args[0].As<Int32>()->Value();
217
1106
  Environment* env = Environment::GetCurrent(args);
218
1106
  new ChannelWrap(env, args.This(), timeout);
219
1106
}
220
221
10288
class GetAddrInfoReqWrap : public ReqWrap<uv_getaddrinfo_t> {
222
 public:
223
  GetAddrInfoReqWrap(Environment* env,
224
                     Local<Object> req_wrap_obj,
225
                     bool verbatim);
226
227
1
  SET_NO_MEMORY_INFO()
228
1
  SET_MEMORY_INFO_NAME(GetAddrInfoReqWrap)
229
1
  SET_SELF_SIZE(GetAddrInfoReqWrap)
230
231
5144
  bool verbatim() const { return verbatim_; }
232
233
 private:
234
  const bool verbatim_;
235
};
236
237
5145
GetAddrInfoReqWrap::GetAddrInfoReqWrap(Environment* env,
238
                                       Local<Object> req_wrap_obj,
239
5145
                                       bool verbatim)
240
    : ReqWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_GETADDRINFOREQWRAP)
241
5145
    , verbatim_(verbatim) {
242
5145
}
243
244
245
8
class GetNameInfoReqWrap : public ReqWrap<uv_getnameinfo_t> {
246
 public:
247
  GetNameInfoReqWrap(Environment* env, Local<Object> req_wrap_obj);
248
249
1
  SET_NO_MEMORY_INFO()
250
1
  SET_MEMORY_INFO_NAME(GetNameInfoReqWrap)
251
1
  SET_SELF_SIZE(GetNameInfoReqWrap)
252
};
253
254
4
GetNameInfoReqWrap::GetNameInfoReqWrap(Environment* env,
255
4
                                       Local<Object> req_wrap_obj)
256
4
    : ReqWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_GETNAMEINFOREQWRAP) {
257
4
}
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
73
void ChannelWrap::AresTimeout(uv_timer_t* handle) {
263
73
  ChannelWrap* channel = static_cast<ChannelWrap*>(handle->data);
264
73
  CHECK_EQ(channel->timer_handle(), handle);
265
73
  CHECK_EQ(false, channel->task_list()->empty());
266
73
  ares_process_fd(channel->cares_channel(), ARES_SOCKET_BAD, ARES_SOCKET_BAD);
267
73
}
268
269
270
16
void ares_poll_cb(uv_poll_t* watcher, int status, int events) {
271
16
  node_ares_task* task = ContainerOf(&node_ares_task::poll_watcher, watcher);
272
16
  ChannelWrap* channel = task->channel;
273
274
  /* Reset the idle timer */
275
16
  uv_timer_again(channel->timer_handle());
276
277
16
  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

32
  ares_process_fd(channel->cares_channel(),
286
16
                  events & UV_READABLE ? task->sock : ARES_SOCKET_BAD,
287
32
                  events & UV_WRITABLE ? task->sock : ARES_SOCKET_BAD);
288
}
289
290
291
29
void ares_poll_close_cb(uv_poll_t* watcher) {
292
29
  node_ares_task* task = ContainerOf(&node_ares_task::poll_watcher, watcher);
293
29
  delete task;
294
29
}
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
29
node_ares_task* ares_task_create(ChannelWrap* channel, ares_socket_t sock) {
302
29
  auto task = new node_ares_task();
303
304
29
  task->channel = channel;
305
29
  task->sock = sock;
306
307
29
  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
29
  return task;
315
}
316
317
318
/* Callback from ares when socket operation is started */
319
58
void ares_sockstate_cb(void* data,
320
                       ares_socket_t sock,
321
                       int read,
322
                       int write) {
323
58
  ChannelWrap* channel = static_cast<ChannelWrap*>(data);
324
  node_ares_task* task;
325
326
116
  node_ares_task lookup_task;
327
58
  lookup_task.sock = sock;
328
58
  auto it = channel->task_list()->find(&lookup_task);
329
330
58
  task = (it == channel->task_list()->end()) ? nullptr : *it;
331
332

58
  if (read || write) {
333
29
    if (!task) {
334
      /* New socket */
335
29
      channel->StartTimer();
336
337
29
      task = ares_task_create(channel, sock);
338
29
      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
29
      channel->task_list()->insert(task);
346
    }
347
348
    /* This should never fail. If it fails anyway, the query will eventually */
349
    /* time out. */
350
29
    uv_poll_start(&task->poll_watcher,
351

29
                  (read ? UV_READABLE : 0) | (write ? UV_WRITABLE : 0),
352
29
                  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
29
    CHECK(task &&
359
          "When an ares socket is closed we should have a handle for it");
360
361
29
    channel->task_list()->erase(it);
362
29
    channel->env()->CloseHandle(&task->poll_watcher, ares_poll_close_cb);
363
364
29
    if (channel->task_list()->empty()) {
365
29
      channel->CloseTimer();
366
    }
367
  }
368
}
369
370
371
6
Local<Array> HostentToNames(Environment* env,
372
                            struct hostent* host,
373
                            Local<Array> append_to = Local<Array>()) {
374
6
  EscapableHandleScope scope(env->isolate());
375
6
  auto context = env->context();
376
6
  bool append = !append_to.IsEmpty();
377
6
  Local<Array> names = append ? append_to : Array::New(env->isolate());
378
6
  size_t offset = names->Length();
379
380
10
  for (uint32_t i = 0; host->h_aliases[i] != nullptr; ++i) {
381
4
    Local<String> address = OneByteString(env->isolate(), host->h_aliases[i]);
382
12
    names->Set(context, i + offset, address).Check();
383
  }
384
385
18
  return append ? names : scope.Escape(names);
386
}
387
388
2
void safe_free_hostent(struct hostent* host) {
389
  int idx;
390
391
2
  if (host->h_addr_list != nullptr) {
392
2
    idx = 0;
393
6
    while (host->h_addr_list[idx]) {
394
2
      free(host->h_addr_list[idx++]);
395
    }
396
2
    free(host->h_addr_list);
397
2
    host->h_addr_list = nullptr;
398
  }
399
400
2
  if (host->h_aliases != nullptr) {
401
2
    idx = 0;
402
2
    while (host->h_aliases[idx]) {
403
      free(host->h_aliases[idx++]);
404
    }
405
2
    free(host->h_aliases);
406
2
    host->h_aliases = nullptr;
407
  }
408
409
2
  free(host->h_name);
410
2
  free(host);
411
2
}
412
413
2
void cares_wrap_hostent_cpy(struct hostent* dest, const struct hostent* src) {
414
2
  dest->h_addr_list = nullptr;
415
2
  dest->h_addrtype = 0;
416
2
  dest->h_aliases = nullptr;
417
2
  dest->h_length = 0;
418
2
  dest->h_name = nullptr;
419
420
  /* copy `h_name` */
421
2
  size_t name_size = strlen(src->h_name) + 1;
422
2
  dest->h_name = node::Malloc<char>(name_size);
423
2
  memcpy(dest->h_name, src->h_name, name_size);
424
425
  /* copy `h_aliases` */
426
  size_t alias_count;
427
2
  for (alias_count = 0;
428
2
      src->h_aliases[alias_count] != nullptr;
429
      alias_count++) {
430
  }
431
432
2
  dest->h_aliases = node::Malloc<char*>(alias_count + 1);
433
2
  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
2
  dest->h_aliases[alias_count] = nullptr;
439
440
  /* copy `h_addr_list` */
441
  size_t list_count;
442
4
  for (list_count = 0;
443
4
      src->h_addr_list[list_count] != nullptr;
444
      list_count++) {
445
  }
446
447
2
  dest->h_addr_list = node::Malloc<char*>(list_count + 1);
448
4
  for (size_t i = 0; i < list_count; i++) {
449
2
    dest->h_addr_list[i] = node::Malloc(src->h_length);
450
2
    memcpy(dest->h_addr_list[i], src->h_addr_list[i], src->h_length);
451
  }
452
2
  dest->h_addr_list[list_count] = nullptr;
453
454
  /* work after work */
455
2
  dest->h_length = src->h_length;
456
2
  dest->h_addrtype = src->h_addrtype;
457
2
}
458
459
class QueryWrap;
460
461
1106
void ChannelWrap::Setup() {
462
  struct ares_options options;
463
1106
  memset(&options, 0, sizeof(options));
464
1106
  options.flags = ARES_FLAG_NOCHECKRESP;
465
1106
  options.sock_state_cb = ares_sockstate_cb;
466
1106
  options.sock_state_cb_data = this;
467
1106
  options.timeout = timeout_;
468
469
  int r;
470
1106
  if (!library_inited_) {
471
2212
    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
1106
    r = ares_library_init(ARES_LIB_INIT_ALL);
475
1106
    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
1106
      ARES_OPT_FLAGS | ARES_OPT_TIMEOUTMS | ARES_OPT_SOCK_STATE_CB;
482
1106
  r = ares_init_options(&channel_, &options, optmask);
483
484
1106
  if (r != ARES_SUCCESS) {
485
    Mutex::ScopedLock lock(ares_library_mutex);
486
    ares_library_cleanup();
487
    return env()->ThrowError(ToErrorCodeString(r));
488
  }
489
490
1106
  library_inited_ = true;
491
}
492
493
29
void ChannelWrap::StartTimer() {
494
29
  if (timer_handle_ == nullptr) {
495
29
    timer_handle_ = new uv_timer_t();
496
29
    timer_handle_->data = static_cast<void*>(this);
497
29
    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
29
  int timeout = timeout_;
502
29
  if (timeout == 0) timeout = 1;
503

29
  if (timeout < 0 || timeout > 1000) timeout = 1000;
504
29
  uv_timer_start(timer_handle_, AresTimeout, timeout, timeout);
505
}
506
507
1107
void ChannelWrap::CloseTimer() {
508
1107
  if (timer_handle_ == nullptr)
509
1078
    return;
510
511
58
  env()->CloseHandle(timer_handle_, [](uv_timer_t* handle) { delete handle; });
512
29
  timer_handle_ = nullptr;
513
}
514
515
3234
ChannelWrap::~ChannelWrap() {
516
1078
  ares_destroy(channel_);
517
518
1078
  if (library_inited_) {
519
2156
    Mutex::ScopedLock lock(ares_library_mutex);
520
    // This decreases the reference counter increased by ares_library_init().
521
1078
    ares_library_cleanup();
522
  }
523
524
1078
  CloseTimer();
525
2156
}
526
527
528
101
void ChannelWrap::ModifyActivityQueryCount(int count) {
529
101
  active_query_count_ += count;
530
101
  CHECK_GE(active_query_count_, 0);
531
101
}
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
48
void ChannelWrap::EnsureServers() {
542
  /* if last query is OK or servers are set by user self, do not check */
543

48
  if (query_last_ok_ || !is_servers_default_) {
544
96
    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
51
  QueryWrap(ChannelWrap* channel, Local<Object> req_wrap_obj, const char* name)
583
51
      : AsyncWrap(channel->env(), req_wrap_obj, AsyncWrap::PROVIDER_QUERYWRAP),
584
        channel_(channel),
585
51
        trace_name_(name) {
586
51
  }
587
588
102
  ~QueryWrap() override {
589
102
    CHECK_EQ(false, persistent().IsEmpty());
590
591
    // Let Callback() know that this object no longer exists.
592
51
    if (callback_ptr_ != nullptr)
593
1
      *callback_ptr_ = nullptr;
594
51
  }
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
48
  void AresQuery(const char* name,
609
                 int dnsclass,
610
                 int type) {
611
48
    channel_->EnsureServers();
612
48
    TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(
613
      TRACING_CATEGORY_NODE2(dns, native), trace_name_, this,
614
      "name", TRACE_STR_COPY(name));
615
48
    ares_query(channel_->cares_channel(), name, dnsclass, type, Callback,
616
144
               MakeCallbackPointer());
617
96
  }
618
619
100
  struct ResponseData {
620
    int status;
621
    bool is_host;
622
    DeleteFnPtr<hostent, safe_free_hostent> host;
623
    MallocedBuffer<unsigned char> buf;
624
  };
625
626
50
  void AfterResponse() {
627
50
    CHECK(response_data_);
628
629
50
    const int status = response_data_->status;
630
631
50
    if (status != ARES_SUCCESS) {
632
31
      ParseError(status);
633
19
    } else if (!response_data_->is_host) {
634
17
      Parse(response_data_->buf.data, response_data_->buf.size);
635
    } else {
636
2
      Parse(response_data_->host.get());
637
    }
638
50
  }
639
640
51
  void* MakeCallbackPointer() {
641
51
    CHECK_NULL(callback_ptr_);
642
51
    callback_ptr_ = new QueryWrap*(this);
643
51
    return callback_ptr_;
644
  }
645
646
51
  static QueryWrap* FromCallbackPointer(void* arg) {
647
102
    std::unique_ptr<QueryWrap*> wrap_ptr { static_cast<QueryWrap**>(arg) };
648
51
    QueryWrap* wrap = *wrap_ptr.get();
649
51
    if (wrap == nullptr) return nullptr;
650
50
    wrap->callback_ptr_ = nullptr;
651
50
    return wrap;
652
  }
653
654
48
  static void Callback(void* arg, int status, int timeouts,
655
                       unsigned char* answer_buf, int answer_len) {
656
48
    QueryWrap* wrap = FromCallbackPointer(arg);
657
48
    if (wrap == nullptr) return;
658
659
47
    unsigned char* buf_copy = nullptr;
660
47
    if (status == ARES_SUCCESS) {
661
17
      buf_copy = node::Malloc<unsigned char>(answer_len);
662
17
      memcpy(buf_copy, answer_buf, answer_len);
663
    }
664
665
47
    wrap->response_data_ = std::make_unique<ResponseData>();
666
47
    ResponseData* data = wrap->response_data_.get();
667
47
    data->status = status;
668
47
    data->is_host = false;
669
47
    data->buf = MallocedBuffer<unsigned char>(buf_copy, answer_len);
670
671
47
    wrap->QueueResponseCallback(status);
672
  }
673
674
3
  static void Callback(void* arg, int status, int timeouts,
675
                       struct hostent* host) {
676
3
    QueryWrap* wrap = FromCallbackPointer(arg);
677
3
    if (wrap == nullptr) return;
678
679
3
    struct hostent* host_copy = nullptr;
680
3
    if (status == ARES_SUCCESS) {
681
2
      host_copy = node::Malloc<hostent>(1);
682
2
      cares_wrap_hostent_cpy(host_copy, host);
683
    }
684
685
3
    wrap->response_data_ = std::make_unique<ResponseData>();
686
3
    ResponseData* data = wrap->response_data_.get();
687
3
    data->status = status;
688
3
    data->host.reset(host_copy);
689
3
    data->is_host = true;
690
691
3
    wrap->QueueResponseCallback(status);
692
  }
693
694
50
  void QueueResponseCallback(int status) {
695
100
    BaseObjectPtr<QueryWrap> strong_ref{this};
696
350
    env()->SetImmediate([this, strong_ref](Environment*) {
697
50
      AfterResponse();
698
699
      // Delete once strong_ref goes out of scope.
700
50
      Detach();
701
100
    });
702
703
50
    channel_->set_query_last_ok(status != ARES_ECONNREFUSED);
704
50
    channel_->ModifyActivityQueryCount(-1);
705
50
  }
706
707
17
  void CallOnComplete(Local<Value> answer,
708
                      Local<Value> extra = Local<Value>()) {
709
34
    HandleScope handle_scope(env()->isolate());
710
17
    Context::Scope context_scope(env()->context());
711
    Local<Value> argv[] = {
712
      Integer::New(env()->isolate(), 0),
713
      answer,
714
      extra
715
34
    };
716
34
    const int argc = arraysize(argv) - extra.IsEmpty();
717
17
    TRACE_EVENT_NESTABLE_ASYNC_END0(
718
        TRACING_CATEGORY_NODE2(dns, native), trace_name_, this);
719
720
23
    MakeCallback(env()->oncomplete_string(), argc, argv);
721
51
  }
722
17
723
33
  void ParseError(int status) {
724
33
    CHECK_NE(status, ARES_SUCCESS);
725
66
    HandleScope handle_scope(env()->isolate());
726
33
    Context::Scope context_scope(env()->context());
727
33
    const char* code = ToErrorCodeString(status);
728
33
    Local<Value> arg = OneByteString(env()->isolate(), code);
729
33
    TRACE_EVENT_NESTABLE_ASYNC_END1(
730
        TRACING_CATEGORY_NODE2(dns, native), trace_name_, this,
731
        "error", status);
732
40
    MakeCallback(env()->oncomplete_string(), 1, &arg);
733
99
  }
734
33
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
9
Local<Array> AddrTTLToArray(Environment* env,
757
                            const T* addrttls,
758
                            size_t naddrttls) {
759
9
  auto isolate = env->isolate();
760
761
18
  MaybeStackBuffer<Local<Value>, 8> ttls(naddrttls);
762

18
  for (size_t i = 0; i < naddrttls; i++)
763
18
    ttls[i] = Integer::NewFromUnsigned(isolate, addrttls[i].ttl);
764
765
18
  return Array::New(isolate, ttls.out(), naddrttls);
766
}
767
768
769
27
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
54
  HandleScope handle_scope(env->isolate());
777
27
  auto context = env->context();
778
  hostent* host;
779
780
  int status;
781

27
  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
13
                                  naddrttls);
790
13
      break;
791
    case ns_t_aaaa:
792
      status = ares_parse_aaaa_reply(buf,
793
                                     len,
794
                                     &host,
795
                                     static_cast<ares_addr6ttl*>(addrttls),
796
6
                                     naddrttls);
797
6
      break;
798
    case ns_t_ns:
799
4
      status = ares_parse_ns_reply(buf, len, &host);
800
4
      break;
801
    case ns_t_ptr:
802
4
      status = ares_parse_ptr_reply(buf, len, nullptr, 0, AF_INET, &host);
803
4
      break;
804
    default:
805
      CHECK(0 && "Bad NS type");
806
      break;
807
  }
808
809
27
  if (status != ARES_SUCCESS)
810
2
    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


50
  if ((*type == ns_t_cname_or_a && host->h_name && host->h_aliases[0]) ||
816
25
      *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
25
  if (*type == ns_t_cname_or_a)
828
4
    *type = ns_t_a;
829
830
25
  if (*type == ns_t_ns) {
831
4
    HostentToNames(env, host, ret);
832
21
  } else if (*type == ns_t_ptr) {
833
4
    uint32_t offset = ret->Length();
834
8
    for (uint32_t i = 0; host->h_aliases[i] != nullptr; i++) {
835
4
      auto alias = OneByteString(env->isolate(), host->h_aliases[i]);
836
12
      ret->Set(context, i + offset, alias).Check();
837
    }
838
  } else {
839
17
    uint32_t offset = ret->Length();
840
    char ip[INET6_ADDRSTRLEN];
841
34
    for (uint32_t i = 0; host->h_addr_list[i] != nullptr; ++i) {
842
17
      uv_inet_ntop(host->h_addrtype, host->h_addr_list[i], ip, sizeof(ip));
843
17
      auto address = OneByteString(env->isolate(), ip);
844
51
      ret->Set(context, i + offset, address).Check();
845
    }
846
  }
847
848
25
  ares_free_hostent(host);
849
850
25
  return ARES_SUCCESS;
851
}
852
853
854
4
int ParseMxReply(Environment* env,
855
                 const unsigned char* buf,
856
                 int len,
857
                 Local<Array> ret,
858
                 bool need_type = false) {
859
8
  HandleScope handle_scope(env->isolate());
860
4
  auto context = env->context();
861
862
  struct ares_mx_reply* mx_start;
863
4
  int status = ares_parse_mx_reply(buf, len, &mx_start);
864
4
  if (status != ARES_SUCCESS) {
865
    return status;
866
  }
867
868
4
  uint32_t offset = ret->Length();
869
4
  ares_mx_reply* current = mx_start;
870
8
  for (uint32_t i = 0; current != nullptr; ++i, current = current->next) {
871
4
    Local<Object> mx_record = Object::New(env->isolate());
872
8
    mx_record->Set(context,
873
                   env->exchange_string(),
874
16
                   OneByteString(env->isolate(), current->host)).Check();
875
8
    mx_record->Set(context,
876
                   env->priority_string(),
877
16
                   Integer::New(env->isolate(), current->priority)).Check();
878
4
    if (need_type)
879
8
      mx_record->Set(context,
880
                     env->type_string(),
881
16
                     env->dns_mx_string()).Check();
882
883
12
    ret->Set(context, i + offset, mx_record).Check();
884
  }
885
886
4
  ares_free_data(mx_start);
887
4
  return ARES_SUCCESS;
888
}
889
890
4
int ParseCaaReply(Environment* env,
891
                  const unsigned char* buf,
892
                  int len,
893
                  Local<Array> ret,
894
                  bool need_type = false) {
895
8
  HandleScope handle_scope(env->isolate());
896
4
  auto context = env->context();
897
898
  struct ares_caa_reply* caa_start;
899
4
  int status = ares_parse_caa_reply(buf, len, &caa_start);
900
4
  if (status != ARES_SUCCESS) {
901
    return status;
902
  }
903
904
4
  uint32_t offset = ret->Length();
905
4
  ares_caa_reply* current = caa_start;
906
6
  for (uint32_t i = 0; current != nullptr; ++i, current = current->next) {
907
2
    Local<Object> caa_record = Object::New(env->isolate());
908
909
4
    caa_record->Set(context,
910
                    env->dns_critical_string(),
911
8
                    Integer::New(env->isolate(), current->critical)).Check();
912
4
    caa_record->Set(context,
913
2
                    OneByteString(env->isolate(), current->property),
914
8
                    OneByteString(env->isolate(), current->value)).Check();
915
2
    if (need_type)
916
4
      caa_record->Set(context,
917
                      env->type_string(),
918
8
                      env->dns_caa_string()).Check();
919
920
6
    ret->Set(context, i + offset, caa_record).Check();
921
  }
922
923
4
  ares_free_data(caa_start);
924
4
  return ARES_SUCCESS;
925
}
926
927
4
int ParseTxtReply(Environment* env,
928
                  const unsigned char* buf,
929
                  int len,
930
                  Local<Array> ret,
931
                  bool need_type = false) {
932
8
  HandleScope handle_scope(env->isolate());
933
4
  auto context = env->context();
934
935
  struct ares_txt_ext* txt_out;
936
937
4
  int status = ares_parse_txt_reply_ext(buf, len, &txt_out);
938
4
  if (status != ARES_SUCCESS) {
939
    return status;
940
  }
941
942
  Local<Array> txt_chunk;
943
944
4
  struct ares_txt_ext* current = txt_out;
945
4
  uint32_t i = 0, j;
946
4
  uint32_t offset = ret->Length();
947
8
  for (j = 0; current != nullptr; current = current->next) {
948
    Local<String> txt =
949
4
        OneByteString(env->isolate(), current->txt, current->length);
950
951
    // New record found - write out the current chunk
952
4
    if (current->record_start) {
953
2
      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
2
      txt_chunk = Array::New(env->isolate());
967
2
      j = 0;
968
    }
969
970
12
    txt_chunk->Set(context, j++, txt).Check();
971
  }
972
973
  // Push last chunk if it isn't empty
974
4
  if (!txt_chunk.IsEmpty()) {
975
2
    if (need_type) {
976
2
      Local<Object> elem = Object::New(env->isolate());
977
6
      elem->Set(context, env->entries_string(), txt_chunk).Check();
978
4
      elem->Set(context,
979
                env->type_string(),
980
8
                env->dns_txt_string()).Check();
981
6
      ret->Set(context, offset + i, elem).Check();
982
    } else {
983
      ret->Set(context, offset + i, txt_chunk).Check();
984
    }
985
  }
986
987
4
  ares_free_data(txt_out);
988
4
  return ARES_SUCCESS;
989
}
990
991
992
4
int ParseSrvReply(Environment* env,
993
                  const unsigned char* buf,
994
                  int len,
995
                  Local<Array> ret,
996
                  bool need_type = false) {
997
8
  HandleScope handle_scope(env->isolate());
998
4
  auto context = env->context();
999
1000
  struct ares_srv_reply* srv_start;
1001
4
  int status = ares_parse_srv_reply(buf, len, &srv_start);
1002
4
  if (status != ARES_SUCCESS) {
1003
    return status;
1004
  }
1005
1006
4
  ares_srv_reply* current = srv_start;
1007
4
  int offset = ret->Length();
1008
4
  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
4
  ares_free_data(srv_start);
1031
4
  return ARES_SUCCESS;
1032
}
1033
1034
1035
4
int ParseNaptrReply(Environment* env,
1036
                    const unsigned char* buf,
1037
                    int len,
1038
                    Local<Array> ret,
1039
                    bool need_type = false) {
1040
8
  HandleScope handle_scope(env->isolate());
1041
4
  auto context = env->context();
1042
1043
  ares_naptr_reply* naptr_start;
1044
4
  int status = ares_parse_naptr_reply(buf, len, &naptr_start);
1045
1046
4
  if (status != ARES_SUCCESS) {
1047
    return status;
1048
  }
1049
1050
4
  ares_naptr_reply* current = naptr_start;
1051
4
  int offset = ret->Length();
1052
4
  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
4
  ares_free_data(naptr_start);
1085
4
  return ARES_SUCCESS;
1086
}
1087
1088
1089
4
int ParseSoaReply(Environment* env,
1090
                  unsigned char* buf,
1091
                  int len,
1092
                  Local<Object>* ret) {
1093
4
  EscapableHandleScope handle_scope(env->isolate());
1094
4
  auto context = env->context();
1095
1096
  // Manage memory using standardard smart pointer std::unique_tr
1097
  struct AresDeleter {
1098
38
    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
4
  const unsigned int ancount = cares_get_16bit(buf + 6);
1104
4
  unsigned char* ptr = buf + NS_HFIXEDSZ;
1105
4
  char* name_temp = nullptr;
1106
  long temp_len;  // NOLINT(runtime/int)
1107
4
  int status = ares_expand_name(ptr, buf, len, &name_temp, &temp_len);
1108
4
  if (status != ARES_SUCCESS) {
1109
    // returns EBADRESP in case of invalid input
1110
    return status == ARES_EBADNAME ? ARES_EBADRESP : status;
1111
  }
1112
1113
8
  const ares_unique_ptr name(name_temp);
1114
1115
4
  if (ptr + temp_len + NS_QFIXEDSZ > buf + len) {
1116
    return ARES_EBADRESP;
1117
  }
1118
4
  ptr += temp_len + NS_QFIXEDSZ;
1119
1120
26
  for (unsigned int i = 0; i < ancount; i++) {
1121
26
    char* rr_name_temp = nullptr;
1122
    long rr_temp_len;  // NOLINT(runtime/int)
1123
26
    int status2 = ares_expand_name(ptr, buf, len, &rr_name_temp, &rr_temp_len);
1124
1125
26
    if (status2 != ARES_SUCCESS)
1126
      return status2 == ARES_EBADNAME ? ARES_EBADRESP : status2;
1127
1128
48
    const ares_unique_ptr rr_name(rr_name_temp);
1129
1130
26
    ptr += rr_temp_len;
1131
26
    if (ptr + NS_RRFIXEDSZ > buf + len) {
1132
      return ARES_EBADRESP;
1133
    }
1134
1135
26
    const int rr_type = cares_get_16bit(ptr);
1136
26
    const int rr_len = cares_get_16bit(ptr + 8);
1137
26
    ptr += NS_RRFIXEDSZ;
1138
1139
    // only need SOA
1140
26
    if (rr_type == ns_t_soa) {
1141
4
      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
4
                                     &nsname_temp_len);
1147
4
      if (status3 != ARES_SUCCESS) {
1148
        return status3 == ARES_EBADNAME ? ARES_EBADRESP : status3;
1149
      }
1150
4
      const ares_unique_ptr nsname(nsname_temp);
1151
4
      ptr += nsname_temp_len;
1152
1153
4
      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
4
                                     &hostmaster_temp_len);
1158
4
      if (status4 != ARES_SUCCESS) {
1159
        return status4 == ARES_EBADNAME ? ARES_EBADRESP : status4;
1160
      }
1161
4
      const ares_unique_ptr hostmaster(hostmaster_temp);
1162
4
      ptr += hostmaster_temp_len;
1163
1164
4
      if (ptr + 5 * 4 > buf + len) {
1165
        return ARES_EBADRESP;
1166
      }
1167
1168
4
      const unsigned int serial = ReadUint32BE(ptr + 0 * 4);
1169
4
      const unsigned int refresh = ReadUint32BE(ptr + 1 * 4);
1170
4
      const unsigned int retry = ReadUint32BE(ptr + 2 * 4);
1171
4
      const unsigned int expire = ReadUint32BE(ptr + 3 * 4);
1172
4
      const unsigned int minttl = ReadUint32BE(ptr + 4 * 4);
1173
1174
4
      Local<Object> soa_record = Object::New(env->isolate());
1175
8
      soa_record->Set(context,
1176
                      env->nsname_string(),
1177
16
                      OneByteString(env->isolate(), nsname.get())).Check();
1178
8
      soa_record->Set(context,
1179
                      env->hostmaster_string(),
1180
                      OneByteString(env->isolate(),
1181
16
                                    hostmaster.get())).Check();
1182
8
      soa_record->Set(context,
1183
                      env->serial_string(),
1184
16
                      Integer::NewFromUnsigned(env->isolate(), serial)).Check();
1185
8
      soa_record->Set(context,
1186
                      env->refresh_string(),
1187
16
                      Integer::New(env->isolate(), refresh)).Check();
1188
8
      soa_record->Set(context,
1189
                      env->retry_string(),
1190
16
                      Integer::New(env->isolate(), retry)).Check();
1191
8
      soa_record->Set(context,
1192
                      env->expire_string(),
1193
16
                      Integer::New(env->isolate(), expire)).Check();
1194
8
      soa_record->Set(context,
1195
                      env->minttl_string(),
1196
16
                      Integer::NewFromUnsigned(env->isolate(), minttl)).Check();
1197
8
      soa_record->Set(context,
1198
                      env->type_string(),
1199
16
                      env->dns_soa_string()).Check();
1200
1201
1202
4
      *ret = handle_scope.Escape(soa_record);
1203

4
      break;
1204
    }
1205
1206
22
    ptr += rr_len;
1207
  }
1208
1209
4
  return ARES_SUCCESS;
1210
}
1211
1212
1213
12
class QueryAnyWrap: public QueryWrap {
1214
 public:
1215
6
  QueryAnyWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1216
6
    : QueryWrap(channel, req_wrap_obj, "resolveAny") {
1217
6
  }
1218
1219
6
  int Send(const char* name) override {
1220
6
    AresQuery(name, ns_c_in, ns_t_any);
1221
6
    return 0;
1222
  }
1223
1224
  SET_NO_MEMORY_INFO()
1225
  SET_MEMORY_INFO_NAME(QueryAnyWrap)
1226
  SET_SELF_SIZE(QueryAnyWrap)
1227
1228
 protected:
1229
6
  void Parse(unsigned char* buf, int len) override {
1230
10
    HandleScope handle_scope(env()->isolate());
1231
6
    auto context = env()->context();
1232
4
    Context::Scope context_scope(context);
1233
1234
6
    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
6
    int naddrttls = arraysize(addrttls);
1240
1241
6
    type = ns_t_cname_or_a;
1242
6
    status = ParseGeneralReply(env(),
1243
                               buf,
1244
                               len,
1245
                               &type,
1246
                               ret,
1247
                               addrttls,
1248
6
                               &naddrttls);
1249
6
    uint32_t a_count = ret->Length();
1250

6
    if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1251
2
      ParseError(status);
1252
2
      return;
1253
    }
1254
1255
4
    if (type == ns_t_a) {
1256
4
      CHECK_EQ(static_cast<uint32_t>(naddrttls), a_count);
1257
8
      for (uint32_t i = 0; i < a_count; i++) {
1258
4
        Local<Object> obj = Object::New(env()->isolate());
1259
8
        obj->Set(context,
1260
                 env()->address_string(),
1261
16
                 ret->Get(context, i).ToLocalChecked()).Check();
1262
8
        obj->Set(context,
1263
                 env()->ttl_string(),
1264
                 Integer::NewFromUnsigned(
1265
16
                   env()->isolate(), addrttls[i].ttl)).Check();
1266
8
        obj->Set(context,
1267
                 env()->type_string(),
1268
16
                 env()->dns_a_string()).Check();
1269
8
        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
4
    int naddr6ttls = arraysize(addr6ttls);
1287
1288
4
    type = ns_t_aaaa;
1289
4
    status = ParseGeneralReply(env(),
1290
                               buf,
1291
                               len,
1292
                               &type,
1293
                               ret,
1294
                               addr6ttls,
1295
4
                               &naddr6ttls);
1296
4
    uint32_t aaaa_count = ret->Length() - a_count;
1297

4
    if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1298
      ParseError(status);
1299
      return;
1300
    }
1301
1302
4
    CHECK_EQ(aaaa_count, static_cast<uint32_t>(naddr6ttls));
1303
4
    CHECK_EQ(ret->Length(), a_count + aaaa_count);
1304
16
    for (uint32_t i = a_count; i < ret->Length(); i++) {
1305
4
      Local<Object> obj = Object::New(env()->isolate());
1306
8
      obj->Set(context,
1307
               env()->address_string(),
1308
16
               ret->Get(context, i).ToLocalChecked()).Check();
1309
8
      obj->Set(context,
1310
               env()->ttl_string(),
1311
               Integer::NewFromUnsigned(
1312
16
                 env()->isolate(), addr6ttls[i - a_count].ttl)).Check();
1313
8
      obj->Set(context,
1314
               env()->type_string(),
1315
16
               env()->dns_aaaa_string()).Check();
1316
8
      ret->Set(context, i, obj).Check();
1317
    }
1318
1319
    /* Parse MX records */
1320
4
    status = ParseMxReply(env(), buf, len, ret, true);
1321

4
    if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1322
      ParseError(status);
1323
      return;
1324
    }
1325
1326
    /* Parse NS records */
1327
4
    type = ns_t_ns;
1328
4
    old_count = ret->Length();
1329
4
    status = ParseGeneralReply(env(), buf, len, &type, ret);
1330

4
    if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1331
      ParseError(status);
1332
      return;
1333
    }
1334
16
    for (uint32_t i = old_count; i < ret->Length(); i++) {
1335
4
      Local<Object> obj = Object::New(env()->isolate());
1336
8
      obj->Set(context,
1337
               env()->value_string(),
1338
16
               ret->Get(context, i).ToLocalChecked()).Check();
1339
8
      obj->Set(context,
1340
               env()->type_string(),
1341
16
               env()->dns_ns_string()).Check();
1342
8
      ret->Set(context, i, obj).Check();
1343
    }
1344
1345
    /* Parse TXT records */
1346
4
    status = ParseTxtReply(env(), buf, len, ret, true);
1347

4
    if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1348
      ParseError(status);
1349
      return;
1350
    }
1351
1352
    /* Parse SRV records */
1353
4
    status = ParseSrvReply(env(), buf, len, ret, true);
1354

4
    if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1355
      return;
1356
    }
1357
1358
    /* Parse PTR records */
1359
4
    type = ns_t_ptr;
1360
4
    old_count = ret->Length();
1361
4
    status = ParseGeneralReply(env(), buf, len, &type, ret);
1362
16
    for (uint32_t i = old_count; i < ret->Length(); i++) {
1363
4
      Local<Object> obj = Object::New(env()->isolate());
1364
8
      obj->Set(context,
1365
               env()->value_string(),
1366
16
               ret->Get(context, i).ToLocalChecked()).Check();
1367
8
      obj->Set(context,
1368
               env()->type_string(),
1369
16
               env()->dns_ptr_string()).Check();
1370
8
      ret->Set(context, i, obj).Check();
1371
    }
1372
1373
    /* Parse NAPTR records */
1374
4
    status = ParseNaptrReply(env(), buf, len, ret, true);
1375

4
    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
4
    status = ParseSoaReply(env(), buf, len, &soa_record);
1383

4
    if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1384
      ParseError(status);
1385
      return;
1386
    }
1387
4
    if (!soa_record.IsEmpty())
1388
12
      ret->Set(context, ret->Length(), soa_record).Check();
1389
1390
    /* Parse CAA records */
1391
4
    status = ParseCaaReply(env(), buf, len, ret, true);
1392

4
    if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1393
      ParseError(status);
1394
      return;
1395
    }
1396
1397
4
    CallOnComplete(ret);
1398
  }
1399
};
1400
1401
1402
72
class QueryAWrap: public QueryWrap {
1403
 public:
1404
36
  QueryAWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1405
36
      : QueryWrap(channel, req_wrap_obj, "resolve4") {
1406
36
  }
1407
1408
36
  int Send(const char* name) override {
1409
36
    AresQuery(name, ns_c_in, ns_t_a);
1410
36
    return 0;
1411
  }
1412
1413
  SET_NO_MEMORY_INFO()
1414
  SET_MEMORY_INFO_NAME(QueryAWrap)
1415
  SET_SELF_SIZE(QueryAWrap)
1416
1417
 protected:
1418
7
  void Parse(unsigned char* buf, int len) override {
1419
14
    HandleScope handle_scope(env()->isolate());
1420
14
    Context::Scope context_scope(env()->context());
1421
1422
    ares_addrttl addrttls[256];
1423
7
    int naddrttls = arraysize(addrttls), status;
1424
7
    Local<Array> ret = Array::New(env()->isolate());
1425
1426
7
    int type = ns_t_a;
1427
7
    status = ParseGeneralReply(env(),
1428
                               buf,
1429
                               len,
1430
                               &type,
1431
                               ret,
1432
                               addrttls,
1433
7
                               &naddrttls);
1434
7
    if (status != ARES_SUCCESS) {
1435
      ParseError(status);
1436
      return;
1437
    }
1438
1439
    Local<Array> ttls = AddrTTLToArray<ares_addrttl>(env(),
1440
                                                     addrttls,
1441
7
                                                     naddrttls);
1442
1443
7
    CallOnComplete(ret, ttls);
1444
  }
1445
};
1446
1447
1448
6
class QueryAaaaWrap: public QueryWrap {
1449
 public:
1450
3
  QueryAaaaWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1451
3
      : QueryWrap(channel, req_wrap_obj, "resolve6") {
1452
3
  }
1453
1454
3
  int Send(const char* name) override {
1455
3
    AresQuery(name, ns_c_in, ns_t_aaaa);
1456
3
    return 0;
1457
  }
1458
1459
1
  SET_NO_MEMORY_INFO()
1460
1
  SET_MEMORY_INFO_NAME(QueryAaaaWrap)
1461
1
  SET_SELF_SIZE(QueryAaaaWrap)
1462
1463
 protected:
1464
2
  void Parse(unsigned char* buf, int len) override {
1465
4
    HandleScope handle_scope(env()->isolate());
1466
4
    Context::Scope context_scope(env()->context());
1467
1468
    ares_addr6ttl addrttls[256];
1469
2
    int naddrttls = arraysize(addrttls), status;
1470
2
    Local<Array> ret = Array::New(env()->isolate());
1471
1472
2
    int type = ns_t_aaaa;
1473
2
    status = ParseGeneralReply(env(),
1474
                               buf,
1475
                               len,
1476
                               &type,
1477
                               ret,
1478
                               addrttls,
1479
2
                               &naddrttls);
1480
2
    if (status != ARES_SUCCESS) {
1481
      ParseError(status);
1482
      return;
1483
    }
1484
1485
    Local<Array> ttls = AddrTTLToArray<ares_addr6ttl>(env(),
1486
                                                      addrttls,
1487
2
                                                      naddrttls);
1488
1489
2
    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
2
class QueryMxWrap: public QueryWrap {
1558
 public:
1559
1
  QueryMxWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1560
1
      : QueryWrap(channel, req_wrap_obj, "resolveMx") {
1561
1
  }
1562
1563
1
  int Send(const char* name) override {
1564
1
    AresQuery(name, ns_c_in, ns_t_mx);
1565
1
    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
4
class QuerySoaWrap: public QueryWrap {
1752
 public:
1753
2
  QuerySoaWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1754
2
      : QueryWrap(channel, req_wrap_obj, "resolveSoa") {
1755
2
  }
1756
1757
2
  int Send(const char* name) override {
1758
2
    AresQuery(name, ns_c_in, ns_t_soa);
1759
2
    return 0;
1760
  }
1761
1762
  SET_NO_MEMORY_INFO()
1763
  SET_MEMORY_INFO_NAME(QuerySoaWrap)
1764
  SET_SELF_SIZE(QuerySoaWrap)
1765
1766
 protected:
1767
2
  void Parse(unsigned char* buf, int len) override {
1768
4
    HandleScope handle_scope(env()->isolate());
1769
2
    auto context = env()->context();
1770
2
    Context::Scope context_scope(context);
1771
1772
    ares_soa_reply* soa_out;
1773
2
    int status = ares_parse_soa_reply(buf, len, &soa_out);
1774
1775
2
    if (status != ARES_SUCCESS) {
1776
      ParseError(status);
1777
      return;
1778
    }
1779
1780
2
    Local<Object> soa_record = Object::New(env()->isolate());
1781
1782
4
    soa_record->Set(context,
1783
                    env()->nsname_string(),
1784
                    OneByteString(env()->isolate(),
1785
8
                                  soa_out->nsname)).Check();
1786
4
    soa_record->Set(context,
1787
                    env()->hostmaster_string(),
1788
                    OneByteString(env()->isolate(),
1789
8
                                  soa_out->hostmaster)).Check();
1790
4
    soa_record->Set(context,
1791
                    env()->serial_string(),
1792
                    Integer::NewFromUnsigned(
1793
8
                      env()->isolate(), soa_out->serial)).Check();
1794
4
    soa_record->Set(context,
1795
                    env()->refresh_string(),
1796
                    Integer::New(env()->isolate(),
1797
8
                                 soa_out->refresh)).Check();
1798
4
    soa_record->Set(context,
1799
                    env()->retry_string(),
1800
8
                    Integer::New(env()->isolate(), soa_out->retry)).Check();
1801
4
    soa_record->Set(context,
1802
                    env()->expire_string(),
1803
8
                    Integer::New(env()->isolate(), soa_out->expire)).Check();
1804
4
    soa_record->Set(context,
1805
                    env()->minttl_string(),
1806
                    Integer::NewFromUnsigned(
1807
8
                      env()->isolate(), soa_out->minttl)).Check();
1808
1809
2
    ares_free_data(soa_out);
1810
1811
2
    this->CallOnComplete(soa_record);
1812
  }
1813
};
1814
1815
1816
6
class GetHostByAddrWrap: public QueryWrap {
1817
 public:
1818
3
  explicit GetHostByAddrWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1819
3
      : QueryWrap(channel, req_wrap_obj, "reverse") {
1820
3
  }
1821
1822
3
  int Send(const char* name) override {
1823
    int length, family;
1824
    char address_buffer[sizeof(struct in6_addr)];
1825
1826
3
    if (uv_inet_pton(AF_INET, name, &address_buffer) == 0) {
1827
3
      length = sizeof(struct in_addr);
1828
3
      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
3
        TRACING_CATEGORY_NODE2(dns, native), "reverse", this,
1838
3
        "name", TRACE_STR_COPY(name),
1839
2
        "family", family == AF_INET ? "ipv4" : "ipv6");
1840
8
1841
6
    ares_gethostbyaddr(channel_->cares_channel(),
1842
                       address_buffer,
1843
                       length,
1844
                       family,
1845
                       Callback,
1846
3
                       MakeCallbackPointer());
1847
3
    return 0;
1848
  }
1849
1850
  SET_NO_MEMORY_INFO()
1851
  SET_MEMORY_INFO_NAME(GetHostByAddrWrap)
1852
  SET_SELF_SIZE(GetHostByAddrWrap)
1853
1854
 protected:
1855
2
  void Parse(struct hostent* host) override {
1856
4
    HandleScope handle_scope(env()->isolate());
1857
2
    Context::Scope context_scope(env()->context());
1858
4
    this->CallOnComplete(HostentToNames(env(), host));
1859
2
  }
1860
};
1861
1862
1863
template <class Wrap>
1864
51
static void Query(const FunctionCallbackInfo<Value>& args) {
1865
51
  Environment* env = Environment::GetCurrent(args);
1866
  ChannelWrap* channel;
1867






51
  ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
1868
1869






51
  CHECK_EQ(false, args.IsConstructCall());
1870






102
  CHECK(args[0]->IsObject());
1871






153
  CHECK(args[1]->IsString());
1872
1873
102
  Local<Object> req_wrap_obj = args[0].As<Object>();
1874
102
  Local<String> string = args[1].As<String>();
1875
102
  auto wrap = std::make_unique<Wrap>(channel, req_wrap_obj);
1876
1877
102
  node::Utf8Value name(env->isolate(), string);
1878
51
  channel->ModifyActivityQueryCount(1);
1879
51
  int err = wrap->Send(*name);
1880






51
  if (err) {
1881
    channel->ModifyActivityQueryCount(-1);
1882
  } else {
1883
    // Release ownership of the pointer allowing the ownership to be transferred
1884
51
    USE(wrap.release());
1885
  }
1886
1887
102
  args.GetReturnValue().Set(err);
1888
}
1889
1890
1891
5144
void AfterGetAddrInfo(uv_getaddrinfo_t* req, int status, struct addrinfo* res) {
1892
  std::unique_ptr<GetAddrInfoReqWrap> req_wrap {
1893
10288
      static_cast<GetAddrInfoReqWrap*>(req->data)};
1894
5144
  Environment* env = req_wrap->env();
1895
1896
10288
  HandleScope handle_scope(env->isolate());
1897
5144
  Context::Scope context_scope(env->context());
1898
1899
  Local<Value> argv[] = {
1900
    Integer::New(env->isolate(), status),
1901
    Null(env->isolate())
1902
15432
  };
1903
1904
5144
  uint32_t n = 0;
1905
5144
  const bool verbatim = req_wrap->verbatim();
1906
1907
5144
  if (status == 0) {
1908
5135
    Local<Array> results = Array::New(env->isolate());
1909
1910
10270
    auto add = [&] (bool want_ipv4, bool want_ipv6) {
1911
41778
      for (auto p = res; p != nullptr; p = p->ai_next) {
1912
31508
        CHECK_EQ(p->ai_socktype, SOCK_STREAM);
1913
1914
        const char* addr;
1915

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

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

15435
  switch (args[2].As<Int32>()->Value()) {
2037
    case 0:
2038
5129
      family = AF_UNSPEC;
2039
5129
      break;
2040
    case 4:
2041
14
      family = AF_INET;
2042
14
      break;
2043
    case 6:
2044
2
      family = AF_INET6;
2045
2
      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
15435
                                                       args[4]->IsTrue());
2053
2054
  struct addrinfo hints;
2055
5145
  memset(&hints, 0, sizeof(hints));
2056
5145
  hints.ai_family = family;
2057
5145
  hints.ai_socktype = SOCK_STREAM;
2058
5145
  hints.ai_flags = flags;
2059
2060
  TRACE_EVENT_NESTABLE_ASYNC_BEGIN2(
2061
5145
      TRACING_CATEGORY_NODE2(dns, native), "lookup", req_wrap.get(),
2062
5145
      "hostname", TRACE_STR_COPY(*hostname),
2063
792
      "family",
2064
11082
      family == AF_INET ? "ipv4" : family == AF_INET6 ? "ipv6" : "unspec");
2065
5145
2066
5145
  int err = req_wrap->Dispatch(uv_getaddrinfo,
2067
                               AfterGetAddrInfo,
2068
                               *hostname,
2069
                               nullptr,
2070
5145
                               &hints);
2071
5145
  if (err == 0)
2072
    // Release ownership of the pointer allowing the ownership to be transferred
2073
5145
    USE(req_wrap.release());
2074
2075
10290
  args.GetReturnValue().Set(err);
2076
5145
}
2077
2078
2079
4
void GetNameInfo(const FunctionCallbackInfo<Value>& args) {
2080
4
  Environment* env = Environment::GetCurrent(args);
2081
2082
8
  CHECK(args[0]->IsObject());
2083
12
  CHECK(args[1]->IsString());
2084
8
  CHECK(args[2]->IsUint32());
2085
8
  Local<Object> req_wrap_obj = args[0].As<Object>();
2086
8
  node::Utf8Value ip(env->isolate(), args[1]);
2087
16
  const unsigned port = args[2]->Uint32Value(env->context()).FromJust();
2088
  struct sockaddr_storage addr;
2089
2090

4
  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
8
  auto req_wrap = std::make_unique<GetNameInfoReqWrap>(env, req_wrap_obj);
2094
2095
4
  TRACE_EVENT_NESTABLE_ASYNC_BEGIN2(
2096
      TRACING_CATEGORY_NODE2(dns, native), "lookupService", req_wrap.get(),
2097
4
      "ip", TRACE_STR_COPY(*ip), "port", port);
2098
3
2099
15
  int err = req_wrap->Dispatch(uv_getnameinfo,
2100
4
                               AfterGetNameInfo,
2101
                               reinterpret_cast<struct sockaddr*>(&addr),
2102
4
                               NI_NAMEREQD);
2103
4
  if (err == 0)
2104
    // Release ownership of the pointer allowing the ownership to be transferred
2105
4
    USE(req_wrap.release());
2106
2107
8
  args.GetReturnValue().Set(err);
2108
4
}
2109
2110
2111
65
void GetServers(const FunctionCallbackInfo<Value>& args) {
2112
65
  Environment* env = Environment::GetCurrent(args);
2113
  ChannelWrap* channel;
2114
65
  ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
2115
2116
65
  Local<Array> server_array = Array::New(env->isolate());
2117
2118
  ares_addr_port_node* servers;
2119
2120
65
  int r = ares_get_servers_ports(channel->cares_channel(), &servers);
2121
65
  CHECK_EQ(r, ARES_SUCCESS);
2122
195
  auto cleanup = OnScopeLeave([&]() { ares_free_data(servers); });
2123
2124
65
  ares_addr_port_node* cur = servers;
2125
2126
141
  for (uint32_t i = 0; cur != nullptr; ++i, cur = cur->next) {
2127
    char ip[INET6_ADDRSTRLEN];
2128
2129
76
    const void* caddr = static_cast<const void*>(&cur->addr);
2130
76
    int err = uv_inet_ntop(cur->family, caddr, ip, sizeof(ip));
2131
76
    CHECK_EQ(err, 0);
2132
2133
    Local<Value> ret[] = {
2134
      OneByteString(env->isolate(), ip),
2135
      Integer::New(env->isolate(), cur->udp_port)
2136
228
    };
2137
2138
228
    if (server_array->Set(env->context(), i,
2139
228
                          Array::New(env->isolate(), ret, arraysize(ret)))
2140
          .IsNothing()) {
2141
      return;
2142
    }
2143
  }
2144
2145
130
  args.GetReturnValue().Set(server_array);
2146
}
2147
2148
2149
28
void SetServers(const FunctionCallbackInfo<Value>& args) {
2150
28
  Environment* env = Environment::GetCurrent(args);
2151
  ChannelWrap* channel;
2152
32
  ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
2153
2154
28
  if (channel->active_query_count()) {
2155
4
    return args.GetReturnValue().Set(DNS_ESETSRVPENDING);
2156
  }
2157
2158
52
  CHECK(args[0]->IsArray());
2159
2160
26
  Local<Array> arr = Local<Array>::Cast(args[0]);
2161
2162
26
  uint32_t len = arr->Length();
2163
2164
26
  if (len == 0) {
2165
2
    int rv = ares_set_servers(channel->cares_channel(), nullptr);
2166
4
    return args.GetReturnValue().Set(rv);
2167
  }
2168
2169
48
  std::vector<ares_addr_port_node> servers(len);
2170
24
  ares_addr_port_node* last = nullptr;
2171
2172
  int err;
2173
2174
59
  for (uint32_t i = 0; i < len; i++) {
2175
140
    CHECK(arr->Get(env->context(), i).ToLocalChecked()->IsArray());
2176
2177
    Local<Array> elm =
2178
105
        Local<Array>::Cast(arr->Get(env->context(), i).ToLocalChecked());
2179
2180
175
    CHECK(elm->Get(env->context(),
2181
                   0).ToLocalChecked()->Int32Value(env->context()).FromJust());
2182
175
    CHECK(elm->Get(env->context(), 1).ToLocalChecked()->IsString());
2183
175
    CHECK(elm->Get(env->context(),
2184
                   2).ToLocalChecked()->Int32Value(env->context()).FromJust());
2185
2186
105
    int fam = elm->Get(env->context(), 0)
2187
140
        .ToLocalChecked()->Int32Value(env->context()).FromJust();
2188
    node::Utf8Value ip(env->isolate(),
2189
140
                       elm->Get(env->context(), 1).ToLocalChecked());
2190
105
    int port = elm->Get(env->context(), 2)
2191
140
        .ToLocalChecked()->Int32Value(env->context()).FromJust();
2192
2193
35
    ares_addr_port_node* cur = &servers[i];
2194
2195
35
    cur->tcp_port = cur->udp_port = port;
2196
35
    switch (fam) {
2197
      case 4:
2198
28
        cur->family = AF_INET;
2199
28
        err = uv_inet_pton(AF_INET, *ip, &cur->addr);
2200
28
        break;
2201
      case 6:
2202
7
        cur->family = AF_INET6;
2203
7
        err = uv_inet_pton(AF_INET6, *ip, &cur->addr);
2204
7
        break;
2205
      default:
2206
        CHECK(0 && "Bad address family.");
2207
    }
2208
2209
35
    if (err)
2210
      break;
2211
2212
35
    cur->next = nullptr;
2213
2214
35
    if (last != nullptr)
2215
11
      last->next = cur;
2216
2217
35
    last = cur;
2218
  }
2219
2220
24
  if (err == 0)
2221
24
    err = ares_set_servers_ports(channel->cares_channel(), &servers[0]);
2222
  else
2223
    err = ARES_EBADSTR;
2224
2225
24
  if (err == ARES_SUCCESS)
2226
24
    channel->set_is_servers_default(false);
2227
2228
48
  args.GetReturnValue().Set(err);
2229
}
2230
2231
7
void SetLocalAddress(const FunctionCallbackInfo<Value>& args) {
2232
7
  Environment* env = Environment::GetCurrent(args);
2233
  ChannelWrap* channel;
2234
10
  ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
2235
2236
7
  CHECK_EQ(args.Length(), 2);
2237
21
  CHECK(args[0]->IsString());
2238
2239
7
  Isolate* isolate = args.GetIsolate();
2240
11
  node::Utf8Value ip0(isolate, args[0]);
2241
2242
  unsigned char addr0[sizeof(struct in6_addr)];
2243
  unsigned char addr1[sizeof(struct in6_addr)];
2244
7
  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
7
  if (uv_inet_pton(AF_INET, *ip0, &addr0) == 0) {
2252
4
    ares_set_local_ip4(channel->cares_channel(), ReadUint32BE(addr0));
2253
4
    type0 = 4;
2254
3
  } else if (uv_inet_pton(AF_INET6, *ip0, &addr0) == 0) {
2255
2
    ares_set_local_ip6(channel->cares_channel(), addr0);
2256
2
    type0 = 6;
2257
  } else {
2258
1
    THROW_ERR_INVALID_ARG_VALUE(env, "Invalid IP address.");
2259
1
    return;
2260
  }
2261
2262
18
  if (!args[1]->IsUndefined()) {
2263
12
    CHECK(args[1]->IsString());
2264
6
    node::Utf8Value ip1(isolate, args[1]);
2265
2266
4
    if (uv_inet_pton(AF_INET, *ip1, &addr1) == 0) {
2267
1
      if (type0 == 4) {
2268
1
        THROW_ERR_INVALID_ARG_VALUE(env, "Cannot specify two IPv4 addresses.");
2269
1
        return;
2270
      } else {
2271
        ares_set_local_ip4(channel->cares_channel(), ReadUint32BE(addr1));
2272
      }
2273
3
    } else if (uv_inet_pton(AF_INET6, *ip1, &addr1) == 0) {
2274
3
      if (type0 == 6) {
2275
1
        THROW_ERR_INVALID_ARG_VALUE(env, "Cannot specify two IPv6 addresses.");
2276
1
        return;
2277
      } else {
2278
2
        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
2
    if (type0 == 4) {
2287
1
      memset(&addr1, 0, sizeof(addr1));
2288
1
      ares_set_local_ip6(channel->cares_channel(), addr1);
2289
    } else {
2290
1
      ares_set_local_ip4(channel->cares_channel(), 0);
2291
    }
2292
  }
2293
}
2294
2295
6
void Cancel(const FunctionCallbackInfo<Value>& args) {
2296
  ChannelWrap* channel;
2297
6
  ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
2298
2299
6
  TRACE_EVENT_INSTANT0(TRACING_CATEGORY_NODE2(dns, native),
2300
      "cancel", TRACE_EVENT_SCOPE_THREAD);
2301
6
2302
10
  ares_cancel(channel->cares_channel());
2303
16
}
2304
6
2305
const char EMSG_ESETSRVPENDING[] = "There are pending queries.";
2306
1
void StrError(const FunctionCallbackInfo<Value>& args) {
2307
1
  Environment* env = Environment::GetCurrent(args);
2308
4
  int code = args[0]->Int32Value(env->context()).FromJust();
2309
1
  const char* errmsg = (code == DNS_ESETSRVPENDING) ?
2310
    EMSG_ESETSRVPENDING :
2311
1
    ares_strerror(code);
2312
3
  args.GetReturnValue().Set(OneByteString(env->isolate(), errmsg));
2313
1
}
2314
2315
2316
1152
void Initialize(Local<Object> target,
2317
                Local<Value> unused,
2318
                Local<Context> context,
2319
                void* priv) {
2320
1152
  Environment* env = Environment::GetCurrent(context);
2321
2322
1152
  env->SetMethod(target, "getaddrinfo", GetAddrInfo);
2323
1152
  env->SetMethod(target, "getnameinfo", GetNameInfo);
2324
1152
  env->SetMethodNoSideEffect(target, "canonicalizeIP", CanonicalizeIP);
2325
2326
1152
  env->SetMethod(target, "strerror", StrError);
2327
2328
2304
  target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(), "AF_INET"),
2329
5760
              Integer::New(env->isolate(), AF_INET)).Check();
2330
2304
  target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(), "AF_INET6"),
2331
5760
              Integer::New(env->isolate(), AF_INET6)).Check();
2332
2304
  target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(),
2333
                                                    "AF_UNSPEC"),
2334
5760
              Integer::New(env->isolate(), AF_UNSPEC)).Check();
2335
2304
  target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(),
2336
                                                    "AI_ADDRCONFIG"),
2337
5760
              Integer::New(env->isolate(), AI_ADDRCONFIG)).Check();
2338
2304
  target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(),
2339
                                                    "AI_ALL"),
2340
5760
              Integer::New(env->isolate(), AI_ALL)).Check();
2341
2304
  target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(),
2342
                                                    "AI_V4MAPPED"),
2343
5760
              Integer::New(env->isolate(), AI_V4MAPPED)).Check();
2344
2345
  Local<FunctionTemplate> aiw =
2346
1152
      BaseObject::MakeLazilyInitializedJSTemplate(env);
2347
2304
  aiw->Inherit(AsyncWrap::GetConstructorTemplate(env));
2348
1152
  env->SetConstructorFunction(target, "GetAddrInfoReqWrap", aiw);
2349
2350
  Local<FunctionTemplate> niw =
2351
1152
      BaseObject::MakeLazilyInitializedJSTemplate(env);
2352
2304
  niw->Inherit(AsyncWrap::GetConstructorTemplate(env));
2353
1152
  env->SetConstructorFunction(target, "GetNameInfoReqWrap", niw);
2354
2355
  Local<FunctionTemplate> qrw =
2356
1152
      BaseObject::MakeLazilyInitializedJSTemplate(env);
2357
2304
  qrw->Inherit(AsyncWrap::GetConstructorTemplate(env));
2358
1152
  env->SetConstructorFunction(target, "QueryReqWrap", qrw);
2359
2360
  Local<FunctionTemplate> channel_wrap =
2361
1152
      env->NewFunctionTemplate(ChannelWrap::New);
2362
3456
  channel_wrap->InstanceTemplate()->SetInternalFieldCount(
2363
1152
      ChannelWrap::kInternalFieldCount);
2364
2304
  channel_wrap->Inherit(AsyncWrap::GetConstructorTemplate(env));
2365
2366
1152
  env->SetProtoMethod(channel_wrap, "queryAny", Query<QueryAnyWrap>);
2367
1152
  env->SetProtoMethod(channel_wrap, "queryA", Query<QueryAWrap>);
2368
1152
  env->SetProtoMethod(channel_wrap, "queryAaaa", Query<QueryAaaaWrap>);
2369
1152
  env->SetProtoMethod(channel_wrap, "queryCaa", Query<QueryCaaWrap>);
2370
1152
  env->SetProtoMethod(channel_wrap, "queryCname", Query<QueryCnameWrap>);
2371
1152
  env->SetProtoMethod(channel_wrap, "queryMx", Query<QueryMxWrap>);
2372
1152
  env->SetProtoMethod(channel_wrap, "queryNs", Query<QueryNsWrap>);
2373
1152
  env->SetProtoMethod(channel_wrap, "queryTxt", Query<QueryTxtWrap>);
2374
1152
  env->SetProtoMethod(channel_wrap, "querySrv", Query<QuerySrvWrap>);
2375
1152
  env->SetProtoMethod(channel_wrap, "queryPtr", Query<QueryPtrWrap>);
2376
1152
  env->SetProtoMethod(channel_wrap, "queryNaptr", Query<QueryNaptrWrap>);
2377
1152
  env->SetProtoMethod(channel_wrap, "querySoa", Query<QuerySoaWrap>);
2378
1152
  env->SetProtoMethod(channel_wrap, "getHostByAddr", Query<GetHostByAddrWrap>);
2379
2380
1152
  env->SetProtoMethodNoSideEffect(channel_wrap, "getServers", GetServers);
2381
1152
  env->SetProtoMethod(channel_wrap, "setServers", SetServers);
2382
1152
  env->SetProtoMethod(channel_wrap, "setLocalAddress", SetLocalAddress);
2383
1152
  env->SetProtoMethod(channel_wrap, "cancel", Cancel);
2384
2385
1152
  env->SetConstructorFunction(target, "ChannelWrap", channel_wrap);
2386
1152
}
2387
2388
}  // anonymous namespace
2389
}  // namespace cares_wrap
2390
}  // namespace node
2391
2392

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