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: 860 1162 74.0 %
Date: 2020-02-19 22:14:06 Branches: 291 618 47.1 %

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 "env-inl.h"
26
#include "memory_tracker-inl.h"
27
#include "node.h"
28
#include "req_wrap-inl.h"
29
#include "util-inl.h"
30
#include "uv.h"
31
32
#include <cerrno>
33
#include <cstring>
34
#include <memory>
35
#include <vector>
36
#include <unordered_set>
37
38
#ifdef __POSIX__
39
# include <netdb.h>
40
#endif  // __POSIX__
41
42
#if defined(__ANDROID__) || \
43
    defined(__MINGW32__) || \
44
    defined(__OpenBSD__) || \
45
    defined(_MSC_VER)
46
47
# include <nameser.h>
48
#else
49
# include <arpa/nameser.h>
50
#endif
51
52
#if defined(__OpenBSD__)
53
# define AI_V4MAPPED 0
54
#endif
55
56
namespace node {
57
namespace cares_wrap {
58
59
using v8::Array;
60
using v8::Context;
61
using v8::EscapableHandleScope;
62
using v8::FunctionCallbackInfo;
63
using v8::FunctionTemplate;
64
using v8::HandleScope;
65
using v8::Int32;
66
using v8::Integer;
67
using v8::Local;
68
using v8::Null;
69
using v8::Object;
70
using v8::String;
71
using v8::Value;
72
73
namespace {
74
75
4186
Mutex ares_library_mutex;
76
77
56
inline uint16_t cares_get_16bit(const unsigned char* p) {
78
56
  return static_cast<uint32_t>(p[0] << 8U) | (static_cast<uint32_t>(p[1]));
79
}
80
81
20
inline uint32_t cares_get_32bit(const unsigned char* p) {
82
40
  return static_cast<uint32_t>(p[0] << 24U) |
83
40
         static_cast<uint32_t>(p[1] << 16U) |
84
20
         static_cast<uint32_t>(p[2] << 8U) |
85
20
         static_cast<uint32_t>(p[3]);
86
}
87
88
const int ns_t_cname_or_a = -1;
89
90
#define DNS_ESETSRVPENDING -1000
91
6
inline const char* ToErrorCodeString(int status) {
92






6
  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
3
    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
    V(ETIMEOUT)
118
#undef V
119
  }
120
121
  return "UNKNOWN_ARES_ERROR";
122
}
123
124
class ChannelWrap;
125
126
140
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
997
struct TaskHash {
137
60
  size_t operator()(node_ares_task* a) const {
138
60
    return std::hash<ares_socket_t>()(a->sock);
139
  }
140
};
141
142
997
struct TaskEqual {
143
20
  inline bool operator()(node_ares_task* a, node_ares_task* b) const {
144
20
    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);
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
16
  inline uv_timer_t* timer_handle() { return timer_handle_; }
166
114
  inline ares_channel cares_channel() { return channel_; }
167
23
  inline void set_query_last_ok(bool ok) { query_last_ok_ = ok; }
168
16
  inline void set_is_servers_default(bool is_default) {
169
16
    is_servers_default_ = is_default;
170
16
  }
171
20
  inline int active_query_count() { return active_query_count_; }
172
140
  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 active_query_count_;
192
  node_ares_task_list task_list_;
193
};
194
195
997
ChannelWrap::ChannelWrap(Environment* env,
196
997
                         Local<Object> object)
197
  : AsyncWrap(env, object, PROVIDER_DNSCHANNEL),
198
    timer_handle_(nullptr),
199
    channel_(nullptr),
200
    query_last_ok_(true),
201
    is_servers_default_(true),
202
    library_inited_(false),
203
997
    active_query_count_(0) {
204
997
  MakeWeak();
205
206
997
  Setup();
207
997
}
208
209
997
void ChannelWrap::New(const FunctionCallbackInfo<Value>& args) {
210
997
  CHECK(args.IsConstructCall());
211
997
  CHECK_EQ(args.Length(), 0);
212
213
997
  Environment* env = Environment::GetCurrent(args);
214
997
  new ChannelWrap(env, args.This());
215
997
}
216
217
9316
class GetAddrInfoReqWrap : public ReqWrap<uv_getaddrinfo_t> {
218
 public:
219
  GetAddrInfoReqWrap(Environment* env,
220
                     Local<Object> req_wrap_obj,
221
                     bool verbatim);
222
223
1
  SET_NO_MEMORY_INFO()
224
1
  SET_MEMORY_INFO_NAME(GetAddrInfoReqWrap)
225
1
  SET_SELF_SIZE(GetAddrInfoReqWrap)
226
227
4658
  bool verbatim() const { return verbatim_; }
228
229
 private:
230
  const bool verbatim_;
231
};
232
233
4659
GetAddrInfoReqWrap::GetAddrInfoReqWrap(Environment* env,
234
                                       Local<Object> req_wrap_obj,
235
4659
                                       bool verbatim)
236
    : ReqWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_GETADDRINFOREQWRAP)
237
4659
    , verbatim_(verbatim) {
238
4659
}
239
240
241
8
class GetNameInfoReqWrap : public ReqWrap<uv_getnameinfo_t> {
242
 public:
243
  GetNameInfoReqWrap(Environment* env, Local<Object> req_wrap_obj);
244
245
1
  SET_NO_MEMORY_INFO()
246
1
  SET_MEMORY_INFO_NAME(GetNameInfoReqWrap)
247
1
  SET_SELF_SIZE(GetNameInfoReqWrap)
248
};
249
250
4
GetNameInfoReqWrap::GetNameInfoReqWrap(Environment* env,
251
4
                                       Local<Object> req_wrap_obj)
252
4
    : ReqWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_GETNAMEINFOREQWRAP) {
253
4
}
254
255
256
/* This is called once per second by loop->timer. It is used to constantly */
257
/* call back into c-ares for possibly processing timeouts. */
258
void ChannelWrap::AresTimeout(uv_timer_t* handle) {
259
  ChannelWrap* channel = static_cast<ChannelWrap*>(handle->data);
260
  CHECK_EQ(channel->timer_handle(), handle);
261
  CHECK_EQ(false, channel->task_list()->empty());
262
  ares_process_fd(channel->cares_channel(), ARES_SOCKET_BAD, ARES_SOCKET_BAD);
263
}
264
265
266
16
void ares_poll_cb(uv_poll_t* watcher, int status, int events) {
267
16
  node_ares_task* task = ContainerOf(&node_ares_task::poll_watcher, watcher);
268
16
  ChannelWrap* channel = task->channel;
269
270
  /* Reset the idle timer */
271
16
  uv_timer_again(channel->timer_handle());
272
273
16
  if (status < 0) {
274
    /* An error happened. Just pretend that the socket is both readable and */
275
    /* writable. */
276
    ares_process_fd(channel->cares_channel(), task->sock, task->sock);
277
    return;
278
  }
279
280
  /* Process DNS responses */
281

32
  ares_process_fd(channel->cares_channel(),
282
16
                  events & UV_READABLE ? task->sock : ARES_SOCKET_BAD,
283
32
                  events & UV_WRITABLE ? task->sock : ARES_SOCKET_BAD);
284
}
285
286
287
20
void ares_poll_close_cb(uv_poll_t* watcher) {
288
20
  node_ares_task* task = ContainerOf(&node_ares_task::poll_watcher, watcher);
289
20
  delete task;
290
20
}
291
292
void node_ares_task::MemoryInfo(MemoryTracker* tracker) const {
293
  tracker->TrackField("channel", channel);
294
}
295
296
/* Allocates and returns a new node_ares_task */
297
20
node_ares_task* ares_task_create(ChannelWrap* channel, ares_socket_t sock) {
298
20
  auto task = new node_ares_task();
299
300
20
  task->channel = channel;
301
20
  task->sock = sock;
302
303
20
  if (uv_poll_init_socket(channel->env()->event_loop(),
304
                          &task->poll_watcher, sock) < 0) {
305
    /* This should never happen. */
306
    delete task;
307
    return nullptr;
308
  }
309
310
20
  return task;
311
}
312
313
314
/* Callback from ares when socket operation is started */
315
40
void ares_sockstate_cb(void* data,
316
                       ares_socket_t sock,
317
                       int read,
318
                       int write) {
319
40
  ChannelWrap* channel = static_cast<ChannelWrap*>(data);
320
  node_ares_task* task;
321
322
80
  node_ares_task lookup_task;
323
40
  lookup_task.sock = sock;
324
40
  auto it = channel->task_list()->find(&lookup_task);
325
326
40
  task = (it == channel->task_list()->end()) ? nullptr : *it;
327
328

40
  if (read || write) {
329
20
    if (!task) {
330
      /* New socket */
331
20
      channel->StartTimer();
332
333
20
      task = ares_task_create(channel, sock);
334
20
      if (task == nullptr) {
335
        /* This should never happen unless we're out of memory or something */
336
        /* is seriously wrong. The socket won't be polled, but the query will */
337
        /* eventually time out. */
338
        return;
339
      }
340
341
20
      channel->task_list()->insert(task);
342
    }
343
344
    /* This should never fail. If it fails anyway, the query will eventually */
345
    /* time out. */
346
20
    uv_poll_start(&task->poll_watcher,
347

20
                  (read ? UV_READABLE : 0) | (write ? UV_WRITABLE : 0),
348
20
                  ares_poll_cb);
349
350
  } else {
351
    /* read == 0 and write == 0 this is c-ares's way of notifying us that */
352
    /* the socket is now closed. We must free the data associated with */
353
    /* socket. */
354
20
    CHECK(task &&
355
          "When an ares socket is closed we should have a handle for it");
356
357
20
    channel->task_list()->erase(it);
358
20
    channel->env()->CloseHandle(&task->poll_watcher, ares_poll_close_cb);
359
360
20
    if (channel->task_list()->empty()) {
361
20
      channel->CloseTimer();
362
    }
363
  }
364
}
365
366
367
6
Local<Array> HostentToNames(Environment* env,
368
                            struct hostent* host,
369
                            Local<Array> append_to = Local<Array>()) {
370
6
  EscapableHandleScope scope(env->isolate());
371
6
  auto context = env->context();
372
6
  bool append = !append_to.IsEmpty();
373
6
  Local<Array> names = append ? append_to : Array::New(env->isolate());
374
6
  size_t offset = names->Length();
375
376
10
  for (uint32_t i = 0; host->h_aliases[i] != nullptr; ++i) {
377
4
    Local<String> address = OneByteString(env->isolate(), host->h_aliases[i]);
378
12
    names->Set(context, i + offset, address).Check();
379
  }
380
381
18
  return append ? names : scope.Escape(names);
382
}
383
384
2
void safe_free_hostent(struct hostent* host) {
385
  int idx;
386
387
2
  if (host->h_addr_list != nullptr) {
388
2
    idx = 0;
389
6
    while (host->h_addr_list[idx]) {
390
2
      free(host->h_addr_list[idx++]);
391
    }
392
2
    free(host->h_addr_list);
393
2
    host->h_addr_list = nullptr;
394
  }
395
396
2
  if (host->h_aliases != nullptr) {
397
2
    idx = 0;
398
2
    while (host->h_aliases[idx]) {
399
      free(host->h_aliases[idx++]);
400
    }
401
2
    free(host->h_aliases);
402
2
    host->h_aliases = nullptr;
403
  }
404
405
2
  free(host->h_name);
406
2
  free(host);
407
2
}
408
409
2
void cares_wrap_hostent_cpy(struct hostent* dest, const struct hostent* src) {
410
2
  dest->h_addr_list = nullptr;
411
2
  dest->h_addrtype = 0;
412
2
  dest->h_aliases = nullptr;
413
2
  dest->h_length = 0;
414
2
  dest->h_name = nullptr;
415
416
  /* copy `h_name` */
417
2
  size_t name_size = strlen(src->h_name) + 1;
418
2
  dest->h_name = node::Malloc<char>(name_size);
419
2
  memcpy(dest->h_name, src->h_name, name_size);
420
421
  /* copy `h_aliases` */
422
  size_t alias_count;
423
2
  for (alias_count = 0;
424
2
      src->h_aliases[alias_count] != nullptr;
425
      alias_count++) {
426
  }
427
428
2
  dest->h_aliases = node::Malloc<char*>(alias_count + 1);
429
2
  for (size_t i = 0; i < alias_count; i++) {
430
    const size_t cur_alias_size = strlen(src->h_aliases[i]) + 1;
431
    dest->h_aliases[i] = node::Malloc(cur_alias_size);
432
    memcpy(dest->h_aliases[i], src->h_aliases[i], cur_alias_size);
433
  }
434
2
  dest->h_aliases[alias_count] = nullptr;
435
436
  /* copy `h_addr_list` */
437
  size_t list_count;
438
4
  for (list_count = 0;
439
4
      src->h_addr_list[list_count] != nullptr;
440
      list_count++) {
441
  }
442
443
2
  dest->h_addr_list = node::Malloc<char*>(list_count + 1);
444
4
  for (size_t i = 0; i < list_count; i++) {
445
2
    dest->h_addr_list[i] = node::Malloc(src->h_length);
446
2
    memcpy(dest->h_addr_list[i], src->h_addr_list[i], src->h_length);
447
  }
448
2
  dest->h_addr_list[list_count] = nullptr;
449
450
  /* work after work */
451
2
  dest->h_length = src->h_length;
452
2
  dest->h_addrtype = src->h_addrtype;
453
2
}
454
455
class QueryWrap;
456
457
997
void ChannelWrap::Setup() {
458
  struct ares_options options;
459
997
  memset(&options, 0, sizeof(options));
460
997
  options.flags = ARES_FLAG_NOCHECKRESP;
461
997
  options.sock_state_cb = ares_sockstate_cb;
462
997
  options.sock_state_cb_data = this;
463
464
  int r;
465
997
  if (!library_inited_) {
466
1994
    Mutex::ScopedLock lock(ares_library_mutex);
467
    // Multiple calls to ares_library_init() increase a reference counter,
468
    // so this is a no-op except for the first call to it.
469
997
    r = ares_library_init(ARES_LIB_INIT_ALL);
470
997
    if (r != ARES_SUCCESS)
471
      return env()->ThrowError(ToErrorCodeString(r));
472
  }
473
474
  /* We do the call to ares_init_option for caller. */
475
997
  r = ares_init_options(&channel_,
476
                        &options,
477
997
                        ARES_OPT_FLAGS | ARES_OPT_SOCK_STATE_CB);
478
479
997
  if (r != ARES_SUCCESS) {
480
    Mutex::ScopedLock lock(ares_library_mutex);
481
    ares_library_cleanup();
482
    return env()->ThrowError(ToErrorCodeString(r));
483
  }
484
485
997
  library_inited_ = true;
486
}
487
488
20
void ChannelWrap::StartTimer() {
489
20
  if (timer_handle_ == nullptr) {
490
20
    timer_handle_ = new uv_timer_t();
491
20
    timer_handle_->data = static_cast<void*>(this);
492
20
    uv_timer_init(env()->event_loop(), timer_handle_);
493
  } else if (uv_is_active(reinterpret_cast<uv_handle_t*>(timer_handle_))) {
494
    return;
495
  }
496
20
  uv_timer_start(timer_handle_, AresTimeout, 1000, 1000);
497
}
498
499
989
void ChannelWrap::CloseTimer() {
500
989
  if (timer_handle_ == nullptr)
501
969
    return;
502
503
40
  env()->CloseHandle(timer_handle_, [](uv_timer_t* handle) { delete handle; });
504
20
  timer_handle_ = nullptr;
505
}
506
507
2907
ChannelWrap::~ChannelWrap() {
508
969
  ares_destroy(channel_);
509
510
969
  if (library_inited_) {
511
1938
    Mutex::ScopedLock lock(ares_library_mutex);
512
    // This decreases the reference counter increased by ares_library_init().
513
969
    ares_library_cleanup();
514
  }
515
516
969
  CloseTimer();
517
1938
}
518
519
520
47
void ChannelWrap::ModifyActivityQueryCount(int count) {
521
47
  active_query_count_ += count;
522
47
  CHECK_GE(active_query_count_, 0);
523
47
}
524
525
526
/**
527
 * This function is to check whether current servers are fallback servers
528
 * when cares initialized.
529
 *
530
 * The fallback servers of cares is [ "127.0.0.1" ] with no user additional
531
 * setting.
532
 */
533
21
void ChannelWrap::EnsureServers() {
534
  /* if last query is OK or servers are set by user self, do not check */
535

21
  if (query_last_ok_ || !is_servers_default_) {
536
42
    return;
537
  }
538
539
  ares_addr_port_node* servers = nullptr;
540
541
  ares_get_servers_ports(channel_, &servers);
542
543
  /* if no server or multi-servers, ignore */
544
  if (servers == nullptr) return;
545
  if (servers->next != nullptr) {
546
    ares_free_data(servers);
547
    is_servers_default_ = false;
548
    return;
549
  }
550
551
  /* if the only server is not 127.0.0.1, ignore */
552
  if (servers[0].family != AF_INET ||
553
      servers[0].addr.addr4.s_addr != htonl(INADDR_LOOPBACK) ||
554
      servers[0].tcp_port != 0 ||
555
      servers[0].udp_port != 0) {
556
    ares_free_data(servers);
557
    is_servers_default_ = false;
558
    return;
559
  }
560
561
  ares_free_data(servers);
562
  servers = nullptr;
563
564
  /* destroy channel and reset channel */
565
  ares_destroy(channel_);
566
567
  CloseTimer();
568
  Setup();
569
}
570
571
572
class QueryWrap : public AsyncWrap {
573
 public:
574
24
  QueryWrap(ChannelWrap* channel, Local<Object> req_wrap_obj, const char* name)
575
24
      : AsyncWrap(channel->env(), req_wrap_obj, AsyncWrap::PROVIDER_QUERYWRAP),
576
        channel_(channel),
577
24
        trace_name_(name) {
578
24
  }
579
580
48
  ~QueryWrap() override {
581
48
    CHECK_EQ(false, persistent().IsEmpty());
582
583
    // Let Callback() know that this object no longer exists.
584
24
    if (callback_ptr_ != nullptr)
585
1
      *callback_ptr_ = nullptr;
586
24
  }
587
588
  // Subclasses should implement the appropriate Send method.
589
  virtual int Send(const char* name) {
590
    UNREACHABLE();
591
    return 0;
592
  }
593
594
  virtual int Send(const char* name, int family) {
595
    UNREACHABLE();
596
    return 0;
597
  }
598
599
 protected:
600
21
  void AresQuery(const char* name,
601
                 int dnsclass,
602
                 int type) {
603
21
    channel_->EnsureServers();
604

42
    TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(
605
      TRACING_CATEGORY_NODE2(dns, native), trace_name_, this,
606
      "name", TRACE_STR_COPY(name));
607
21
    ares_query(channel_->cares_channel(), name, dnsclass, type, Callback,
608
21
               MakeCallbackPointer());
609
21
  }
610
611
46
  struct ResponseData {
612
    int status;
613
    bool is_host;
614
    DeleteFnPtr<hostent, safe_free_hostent> host;
615
    MallocedBuffer<unsigned char> buf;
616
  };
617
618
23
  void AfterResponse() {
619
23
    CHECK(response_data_);
620
621
23
    const int status = response_data_->status;
622
623
23
    if (status != ARES_SUCCESS) {
624
4
      ParseError(status);
625
19
    } else if (!response_data_->is_host) {
626
17
      Parse(response_data_->buf.data, response_data_->buf.size);
627
    } else {
628
2
      Parse(response_data_->host.get());
629
    }
630
23
  }
631
632
24
  void* MakeCallbackPointer() {
633
24
    CHECK_NULL(callback_ptr_);
634
24
    callback_ptr_ = new QueryWrap*(this);
635
24
    return callback_ptr_;
636
  }
637
638
24
  static QueryWrap* FromCallbackPointer(void* arg) {
639
48
    std::unique_ptr<QueryWrap*> wrap_ptr { static_cast<QueryWrap**>(arg) };
640
24
    QueryWrap* wrap = *wrap_ptr.get();
641
24
    if (wrap == nullptr) return nullptr;
642
23
    wrap->callback_ptr_ = nullptr;
643
23
    return wrap;
644
  }
645
646
21
  static void Callback(void* arg, int status, int timeouts,
647
                       unsigned char* answer_buf, int answer_len) {
648
21
    QueryWrap* wrap = FromCallbackPointer(arg);
649
21
    if (wrap == nullptr) return;
650
651
20
    unsigned char* buf_copy = nullptr;
652
20
    if (status == ARES_SUCCESS) {
653
17
      buf_copy = node::Malloc<unsigned char>(answer_len);
654
17
      memcpy(buf_copy, answer_buf, answer_len);
655
    }
656
657
20
    wrap->response_data_ = std::make_unique<ResponseData>();
658
20
    ResponseData* data = wrap->response_data_.get();
659
20
    data->status = status;
660
20
    data->is_host = false;
661
20
    data->buf = MallocedBuffer<unsigned char>(buf_copy, answer_len);
662
663
20
    wrap->QueueResponseCallback(status);
664
  }
665
666
3
  static void Callback(void* arg, int status, int timeouts,
667
                       struct hostent* host) {
668
3
    QueryWrap* wrap = FromCallbackPointer(arg);
669
3
    if (wrap == nullptr) return;
670
671
3
    struct hostent* host_copy = nullptr;
672
3
    if (status == ARES_SUCCESS) {
673
2
      host_copy = node::Malloc<hostent>(1);
674
2
      cares_wrap_hostent_cpy(host_copy, host);
675
    }
676
677
3
    wrap->response_data_ = std::make_unique<ResponseData>();
678
3
    ResponseData* data = wrap->response_data_.get();
679
3
    data->status = status;
680
3
    data->host.reset(host_copy);
681
3
    data->is_host = true;
682
683
3
    wrap->QueueResponseCallback(status);
684
  }
685
686
23
  void QueueResponseCallback(int status) {
687
46
    BaseObjectPtr<QueryWrap> strong_ref{this};
688
161
    env()->SetImmediate([this, strong_ref](Environment*) {
689
23
      AfterResponse();
690
691
      // Delete once strong_ref goes out of scope.
692
23
      Detach();
693
46
    });
694
695
23
    channel_->set_query_last_ok(status != ARES_ECONNREFUSED);
696
23
    channel_->ModifyActivityQueryCount(-1);
697
23
  }
698
699
17
  void CallOnComplete(Local<Value> answer,
700
                      Local<Value> extra = Local<Value>()) {
701
34
    HandleScope handle_scope(env()->isolate());
702
17
    Context::Scope context_scope(env()->context());
703
    Local<Value> argv[] = {
704
      Integer::New(env()->isolate(), 0),
705
      answer,
706
      extra
707
34
    };
708
34
    const int argc = arraysize(argv) - extra.IsEmpty();
709

34
    TRACE_EVENT_NESTABLE_ASYNC_END0(
710
        TRACING_CATEGORY_NODE2(dns, native), trace_name_, this);
711
712
17
    MakeCallback(env()->oncomplete_string(), argc, argv);
713
17
  }
714
715
6
  void ParseError(int status) {
716
6
    CHECK_NE(status, ARES_SUCCESS);
717
12
    HandleScope handle_scope(env()->isolate());
718
6
    Context::Scope context_scope(env()->context());
719
6
    const char* code = ToErrorCodeString(status);
720
6
    Local<Value> arg = OneByteString(env()->isolate(), code);
721

12
    TRACE_EVENT_NESTABLE_ASYNC_END1(
722
        TRACING_CATEGORY_NODE2(dns, native), trace_name_, this,
723
        "error", status);
724
6
    MakeCallback(env()->oncomplete_string(), 1, &arg);
725
6
  }
726
727
  // Subclasses should implement the appropriate Parse method.
728
  virtual void Parse(unsigned char* buf, int len) {
729
    UNREACHABLE();
730
  }
731
732
  virtual void Parse(struct hostent* host) {
733
    UNREACHABLE();
734
  }
735
736
  BaseObjectPtr<ChannelWrap> channel_;
737
738
 private:
739
  std::unique_ptr<ResponseData> response_data_;
740
  const char* trace_name_;
741
  // Pointer to pointer to 'this' that can be reset from the destructor,
742
  // in order to let Callback() know that 'this' no longer exists.
743
  QueryWrap** callback_ptr_ = nullptr;
744
};
745
746
747
template <typename T>
748
9
Local<Array> AddrTTLToArray(Environment* env,
749
                            const T* addrttls,
750
                            size_t naddrttls) {
751
9
  auto isolate = env->isolate();
752
753
18
  MaybeStackBuffer<Local<Value>, 8> ttls(naddrttls);
754

18
  for (size_t i = 0; i < naddrttls; i++)
755
18
    ttls[i] = Integer::NewFromUnsigned(isolate, addrttls[i].ttl);
756
757
18
  return Array::New(isolate, ttls.out(), naddrttls);
758
}
759
760
761
27
int ParseGeneralReply(Environment* env,
762
                      const unsigned char* buf,
763
                      int len,
764
                      int* type,
765
                      Local<Array> ret,
766
                      void* addrttls = nullptr,
767
                      int* naddrttls = nullptr) {
768
54
  HandleScope handle_scope(env->isolate());
769
27
  auto context = env->context();
770
  hostent* host;
771
772
  int status;
773

27
  switch (*type) {
774
    case ns_t_a:
775
    case ns_t_cname:
776
    case ns_t_cname_or_a:
777
      status = ares_parse_a_reply(buf,
778
                                  len,
779
                                  &host,
780
                                  static_cast<ares_addrttl*>(addrttls),
781
13
                                  naddrttls);
782
13
      break;
783
    case ns_t_aaaa:
784
      status = ares_parse_aaaa_reply(buf,
785
                                     len,
786
                                     &host,
787
                                     static_cast<ares_addr6ttl*>(addrttls),
788
6
                                     naddrttls);
789
6
      break;
790
    case ns_t_ns:
791
4
      status = ares_parse_ns_reply(buf, len, &host);
792
4
      break;
793
    case ns_t_ptr:
794
4
      status = ares_parse_ptr_reply(buf, len, nullptr, 0, AF_INET, &host);
795
4
      break;
796
    default:
797
      CHECK(0 && "Bad NS type");
798
      break;
799
  }
800
801
27
  if (status != ARES_SUCCESS)
802
2
    return status;
803
804
  /* If it's `CNAME`, return the CNAME value;
805
   * And if it's `CNAME_OR_A` and it has value in `h_name` and `h_aliases[0]`,
806
   * we consider it's a CNAME record, otherwise we consider it's an A record. */
807


50
  if ((*type == ns_t_cname_or_a && host->h_name && host->h_aliases[0]) ||
808
25
      *type == ns_t_cname) {
809
    // A cname lookup always returns a single record but we follow the
810
    // common API here.
811
    *type = ns_t_cname;
812
    ret->Set(context,
813
             ret->Length(),
814
             OneByteString(env->isolate(), host->h_name)).Check();
815
    ares_free_hostent(host);
816
    return ARES_SUCCESS;
817
  }
818
819
25
  if (*type == ns_t_cname_or_a)
820
4
    *type = ns_t_a;
821
822
25
  if (*type == ns_t_ns) {
823
4
    HostentToNames(env, host, ret);
824
21
  } else if (*type == ns_t_ptr) {
825
4
    uint32_t offset = ret->Length();
826
8
    for (uint32_t i = 0; host->h_aliases[i] != nullptr; i++) {
827
4
      auto alias = OneByteString(env->isolate(), host->h_aliases[i]);
828
12
      ret->Set(context, i + offset, alias).Check();
829
    }
830
  } else {
831
17
    uint32_t offset = ret->Length();
832
    char ip[INET6_ADDRSTRLEN];
833
34
    for (uint32_t i = 0; host->h_addr_list[i] != nullptr; ++i) {
834
17
      uv_inet_ntop(host->h_addrtype, host->h_addr_list[i], ip, sizeof(ip));
835
17
      auto address = OneByteString(env->isolate(), ip);
836
51
      ret->Set(context, i + offset, address).Check();
837
    }
838
  }
839
840
25
  ares_free_hostent(host);
841
842
25
  return ARES_SUCCESS;
843
}
844
845
846
4
int ParseMxReply(Environment* env,
847
                 const unsigned char* buf,
848
                 int len,
849
                 Local<Array> ret,
850
                 bool need_type = false) {
851
8
  HandleScope handle_scope(env->isolate());
852
4
  auto context = env->context();
853
854
  struct ares_mx_reply* mx_start;
855
4
  int status = ares_parse_mx_reply(buf, len, &mx_start);
856
4
  if (status != ARES_SUCCESS) {
857
    return status;
858
  }
859
860
4
  uint32_t offset = ret->Length();
861
4
  ares_mx_reply* current = mx_start;
862
8
  for (uint32_t i = 0; current != nullptr; ++i, current = current->next) {
863
4
    Local<Object> mx_record = Object::New(env->isolate());
864
8
    mx_record->Set(context,
865
                   env->exchange_string(),
866
16
                   OneByteString(env->isolate(), current->host)).Check();
867
8
    mx_record->Set(context,
868
                   env->priority_string(),
869
16
                   Integer::New(env->isolate(), current->priority)).Check();
870
4
    if (need_type)
871
8
      mx_record->Set(context,
872
                     env->type_string(),
873
16
                     env->dns_mx_string()).Check();
874
875
12
    ret->Set(context, i + offset, mx_record).Check();
876
  }
877
878
4
  ares_free_data(mx_start);
879
4
  return ARES_SUCCESS;
880
}
881
882
4
int ParseTxtReply(Environment* env,
883
                  const unsigned char* buf,
884
                  int len,
885
                  Local<Array> ret,
886
                  bool need_type = false) {
887
8
  HandleScope handle_scope(env->isolate());
888
4
  auto context = env->context();
889
890
  struct ares_txt_ext* txt_out;
891
892
4
  int status = ares_parse_txt_reply_ext(buf, len, &txt_out);
893
4
  if (status != ARES_SUCCESS) {
894
    return status;
895
  }
896
897
  Local<Array> txt_chunk;
898
899
4
  struct ares_txt_ext* current = txt_out;
900
4
  uint32_t i = 0, j;
901
4
  uint32_t offset = ret->Length();
902
8
  for (j = 0; current != nullptr; current = current->next) {
903
    Local<String> txt =
904
4
        OneByteString(env->isolate(), current->txt, current->length);
905
906
    // New record found - write out the current chunk
907
4
    if (current->record_start) {
908
2
      if (!txt_chunk.IsEmpty()) {
909
        if (need_type) {
910
          Local<Object> elem = Object::New(env->isolate());
911
          elem->Set(context, env->entries_string(), txt_chunk).Check();
912
          elem->Set(context,
913
                    env->type_string(),
914
                    env->dns_txt_string()).Check();
915
          ret->Set(context, offset + i++, elem).Check();
916
        } else {
917
          ret->Set(context, offset + i++, txt_chunk).Check();
918
        }
919
      }
920
921
2
      txt_chunk = Array::New(env->isolate());
922
2
      j = 0;
923
    }
924
925
12
    txt_chunk->Set(context, j++, txt).Check();
926
  }
927
928
  // Push last chunk if it isn't empty
929
4
  if (!txt_chunk.IsEmpty()) {
930
2
    if (need_type) {
931
2
      Local<Object> elem = Object::New(env->isolate());
932
6
      elem->Set(context, env->entries_string(), txt_chunk).Check();
933
4
      elem->Set(context,
934
                env->type_string(),
935
8
                env->dns_txt_string()).Check();
936
6
      ret->Set(context, offset + i, elem).Check();
937
    } else {
938
      ret->Set(context, offset + i, txt_chunk).Check();
939
    }
940
  }
941
942
4
  ares_free_data(txt_out);
943
4
  return ARES_SUCCESS;
944
}
945
946
947
4
int ParseSrvReply(Environment* env,
948
                  const unsigned char* buf,
949
                  int len,
950
                  Local<Array> ret,
951
                  bool need_type = false) {
952
8
  HandleScope handle_scope(env->isolate());
953
4
  auto context = env->context();
954
955
  struct ares_srv_reply* srv_start;
956
4
  int status = ares_parse_srv_reply(buf, len, &srv_start);
957
4
  if (status != ARES_SUCCESS) {
958
    return status;
959
  }
960
961
4
  ares_srv_reply* current = srv_start;
962
4
  int offset = ret->Length();
963
4
  for (uint32_t i = 0; current != nullptr; ++i, current = current->next) {
964
    Local<Object> srv_record = Object::New(env->isolate());
965
    srv_record->Set(context,
966
                    env->name_string(),
967
                    OneByteString(env->isolate(), current->host)).Check();
968
    srv_record->Set(context,
969
                    env->port_string(),
970
                    Integer::New(env->isolate(), current->port)).Check();
971
    srv_record->Set(context,
972
                    env->priority_string(),
973
                    Integer::New(env->isolate(), current->priority)).Check();
974
    srv_record->Set(context,
975
                    env->weight_string(),
976
                    Integer::New(env->isolate(), current->weight)).Check();
977
    if (need_type)
978
      srv_record->Set(context,
979
                      env->type_string(),
980
                      env->dns_srv_string()).Check();
981
982
    ret->Set(context, i + offset, srv_record).Check();
983
  }
984
985
4
  ares_free_data(srv_start);
986
4
  return ARES_SUCCESS;
987
}
988
989
990
4
int ParseNaptrReply(Environment* env,
991
                    const unsigned char* buf,
992
                    int len,
993
                    Local<Array> ret,
994
                    bool need_type = false) {
995
8
  HandleScope handle_scope(env->isolate());
996
4
  auto context = env->context();
997
998
  ares_naptr_reply* naptr_start;
999
4
  int status = ares_parse_naptr_reply(buf, len, &naptr_start);
1000
1001
4
  if (status != ARES_SUCCESS) {
1002
    return status;
1003
  }
1004
1005
4
  ares_naptr_reply* current = naptr_start;
1006
4
  int offset = ret->Length();
1007
4
  for (uint32_t i = 0; current != nullptr; ++i, current = current->next) {
1008
    Local<Object> naptr_record = Object::New(env->isolate());
1009
    naptr_record->Set(context,
1010
                      env->flags_string(),
1011
                      OneByteString(env->isolate(), current->flags)).Check();
1012
    naptr_record->Set(context,
1013
                      env->service_string(),
1014
                      OneByteString(env->isolate(),
1015
                                    current->service)).Check();
1016
    naptr_record->Set(context,
1017
                      env->regexp_string(),
1018
                      OneByteString(env->isolate(),
1019
                                    current->regexp)).Check();
1020
    naptr_record->Set(context,
1021
                      env->replacement_string(),
1022
                      OneByteString(env->isolate(),
1023
                                    current->replacement)).Check();
1024
    naptr_record->Set(context,
1025
                      env->order_string(),
1026
                      Integer::New(env->isolate(), current->order)).Check();
1027
    naptr_record->Set(context,
1028
                      env->preference_string(),
1029
                      Integer::New(env->isolate(),
1030
                                   current->preference)).Check();
1031
    if (need_type)
1032
      naptr_record->Set(context,
1033
                        env->type_string(),
1034
                        env->dns_naptr_string()).Check();
1035
1036
    ret->Set(context, i + offset, naptr_record).Check();
1037
  }
1038
1039
4
  ares_free_data(naptr_start);
1040
4
  return ARES_SUCCESS;
1041
}
1042
1043
1044
4
int ParseSoaReply(Environment* env,
1045
                  unsigned char* buf,
1046
                  int len,
1047
                  Local<Object>* ret) {
1048
4
  EscapableHandleScope handle_scope(env->isolate());
1049
4
  auto context = env->context();
1050
1051
  // Manage memory using standardard smart pointer std::unique_tr
1052
  struct AresDeleter {
1053
38
    void operator()(char* ptr) const noexcept { ares_free_string(ptr); }
1054
  };
1055
  using ares_unique_ptr = std::unique_ptr<char[], AresDeleter>;
1056
1057
  // Can't use ares_parse_soa_reply() here which can only parse single record
1058
4
  const unsigned int ancount = cares_get_16bit(buf + 6);
1059
4
  unsigned char* ptr = buf + NS_HFIXEDSZ;
1060
  char* name_temp;
1061
  long temp_len;  // NOLINT(runtime/int)
1062
4
  int status = ares_expand_name(ptr, buf, len, &name_temp, &temp_len);
1063
8
  const ares_unique_ptr name(name_temp);
1064
4
  if (status != ARES_SUCCESS) {
1065
    // returns EBADRESP in case of invalid input
1066
    return status == ARES_EBADNAME ? ARES_EBADRESP : status;
1067
  }
1068
1069
4
  if (ptr + temp_len + NS_QFIXEDSZ > buf + len) {
1070
    return ARES_EBADRESP;
1071
  }
1072
4
  ptr += temp_len + NS_QFIXEDSZ;
1073
1074
26
  for (unsigned int i = 0; i < ancount; i++) {
1075
    char* rr_name_temp;
1076
    long rr_temp_len;  // NOLINT(runtime/int)
1077
26
    int status2 = ares_expand_name(ptr, buf, len, &rr_name_temp, &rr_temp_len);
1078
48
    const ares_unique_ptr rr_name(rr_name_temp);
1079
1080
26
    if (status2 != ARES_SUCCESS)
1081
      return status2 == ARES_EBADNAME ? ARES_EBADRESP : status2;
1082
1083
26
    ptr += rr_temp_len;
1084
26
    if (ptr + NS_RRFIXEDSZ > buf + len) {
1085
      return ARES_EBADRESP;
1086
    }
1087
1088
26
    const int rr_type = cares_get_16bit(ptr);
1089
26
    const int rr_len = cares_get_16bit(ptr + 8);
1090
26
    ptr += NS_RRFIXEDSZ;
1091
1092
    // only need SOA
1093
26
    if (rr_type == ns_t_soa) {
1094
      char* nsname_temp;
1095
      long nsname_temp_len;  // NOLINT(runtime/int)
1096
1097
      int status3 = ares_expand_name(ptr, buf, len,
1098
                                     &nsname_temp,
1099
4
                                     &nsname_temp_len);
1100
4
      const ares_unique_ptr nsname(nsname_temp);
1101
4
      if (status3 != ARES_SUCCESS) {
1102
        return status3 == ARES_EBADNAME ? ARES_EBADRESP : status3;
1103
      }
1104
4
      ptr += nsname_temp_len;
1105
1106
      char* hostmaster_temp;
1107
      long hostmaster_temp_len;  // NOLINT(runtime/int)
1108
      int status4 = ares_expand_name(ptr, buf, len,
1109
                                     &hostmaster_temp,
1110
4
                                     &hostmaster_temp_len);
1111
4
      const ares_unique_ptr hostmaster(hostmaster_temp);
1112
4
      if (status4 != ARES_SUCCESS) {
1113
        return status4 == ARES_EBADNAME ? ARES_EBADRESP : status4;
1114
      }
1115
4
      ptr += hostmaster_temp_len;
1116
1117
4
      if (ptr + 5 * 4 > buf + len) {
1118
        return ARES_EBADRESP;
1119
      }
1120
1121
4
      const unsigned int serial = cares_get_32bit(ptr + 0 * 4);
1122
4
      const unsigned int refresh = cares_get_32bit(ptr + 1 * 4);
1123
4
      const unsigned int retry = cares_get_32bit(ptr + 2 * 4);
1124
4
      const unsigned int expire = cares_get_32bit(ptr + 3 * 4);
1125
4
      const unsigned int minttl = cares_get_32bit(ptr + 4 * 4);
1126
1127
4
      Local<Object> soa_record = Object::New(env->isolate());
1128
8
      soa_record->Set(context,
1129
                      env->nsname_string(),
1130
16
                      OneByteString(env->isolate(), nsname.get())).Check();
1131
8
      soa_record->Set(context,
1132
                      env->hostmaster_string(),
1133
                      OneByteString(env->isolate(),
1134
16
                                    hostmaster.get())).Check();
1135
8
      soa_record->Set(context,
1136
                      env->serial_string(),
1137
16
                      Integer::NewFromUnsigned(env->isolate(), serial)).Check();
1138
8
      soa_record->Set(context,
1139
                      env->refresh_string(),
1140
16
                      Integer::New(env->isolate(), refresh)).Check();
1141
8
      soa_record->Set(context,
1142
                      env->retry_string(),
1143
16
                      Integer::New(env->isolate(), retry)).Check();
1144
8
      soa_record->Set(context,
1145
                      env->expire_string(),
1146
16
                      Integer::New(env->isolate(), expire)).Check();
1147
8
      soa_record->Set(context,
1148
                      env->minttl_string(),
1149
16
                      Integer::NewFromUnsigned(env->isolate(), minttl)).Check();
1150
8
      soa_record->Set(context,
1151
                      env->type_string(),
1152
16
                      env->dns_soa_string()).Check();
1153
1154
1155
4
      *ret = handle_scope.Escape(soa_record);
1156

4
      break;
1157
    }
1158
1159
22
    ptr += rr_len;
1160
  }
1161
1162
4
  return ARES_SUCCESS;
1163
}
1164
1165
1166
12
class QueryAnyWrap: public QueryWrap {
1167
 public:
1168
6
  QueryAnyWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1169
6
    : QueryWrap(channel, req_wrap_obj, "resolveAny") {
1170
6
  }
1171
1172
6
  int Send(const char* name) override {
1173
6
    AresQuery(name, ns_c_in, ns_t_any);
1174
6
    return 0;
1175
  }
1176
1177
  SET_NO_MEMORY_INFO()
1178
  SET_MEMORY_INFO_NAME(QueryAnyWrap)
1179
  SET_SELF_SIZE(QueryAnyWrap)
1180
1181
 protected:
1182
6
  void Parse(unsigned char* buf, int len) override {
1183
10
    HandleScope handle_scope(env()->isolate());
1184
6
    auto context = env()->context();
1185
4
    Context::Scope context_scope(context);
1186
1187
6
    Local<Array> ret = Array::New(env()->isolate());
1188
    int type, status, old_count;
1189
1190
    /* Parse A records or CNAME records */
1191
    ares_addrttl addrttls[256];
1192
6
    int naddrttls = arraysize(addrttls);
1193
1194
6
    type = ns_t_cname_or_a;
1195
6
    status = ParseGeneralReply(env(),
1196
                               buf,
1197
                               len,
1198
                               &type,
1199
                               ret,
1200
                               addrttls,
1201
6
                               &naddrttls);
1202
6
    uint32_t a_count = ret->Length();
1203

6
    if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1204
2
      ParseError(status);
1205
2
      return;
1206
    }
1207
1208
4
    if (type == ns_t_a) {
1209
4
      CHECK_EQ(static_cast<uint32_t>(naddrttls), a_count);
1210
8
      for (uint32_t i = 0; i < a_count; i++) {
1211
4
        Local<Object> obj = Object::New(env()->isolate());
1212
8
        obj->Set(context,
1213
                 env()->address_string(),
1214
16
                 ret->Get(context, i).ToLocalChecked()).Check();
1215
8
        obj->Set(context,
1216
                 env()->ttl_string(),
1217
                 Integer::NewFromUnsigned(
1218
16
                   env()->isolate(), addrttls[i].ttl)).Check();
1219
8
        obj->Set(context,
1220
                 env()->type_string(),
1221
16
                 env()->dns_a_string()).Check();
1222
8
        ret->Set(context, i, obj).Check();
1223
      }
1224
    } else {
1225
      for (uint32_t i = 0; i < a_count; i++) {
1226
        Local<Object> obj = Object::New(env()->isolate());
1227
        obj->Set(context,
1228
                 env()->value_string(),
1229
                 ret->Get(context, i).ToLocalChecked()).Check();
1230
        obj->Set(context,
1231
                 env()->type_string(),
1232
                 env()->dns_cname_string()).Check();
1233
        ret->Set(context, i, obj).Check();
1234
      }
1235
    }
1236
1237
    /* Parse AAAA records */
1238
    ares_addr6ttl addr6ttls[256];
1239
4
    int naddr6ttls = arraysize(addr6ttls);
1240
1241
4
    type = ns_t_aaaa;
1242
4
    status = ParseGeneralReply(env(),
1243
                               buf,
1244
                               len,
1245
                               &type,
1246
                               ret,
1247
                               addr6ttls,
1248
4
                               &naddr6ttls);
1249
4
    uint32_t aaaa_count = ret->Length() - a_count;
1250

4
    if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1251
      ParseError(status);
1252
      return;
1253
    }
1254
1255
4
    CHECK_EQ(aaaa_count, static_cast<uint32_t>(naddr6ttls));
1256
4
    CHECK_EQ(ret->Length(), a_count + aaaa_count);
1257
16
    for (uint32_t i = a_count; i < ret->Length(); 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(), addr6ttls[i - a_count].ttl)).Check();
1266
8
      obj->Set(context,
1267
               env()->type_string(),
1268
16
               env()->dns_aaaa_string()).Check();
1269
8
      ret->Set(context, i, obj).Check();
1270
    }
1271
1272
    /* Parse MX records */
1273
4
    status = ParseMxReply(env(), buf, len, ret, true);
1274

4
    if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1275
      ParseError(status);
1276
      return;
1277
    }
1278
1279
    /* Parse NS records */
1280
4
    type = ns_t_ns;
1281
4
    old_count = ret->Length();
1282
4
    status = ParseGeneralReply(env(), buf, len, &type, ret);
1283

4
    if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1284
      ParseError(status);
1285
      return;
1286
    }
1287
16
    for (uint32_t i = old_count; i < ret->Length(); i++) {
1288
4
      Local<Object> obj = Object::New(env()->isolate());
1289
8
      obj->Set(context,
1290
               env()->value_string(),
1291
16
               ret->Get(context, i).ToLocalChecked()).Check();
1292
8
      obj->Set(context,
1293
               env()->type_string(),
1294
16
               env()->dns_ns_string()).Check();
1295
8
      ret->Set(context, i, obj).Check();
1296
    }
1297
1298
    /* Parse TXT records */
1299
4
    status = ParseTxtReply(env(), buf, len, ret, true);
1300

4
    if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1301
      ParseError(status);
1302
      return;
1303
    }
1304
1305
    /* Parse SRV records */
1306
4
    status = ParseSrvReply(env(), buf, len, ret, true);
1307

4
    if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1308
      return;
1309
    }
1310
1311
    /* Parse PTR records */
1312
4
    type = ns_t_ptr;
1313
4
    old_count = ret->Length();
1314
4
    status = ParseGeneralReply(env(), buf, len, &type, ret);
1315
16
    for (uint32_t i = old_count; i < ret->Length(); i++) {
1316
4
      Local<Object> obj = Object::New(env()->isolate());
1317
8
      obj->Set(context,
1318
               env()->value_string(),
1319
16
               ret->Get(context, i).ToLocalChecked()).Check();
1320
8
      obj->Set(context,
1321
               env()->type_string(),
1322
16
               env()->dns_ptr_string()).Check();
1323
8
      ret->Set(context, i, obj).Check();
1324
    }
1325
1326
    /* Parse NAPTR records */
1327
4
    status = ParseNaptrReply(env(), buf, len, ret, true);
1328

4
    if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1329
      ParseError(status);
1330
      return;
1331
    }
1332
1333
    /* Parse SOA records */
1334
    Local<Object> soa_record = Local<Object>();
1335
4
    status = ParseSoaReply(env(), buf, len, &soa_record);
1336

4
    if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1337
      ParseError(status);
1338
      return;
1339
    }
1340
4
    if (!soa_record.IsEmpty())
1341
12
      ret->Set(context, ret->Length(), soa_record).Check();
1342
1343
4
    CallOnComplete(ret);
1344
  }
1345
};
1346
1347
1348
18
class QueryAWrap: public QueryWrap {
1349
 public:
1350
9
  QueryAWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1351
9
      : QueryWrap(channel, req_wrap_obj, "resolve4") {
1352
9
  }
1353
1354
9
  int Send(const char* name) override {
1355
9
    AresQuery(name, ns_c_in, ns_t_a);
1356
9
    return 0;
1357
  }
1358
1359
  SET_NO_MEMORY_INFO()
1360
  SET_MEMORY_INFO_NAME(QueryAWrap)
1361
  SET_SELF_SIZE(QueryAWrap)
1362
1363
 protected:
1364
7
  void Parse(unsigned char* buf, int len) override {
1365
14
    HandleScope handle_scope(env()->isolate());
1366
14
    Context::Scope context_scope(env()->context());
1367
1368
    ares_addrttl addrttls[256];
1369
7
    int naddrttls = arraysize(addrttls), status;
1370
7
    Local<Array> ret = Array::New(env()->isolate());
1371
1372
7
    int type = ns_t_a;
1373
7
    status = ParseGeneralReply(env(),
1374
                               buf,
1375
                               len,
1376
                               &type,
1377
                               ret,
1378
                               addrttls,
1379
7
                               &naddrttls);
1380
7
    if (status != ARES_SUCCESS) {
1381
      ParseError(status);
1382
      return;
1383
    }
1384
1385
    Local<Array> ttls = AddrTTLToArray<ares_addrttl>(env(),
1386
                                                     addrttls,
1387
7
                                                     naddrttls);
1388
1389
7
    CallOnComplete(ret, ttls);
1390
  }
1391
};
1392
1393
1394
6
class QueryAaaaWrap: public QueryWrap {
1395
 public:
1396
3
  QueryAaaaWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1397
3
      : QueryWrap(channel, req_wrap_obj, "resolve6") {
1398
3
  }
1399
1400
3
  int Send(const char* name) override {
1401
3
    AresQuery(name, ns_c_in, ns_t_aaaa);
1402
3
    return 0;
1403
  }
1404
1405
1
  SET_NO_MEMORY_INFO()
1406
1
  SET_MEMORY_INFO_NAME(QueryAaaaWrap)
1407
1
  SET_SELF_SIZE(QueryAaaaWrap)
1408
1409
 protected:
1410
2
  void Parse(unsigned char* buf, int len) override {
1411
4
    HandleScope handle_scope(env()->isolate());
1412
4
    Context::Scope context_scope(env()->context());
1413
1414
    ares_addr6ttl addrttls[256];
1415
2
    int naddrttls = arraysize(addrttls), status;
1416
2
    Local<Array> ret = Array::New(env()->isolate());
1417
1418
2
    int type = ns_t_aaaa;
1419
2
    status = ParseGeneralReply(env(),
1420
                               buf,
1421
                               len,
1422
                               &type,
1423
                               ret,
1424
                               addrttls,
1425
2
                               &naddrttls);
1426
2
    if (status != ARES_SUCCESS) {
1427
      ParseError(status);
1428
      return;
1429
    }
1430
1431
    Local<Array> ttls = AddrTTLToArray<ares_addr6ttl>(env(),
1432
                                                      addrttls,
1433
2
                                                      naddrttls);
1434
1435
2
    CallOnComplete(ret, ttls);
1436
  }
1437
};
1438
1439
1440
class QueryCnameWrap: public QueryWrap {
1441
 public:
1442
  QueryCnameWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1443
      : QueryWrap(channel, req_wrap_obj, "resolveCname") {
1444
  }
1445
1446
  int Send(const char* name) override {
1447
    AresQuery(name, ns_c_in, ns_t_cname);
1448
    return 0;
1449
  }
1450
1451
  SET_NO_MEMORY_INFO()
1452
  SET_MEMORY_INFO_NAME(QueryCnameWrap)
1453
  SET_SELF_SIZE(QueryCnameWrap)
1454
1455
 protected:
1456
  void Parse(unsigned char* buf, int len) override {
1457
    HandleScope handle_scope(env()->isolate());
1458
    Context::Scope context_scope(env()->context());
1459
1460
    Local<Array> ret = Array::New(env()->isolate());
1461
    int type = ns_t_cname;
1462
    int status = ParseGeneralReply(env(), buf, len, &type, ret);
1463
    if (status != ARES_SUCCESS) {
1464
      ParseError(status);
1465
      return;
1466
    }
1467
1468
    this->CallOnComplete(ret);
1469
  }
1470
};
1471
1472
1473
2
class QueryMxWrap: public QueryWrap {
1474
 public:
1475
1
  QueryMxWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1476
1
      : QueryWrap(channel, req_wrap_obj, "resolveMx") {
1477
1
  }
1478
1479
1
  int Send(const char* name) override {
1480
1
    AresQuery(name, ns_c_in, ns_t_mx);
1481
1
    return 0;
1482
  }
1483
1484
  SET_NO_MEMORY_INFO()
1485
  SET_MEMORY_INFO_NAME(QueryMxWrap)
1486
  SET_SELF_SIZE(QueryMxWrap)
1487
1488
 protected:
1489
  void Parse(unsigned char* buf, int len) override {
1490
    HandleScope handle_scope(env()->isolate());
1491
    Context::Scope context_scope(env()->context());
1492
1493
    Local<Array> mx_records = Array::New(env()->isolate());
1494
    int status = ParseMxReply(env(), buf, len, mx_records);
1495
1496
    if (status != ARES_SUCCESS) {
1497
      ParseError(status);
1498
      return;
1499
    }
1500
1501
    this->CallOnComplete(mx_records);
1502
  }
1503
};
1504
1505
1506
class QueryNsWrap: public QueryWrap {
1507
 public:
1508
  QueryNsWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1509
      : QueryWrap(channel, req_wrap_obj, "resolveNs") {
1510
  }
1511
1512
  int Send(const char* name) override {
1513
    AresQuery(name, ns_c_in, ns_t_ns);
1514
    return 0;
1515
  }
1516
1517
  SET_NO_MEMORY_INFO()
1518
  SET_MEMORY_INFO_NAME(QueryNsWrap)
1519
  SET_SELF_SIZE(QueryNsWrap)
1520
1521
 protected:
1522
  void Parse(unsigned char* buf, int len) override {
1523
    HandleScope handle_scope(env()->isolate());
1524
    Context::Scope context_scope(env()->context());
1525
1526
    int type = ns_t_ns;
1527
    Local<Array> names = Array::New(env()->isolate());
1528
    int status = ParseGeneralReply(env(), buf, len, &type, names);
1529
    if (status != ARES_SUCCESS) {
1530
      ParseError(status);
1531
      return;
1532
    }
1533
1534
    this->CallOnComplete(names);
1535
  }
1536
};
1537
1538
1539
class QueryTxtWrap: public QueryWrap {
1540
 public:
1541
  QueryTxtWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1542
      : QueryWrap(channel, req_wrap_obj, "resolveTxt") {
1543
  }
1544
1545
  int Send(const char* name) override {
1546
    AresQuery(name, ns_c_in, ns_t_txt);
1547
    return 0;
1548
  }
1549
1550
  SET_NO_MEMORY_INFO()
1551
  SET_MEMORY_INFO_NAME(QueryTxtWrap)
1552
  SET_SELF_SIZE(QueryTxtWrap)
1553
1554
 protected:
1555
  void Parse(unsigned char* buf, int len) override {
1556
    HandleScope handle_scope(env()->isolate());
1557
    Context::Scope context_scope(env()->context());
1558
1559
    Local<Array> txt_records = Array::New(env()->isolate());
1560
    int status = ParseTxtReply(env(), buf, len, txt_records);
1561
    if (status != ARES_SUCCESS) {
1562
      ParseError(status);
1563
      return;
1564
    }
1565
1566
    this->CallOnComplete(txt_records);
1567
  }
1568
};
1569
1570
1571
class QuerySrvWrap: public QueryWrap {
1572
 public:
1573
  explicit QuerySrvWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1574
      : QueryWrap(channel, req_wrap_obj, "resolveSrv") {
1575
  }
1576
1577
  int Send(const char* name) override {
1578
    AresQuery(name, ns_c_in, ns_t_srv);
1579
    return 0;
1580
  }
1581
1582
  SET_NO_MEMORY_INFO()
1583
  SET_MEMORY_INFO_NAME(QuerySrvWrap)
1584
  SET_SELF_SIZE(QuerySrvWrap)
1585
1586
 protected:
1587
  void Parse(unsigned char* buf, int len) override {
1588
    HandleScope handle_scope(env()->isolate());
1589
    Context::Scope context_scope(env()->context());
1590
1591
    Local<Array> srv_records = Array::New(env()->isolate());
1592
    int status = ParseSrvReply(env(), buf, len, srv_records);
1593
    if (status != ARES_SUCCESS) {
1594
      ParseError(status);
1595
      return;
1596
    }
1597
1598
    this->CallOnComplete(srv_records);
1599
  }
1600
};
1601
1602
class QueryPtrWrap: public QueryWrap {
1603
 public:
1604
  explicit QueryPtrWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1605
      : QueryWrap(channel, req_wrap_obj, "resolvePtr") {
1606
  }
1607
1608
  int Send(const char* name) override {
1609
    AresQuery(name, ns_c_in, ns_t_ptr);
1610
    return 0;
1611
  }
1612
1613
  SET_NO_MEMORY_INFO()
1614
  SET_MEMORY_INFO_NAME(QueryPtrWrap)
1615
  SET_SELF_SIZE(QueryPtrWrap)
1616
1617
 protected:
1618
  void Parse(unsigned char* buf, int len) override {
1619
    HandleScope handle_scope(env()->isolate());
1620
    Context::Scope context_scope(env()->context());
1621
1622
    int type = ns_t_ptr;
1623
    Local<Array> aliases = Array::New(env()->isolate());
1624
1625
    int status = ParseGeneralReply(env(), buf, len, &type, aliases);
1626
    if (status != ARES_SUCCESS) {
1627
      ParseError(status);
1628
      return;
1629
    }
1630
1631
    this->CallOnComplete(aliases);
1632
  }
1633
};
1634
1635
class QueryNaptrWrap: public QueryWrap {
1636
 public:
1637
  explicit QueryNaptrWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1638
      : QueryWrap(channel, req_wrap_obj, "resolveNaptr") {
1639
  }
1640
1641
  int Send(const char* name) override {
1642
    AresQuery(name, ns_c_in, ns_t_naptr);
1643
    return 0;
1644
  }
1645
1646
  SET_NO_MEMORY_INFO()
1647
  SET_MEMORY_INFO_NAME(QueryNaptrWrap)
1648
  SET_SELF_SIZE(QueryNaptrWrap)
1649
1650
 protected:
1651
  void Parse(unsigned char* buf, int len) override {
1652
    HandleScope handle_scope(env()->isolate());
1653
    Context::Scope context_scope(env()->context());
1654
1655
    Local<Array> naptr_records = Array::New(env()->isolate());
1656
    int status = ParseNaptrReply(env(), buf, len, naptr_records);
1657
    if (status != ARES_SUCCESS) {
1658
      ParseError(status);
1659
      return;
1660
    }
1661
1662
    this->CallOnComplete(naptr_records);
1663
  }
1664
};
1665
1666
1667
4
class QuerySoaWrap: public QueryWrap {
1668
 public:
1669
2
  QuerySoaWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1670
2
      : QueryWrap(channel, req_wrap_obj, "resolveSoa") {
1671
2
  }
1672
1673
2
  int Send(const char* name) override {
1674
2
    AresQuery(name, ns_c_in, ns_t_soa);
1675
2
    return 0;
1676
  }
1677
1678
  SET_NO_MEMORY_INFO()
1679
  SET_MEMORY_INFO_NAME(QuerySoaWrap)
1680
  SET_SELF_SIZE(QuerySoaWrap)
1681
1682
 protected:
1683
2
  void Parse(unsigned char* buf, int len) override {
1684
4
    HandleScope handle_scope(env()->isolate());
1685
2
    auto context = env()->context();
1686
2
    Context::Scope context_scope(context);
1687
1688
    ares_soa_reply* soa_out;
1689
2
    int status = ares_parse_soa_reply(buf, len, &soa_out);
1690
1691
2
    if (status != ARES_SUCCESS) {
1692
      ParseError(status);
1693
      return;
1694
    }
1695
1696
2
    Local<Object> soa_record = Object::New(env()->isolate());
1697
1698
4
    soa_record->Set(context,
1699
                    env()->nsname_string(),
1700
                    OneByteString(env()->isolate(),
1701
8
                                  soa_out->nsname)).Check();
1702
4
    soa_record->Set(context,
1703
                    env()->hostmaster_string(),
1704
                    OneByteString(env()->isolate(),
1705
8
                                  soa_out->hostmaster)).Check();
1706
4
    soa_record->Set(context,
1707
                    env()->serial_string(),
1708
                    Integer::NewFromUnsigned(
1709
8
                      env()->isolate(), soa_out->serial)).Check();
1710
4
    soa_record->Set(context,
1711
                    env()->refresh_string(),
1712
                    Integer::New(env()->isolate(),
1713
8
                                 soa_out->refresh)).Check();
1714
4
    soa_record->Set(context,
1715
                    env()->retry_string(),
1716
8
                    Integer::New(env()->isolate(), soa_out->retry)).Check();
1717
4
    soa_record->Set(context,
1718
                    env()->expire_string(),
1719
8
                    Integer::New(env()->isolate(), soa_out->expire)).Check();
1720
4
    soa_record->Set(context,
1721
                    env()->minttl_string(),
1722
                    Integer::NewFromUnsigned(
1723
8
                      env()->isolate(), soa_out->minttl)).Check();
1724
1725
2
    ares_free_data(soa_out);
1726
1727
2
    this->CallOnComplete(soa_record);
1728
  }
1729
};
1730
1731
1732
6
class GetHostByAddrWrap: public QueryWrap {
1733
 public:
1734
3
  explicit GetHostByAddrWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1735
3
      : QueryWrap(channel, req_wrap_obj, "reverse") {
1736
3
  }
1737
1738
3
  int Send(const char* name) override {
1739
    int length, family;
1740
    char address_buffer[sizeof(struct in6_addr)];
1741
1742
3
    if (uv_inet_pton(AF_INET, name, &address_buffer) == 0) {
1743
3
      length = sizeof(struct in_addr);
1744
3
      family = AF_INET;
1745
    } else if (uv_inet_pton(AF_INET6, name, &address_buffer) == 0) {
1746
      length = sizeof(struct in6_addr);
1747
      family = AF_INET6;
1748
    } else {
1749
      return UV_EINVAL;  // So errnoException() reports a proper error.
1750
    }
1751
1752

6
    TRACE_EVENT_NESTABLE_ASYNC_BEGIN2(
1753
        TRACING_CATEGORY_NODE2(dns, native), "reverse", this,
1754
        "name", TRACE_STR_COPY(name),
1755
        "family", family == AF_INET ? "ipv4" : "ipv6");
1756
1757
3
    ares_gethostbyaddr(channel_->cares_channel(),
1758
                       address_buffer,
1759
                       length,
1760
                       family,
1761
                       Callback,
1762
3
                       MakeCallbackPointer());
1763
3
    return 0;
1764
  }
1765
1766
  SET_NO_MEMORY_INFO()
1767
  SET_MEMORY_INFO_NAME(GetHostByAddrWrap)
1768
  SET_SELF_SIZE(GetHostByAddrWrap)
1769
1770
 protected:
1771
2
  void Parse(struct hostent* host) override {
1772
4
    HandleScope handle_scope(env()->isolate());
1773
2
    Context::Scope context_scope(env()->context());
1774
4
    this->CallOnComplete(HostentToNames(env(), host));
1775
2
  }
1776
};
1777
1778
1779
template <class Wrap>
1780
24
static void Query(const FunctionCallbackInfo<Value>& args) {
1781
24
  Environment* env = Environment::GetCurrent(args);
1782
  ChannelWrap* channel;
1783






24
  ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
1784
1785






24
  CHECK_EQ(false, args.IsConstructCall());
1786






48
  CHECK(args[0]->IsObject());
1787






72
  CHECK(args[1]->IsString());
1788
1789
48
  Local<Object> req_wrap_obj = args[0].As<Object>();
1790
48
  Local<String> string = args[1].As<String>();
1791
48
  auto wrap = std::make_unique<Wrap>(channel, req_wrap_obj);
1792
1793
48
  node::Utf8Value name(env->isolate(), string);
1794
24
  channel->ModifyActivityQueryCount(1);
1795
24
  int err = wrap->Send(*name);
1796






24
  if (err) {
1797
    channel->ModifyActivityQueryCount(-1);
1798
  } else {
1799
    // Release ownership of the pointer allowing the ownership to be transferred
1800
24
    USE(wrap.release());
1801
  }
1802
1803
48
  args.GetReturnValue().Set(err);
1804
}
1805
1806
1807
4658
void AfterGetAddrInfo(uv_getaddrinfo_t* req, int status, struct addrinfo* res) {
1808
  std::unique_ptr<GetAddrInfoReqWrap> req_wrap {
1809
9316
      static_cast<GetAddrInfoReqWrap*>(req->data)};
1810
4658
  Environment* env = req_wrap->env();
1811
1812
9316
  HandleScope handle_scope(env->isolate());
1813
4658
  Context::Scope context_scope(env->context());
1814
1815
  Local<Value> argv[] = {
1816
    Integer::New(env->isolate(), status),
1817
    Null(env->isolate())
1818
13974
  };
1819
1820
4658
  uint64_t n = 0;
1821
4658
  const bool verbatim = req_wrap->verbatim();
1822
1823
4658
  if (status == 0) {
1824
4648
    Local<Array> results = Array::New(env->isolate());
1825
1826
9296
    auto add = [&] (bool want_ipv4, bool want_ipv6) {
1827
37932
      for (auto p = res; p != nullptr; p = p->ai_next) {
1828
28636
        CHECK_EQ(p->ai_socktype, SOCK_STREAM);
1829
1830
        const char* addr;
1831

28636
        if (want_ipv4 && p->ai_family == AF_INET) {
1832
4868
          addr = reinterpret_cast<char*>(
1833
9736
              &(reinterpret_cast<struct sockaddr_in*>(p->ai_addr)->sin_addr));
1834

23768
        } else if (want_ipv6 && p->ai_family == AF_INET6) {
1835
9450
          addr = reinterpret_cast<char*>(
1836
18900
              &(reinterpret_cast<struct sockaddr_in6*>(p->ai_addr)->sin6_addr));
1837
        } else {
1838
28636
          continue;
1839
        }
1840
1841
        char ip[INET6_ADDRSTRLEN];
1842
14318
        if (uv_inet_ntop(p->ai_family, addr, ip, sizeof(ip)))
1843
          continue;
1844
1845
28636
        Local<String> s = OneByteString(env->isolate(), ip);
1846
57272
        results->Set(env->context(), n, s).Check();
1847
14318
        n++;
1848
      }
1849
13944
    };
1850
1851
4648
    add(true, verbatim);
1852
4648
    if (verbatim == false)
1853
4648
      add(false, true);
1854
1855
    // No responses were found to return
1856
4648
    if (n == 0) {
1857
      argv[0] = Integer::New(env->isolate(), UV_EAI_NODATA);
1858
    }
1859
1860
4648
    argv[1] = results;
1861
  }
1862
1863
4658
  uv_freeaddrinfo(res);
1864
1865

9316
  TRACE_EVENT_NESTABLE_ASYNC_END2(
1866
      TRACING_CATEGORY_NODE2(dns, native), "lookup", req_wrap.get(),
1867
      "count", n, "verbatim", verbatim);
1868
1869
  // Make the callback into JavaScript
1870
4658
  req_wrap->MakeCallback(env->oncomplete_string(), arraysize(argv), argv);
1871
4658
}
1872
1873
1874
4
void AfterGetNameInfo(uv_getnameinfo_t* req,
1875
                      int status,
1876
                      const char* hostname,
1877
                      const char* service) {
1878
  std::unique_ptr<GetNameInfoReqWrap> req_wrap {
1879
8
      static_cast<GetNameInfoReqWrap*>(req->data)};
1880
4
  Environment* env = req_wrap->env();
1881
1882
8
  HandleScope handle_scope(env->isolate());
1883
4
  Context::Scope context_scope(env->context());
1884
1885
  Local<Value> argv[] = {
1886
    Integer::New(env->isolate(), status),
1887
    Null(env->isolate()),
1888
    Null(env->isolate())
1889
16
  };
1890
1891
4
  if (status == 0) {
1892
    // Success
1893
3
    Local<String> js_hostname = OneByteString(env->isolate(), hostname);
1894
3
    Local<String> js_service = OneByteString(env->isolate(), service);
1895
3
    argv[1] = js_hostname;
1896
3
    argv[2] = js_service;
1897
  }
1898
1899

8
  TRACE_EVENT_NESTABLE_ASYNC_END2(
1900
      TRACING_CATEGORY_NODE2(dns, native), "lookupService", req_wrap.get(),
1901
      "hostname", TRACE_STR_COPY(hostname),
1902
      "service", TRACE_STR_COPY(service));
1903
1904
  // Make the callback into JavaScript
1905
4
  req_wrap->MakeCallback(env->oncomplete_string(), arraysize(argv), argv);
1906
4
}
1907
1908
using ParseIPResult =
1909
    decltype(static_cast<ares_addr_port_node*>(nullptr)->addr);
1910
1911
24
int ParseIP(const char* ip, ParseIPResult* result = nullptr) {
1912
  ParseIPResult tmp;
1913
24
  if (result == nullptr) result = &tmp;
1914
24
  if (0 == uv_inet_pton(AF_INET, ip, result)) return 4;
1915
10
  if (0 == uv_inet_pton(AF_INET6, ip, result)) return 6;
1916
1
  return 0;
1917
}
1918
1919
24
void CanonicalizeIP(const FunctionCallbackInfo<Value>& args) {
1920
24
  v8::Isolate* isolate = args.GetIsolate();
1921
47
  node::Utf8Value ip(isolate, args[0]);
1922
1923
  ParseIPResult result;
1924
24
  const int rc = ParseIP(*ip, &result);
1925
24
  if (rc == 0) return;
1926
1927
  char canonical_ip[INET6_ADDRSTRLEN];
1928
23
  const int af = (rc == 4 ? AF_INET : AF_INET6);
1929
23
  CHECK_EQ(0, uv_inet_ntop(af, &result, canonical_ip, sizeof(canonical_ip)));
1930
46
  v8::Local<String> val = String::NewFromUtf8(isolate, canonical_ip,
1931
23
      v8::NewStringType::kNormal).ToLocalChecked();
1932
46
  args.GetReturnValue().Set(val);
1933
}
1934
1935
4659
void GetAddrInfo(const FunctionCallbackInfo<Value>& args) {
1936
4659
  Environment* env = Environment::GetCurrent(args);
1937
1938
9318
  CHECK(args[0]->IsObject());
1939
13977
  CHECK(args[1]->IsString());
1940
9318
  CHECK(args[2]->IsInt32());
1941
9318
  CHECK(args[4]->IsBoolean());
1942
9318
  Local<Object> req_wrap_obj = args[0].As<Object>();
1943
9318
  node::Utf8Value hostname(env->isolate(), args[1]);
1944
1945
4659
  int32_t flags = 0;
1946
9318
  if (args[3]->IsInt32()) {
1947
13977
    flags = args[3].As<Int32>()->Value();
1948
  }
1949
1950
  int family;
1951
1952

13977
  switch (args[2].As<Int32>()->Value()) {
1953
    case 0:
1954
4643
      family = AF_UNSPEC;
1955
4643
      break;
1956
    case 4:
1957
14
      family = AF_INET;
1958
14
      break;
1959
    case 6:
1960
2
      family = AF_INET6;
1961
2
      break;
1962
    default:
1963
      CHECK(0 && "bad address family");
1964
  }
1965
1966
  auto req_wrap = std::make_unique<GetAddrInfoReqWrap>(env,
1967
                                                       req_wrap_obj,
1968
13977
                                                       args[4]->IsTrue());
1969
1970
  struct addrinfo hints;
1971
4659
  memset(&hints, 0, sizeof(hints));
1972
4659
  hints.ai_family = family;
1973
4659
  hints.ai_socktype = SOCK_STREAM;
1974
4659
  hints.ai_flags = flags;
1975
1976


9318
  TRACE_EVENT_NESTABLE_ASYNC_BEGIN2(
1977
      TRACING_CATEGORY_NODE2(dns, native), "lookup", req_wrap.get(),
1978
      "hostname", TRACE_STR_COPY(*hostname),
1979
      "family",
1980
      family == AF_INET ? "ipv4" : family == AF_INET6 ? "ipv6" : "unspec");
1981
1982
4659
  int err = req_wrap->Dispatch(uv_getaddrinfo,
1983
                               AfterGetAddrInfo,
1984
                               *hostname,
1985
                               nullptr,
1986
4659
                               &hints);
1987
4659
  if (err == 0)
1988
    // Release ownership of the pointer allowing the ownership to be transferred
1989
4659
    USE(req_wrap.release());
1990
1991
9318
  args.GetReturnValue().Set(err);
1992
4659
}
1993
1994
1995
4
void GetNameInfo(const FunctionCallbackInfo<Value>& args) {
1996
4
  Environment* env = Environment::GetCurrent(args);
1997
1998
8
  CHECK(args[0]->IsObject());
1999
12
  CHECK(args[1]->IsString());
2000
8
  CHECK(args[2]->IsUint32());
2001
8
  Local<Object> req_wrap_obj = args[0].As<Object>();
2002
8
  node::Utf8Value ip(env->isolate(), args[1]);
2003
16
  const unsigned port = args[2]->Uint32Value(env->context()).FromJust();
2004
  struct sockaddr_storage addr;
2005
2006

4
  CHECK(uv_ip4_addr(*ip, port, reinterpret_cast<sockaddr_in*>(&addr)) == 0 ||
2007
        uv_ip6_addr(*ip, port, reinterpret_cast<sockaddr_in6*>(&addr)) == 0);
2008
2009
8
  auto req_wrap = std::make_unique<GetNameInfoReqWrap>(env, req_wrap_obj);
2010
2011

8
  TRACE_EVENT_NESTABLE_ASYNC_BEGIN2(
2012
      TRACING_CATEGORY_NODE2(dns, native), "lookupService", req_wrap.get(),
2013
      "ip", TRACE_STR_COPY(*ip), "port", port);
2014
2015
4
  int err = req_wrap->Dispatch(uv_getnameinfo,
2016
                               AfterGetNameInfo,
2017
                               reinterpret_cast<struct sockaddr*>(&addr),
2018
4
                               NI_NAMEREQD);
2019
4
  if (err == 0)
2020
    // Release ownership of the pointer allowing the ownership to be transferred
2021
4
    USE(req_wrap.release());
2022
2023
8
  args.GetReturnValue().Set(err);
2024
4
}
2025
2026
2027
53
void GetServers(const FunctionCallbackInfo<Value>& args) {
2028
53
  Environment* env = Environment::GetCurrent(args);
2029
  ChannelWrap* channel;
2030
53
  ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
2031
2032
53
  Local<Array> server_array = Array::New(env->isolate());
2033
2034
  ares_addr_port_node* servers;
2035
2036
53
  int r = ares_get_servers_ports(channel->cares_channel(), &servers);
2037
53
  CHECK_EQ(r, ARES_SUCCESS);
2038
159
  auto cleanup = OnScopeLeave([&]() { ares_free_data(servers); });
2039
2040
53
  ares_addr_port_node* cur = servers;
2041
2042
162
  for (uint32_t i = 0; cur != nullptr; ++i, cur = cur->next) {
2043
    char ip[INET6_ADDRSTRLEN];
2044
2045
109
    const void* caddr = static_cast<const void*>(&cur->addr);
2046
109
    int err = uv_inet_ntop(cur->family, caddr, ip, sizeof(ip));
2047
109
    CHECK_EQ(err, 0);
2048
2049
    Local<Value> ret[] = {
2050
      OneByteString(env->isolate(), ip),
2051
      Integer::New(env->isolate(), cur->udp_port)
2052
327
    };
2053
2054
327
    if (server_array->Set(env->context(), i,
2055
327
                          Array::New(env->isolate(), ret, arraysize(ret)))
2056
          .IsNothing()) {
2057
      return;
2058
    }
2059
  }
2060
2061
106
  args.GetReturnValue().Set(server_array);
2062
}
2063
2064
2065
20
void SetServers(const FunctionCallbackInfo<Value>& args) {
2066
20
  Environment* env = Environment::GetCurrent(args);
2067
  ChannelWrap* channel;
2068
24
  ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
2069
2070
20
  if (channel->active_query_count()) {
2071
4
    return args.GetReturnValue().Set(DNS_ESETSRVPENDING);
2072
  }
2073
2074
36
  CHECK(args[0]->IsArray());
2075
2076
18
  Local<Array> arr = Local<Array>::Cast(args[0]);
2077
2078
18
  uint32_t len = arr->Length();
2079
2080
18
  if (len == 0) {
2081
2
    int rv = ares_set_servers(channel->cares_channel(), nullptr);
2082
4
    return args.GetReturnValue().Set(rv);
2083
  }
2084
2085
32
  std::vector<ares_addr_port_node> servers(len);
2086
16
  ares_addr_port_node* last = nullptr;
2087
2088
  int err;
2089
2090
43
  for (uint32_t i = 0; i < len; i++) {
2091
108
    CHECK(arr->Get(env->context(), i).ToLocalChecked()->IsArray());
2092
2093
    Local<Array> elm =
2094
81
        Local<Array>::Cast(arr->Get(env->context(), i).ToLocalChecked());
2095
2096
135
    CHECK(elm->Get(env->context(),
2097
                   0).ToLocalChecked()->Int32Value(env->context()).FromJust());
2098
135
    CHECK(elm->Get(env->context(), 1).ToLocalChecked()->IsString());
2099
135
    CHECK(elm->Get(env->context(),
2100
                   2).ToLocalChecked()->Int32Value(env->context()).FromJust());
2101
2102
81
    int fam = elm->Get(env->context(), 0)
2103
108
        .ToLocalChecked()->Int32Value(env->context()).FromJust();
2104
    node::Utf8Value ip(env->isolate(),
2105
108
                       elm->Get(env->context(), 1).ToLocalChecked());
2106
81
    int port = elm->Get(env->context(), 2)
2107
108
        .ToLocalChecked()->Int32Value(env->context()).FromJust();
2108
2109
27
    ares_addr_port_node* cur = &servers[i];
2110
2111
27
    cur->tcp_port = cur->udp_port = port;
2112
27
    switch (fam) {
2113
      case 4:
2114
20
        cur->family = AF_INET;
2115
20
        err = uv_inet_pton(AF_INET, *ip, &cur->addr);
2116
20
        break;
2117
      case 6:
2118
7
        cur->family = AF_INET6;
2119
7
        err = uv_inet_pton(AF_INET6, *ip, &cur->addr);
2120
7
        break;
2121
      default:
2122
        CHECK(0 && "Bad address family.");
2123
    }
2124
2125
27
    if (err)
2126
      break;
2127
2128
27
    cur->next = nullptr;
2129
2130
27
    if (last != nullptr)
2131
11
      last->next = cur;
2132
2133
27
    last = cur;
2134
  }
2135
2136
16
  if (err == 0)
2137
16
    err = ares_set_servers_ports(channel->cares_channel(), &servers[0]);
2138
  else
2139
    err = ARES_EBADSTR;
2140
2141
16
  if (err == ARES_SUCCESS)
2142
16
    channel->set_is_servers_default(false);
2143
2144
32
  args.GetReturnValue().Set(err);
2145
}
2146
2147
3
void Cancel(const FunctionCallbackInfo<Value>& args) {
2148
  ChannelWrap* channel;
2149
3
  ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
2150
2151

6
  TRACE_EVENT_INSTANT0(TRACING_CATEGORY_NODE2(dns, native),
2152
      "cancel", TRACE_EVENT_SCOPE_THREAD);
2153
2154
3
  ares_cancel(channel->cares_channel());
2155
}
2156
2157
const char EMSG_ESETSRVPENDING[] = "There are pending queries.";
2158
1
void StrError(const FunctionCallbackInfo<Value>& args) {
2159
1
  Environment* env = Environment::GetCurrent(args);
2160
4
  int code = args[0]->Int32Value(env->context()).FromJust();
2161
1
  const char* errmsg = (code == DNS_ESETSRVPENDING) ?
2162
    EMSG_ESETSRVPENDING :
2163
1
    ares_strerror(code);
2164
3
  args.GetReturnValue().Set(OneByteString(env->isolate(), errmsg));
2165
1
}
2166
2167
2168
1043
void Initialize(Local<Object> target,
2169
                Local<Value> unused,
2170
                Local<Context> context,
2171
                void* priv) {
2172
1043
  Environment* env = Environment::GetCurrent(context);
2173
2174
1043
  env->SetMethod(target, "getaddrinfo", GetAddrInfo);
2175
1043
  env->SetMethod(target, "getnameinfo", GetNameInfo);
2176
1043
  env->SetMethodNoSideEffect(target, "canonicalizeIP", CanonicalizeIP);
2177
2178
1043
  env->SetMethod(target, "strerror", StrError);
2179
2180
2086
  target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(), "AF_INET"),
2181
5215
              Integer::New(env->isolate(), AF_INET)).Check();
2182
2086
  target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(), "AF_INET6"),
2183
5215
              Integer::New(env->isolate(), AF_INET6)).Check();
2184
2086
  target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(),
2185
                                                    "AF_UNSPEC"),
2186
5215
              Integer::New(env->isolate(), AF_UNSPEC)).Check();
2187
2086
  target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(),
2188
                                                    "AI_ADDRCONFIG"),
2189
5215
              Integer::New(env->isolate(), AI_ADDRCONFIG)).Check();
2190
2086
  target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(),
2191
                                                    "AI_V4MAPPED"),
2192
5215
              Integer::New(env->isolate(), AI_V4MAPPED)).Check();
2193
2194
  Local<FunctionTemplate> aiw =
2195
1043
      BaseObject::MakeLazilyInitializedJSTemplate(env);
2196
2086
  aiw->Inherit(AsyncWrap::GetConstructorTemplate(env));
2197
  Local<String> addrInfoWrapString =
2198
1043
      FIXED_ONE_BYTE_STRING(env->isolate(), "GetAddrInfoReqWrap");
2199
1043
  aiw->SetClassName(addrInfoWrapString);
2200
2086
  target->Set(env->context(),
2201
              addrInfoWrapString,
2202
4172
              aiw->GetFunction(context).ToLocalChecked()).Check();
2203
2204
  Local<FunctionTemplate> niw =
2205
1043
      BaseObject::MakeLazilyInitializedJSTemplate(env);
2206
2086
  niw->Inherit(AsyncWrap::GetConstructorTemplate(env));
2207
  Local<String> nameInfoWrapString =
2208
1043
      FIXED_ONE_BYTE_STRING(env->isolate(), "GetNameInfoReqWrap");
2209
1043
  niw->SetClassName(nameInfoWrapString);
2210
2086
  target->Set(env->context(),
2211
              nameInfoWrapString,
2212
4172
              niw->GetFunction(context).ToLocalChecked()).Check();
2213
2214
  Local<FunctionTemplate> qrw =
2215
1043
      BaseObject::MakeLazilyInitializedJSTemplate(env);
2216
2086
  qrw->Inherit(AsyncWrap::GetConstructorTemplate(env));
2217
  Local<String> queryWrapString =
2218
1043
      FIXED_ONE_BYTE_STRING(env->isolate(), "QueryReqWrap");
2219
1043
  qrw->SetClassName(queryWrapString);
2220
2086
  target->Set(env->context(),
2221
              queryWrapString,
2222
4172
              qrw->GetFunction(context).ToLocalChecked()).Check();
2223
2224
  Local<FunctionTemplate> channel_wrap =
2225
1043
      env->NewFunctionTemplate(ChannelWrap::New);
2226
2086
  channel_wrap->InstanceTemplate()->SetInternalFieldCount(1);
2227
2086
  channel_wrap->Inherit(AsyncWrap::GetConstructorTemplate(env));
2228
2229
1043
  env->SetProtoMethod(channel_wrap, "queryAny", Query<QueryAnyWrap>);
2230
1043
  env->SetProtoMethod(channel_wrap, "queryA", Query<QueryAWrap>);
2231
1043
  env->SetProtoMethod(channel_wrap, "queryAaaa", Query<QueryAaaaWrap>);
2232
1043
  env->SetProtoMethod(channel_wrap, "queryCname", Query<QueryCnameWrap>);
2233
1043
  env->SetProtoMethod(channel_wrap, "queryMx", Query<QueryMxWrap>);
2234
1043
  env->SetProtoMethod(channel_wrap, "queryNs", Query<QueryNsWrap>);
2235
1043
  env->SetProtoMethod(channel_wrap, "queryTxt", Query<QueryTxtWrap>);
2236
1043
  env->SetProtoMethod(channel_wrap, "querySrv", Query<QuerySrvWrap>);
2237
1043
  env->SetProtoMethod(channel_wrap, "queryPtr", Query<QueryPtrWrap>);
2238
1043
  env->SetProtoMethod(channel_wrap, "queryNaptr", Query<QueryNaptrWrap>);
2239
1043
  env->SetProtoMethod(channel_wrap, "querySoa", Query<QuerySoaWrap>);
2240
1043
  env->SetProtoMethod(channel_wrap, "getHostByAddr", Query<GetHostByAddrWrap>);
2241
2242
1043
  env->SetProtoMethodNoSideEffect(channel_wrap, "getServers", GetServers);
2243
1043
  env->SetProtoMethod(channel_wrap, "setServers", SetServers);
2244
1043
  env->SetProtoMethod(channel_wrap, "cancel", Cancel);
2245
2246
  Local<String> channelWrapString =
2247
1043
      FIXED_ONE_BYTE_STRING(env->isolate(), "ChannelWrap");
2248
1043
  channel_wrap->SetClassName(channelWrapString);
2249
2086
  target->Set(env->context(), channelWrapString,
2250
4172
              channel_wrap->GetFunction(context).ToLocalChecked()).Check();
2251
1043
}
2252
2253
}  // anonymous namespace
2254
}  // namespace cares_wrap
2255
}  // namespace node
2256
2257

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