GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: cares_wrap.cc Lines: 788 1059 74.4 %
Date: 2022-11-05 03:21:31 Branches: 257 490 52.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
#include "cares_wrap.h"
23
#include "async_wrap-inl.h"
24
#include "base64-inl.h"
25
#include "base_object-inl.h"
26
#include "env-inl.h"
27
#include "memory_tracker-inl.h"
28
#include "node.h"
29
#include "node_errors.h"
30
#include "node_external_reference.h"
31
#include "req_wrap-inl.h"
32
#include "util-inl.h"
33
#include "uv.h"
34
#include "v8.h"
35
36
#include <cerrno>
37
#include <cstring>
38
#include <memory>
39
#include <vector>
40
#include <unordered_set>
41
42
#ifndef T_CAA
43
# define T_CAA    257 /* Certification Authority Authorization */
44
#endif
45
46
// OpenBSD does not define these
47
#ifndef AI_ALL
48
# define AI_ALL 0
49
#endif
50
#ifndef AI_V4MAPPED
51
# define AI_V4MAPPED 0
52
#endif
53
54
55
namespace node {
56
namespace cares_wrap {
57
58
using v8::Array;
59
using v8::Context;
60
using v8::EscapableHandleScope;
61
using v8::FunctionCallbackInfo;
62
using v8::FunctionTemplate;
63
using v8::HandleScope;
64
using v8::Int32;
65
using v8::Integer;
66
using v8::Isolate;
67
using v8::Just;
68
using v8::Local;
69
using v8::Maybe;
70
using v8::Nothing;
71
using v8::Null;
72
using v8::Object;
73
using v8::String;
74
using v8::Value;
75
76
namespace {
77
78
Mutex ares_library_mutex;
79
80
56
inline uint16_t cares_get_16bit(const unsigned char* p) {
81
56
  return static_cast<uint32_t>(p[0] << 8U) | (static_cast<uint32_t>(p[1]));
82
}
83
84
18
void ares_poll_cb(uv_poll_t* watcher, int status, int events) {
85
18
  NodeAresTask* task = ContainerOf(&NodeAresTask::poll_watcher, watcher);
86
18
  ChannelWrap* channel = task->channel;
87
88
  /* Reset the idle timer */
89
18
  uv_timer_again(channel->timer_handle());
90
91
18
  if (status < 0) {
92
    /* An error happened. Just pretend that the socket is both readable and */
93
    /* writable. */
94
    ares_process_fd(channel->cares_channel(), task->sock, task->sock);
95
    return;
96
  }
97
98
  /* Process DNS responses */
99
36
  ares_process_fd(channel->cares_channel(),
100
18
                  events & UV_READABLE ? task->sock : ARES_SOCKET_BAD,
101
18
                  events & UV_WRITABLE ? task->sock : ARES_SOCKET_BAD);
102
}
103
104
105
30
void ares_poll_close_cb(uv_poll_t* watcher) {
106
  std::unique_ptr<NodeAresTask> free_me(
107
30
        ContainerOf(&NodeAresTask::poll_watcher, watcher));
108
30
}
109
110
111
/* Callback from ares when socket operation is started */
112
60
void ares_sockstate_cb(void* data, ares_socket_t sock, int read, int write) {
113
60
  ChannelWrap* channel = static_cast<ChannelWrap*>(data);
114
  NodeAresTask* task;
115
116
60
  NodeAresTask lookup_task;
117
60
  lookup_task.sock = sock;
118
60
  auto it = channel->task_list()->find(&lookup_task);
119
120
60
  task = (it == channel->task_list()->end()) ? nullptr : *it;
121
122

60
  if (read || write) {
123
30
    if (!task) {
124
      /* New socket */
125
30
      channel->StartTimer();
126
127
30
      task = NodeAresTask::Create(channel, sock);
128
30
      if (task == nullptr) {
129
        /* This should never happen unless we're out of memory or something */
130
        /* is seriously wrong. The socket won't be polled, but the query will */
131
        /* eventually time out. */
132
        return;
133
      }
134
135
30
      channel->task_list()->insert(task);
136
    }
137
138
    /* This should never fail. If it fails anyway, the query will eventually */
139
    /* time out. */
140
30
    uv_poll_start(&task->poll_watcher,
141

30
                  (read ? UV_READABLE : 0) | (write ? UV_WRITABLE : 0),
142
                  ares_poll_cb);
143
144
  } else {
145
    /* read == 0 and write == 0 this is c-ares's way of notifying us that */
146
    /* the socket is now closed. We must free the data associated with */
147
    /* socket. */
148
30
    CHECK(task &&
149
          "When an ares socket is closed we should have a handle for it");
150
151
30
    channel->task_list()->erase(it);
152
30
    channel->env()->CloseHandle(&task->poll_watcher, ares_poll_close_cb);
153
154
30
    if (channel->task_list()->empty()) {
155
30
      channel->CloseTimer();
156
    }
157
  }
158
}
159
160
2
Local<Array> HostentToNames(Environment* env, struct hostent* host) {
161
2
  EscapableHandleScope scope(env->isolate());
162
163
2
  std::vector<Local<Value>> names;
164
165
2
  for (uint32_t i = 0; host->h_aliases[i] != nullptr; ++i)
166
    names.emplace_back(OneByteString(env->isolate(), host->h_aliases[i]));
167
168
2
  Local<Array> ret = Array::New(env->isolate(), names.data(), names.size());
169
170
2
  return scope.Escape(ret);
171
}
172
173
4
Local<Array> HostentToNames(Environment* env,
174
                            struct hostent* host,
175
                            Local<Array> names) {
176
4
  size_t offset = names->Length();
177
178
8
  for (uint32_t i = 0; host->h_aliases[i] != nullptr; ++i) {
179
8
    names->Set(
180
        env->context(),
181
        i + offset,
182
12
        OneByteString(env->isolate(), host->h_aliases[i])).Check();
183
  }
184
185
4
  return names;
186
}
187
188
template <typename T>
189
18
Local<Array> AddrTTLToArray(
190
    Environment* env,
191
    const T* addrttls,
192
    size_t naddrttls) {
193
36
  MaybeStackBuffer<Local<Value>, 8> ttls(naddrttls);
194
36
  for (size_t i = 0; i < naddrttls; i++)
195
36
    ttls[i] = Integer::NewFromUnsigned(env->isolate(), addrttls[i].ttl);
196
197
18
  return Array::New(env->isolate(), ttls.out(), naddrttls);
198
}
199
200
27
int ParseGeneralReply(
201
    Environment* env,
202
    const unsigned char* buf,
203
    int len,
204
    int* type,
205
    Local<Array> ret,
206
    void* addrttls = nullptr,
207
    int* naddrttls = nullptr) {
208
54
  HandleScope handle_scope(env->isolate());
209
  hostent* host;
210
211
  int status;
212

27
  switch (*type) {
213
13
    case ns_t_a:
214
    case ns_t_cname:
215
    case ns_t_cname_or_a:
216
13
      status = ares_parse_a_reply(buf,
217
                                  len,
218
                                  &host,
219
                                  static_cast<ares_addrttl*>(addrttls),
220
                                  naddrttls);
221
13
      break;
222
6
    case ns_t_aaaa:
223
6
      status = ares_parse_aaaa_reply(buf,
224
                                     len,
225
                                     &host,
226
                                     static_cast<ares_addr6ttl*>(addrttls),
227
                                     naddrttls);
228
6
      break;
229
4
    case ns_t_ns:
230
4
      status = ares_parse_ns_reply(buf, len, &host);
231
4
      break;
232
4
    case ns_t_ptr:
233
4
      status = ares_parse_ptr_reply(buf, len, nullptr, 0, AF_INET, &host);
234
4
      break;
235
    default:
236
      CHECK(0 && "Bad NS type");
237
      break;
238
  }
239
240
27
  if (status != ARES_SUCCESS)
241
2
    return status;
242
243
25
  CHECK_NOT_NULL(host);
244
50
  HostEntPointer ptr(host);
245
246
  /* If it's `CNAME`, return the CNAME value;
247
   * And if it's `CNAME_OR_A` and it has value in `h_name` and `h_aliases[0]`,
248
   * we consider it's a CNAME record, otherwise we consider it's an A record. */
249


50
  if ((*type == ns_t_cname_or_a && ptr->h_name && ptr->h_aliases[0]) ||
250
25
      *type == ns_t_cname) {
251
    // A cname lookup always returns a single record but we follow the
252
    // common API here.
253
    *type = ns_t_cname;
254
    ret->Set(env->context(),
255
             ret->Length(),
256
             OneByteString(env->isolate(), ptr->h_name)).Check();
257
    return ARES_SUCCESS;
258
  }
259
260
25
  if (*type == ns_t_cname_or_a)
261
4
    *type = ns_t_a;
262
263
25
  if (*type == ns_t_ns) {
264
4
    HostentToNames(env, ptr.get(), ret);
265
21
  } else if (*type == ns_t_ptr) {
266
4
    uint32_t offset = ret->Length();
267
8
    for (uint32_t i = 0; ptr->h_aliases[i] != nullptr; i++) {
268
4
      auto alias = OneByteString(env->isolate(), ptr->h_aliases[i]);
269
8
      ret->Set(env->context(), i + offset, alias).Check();
270
    }
271
  } else {
272
17
    uint32_t offset = ret->Length();
273
    char ip[INET6_ADDRSTRLEN];
274
34
    for (uint32_t i = 0; ptr->h_addr_list[i] != nullptr; ++i) {
275
17
      uv_inet_ntop(ptr->h_addrtype, ptr->h_addr_list[i], ip, sizeof(ip));
276
17
      auto address = OneByteString(env->isolate(), ip);
277
34
      ret->Set(env->context(), i + offset, address).Check();
278
    }
279
  }
280
281
25
  return ARES_SUCCESS;
282
}
283
284
4
int ParseMxReply(
285
    Environment* env,
286
    const unsigned char* buf,
287
    int len,
288
    Local<Array> ret,
289
    bool need_type = false) {
290
8
  HandleScope handle_scope(env->isolate());
291
292
  struct ares_mx_reply* mx_start;
293
4
  int status = ares_parse_mx_reply(buf, len, &mx_start);
294
4
  if (status != ARES_SUCCESS)
295
    return status;
296
297
4
  uint32_t offset = ret->Length();
298
4
  ares_mx_reply* current = mx_start;
299
8
  for (uint32_t i = 0; current != nullptr; ++i, current = current->next) {
300
4
    Local<Object> mx_record = Object::New(env->isolate());
301
4
    mx_record->Set(env->context(),
302
                   env->exchange_string(),
303
16
                   OneByteString(env->isolate(), current->host)).Check();
304
4
    mx_record->Set(env->context(),
305
                   env->priority_string(),
306
12
                   Integer::New(env->isolate(), current->priority)).Check();
307
4
    if (need_type)
308
4
      mx_record->Set(env->context(),
309
                     env->type_string(),
310
16
                     env->dns_mx_string()).Check();
311
312
8
    ret->Set(env->context(), i + offset, mx_record).Check();
313
  }
314
315
4
  ares_free_data(mx_start);
316
4
  return ARES_SUCCESS;
317
}
318
319
4
int ParseCaaReply(
320
    Environment* env,
321
    const unsigned char* buf,
322
    int len,
323
    Local<Array> ret,
324
    bool need_type = false) {
325
8
  HandleScope handle_scope(env->isolate());
326
327
  struct ares_caa_reply* caa_start;
328
4
  int status = ares_parse_caa_reply(buf, len, &caa_start);
329
4
  if (status != ARES_SUCCESS)
330
    return status;
331
332
4
  uint32_t offset = ret->Length();
333
4
  ares_caa_reply* current = caa_start;
334
6
  for (uint32_t i = 0; current != nullptr; ++i, current = current->next) {
335
2
    Local<Object> caa_record = Object::New(env->isolate());
336
337
2
    caa_record->Set(env->context(),
338
                    env->dns_critical_string(),
339
8
                    Integer::New(env->isolate(), current->critical)).Check();
340
2
    caa_record->Set(env->context(),
341
2
                    OneByteString(env->isolate(), current->property),
342
6
                    OneByteString(env->isolate(), current->value)).Check();
343
2
    if (need_type)
344
2
      caa_record->Set(env->context(),
345
                      env->type_string(),
346
8
                      env->dns_caa_string()).Check();
347
348
4
    ret->Set(env->context(), i + offset, caa_record).Check();
349
  }
350
351
4
  ares_free_data(caa_start);
352
4
  return ARES_SUCCESS;
353
}
354
355
4
int ParseTxtReply(
356
    Environment* env,
357
    const unsigned char* buf,
358
    int len,
359
    Local<Array> ret,
360
    bool need_type = false) {
361
8
  HandleScope handle_scope(env->isolate());
362
363
  struct ares_txt_ext* txt_out;
364
365
4
  int status = ares_parse_txt_reply_ext(buf, len, &txt_out);
366
4
  if (status != ARES_SUCCESS)
367
    return status;
368
369
  Local<Array> txt_chunk;
370
371
4
  struct ares_txt_ext* current = txt_out;
372
4
  uint32_t i = 0, j;
373
4
  uint32_t offset = ret->Length();
374
8
  for (j = 0; current != nullptr; current = current->next) {
375
    Local<String> txt =
376
4
        OneByteString(env->isolate(), current->txt, current->length);
377
378
    // New record found - write out the current chunk
379
4
    if (current->record_start) {
380
2
      if (!txt_chunk.IsEmpty()) {
381
        if (need_type) {
382
          Local<Object> elem = Object::New(env->isolate());
383
          elem->Set(env->context(), env->entries_string(), txt_chunk).Check();
384
          elem->Set(env->context(),
385
                    env->type_string(),
386
                    env->dns_txt_string()).Check();
387
          ret->Set(env->context(), offset + i++, elem).Check();
388
        } else {
389
          ret->Set(env->context(), offset + i++, txt_chunk).Check();
390
        }
391
      }
392
393
2
      txt_chunk = Array::New(env->isolate());
394
2
      j = 0;
395
    }
396
397
8
    txt_chunk->Set(env->context(), j++, txt).Check();
398
  }
399
400
  // Push last chunk if it isn't empty
401
4
  if (!txt_chunk.IsEmpty()) {
402
2
    if (need_type) {
403
2
      Local<Object> elem = Object::New(env->isolate());
404
6
      elem->Set(env->context(), env->entries_string(), txt_chunk).Check();
405
2
      elem->Set(env->context(),
406
                env->type_string(),
407
8
                env->dns_txt_string()).Check();
408
4
      ret->Set(env->context(), offset + i, elem).Check();
409
    } else {
410
      ret->Set(env->context(), offset + i, txt_chunk).Check();
411
    }
412
  }
413
414
4
  ares_free_data(txt_out);
415
4
  return ARES_SUCCESS;
416
}
417
418
419
4
int ParseSrvReply(
420
    Environment* env,
421
    const unsigned char* buf,
422
    int len,
423
    Local<Array> ret,
424
    bool need_type = false) {
425
8
  HandleScope handle_scope(env->isolate());
426
427
  struct ares_srv_reply* srv_start;
428
4
  int status = ares_parse_srv_reply(buf, len, &srv_start);
429
4
  if (status != ARES_SUCCESS)
430
    return status;
431
432
4
  ares_srv_reply* current = srv_start;
433
4
  int offset = ret->Length();
434
4
  for (uint32_t i = 0; current != nullptr; ++i, current = current->next) {
435
    Local<Object> srv_record = Object::New(env->isolate());
436
    srv_record->Set(env->context(),
437
                    env->name_string(),
438
                    OneByteString(env->isolate(), current->host)).Check();
439
    srv_record->Set(env->context(),
440
                    env->port_string(),
441
                    Integer::New(env->isolate(), current->port)).Check();
442
    srv_record->Set(env->context(),
443
                    env->priority_string(),
444
                    Integer::New(env->isolate(), current->priority)).Check();
445
    srv_record->Set(env->context(),
446
                    env->weight_string(),
447
                    Integer::New(env->isolate(), current->weight)).Check();
448
    if (need_type)
449
      srv_record->Set(env->context(),
450
                      env->type_string(),
451
                      env->dns_srv_string()).Check();
452
453
    ret->Set(env->context(), i + offset, srv_record).Check();
454
  }
455
456
4
  ares_free_data(srv_start);
457
4
  return ARES_SUCCESS;
458
}
459
460
461
4
int ParseNaptrReply(
462
    Environment* env,
463
    const unsigned char* buf,
464
    int len,
465
    Local<Array> ret,
466
    bool need_type = false) {
467
8
  HandleScope handle_scope(env->isolate());
468
469
  ares_naptr_reply* naptr_start;
470
4
  int status = ares_parse_naptr_reply(buf, len, &naptr_start);
471
472
4
  if (status != ARES_SUCCESS)
473
    return status;
474
475
4
  ares_naptr_reply* current = naptr_start;
476
4
  int offset = ret->Length();
477
4
  for (uint32_t i = 0; current != nullptr; ++i, current = current->next) {
478
    Local<Object> naptr_record = Object::New(env->isolate());
479
    naptr_record->Set(env->context(),
480
                      env->flags_string(),
481
                      OneByteString(env->isolate(), current->flags)).Check();
482
    naptr_record->Set(env->context(),
483
                      env->service_string(),
484
                      OneByteString(env->isolate(),
485
                                    current->service)).Check();
486
    naptr_record->Set(env->context(),
487
                      env->regexp_string(),
488
                      OneByteString(env->isolate(),
489
                                    current->regexp)).Check();
490
    naptr_record->Set(env->context(),
491
                      env->replacement_string(),
492
                      OneByteString(env->isolate(),
493
                                    current->replacement)).Check();
494
    naptr_record->Set(env->context(),
495
                      env->order_string(),
496
                      Integer::New(env->isolate(), current->order)).Check();
497
    naptr_record->Set(env->context(),
498
                      env->preference_string(),
499
                      Integer::New(env->isolate(),
500
                                   current->preference)).Check();
501
    if (need_type)
502
      naptr_record->Set(env->context(),
503
                        env->type_string(),
504
                        env->dns_naptr_string()).Check();
505
506
    ret->Set(env->context(), i + offset, naptr_record).Check();
507
  }
508
509
4
  ares_free_data(naptr_start);
510
4
  return ARES_SUCCESS;
511
}
512
513
514
4
int ParseSoaReply(
515
    Environment* env,
516
    unsigned char* buf,
517
    int len,
518
    Local<Object>* ret) {
519
4
  EscapableHandleScope handle_scope(env->isolate());
520
521
  // Manage memory using standardard smart pointer std::unique_tr
522
  struct AresDeleter {
523
38
    void operator()(char* ptr) const noexcept { ares_free_string(ptr); }
524
  };
525
  using ares_unique_ptr = std::unique_ptr<char[], AresDeleter>;
526
527
  // Can't use ares_parse_soa_reply() here which can only parse single record
528
4
  const unsigned int ancount = cares_get_16bit(buf + 6);
529
4
  unsigned char* ptr = buf + NS_HFIXEDSZ;
530
4
  char* name_temp = nullptr;
531
  long temp_len;  // NOLINT(runtime/int)
532
4
  int status = ares_expand_name(ptr, buf, len, &name_temp, &temp_len);
533
4
  if (status != ARES_SUCCESS) {
534
    // returns EBADRESP in case of invalid input
535
    return status == ARES_EBADNAME ? ARES_EBADRESP : status;
536
  }
537
538
8
  const ares_unique_ptr name(name_temp);
539
540
4
  if (ptr + temp_len + NS_QFIXEDSZ > buf + len) {
541
    return ARES_EBADRESP;
542
  }
543
4
  ptr += temp_len + NS_QFIXEDSZ;
544
545
26
  for (unsigned int i = 0; i < ancount; i++) {
546
26
    char* rr_name_temp = nullptr;
547
    long rr_temp_len;  // NOLINT(runtime/int)
548
26
    int status2 = ares_expand_name(ptr, buf, len, &rr_name_temp, &rr_temp_len);
549
550
26
    if (status2 != ARES_SUCCESS)
551
      return status2 == ARES_EBADNAME ? ARES_EBADRESP : status2;
552
553
26
    const ares_unique_ptr rr_name(rr_name_temp);
554
555
26
    ptr += rr_temp_len;
556
26
    if (ptr + NS_RRFIXEDSZ > buf + len) {
557
      return ARES_EBADRESP;
558
    }
559
560
26
    const int rr_type = cares_get_16bit(ptr);
561
26
    const int rr_len = cares_get_16bit(ptr + 8);
562
26
    ptr += NS_RRFIXEDSZ;
563
564
    // only need SOA
565
26
    if (rr_type == ns_t_soa) {
566
4
      char* nsname_temp = nullptr;
567
      long nsname_temp_len;  // NOLINT(runtime/int)
568
569
4
      int status3 = ares_expand_name(ptr, buf, len,
570
                                     &nsname_temp,
571
                                     &nsname_temp_len);
572
4
      if (status3 != ARES_SUCCESS) {
573
        return status3 == ARES_EBADNAME ? ARES_EBADRESP : status3;
574
      }
575
4
      const ares_unique_ptr nsname(nsname_temp);
576
4
      ptr += nsname_temp_len;
577
578
4
      char* hostmaster_temp = nullptr;
579
      long hostmaster_temp_len;  // NOLINT(runtime/int)
580
4
      int status4 = ares_expand_name(ptr, buf, len,
581
                                     &hostmaster_temp,
582
                                     &hostmaster_temp_len);
583
4
      if (status4 != ARES_SUCCESS) {
584
        return status4 == ARES_EBADNAME ? ARES_EBADRESP : status4;
585
      }
586
4
      const ares_unique_ptr hostmaster(hostmaster_temp);
587
4
      ptr += hostmaster_temp_len;
588
589
4
      if (ptr + 5 * 4 > buf + len) {
590
        return ARES_EBADRESP;
591
      }
592
593
4
      const unsigned int serial = ReadUint32BE(ptr + 0 * 4);
594
4
      const unsigned int refresh = ReadUint32BE(ptr + 1 * 4);
595
4
      const unsigned int retry = ReadUint32BE(ptr + 2 * 4);
596
4
      const unsigned int expire = ReadUint32BE(ptr + 3 * 4);
597
4
      const unsigned int minttl = ReadUint32BE(ptr + 4 * 4);
598
599
4
      Local<Object> soa_record = Object::New(env->isolate());
600
4
      soa_record->Set(env->context(),
601
                      env->nsname_string(),
602
16
                      OneByteString(env->isolate(), nsname.get())).Check();
603
4
      soa_record->Set(env->context(),
604
                      env->hostmaster_string(),
605
                      OneByteString(env->isolate(),
606
16
                                    hostmaster.get())).Check();
607
4
      soa_record->Set(env->context(),
608
                      env->serial_string(),
609
16
                      Integer::NewFromUnsigned(env->isolate(), serial)).Check();
610
4
      soa_record->Set(env->context(),
611
                      env->refresh_string(),
612
16
                      Integer::New(env->isolate(), refresh)).Check();
613
4
      soa_record->Set(env->context(),
614
                      env->retry_string(),
615
16
                      Integer::New(env->isolate(), retry)).Check();
616
4
      soa_record->Set(env->context(),
617
                      env->expire_string(),
618
16
                      Integer::New(env->isolate(), expire)).Check();
619
4
      soa_record->Set(env->context(),
620
                      env->minttl_string(),
621
16
                      Integer::NewFromUnsigned(env->isolate(), minttl)).Check();
622
4
      soa_record->Set(env->context(),
623
                      env->type_string(),
624
16
                      env->dns_soa_string()).Check();
625
626
627
4
      *ret = handle_scope.Escape(soa_record);
628
4
      break;
629
    }
630
631
22
    ptr += rr_len;
632
  }
633
634
4
  return ARES_SUCCESS;
635
}
636
}  // anonymous namespace
637
638
1193
ChannelWrap::ChannelWrap(
639
      Environment* env,
640
      Local<Object> object,
641
      int timeout,
642
1193
      int tries)
643
    : AsyncWrap(env, object, PROVIDER_DNSCHANNEL),
644
      timeout_(timeout),
645
1193
      tries_(tries) {
646
1193
  MakeWeak();
647
648
1193
  Setup();
649
1193
}
650
651
4
void ChannelWrap::MemoryInfo(MemoryTracker* tracker) const {
652
4
  if (timer_handle_ != nullptr)
653
    tracker->TrackField("timer_handle", *timer_handle_);
654
4
  tracker->TrackField("task_list", task_list_, "NodeAresTask::List");
655
4
}
656
657
1193
void ChannelWrap::New(const FunctionCallbackInfo<Value>& args) {
658
1193
  CHECK(args.IsConstructCall());
659
1193
  CHECK_EQ(args.Length(), 2);
660
1193
  CHECK(args[0]->IsInt32());
661
1193
  CHECK(args[1]->IsInt32());
662
2386
  const int timeout = args[0].As<Int32>()->Value();
663
2386
  const int tries = args[1].As<Int32>()->Value();
664
1193
  Environment* env = Environment::GetCurrent(args);
665
1193
  new ChannelWrap(env, args.This(), timeout, tries);
666
1193
}
667
668
5241
GetAddrInfoReqWrap::GetAddrInfoReqWrap(
669
    Environment* env,
670
    Local<Object> req_wrap_obj,
671
5241
    bool verbatim)
672
    : ReqWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_GETADDRINFOREQWRAP),
673
5241
      verbatim_(verbatim) {}
674
675
6
GetNameInfoReqWrap::GetNameInfoReqWrap(
676
    Environment* env,
677
6
    Local<Object> req_wrap_obj)
678
6
    : ReqWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_GETNAMEINFOREQWRAP) {}
679
680
/* This is called once per second by loop->timer. It is used to constantly */
681
/* call back into c-ares for possibly processing timeouts. */
682
77
void ChannelWrap::AresTimeout(uv_timer_t* handle) {
683
77
  ChannelWrap* channel = static_cast<ChannelWrap*>(handle->data);
684
77
  CHECK_EQ(channel->timer_handle(), handle);
685
77
  CHECK_EQ(false, channel->task_list()->empty());
686
77
  ares_process_fd(channel->cares_channel(), ARES_SOCKET_BAD, ARES_SOCKET_BAD);
687
77
}
688
689
690
void NodeAresTask::MemoryInfo(MemoryTracker* tracker) const {
691
  tracker->TrackField("channel", channel);
692
}
693
694
/* Allocates and returns a new NodeAresTask */
695
30
NodeAresTask* NodeAresTask::Create(ChannelWrap* channel, ares_socket_t sock) {
696
30
  auto task = new NodeAresTask();
697
698
30
  task->channel = channel;
699
30
  task->sock = sock;
700
701
30
  if (uv_poll_init_socket(channel->env()->event_loop(),
702
30
                          &task->poll_watcher, sock) < 0) {
703
    /* This should never happen. */
704
    delete task;
705
    return nullptr;
706
  }
707
708
30
  return task;
709
}
710
711
1193
void ChannelWrap::Setup() {
712
  struct ares_options options;
713
1193
  memset(&options, 0, sizeof(options));
714
1193
  options.flags = ARES_FLAG_NOCHECKRESP;
715
1193
  options.sock_state_cb = ares_sockstate_cb;
716
1193
  options.sock_state_cb_data = this;
717
1193
  options.timeout = timeout_;
718
1193
  options.tries = tries_;
719
720
  int r;
721
1193
  if (!library_inited_) {
722
1193
    Mutex::ScopedLock lock(ares_library_mutex);
723
    // Multiple calls to ares_library_init() increase a reference counter,
724
    // so this is a no-op except for the first call to it.
725
1193
    r = ares_library_init(ARES_LIB_INIT_ALL);
726
1193
    if (r != ARES_SUCCESS)
727
      return env()->ThrowError(ToErrorCodeString(r));
728
  }
729
730
  /* We do the call to ares_init_option for caller. */
731
1193
  const int optmask =
732
      ARES_OPT_FLAGS | ARES_OPT_TIMEOUTMS |
733
      ARES_OPT_SOCK_STATE_CB | ARES_OPT_TRIES;
734
1193
  r = ares_init_options(&channel_, &options, optmask);
735
736
1193
  if (r != ARES_SUCCESS) {
737
    Mutex::ScopedLock lock(ares_library_mutex);
738
    ares_library_cleanup();
739
    return env()->ThrowError(ToErrorCodeString(r));
740
  }
741
742
1193
  library_inited_ = true;
743
}
744
745
30
void ChannelWrap::StartTimer() {
746
30
  if (timer_handle_ == nullptr) {
747
30
    timer_handle_ = new uv_timer_t();
748
30
    timer_handle_->data = static_cast<void*>(this);
749
30
    uv_timer_init(env()->event_loop(), timer_handle_);
750
  } else if (uv_is_active(reinterpret_cast<uv_handle_t*>(timer_handle_))) {
751
    return;
752
  }
753
30
  int timeout = timeout_;
754
30
  if (timeout == 0) timeout = 1;
755

30
  if (timeout < 0 || timeout > 1000) timeout = 1000;
756
30
  uv_timer_start(timer_handle_, AresTimeout, timeout, timeout);
757
}
758
759
1185
void ChannelWrap::CloseTimer() {
760
1185
  if (timer_handle_ == nullptr)
761
1155
    return;
762
763
60
  env()->CloseHandle(timer_handle_, [](uv_timer_t* handle) { delete handle; });
764
30
  timer_handle_ = nullptr;
765
}
766
767
4620
ChannelWrap::~ChannelWrap() {
768
2310
  ares_destroy(channel_);
769
770
2310
  if (library_inited_) {
771
4620
    Mutex::ScopedLock lock(ares_library_mutex);
772
    // This decreases the reference counter increased by ares_library_init().
773
2310
    ares_library_cleanup();
774
  }
775
776
2310
  CloseTimer();
777
4620
}
778
779
780
105
void ChannelWrap::ModifyActivityQueryCount(int count) {
781
105
  active_query_count_ += count;
782
105
  CHECK_GE(active_query_count_, 0);
783
105
}
784
785
786
/**
787
 * This function is to check whether current servers are fallback servers
788
 * when cares initialized.
789
 *
790
 * The fallback servers of cares is [ "127.0.0.1" ] with no user additional
791
 * setting.
792
 */
793
50
void ChannelWrap::EnsureServers() {
794
  /* if last query is OK or servers are set by user self, do not check */
795

50
  if (query_last_ok_ || !is_servers_default_) {
796
50
    return;
797
  }
798
799
  ares_addr_port_node* servers = nullptr;
800
801
  ares_get_servers_ports(channel_, &servers);
802
803
  /* if no server or multi-servers, ignore */
804
  if (servers == nullptr) return;
805
  if (servers->next != nullptr) {
806
    ares_free_data(servers);
807
    is_servers_default_ = false;
808
    return;
809
  }
810
811
  /* if the only server is not 127.0.0.1, ignore */
812
  if (servers[0].family != AF_INET ||
813
      servers[0].addr.addr4.s_addr != htonl(INADDR_LOOPBACK) ||
814
      servers[0].tcp_port != 0 ||
815
      servers[0].udp_port != 0) {
816
    ares_free_data(servers);
817
    is_servers_default_ = false;
818
    return;
819
  }
820
821
  ares_free_data(servers);
822
  servers = nullptr;
823
824
  /* destroy channel and reset channel */
825
  ares_destroy(channel_);
826
827
  CloseTimer();
828
  Setup();
829
}
830
831
8
int AnyTraits::Send(QueryWrap<AnyTraits>* wrap, const char* name) {
832
8
  wrap->AresQuery(name, ns_c_in, ns_t_any);
833
8
  return 0;
834
}
835
836
36
int ATraits::Send(QueryWrap<ATraits>* wrap, const char* name) {
837
36
  wrap->AresQuery(name, ns_c_in, ns_t_a);
838
36
  return 0;
839
}
840
841
3
int AaaaTraits::Send(QueryWrap<AaaaTraits>* wrap, const char* name) {
842
3
  wrap->AresQuery(name, ns_c_in, ns_t_aaaa);
843
3
  return 0;
844
}
845
846
int CaaTraits::Send(QueryWrap<CaaTraits>* wrap, const char* name) {
847
  wrap->AresQuery(name, ns_c_in, T_CAA);
848
  return 0;
849
}
850
851
int CnameTraits::Send(QueryWrap<CnameTraits>* wrap, const char* name) {
852
  wrap->AresQuery(name, ns_c_in, ns_t_cname);
853
  return 0;
854
}
855
856
1
int MxTraits::Send(QueryWrap<MxTraits>* wrap, const char* name) {
857
1
  wrap->AresQuery(name, ns_c_in, ns_t_mx);
858
1
  return 0;
859
}
860
861
int NsTraits::Send(QueryWrap<NsTraits>* wrap, const char* name) {
862
  wrap->AresQuery(name, ns_c_in, ns_t_ns);
863
  return 0;
864
}
865
866
int TxtTraits::Send(QueryWrap<TxtTraits>* wrap, const char* name) {
867
  wrap->AresQuery(name, ns_c_in, ns_t_txt);
868
  return 0;
869
}
870
871
int SrvTraits::Send(QueryWrap<SrvTraits>* wrap, const char* name) {
872
  wrap->AresQuery(name, ns_c_in, ns_t_srv);
873
  return 0;
874
}
875
876
int PtrTraits::Send(QueryWrap<PtrTraits>* wrap, const char* name) {
877
  wrap->AresQuery(name, ns_c_in, ns_t_ptr);
878
  return 0;
879
}
880
881
int NaptrTraits::Send(QueryWrap<NaptrTraits>* wrap, const char* name) {
882
  wrap->AresQuery(name, ns_c_in, ns_t_naptr);
883
  return 0;
884
}
885
886
2
int SoaTraits::Send(QueryWrap<SoaTraits>* wrap, const char* name) {
887
2
  wrap->AresQuery(name, ns_c_in, ns_t_soa);
888
2
  return 0;
889
}
890
891
6
int AnyTraits::Parse(
892
    QueryAnyWrap* wrap,
893
    const std::unique_ptr<ResponseData>& response) {
894
6
  if (UNLIKELY(response->is_host))
895
    return ARES_EBADRESP;
896
897
6
  unsigned char* buf = response->buf.data;
898
6
  int len = response->buf.size;
899
900
6
  Environment* env = wrap->env();
901
12
  HandleScope handle_scope(env->isolate());
902
6
  Context::Scope context_scope(env->context());
903
904
6
  Local<Array> ret = Array::New(env->isolate());
905
  int type, status, old_count;
906
907
  /* Parse A records or CNAME records */
908
  ares_addrttl addrttls[256];
909
6
  int naddrttls = arraysize(addrttls);
910
911
6
  type = ns_t_cname_or_a;
912
6
  status = ParseGeneralReply(env,
913
                             buf,
914
                             len,
915
                             &type,
916
                             ret,
917
                             addrttls,
918
                             &naddrttls);
919
6
  uint32_t a_count = ret->Length();
920

6
  if (status != ARES_SUCCESS && status != ARES_ENODATA)
921
2
    return status;
922
923
4
  if (type == ns_t_a) {
924
4
    CHECK_EQ(static_cast<uint32_t>(naddrttls), a_count);
925
8
    for (uint32_t i = 0; i < a_count; i++) {
926
4
      Local<Object> obj = Object::New(env->isolate());
927
4
      obj->Set(env->context(),
928
                env->address_string(),
929
16
                ret->Get(env->context(), i).ToLocalChecked()).Check();
930
4
      obj->Set(env->context(),
931
                env->ttl_string(),
932
                Integer::NewFromUnsigned(
933
16
                  env->isolate(), addrttls[i].ttl)).Check();
934
4
      obj->Set(env->context(),
935
                env->type_string(),
936
16
                env->dns_a_string()).Check();
937
8
      ret->Set(env->context(), i, obj).Check();
938
    }
939
  } else {
940
    for (uint32_t i = 0; i < a_count; i++) {
941
      Local<Object> obj = Object::New(env->isolate());
942
      obj->Set(env->context(),
943
                env->value_string(),
944
                ret->Get(env->context(), i).ToLocalChecked()).Check();
945
      obj->Set(env->context(),
946
                env->type_string(),
947
                env->dns_cname_string()).Check();
948
      ret->Set(env->context(), i, obj).Check();
949
    }
950
  }
951
952
  /* Parse AAAA records */
953
  ares_addr6ttl addr6ttls[256];
954
4
  int naddr6ttls = arraysize(addr6ttls);
955
956
4
  type = ns_t_aaaa;
957
4
  status = ParseGeneralReply(env,
958
                             buf,
959
                             len,
960
                             &type,
961
                             ret,
962
                             addr6ttls,
963
                             &naddr6ttls);
964
4
  uint32_t aaaa_count = ret->Length() - a_count;
965

4
  if (status != ARES_SUCCESS && status != ARES_ENODATA)
966
    return status;
967
968
4
  CHECK_EQ(aaaa_count, static_cast<uint32_t>(naddr6ttls));
969
4
  CHECK_EQ(ret->Length(), a_count + aaaa_count);
970
12
  for (uint32_t i = a_count; i < ret->Length(); i++) {
971
4
    Local<Object> obj = Object::New(env->isolate());
972
4
    obj->Set(env->context(),
973
              env->address_string(),
974
16
              ret->Get(env->context(), i).ToLocalChecked()).Check();
975
4
    obj->Set(env->context(),
976
              env->ttl_string(),
977
              Integer::NewFromUnsigned(
978
16
                env->isolate(), addr6ttls[i - a_count].ttl)).Check();
979
4
    obj->Set(env->context(),
980
              env->type_string(),
981
16
              env->dns_aaaa_string()).Check();
982
8
    ret->Set(env->context(), i, obj).Check();
983
  }
984
985
  /* Parse MX records */
986
4
  status = ParseMxReply(env, buf, len, ret, true);
987

4
  if (status != ARES_SUCCESS && status != ARES_ENODATA)
988
    return status;
989
990
  /* Parse NS records */
991
4
  type = ns_t_ns;
992
4
  old_count = ret->Length();
993
4
  status = ParseGeneralReply(env, buf, len, &type, ret);
994

4
  if (status != ARES_SUCCESS && status != ARES_ENODATA)
995
    return status;
996
997
12
  for (uint32_t i = old_count; i < ret->Length(); i++) {
998
4
    Local<Object> obj = Object::New(env->isolate());
999
4
    obj->Set(env->context(),
1000
             env->value_string(),
1001
16
             ret->Get(env->context(), i).ToLocalChecked()).Check();
1002
4
    obj->Set(env->context(),
1003
              env->type_string(),
1004
16
              env->dns_ns_string()).Check();
1005
8
    ret->Set(env->context(), i, obj).Check();
1006
  }
1007
1008
  /* Parse TXT records */
1009
4
  status = ParseTxtReply(env, buf, len, ret, true);
1010

4
  if (status != ARES_SUCCESS && status != ARES_ENODATA)
1011
    return status;
1012
1013
  /* Parse SRV records */
1014
4
  status = ParseSrvReply(env, buf, len, ret, true);
1015

4
  if (status != ARES_SUCCESS && status != ARES_ENODATA)
1016
    return status;
1017
1018
  /* Parse PTR records */
1019
4
  type = ns_t_ptr;
1020
4
  old_count = ret->Length();
1021
4
  status = ParseGeneralReply(env, buf, len, &type, ret);
1022

4
  if (status != ARES_SUCCESS && status != ARES_ENODATA)
1023
    return status;
1024
12
  for (uint32_t i = old_count; i < ret->Length(); i++) {
1025
4
    Local<Object> obj = Object::New(env->isolate());
1026
4
    obj->Set(env->context(),
1027
              env->value_string(),
1028
16
              ret->Get(env->context(), i).ToLocalChecked()).Check();
1029
4
    obj->Set(env->context(),
1030
              env->type_string(),
1031
16
              env->dns_ptr_string()).Check();
1032
8
    ret->Set(env->context(), i, obj).Check();
1033
  }
1034
1035
  /* Parse NAPTR records */
1036
4
  status = ParseNaptrReply(env, buf, len, ret, true);
1037

4
  if (status != ARES_SUCCESS && status != ARES_ENODATA)
1038
    return status;
1039
1040
  /* Parse SOA records */
1041
  Local<Object> soa_record = Local<Object>();
1042
4
  status = ParseSoaReply(env, buf, len, &soa_record);
1043

4
  if (status != ARES_SUCCESS && status != ARES_ENODATA)
1044
    return status;
1045
1046
4
  if (!soa_record.IsEmpty())
1047
8
    ret->Set(env->context(), ret->Length(), soa_record).Check();
1048
1049
  /* Parse CAA records */
1050
4
  status = ParseCaaReply(env, buf, len, ret, true);
1051

4
  if (status != ARES_SUCCESS && status != ARES_ENODATA)
1052
    return status;
1053
1054
4
  wrap->CallOnComplete(ret);
1055
4
  return 0;
1056
}
1057
1058
7
int ATraits::Parse(
1059
    QueryAWrap* wrap,
1060
    const std::unique_ptr<ResponseData>& response) {
1061
7
  if (UNLIKELY(response->is_host))
1062
    return ARES_EBADRESP;
1063
1064
7
  unsigned char* buf = response->buf.data;
1065
7
  int len = response->buf.size;
1066
1067
7
  Environment* env = wrap->env();
1068
14
  HandleScope handle_scope(env->isolate());
1069
7
  Context::Scope context_scope(env->context());
1070
1071
  ares_addrttl addrttls[256];
1072
7
  int naddrttls = arraysize(addrttls), status;
1073
7
  Local<Array> ret = Array::New(env->isolate());
1074
1075
7
  int type = ns_t_a;
1076
7
  status = ParseGeneralReply(env,
1077
                             buf,
1078
                             len,
1079
                             &type,
1080
                             ret,
1081
                             addrttls,
1082
                             &naddrttls);
1083
7
  if (status != ARES_SUCCESS)
1084
    return status;
1085
1086
7
  Local<Array> ttls = AddrTTLToArray<ares_addrttl>(env, addrttls, naddrttls);
1087
1088
7
  wrap->CallOnComplete(ret, ttls);
1089
7
  return 0;
1090
}
1091
1092
2
int AaaaTraits::Parse(
1093
    QueryAaaaWrap* wrap,
1094
    const std::unique_ptr<ResponseData>& response) {
1095
2
  if (UNLIKELY(response->is_host))
1096
    return ARES_EBADRESP;
1097
1098
2
  unsigned char* buf = response->buf.data;
1099
2
  int len = response->buf.size;
1100
1101
2
  Environment* env = wrap->env();
1102
4
  HandleScope handle_scope(env->isolate());
1103
2
  Context::Scope context_scope(env->context());
1104
1105
  ares_addr6ttl addrttls[256];
1106
2
  int naddrttls = arraysize(addrttls), status;
1107
2
  Local<Array> ret = Array::New(env->isolate());
1108
1109
2
  int type = ns_t_aaaa;
1110
2
  status = ParseGeneralReply(env,
1111
                             buf,
1112
                             len,
1113
                             &type,
1114
                             ret,
1115
                             addrttls,
1116
                             &naddrttls);
1117
2
  if (status != ARES_SUCCESS)
1118
    return status;
1119
1120
2
  Local<Array> ttls = AddrTTLToArray<ares_addr6ttl>(env, addrttls, naddrttls);
1121
1122
2
  wrap->CallOnComplete(ret, ttls);
1123
2
  return 0;
1124
}
1125
1126
int CaaTraits::Parse(
1127
    QueryCaaWrap* wrap,
1128
    const std::unique_ptr<ResponseData>& response) {
1129
  if (UNLIKELY(response->is_host))
1130
    return ARES_EBADRESP;
1131
1132
  unsigned char* buf = response->buf.data;
1133
  int len = response->buf.size;
1134
1135
  Environment* env = wrap->env();
1136
  HandleScope handle_scope(env->isolate());
1137
  Context::Scope context_scope(env->context());
1138
1139
  Local<Array> ret = Array::New(env->isolate());
1140
  int status = ParseCaaReply(env, buf, len, ret);
1141
  if (status != ARES_SUCCESS)
1142
    return status;
1143
1144
  wrap->CallOnComplete(ret);
1145
  return 0;
1146
}
1147
1148
int CnameTraits::Parse(
1149
    QueryCnameWrap* wrap,
1150
    const std::unique_ptr<ResponseData>& response) {
1151
  if (UNLIKELY(response->is_host))
1152
    return ARES_EBADRESP;
1153
1154
  unsigned char* buf = response->buf.data;
1155
  int len = response->buf.size;
1156
1157
  Environment* env = wrap->env();
1158
  HandleScope handle_scope(env->isolate());
1159
  Context::Scope context_scope(env->context());
1160
1161
  Local<Array> ret = Array::New(env->isolate());
1162
  int type = ns_t_cname;
1163
  int status = ParseGeneralReply(env, buf, len, &type, ret);
1164
  if (status != ARES_SUCCESS)
1165
    return status;
1166
1167
  wrap->CallOnComplete(ret);
1168
  return 0;
1169
}
1170
1171
int MxTraits::Parse(
1172
    QueryMxWrap* wrap,
1173
    const std::unique_ptr<ResponseData>& response) {
1174
  if (UNLIKELY(response->is_host))
1175
    return ARES_EBADRESP;
1176
1177
  unsigned char* buf = response->buf.data;
1178
  int len = response->buf.size;
1179
1180
  Environment* env = wrap->env();
1181
  HandleScope handle_scope(env->isolate());
1182
  Context::Scope context_scope(env->context());
1183
1184
  Local<Array> mx_records = Array::New(env->isolate());
1185
  int status = ParseMxReply(env, buf, len, mx_records);
1186
1187
  if (status != ARES_SUCCESS)
1188
    return status;
1189
1190
  wrap->CallOnComplete(mx_records);
1191
  return 0;
1192
}
1193
1194
int NsTraits::Parse(
1195
    QueryNsWrap* wrap,
1196
    const std::unique_ptr<ResponseData>& response) {
1197
  if (UNLIKELY(response->is_host))
1198
    return ARES_EBADRESP;
1199
1200
  unsigned char* buf = response->buf.data;
1201
  int len = response->buf.size;
1202
1203
  Environment* env = wrap->env();
1204
  HandleScope handle_scope(env->isolate());
1205
  Context::Scope context_scope(env->context());
1206
1207
  int type = ns_t_ns;
1208
  Local<Array> names = Array::New(env->isolate());
1209
  int status = ParseGeneralReply(env, buf, len, &type, names);
1210
  if (status != ARES_SUCCESS)
1211
    return status;
1212
1213
  wrap->CallOnComplete(names);
1214
  return 0;
1215
}
1216
1217
int TxtTraits::Parse(
1218
    QueryTxtWrap* wrap,
1219
    const std::unique_ptr<ResponseData>& response) {
1220
  if (UNLIKELY(response->is_host))
1221
    return ARES_EBADRESP;
1222
1223
  unsigned char* buf = response->buf.data;
1224
  int len = response->buf.size;
1225
1226
  Environment* env = wrap->env();
1227
  HandleScope handle_scope(env->isolate());
1228
  Context::Scope context_scope(env->context());
1229
1230
  Local<Array> txt_records = Array::New(env->isolate());
1231
  int status = ParseTxtReply(env, buf, len, txt_records);
1232
  if (status != ARES_SUCCESS)
1233
    return status;
1234
1235
  wrap->CallOnComplete(txt_records);
1236
  return 0;
1237
}
1238
1239
int SrvTraits::Parse(
1240
    QuerySrvWrap* wrap,
1241
    const std::unique_ptr<ResponseData>& response) {
1242
  if (UNLIKELY(response->is_host))
1243
    return ARES_EBADRESP;
1244
1245
  unsigned char* buf = response->buf.data;
1246
  int len = response->buf.size;
1247
1248
  Environment* env = wrap->env();
1249
  HandleScope handle_scope(env->isolate());
1250
  Context::Scope context_scope(env->context());
1251
1252
  Local<Array> srv_records = Array::New(env->isolate());
1253
  int status = ParseSrvReply(env, buf, len, srv_records);
1254
  if (status != ARES_SUCCESS)
1255
    return status;
1256
1257
  wrap->CallOnComplete(srv_records);
1258
  return 0;
1259
}
1260
1261
int PtrTraits::Parse(
1262
    QueryPtrWrap* wrap,
1263
    const std::unique_ptr<ResponseData>& response) {
1264
  if (UNLIKELY(response->is_host))
1265
    return ARES_EBADRESP;
1266
1267
  unsigned char* buf = response->buf.data;
1268
  int len = response->buf.size;
1269
1270
  Environment* env = wrap->env();
1271
  HandleScope handle_scope(env->isolate());
1272
  Context::Scope context_scope(env->context());
1273
1274
  int type = ns_t_ptr;
1275
  Local<Array> aliases = Array::New(env->isolate());
1276
1277
  int status = ParseGeneralReply(env, buf, len, &type, aliases);
1278
  if (status != ARES_SUCCESS)
1279
    return status;
1280
1281
  wrap->CallOnComplete(aliases);
1282
  return 0;
1283
}
1284
1285
int NaptrTraits::Parse(
1286
    QueryNaptrWrap* wrap,
1287
    const std::unique_ptr<ResponseData>& response) {
1288
  if (UNLIKELY(response->is_host))
1289
    return ARES_EBADRESP;
1290
1291
  unsigned char* buf = response->buf.data;
1292
  int len = response->buf.size;
1293
1294
  Environment* env = wrap->env();
1295
  HandleScope handle_scope(env->isolate());
1296
  Context::Scope context_scope(env->context());
1297
1298
  Local<Array> naptr_records = Array::New(env->isolate());
1299
  int status = ParseNaptrReply(env, buf, len, naptr_records);
1300
  if (status != ARES_SUCCESS)
1301
    return status;
1302
1303
  wrap->CallOnComplete(naptr_records);
1304
  return 0;
1305
}
1306
1307
2
int SoaTraits::Parse(
1308
    QuerySoaWrap* wrap,
1309
    const std::unique_ptr<ResponseData>& response) {
1310
2
  if (UNLIKELY(response->is_host))
1311
    return ARES_EBADRESP;
1312
1313
2
  unsigned char* buf = response->buf.data;
1314
2
  int len = response->buf.size;
1315
1316
2
  Environment* env = wrap->env();
1317
4
  HandleScope handle_scope(env->isolate());
1318
2
  Context::Scope context_scope(env->context());
1319
1320
  ares_soa_reply* soa_out;
1321
2
  int status = ares_parse_soa_reply(buf, len, &soa_out);
1322
1323
2
  if (status != ARES_SUCCESS)
1324
    return status;
1325
1326
2
  Local<Object> soa_record = Object::New(env->isolate());
1327
1328
2
  soa_record->Set(env->context(),
1329
                  env->nsname_string(),
1330
8
                  OneByteString(env->isolate(), soa_out->nsname)).Check();
1331
2
  soa_record->Set(env->context(),
1332
                  env->hostmaster_string(),
1333
8
                  OneByteString(env->isolate(), soa_out->hostmaster)).Check();
1334
2
  soa_record->Set(env->context(),
1335
                  env->serial_string(),
1336
                  Integer::NewFromUnsigned(
1337
8
                      env->isolate(), soa_out->serial)).Check();
1338
2
  soa_record->Set(env->context(),
1339
                  env->refresh_string(),
1340
8
                  Integer::New(env->isolate(), soa_out->refresh)).Check();
1341
2
  soa_record->Set(env->context(),
1342
                  env->retry_string(),
1343
8
                  Integer::New(env->isolate(), soa_out->retry)).Check();
1344
2
  soa_record->Set(env->context(),
1345
                  env->expire_string(),
1346
8
                  Integer::New(env->isolate(), soa_out->expire)).Check();
1347
2
  soa_record->Set(env->context(),
1348
                  env->minttl_string(),
1349
                  Integer::NewFromUnsigned(
1350
6
                      env->isolate(), soa_out->minttl)).Check();
1351
1352
2
  ares_free_data(soa_out);
1353
1354
2
  wrap->CallOnComplete(soa_record);
1355
2
  return 0;
1356
}
1357
1358
3
int ReverseTraits::Send(GetHostByAddrWrap* wrap, const char* name) {
1359
  int length, family;
1360
  char address_buffer[sizeof(struct in6_addr)];
1361
1362
3
  if (uv_inet_pton(AF_INET, name, &address_buffer) == 0) {
1363
3
    length = sizeof(struct in_addr);
1364
3
    family = AF_INET;
1365
  } else if (uv_inet_pton(AF_INET6, name, &address_buffer) == 0) {
1366
    length = sizeof(struct in6_addr);
1367
    family = AF_INET6;
1368
  } else {
1369
    return UV_EINVAL;  // So errnoException() reports a proper error.
1370
  }
1371
1372

5
  TRACE_EVENT_NESTABLE_ASYNC_BEGIN2(
1373
      TRACING_CATEGORY_NODE2(dns, native), "reverse", wrap,
1374
      "name", TRACE_STR_COPY(name),
1375
      "family", family == AF_INET ? "ipv4" : "ipv6");
1376
1377
6
  ares_gethostbyaddr(
1378
3
      wrap->channel()->cares_channel(),
1379
      address_buffer,
1380
      length,
1381
      family,
1382
      GetHostByAddrWrap::Callback,
1383
      wrap->MakeCallbackPointer());
1384
3
  return 0;
1385
}
1386
1387
2
int ReverseTraits::Parse(
1388
    GetHostByAddrWrap* wrap,
1389
    const std::unique_ptr<ResponseData>& response) {
1390
2
  if (UNLIKELY(!response->is_host))
1391
    return ARES_EBADRESP;
1392
1393
2
  struct hostent* host = response->host.get();
1394
1395
2
  Environment* env = wrap->env();
1396
4
  HandleScope handle_scope(env->isolate());
1397
4
  Context::Scope context_scope(env->context());
1398
4
  wrap->CallOnComplete(HostentToNames(env, host));
1399
2
  return 0;
1400
}
1401
1402
namespace {
1403
template <class Wrap>
1404
106
static void Query(const FunctionCallbackInfo<Value>& args) {
1405
106
  Environment* env = Environment::GetCurrent(args);
1406
  ChannelWrap* channel;
1407
106
  ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
1408
1409
106
  CHECK_EQ(false, args.IsConstructCall());
1410
106
  CHECK(args[0]->IsObject());
1411
212
  CHECK(args[1]->IsString());
1412
1413
212
  Local<Object> req_wrap_obj = args[0].As<Object>();
1414
106
  Local<String> string = args[1].As<String>();
1415
212
  auto wrap = std::make_unique<Wrap>(channel, req_wrap_obj);
1416
1417
106
  node::Utf8Value name(env->isolate(), string);
1418
106
  channel->ModifyActivityQueryCount(1);
1419
106
  int err = wrap->Send(*name);
1420
106
  if (err) {
1421
    channel->ModifyActivityQueryCount(-1);
1422
  } else {
1423
    // Release ownership of the pointer allowing the ownership to be transferred
1424
106
    USE(wrap.release());
1425
  }
1426
1427
212
  args.GetReturnValue().Set(err);
1428
}
1429
1430
1431
5240
void AfterGetAddrInfo(uv_getaddrinfo_t* req, int status, struct addrinfo* res) {
1432
10478
  auto cleanup = OnScopeLeave([&]() { uv_freeaddrinfo(res); });
1433
  BaseObjectPtr<GetAddrInfoReqWrap> req_wrap{
1434
5240
      static_cast<GetAddrInfoReqWrap*>(req->data)};
1435
5240
  Environment* env = req_wrap->env();
1436
1437
5240
  HandleScope handle_scope(env->isolate());
1438
5240
  Context::Scope context_scope(env->context());
1439
1440
  Local<Value> argv[] = {
1441
    Integer::New(env->isolate(), status),
1442
    Null(env->isolate())
1443
10480
  };
1444
1445
5240
  uint32_t n = 0;
1446
5240
  const bool verbatim = req_wrap->verbatim();
1447
1448
5240
  if (status == 0) {
1449
5231
    Local<Array> results = Array::New(env->isolate());
1450
1451
5251
    auto add = [&] (bool want_ipv4, bool want_ipv6) -> Maybe<bool> {
1452
20997
      for (auto p = res; p != nullptr; p = p->ai_next) {
1453
15746
        CHECK_EQ(p->ai_socktype, SOCK_STREAM);
1454
1455
        const char* addr;
1456

15746
        if (want_ipv4 && p->ai_family == AF_INET) {
1457
5766
          addr = reinterpret_cast<char*>(
1458
5766
              &(reinterpret_cast<struct sockaddr_in*>(p->ai_addr)->sin_addr));
1459

9980
        } else if (want_ipv6 && p->ai_family == AF_INET6) {
1460
9932
          addr = reinterpret_cast<char*>(
1461
9932
              &(reinterpret_cast<struct sockaddr_in6*>(p->ai_addr)->sin6_addr));
1462
        } else {
1463
48
          continue;
1464
        }
1465
1466
        char ip[INET6_ADDRSTRLEN];
1467
15698
        if (uv_inet_ntop(p->ai_family, addr, ip, sizeof(ip)))
1468
          continue;
1469
1470
15698
        Local<String> s = OneByteString(env->isolate(), ip);
1471
31396
        if (results->Set(env->context(), n, s).IsNothing())
1472
          return Nothing<bool>();
1473
15698
        n++;
1474
      }
1475
5251
      return Just(true);
1476
5231
    };
1477
1478
10462
    if (add(true, verbatim).IsNothing())
1479
      return;
1480
5231
    if (verbatim == false) {
1481
40
      if (add(false, true).IsNothing())
1482
        return;
1483
    }
1484
1485
    // No responses were found to return
1486
5231
    if (n == 0) {
1487
      argv[0] = Integer::New(env->isolate(), UV_EAI_NODATA);
1488
    }
1489
1490
5231
    argv[1] = results;
1491
  }
1492
1493

6099
  TRACE_EVENT_NESTABLE_ASYNC_END2(
1494
      TRACING_CATEGORY_NODE2(dns, native), "lookup", req_wrap.get(),
1495
      "count", n, "verbatim", verbatim);
1496
1497
  // Make the callback into JavaScript
1498
5240
  req_wrap->MakeCallback(env->oncomplete_string(), arraysize(argv), argv);
1499
}
1500
1501
1502
6
void AfterGetNameInfo(uv_getnameinfo_t* req,
1503
                      int status,
1504
                      const char* hostname,
1505
                      const char* service) {
1506
  BaseObjectPtr<GetNameInfoReqWrap> req_wrap{
1507
12
      static_cast<GetNameInfoReqWrap*>(req->data)};
1508
6
  Environment* env = req_wrap->env();
1509
1510
12
  HandleScope handle_scope(env->isolate());
1511
6
  Context::Scope context_scope(env->context());
1512
1513
  Local<Value> argv[] = {
1514
    Integer::New(env->isolate(), status),
1515
    Null(env->isolate()),
1516
    Null(env->isolate())
1517
18
  };
1518
1519
6
  if (status == 0) {
1520
    // Success
1521
5
    Local<String> js_hostname = OneByteString(env->isolate(), hostname);
1522
5
    Local<String> js_service = OneByteString(env->isolate(), service);
1523
5
    argv[1] = js_hostname;
1524
5
    argv[2] = js_service;
1525
  }
1526
1527

10
  TRACE_EVENT_NESTABLE_ASYNC_END2(
1528
      TRACING_CATEGORY_NODE2(dns, native), "lookupService", req_wrap.get(),
1529
      "hostname", TRACE_STR_COPY(hostname),
1530
      "service", TRACE_STR_COPY(service));
1531
1532
  // Make the callback into JavaScript
1533
6
  req_wrap->MakeCallback(env->oncomplete_string(), arraysize(argv), argv);
1534
6
}
1535
1536
27
void CanonicalizeIP(const FunctionCallbackInfo<Value>& args) {
1537
27
  Isolate* isolate = args.GetIsolate();
1538
27
  node::Utf8Value ip(isolate, args[0]);
1539
1540
  int af;
1541
  unsigned char result[sizeof(ares_addr_port_node::addr)];
1542

37
  if (uv_inet_pton(af = AF_INET, *ip, result) != 0 &&
1543
10
      uv_inet_pton(af = AF_INET6, *ip, result) != 0)
1544
1
    return;
1545
1546
  char canonical_ip[INET6_ADDRSTRLEN];
1547
26
  CHECK_EQ(0, uv_inet_ntop(af, result, canonical_ip, sizeof(canonical_ip)));
1548
26
  Local<String> val = String::NewFromUtf8(isolate, canonical_ip)
1549
26
      .ToLocalChecked();
1550
52
  args.GetReturnValue().Set(val);
1551
}
1552
1553
5241
void GetAddrInfo(const FunctionCallbackInfo<Value>& args) {
1554
5241
  Environment* env = Environment::GetCurrent(args);
1555
1556
5241
  CHECK(args[0]->IsObject());
1557
10482
  CHECK(args[1]->IsString());
1558
5241
  CHECK(args[2]->IsInt32());
1559
5241
  CHECK(args[4]->IsBoolean());
1560
10482
  Local<Object> req_wrap_obj = args[0].As<Object>();
1561
10482
  node::Utf8Value hostname(env->isolate(), args[1]);
1562
1563
5241
  int32_t flags = 0;
1564
5241
  if (args[3]->IsInt32()) {
1565
10482
    flags = args[3].As<Int32>()->Value();
1566
  }
1567
1568
  int family;
1569
1570

10482
  switch (args[2].As<Int32>()->Value()) {
1571
4976
    case 0:
1572
4976
      family = AF_UNSPEC;
1573
4976
      break;
1574
260
    case 4:
1575
260
      family = AF_INET;
1576
260
      break;
1577
5
    case 6:
1578
5
      family = AF_INET6;
1579
5
      break;
1580
    default:
1581
      CHECK(0 && "bad address family");
1582
  }
1583
1584
  auto req_wrap = std::make_unique<GetAddrInfoReqWrap>(env,
1585
                                                       req_wrap_obj,
1586
5241
                                                       args[4]->IsTrue());
1587
1588
  struct addrinfo hints;
1589
5241
  memset(&hints, 0, sizeof(hints));
1590
5241
  hints.ai_family = family;
1591
5241
  hints.ai_socktype = SOCK_STREAM;
1592
5241
  hints.ai_flags = flags;
1593
1594


6101
  TRACE_EVENT_NESTABLE_ASYNC_BEGIN2(
1595
      TRACING_CATEGORY_NODE2(dns, native), "lookup", req_wrap.get(),
1596
      "hostname", TRACE_STR_COPY(*hostname),
1597
      "family",
1598
      family == AF_INET ? "ipv4" : family == AF_INET6 ? "ipv6" : "unspec");
1599
1600
5241
  int err = req_wrap->Dispatch(uv_getaddrinfo,
1601
                               AfterGetAddrInfo,
1602
                               *hostname,
1603
                               nullptr,
1604
                               &hints);
1605
5241
  if (err == 0)
1606
    // Release ownership of the pointer allowing the ownership to be transferred
1607
5241
    USE(req_wrap.release());
1608
1609
10482
  args.GetReturnValue().Set(err);
1610
5241
}
1611
1612
1613
6
void GetNameInfo(const FunctionCallbackInfo<Value>& args) {
1614
6
  Environment* env = Environment::GetCurrent(args);
1615
1616
6
  CHECK(args[0]->IsObject());
1617
12
  CHECK(args[1]->IsString());
1618
6
  CHECK(args[2]->IsUint32());
1619
12
  Local<Object> req_wrap_obj = args[0].As<Object>();
1620
12
  node::Utf8Value ip(env->isolate(), args[1]);
1621
6
  const unsigned port = args[2]->Uint32Value(env->context()).FromJust();
1622
  struct sockaddr_storage addr;
1623
1624

6
  CHECK(uv_ip4_addr(*ip, port, reinterpret_cast<sockaddr_in*>(&addr)) == 0 ||
1625
        uv_ip6_addr(*ip, port, reinterpret_cast<sockaddr_in6*>(&addr)) == 0);
1626
1627
6
  auto req_wrap = std::make_unique<GetNameInfoReqWrap>(env, req_wrap_obj);
1628
1629

10
  TRACE_EVENT_NESTABLE_ASYNC_BEGIN2(
1630
      TRACING_CATEGORY_NODE2(dns, native), "lookupService", req_wrap.get(),
1631
      "ip", TRACE_STR_COPY(*ip), "port", port);
1632
1633
6
  int err = req_wrap->Dispatch(uv_getnameinfo,
1634
                               AfterGetNameInfo,
1635
                               reinterpret_cast<struct sockaddr*>(&addr),
1636
                               NI_NAMEREQD);
1637
6
  if (err == 0)
1638
    // Release ownership of the pointer allowing the ownership to be transferred
1639
6
    USE(req_wrap.release());
1640
1641
12
  args.GetReturnValue().Set(err);
1642
6
}
1643
1644
1645
37
void GetServers(const FunctionCallbackInfo<Value>& args) {
1646
37
  Environment* env = Environment::GetCurrent(args);
1647
  ChannelWrap* channel;
1648
37
  ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
1649
1650
37
  Local<Array> server_array = Array::New(env->isolate());
1651
1652
  ares_addr_port_node* servers;
1653
1654
37
  int r = ares_get_servers_ports(channel->cares_channel(), &servers);
1655
37
  CHECK_EQ(r, ARES_SUCCESS);
1656
74
  auto cleanup = OnScopeLeave([&]() { ares_free_data(servers); });
1657
1658
37
  ares_addr_port_node* cur = servers;
1659
1660
114
  for (uint32_t i = 0; cur != nullptr; ++i, cur = cur->next) {
1661
    char ip[INET6_ADDRSTRLEN];
1662
1663
77
    const void* caddr = static_cast<const void*>(&cur->addr);
1664
77
    int err = uv_inet_ntop(cur->family, caddr, ip, sizeof(ip));
1665
77
    CHECK_EQ(err, 0);
1666
1667
    Local<Value> ret[] = {
1668
      OneByteString(env->isolate(), ip),
1669
      Integer::New(env->isolate(), cur->udp_port)
1670
231
    };
1671
1672
231
    if (server_array->Set(env->context(), i,
1673
154
                          Array::New(env->isolate(), ret, arraysize(ret)))
1674
77
          .IsNothing()) {
1675
      return;
1676
    }
1677
  }
1678
1679
74
  args.GetReturnValue().Set(server_array);
1680
}
1681
1682
1683
28
void SetServers(const FunctionCallbackInfo<Value>& args) {
1684
28
  Environment* env = Environment::GetCurrent(args);
1685
  ChannelWrap* channel;
1686
32
  ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
1687
1688
28
  if (channel->active_query_count()) {
1689
4
    return args.GetReturnValue().Set(DNS_ESETSRVPENDING);
1690
  }
1691
1692
26
  CHECK(args[0]->IsArray());
1693
1694
52
  Local<Array> arr = args[0].As<Array>();
1695
1696
26
  uint32_t len = arr->Length();
1697
1698
26
  if (len == 0) {
1699
2
    int rv = ares_set_servers(channel->cares_channel(), nullptr);
1700
4
    return args.GetReturnValue().Set(rv);
1701
  }
1702
1703
24
  std::vector<ares_addr_port_node> servers(len);
1704
24
  ares_addr_port_node* last = nullptr;
1705
1706
  int err;
1707
1708
59
  for (uint32_t i = 0; i < len; i++) {
1709
70
    CHECK(arr->Get(env->context(), i).ToLocalChecked()->IsArray());
1710
1711
105
    Local<Array> elm = arr->Get(env->context(), i).ToLocalChecked().As<Array>();
1712
1713
105
    CHECK(elm->Get(env->context(),
1714
                   0).ToLocalChecked()->Int32Value(env->context()).FromJust());
1715
105
    CHECK(elm->Get(env->context(), 1).ToLocalChecked()->IsString());
1716
105
    CHECK(elm->Get(env->context(),
1717
                   2).ToLocalChecked()->Int32Value(env->context()).FromJust());
1718
1719
35
    int fam = elm->Get(env->context(), 0)
1720
70
        .ToLocalChecked()->Int32Value(env->context()).FromJust();
1721
    node::Utf8Value ip(env->isolate(),
1722
70
                       elm->Get(env->context(), 1).ToLocalChecked());
1723
35
    int port = elm->Get(env->context(), 2)
1724
35
        .ToLocalChecked()->Int32Value(env->context()).FromJust();
1725
1726
35
    ares_addr_port_node* cur = &servers[i];
1727
1728
35
    cur->tcp_port = cur->udp_port = port;
1729
35
    switch (fam) {
1730
28
      case 4:
1731
28
        cur->family = AF_INET;
1732
28
        err = uv_inet_pton(AF_INET, *ip, &cur->addr);
1733
28
        break;
1734
7
      case 6:
1735
7
        cur->family = AF_INET6;
1736
7
        err = uv_inet_pton(AF_INET6, *ip, &cur->addr);
1737
7
        break;
1738
      default:
1739
        CHECK(0 && "Bad address family.");
1740
    }
1741
1742
35
    if (err)
1743
      break;
1744
1745
35
    cur->next = nullptr;
1746
1747
35
    if (last != nullptr)
1748
11
      last->next = cur;
1749
1750
35
    last = cur;
1751
  }
1752
1753
24
  if (err == 0)
1754
24
    err = ares_set_servers_ports(channel->cares_channel(), &servers[0]);
1755
  else
1756
    err = ARES_EBADSTR;
1757
1758
24
  if (err == ARES_SUCCESS)
1759
24
    channel->set_is_servers_default(false);
1760
1761
48
  args.GetReturnValue().Set(err);
1762
}
1763
1764
7
void SetLocalAddress(const FunctionCallbackInfo<Value>& args) {
1765
7
  Environment* env = Environment::GetCurrent(args);
1766
  ChannelWrap* channel;
1767
10
  ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
1768
1769
7
  CHECK_EQ(args.Length(), 2);
1770
14
  CHECK(args[0]->IsString());
1771
1772
7
  Isolate* isolate = args.GetIsolate();
1773
7
  node::Utf8Value ip0(isolate, args[0]);
1774
1775
  unsigned char addr0[sizeof(struct in6_addr)];
1776
  unsigned char addr1[sizeof(struct in6_addr)];
1777
7
  int type0 = 0;
1778
1779
  // This function accepts 2 arguments.  The first may be either an IPv4
1780
  // address or an IPv6 address.  If present, the second argument must be the
1781
  // other type of address.  Otherwise, the unspecified type of IP is set
1782
  // to 0 (any).
1783
1784
7
  if (uv_inet_pton(AF_INET, *ip0, &addr0) == 0) {
1785
4
    ares_set_local_ip4(channel->cares_channel(), ReadUint32BE(addr0));
1786
4
    type0 = 4;
1787
3
  } else if (uv_inet_pton(AF_INET6, *ip0, &addr0) == 0) {
1788
2
    ares_set_local_ip6(channel->cares_channel(), addr0);
1789
2
    type0 = 6;
1790
  } else {
1791
1
    THROW_ERR_INVALID_ARG_VALUE(env, "Invalid IP address.");
1792
1
    return;
1793
  }
1794
1795
12
  if (!args[1]->IsUndefined()) {
1796
8
    CHECK(args[1]->IsString());
1797
4
    node::Utf8Value ip1(isolate, args[1]);
1798
1799
4
    if (uv_inet_pton(AF_INET, *ip1, &addr1) == 0) {
1800
1
      if (type0 == 4) {
1801
1
        THROW_ERR_INVALID_ARG_VALUE(env, "Cannot specify two IPv4 addresses.");
1802
1
        return;
1803
      } else {
1804
        ares_set_local_ip4(channel->cares_channel(), ReadUint32BE(addr1));
1805
      }
1806
3
    } else if (uv_inet_pton(AF_INET6, *ip1, &addr1) == 0) {
1807
3
      if (type0 == 6) {
1808
1
        THROW_ERR_INVALID_ARG_VALUE(env, "Cannot specify two IPv6 addresses.");
1809
1
        return;
1810
      } else {
1811
2
        ares_set_local_ip6(channel->cares_channel(), addr1);
1812
      }
1813
    } else {
1814
      THROW_ERR_INVALID_ARG_VALUE(env, "Invalid IP address.");
1815
      return;
1816
    }
1817
  } else {
1818
    // No second arg specified
1819
2
    if (type0 == 4) {
1820
1
      memset(&addr1, 0, sizeof(addr1));
1821
1
      ares_set_local_ip6(channel->cares_channel(), addr1);
1822
    } else {
1823
1
      ares_set_local_ip4(channel->cares_channel(), 0);
1824
    }
1825
  }
1826
}
1827
1828
6
void Cancel(const FunctionCallbackInfo<Value>& args) {
1829
  ChannelWrap* channel;
1830
6
  ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
1831
1832

10
  TRACE_EVENT_INSTANT0(TRACING_CATEGORY_NODE2(dns, native),
1833
      "cancel", TRACE_EVENT_SCOPE_THREAD);
1834
1835
6
  ares_cancel(channel->cares_channel());
1836
}
1837
1838
const char EMSG_ESETSRVPENDING[] = "There are pending queries.";
1839
1
void StrError(const FunctionCallbackInfo<Value>& args) {
1840
1
  Environment* env = Environment::GetCurrent(args);
1841
1
  int code = args[0]->Int32Value(env->context()).FromJust();
1842
1
  const char* errmsg = (code == DNS_ESETSRVPENDING) ?
1843
    EMSG_ESETSRVPENDING :
1844
1
    ares_strerror(code);
1845
1
  args.GetReturnValue().Set(OneByteString(env->isolate(), errmsg));
1846
1
}
1847
1848
}  // namespace
1849
1850
2
inline void safe_free_hostent(struct hostent* host) {
1851
  int idx;
1852
1853
2
  if (host->h_addr_list != nullptr) {
1854
2
    idx = 0;
1855
4
    while (host->h_addr_list[idx]) {
1856
2
      free(host->h_addr_list[idx++]);
1857
    }
1858
2
    free(host->h_addr_list);
1859
2
    host->h_addr_list = nullptr;
1860
  }
1861
1862
2
  if (host->h_aliases != nullptr) {
1863
2
    idx = 0;
1864
2
    while (host->h_aliases[idx]) {
1865
      free(host->h_aliases[idx++]);
1866
    }
1867
2
    free(host->h_aliases);
1868
2
    host->h_aliases = nullptr;
1869
  }
1870
1871
2
  free(host->h_name);
1872
2
  free(host);
1873
2
}
1874
1875
1278
void Initialize(Local<Object> target,
1876
                Local<Value> unused,
1877
                Local<Context> context,
1878
                void* priv) {
1879
1278
  Environment* env = Environment::GetCurrent(context);
1880
1278
  Isolate* isolate = env->isolate();
1881
1882
1278
  SetMethod(context, target, "getaddrinfo", GetAddrInfo);
1883
1278
  SetMethod(context, target, "getnameinfo", GetNameInfo);
1884
1278
  SetMethodNoSideEffect(context, target, "canonicalizeIP", CanonicalizeIP);
1885
1886
1278
  SetMethod(context, target, "strerror", StrError);
1887
1888
1278
  target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(), "AF_INET"),
1889
5112
              Integer::New(env->isolate(), AF_INET)).Check();
1890
1278
  target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(), "AF_INET6"),
1891
5112
              Integer::New(env->isolate(), AF_INET6)).Check();
1892
1278
  target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(),
1893
                                                    "AF_UNSPEC"),
1894
5112
              Integer::New(env->isolate(), AF_UNSPEC)).Check();
1895
1278
  target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(),
1896
                                                    "AI_ADDRCONFIG"),
1897
5112
              Integer::New(env->isolate(), AI_ADDRCONFIG)).Check();
1898
1278
  target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(),
1899
                                                    "AI_ALL"),
1900
5112
              Integer::New(env->isolate(), AI_ALL)).Check();
1901
1278
  target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(),
1902
                                                    "AI_V4MAPPED"),
1903
3834
              Integer::New(env->isolate(), AI_V4MAPPED)).Check();
1904
1905
  Local<FunctionTemplate> aiw =
1906
1278
      BaseObject::MakeLazilyInitializedJSTemplate(env);
1907
1278
  aiw->Inherit(AsyncWrap::GetConstructorTemplate(env));
1908
1278
  SetConstructorFunction(context, target, "GetAddrInfoReqWrap", aiw);
1909
1910
  Local<FunctionTemplate> niw =
1911
1278
      BaseObject::MakeLazilyInitializedJSTemplate(env);
1912
1278
  niw->Inherit(AsyncWrap::GetConstructorTemplate(env));
1913
1278
  SetConstructorFunction(context, target, "GetNameInfoReqWrap", niw);
1914
1915
  Local<FunctionTemplate> qrw =
1916
1278
      BaseObject::MakeLazilyInitializedJSTemplate(env);
1917
1278
  qrw->Inherit(AsyncWrap::GetConstructorTemplate(env));
1918
1278
  SetConstructorFunction(context, target, "QueryReqWrap", qrw);
1919
1920
  Local<FunctionTemplate> channel_wrap =
1921
1278
      NewFunctionTemplate(isolate, ChannelWrap::New);
1922
2556
  channel_wrap->InstanceTemplate()->SetInternalFieldCount(
1923
      ChannelWrap::kInternalFieldCount);
1924
1278
  channel_wrap->Inherit(AsyncWrap::GetConstructorTemplate(env));
1925
1926
1278
  SetProtoMethod(isolate, channel_wrap, "queryAny", Query<QueryAnyWrap>);
1927
1278
  SetProtoMethod(isolate, channel_wrap, "queryA", Query<QueryAWrap>);
1928
1278
  SetProtoMethod(isolate, channel_wrap, "queryAaaa", Query<QueryAaaaWrap>);
1929
1278
  SetProtoMethod(isolate, channel_wrap, "queryCaa", Query<QueryCaaWrap>);
1930
1278
  SetProtoMethod(isolate, channel_wrap, "queryCname", Query<QueryCnameWrap>);
1931
1278
  SetProtoMethod(isolate, channel_wrap, "queryMx", Query<QueryMxWrap>);
1932
1278
  SetProtoMethod(isolate, channel_wrap, "queryNs", Query<QueryNsWrap>);
1933
1278
  SetProtoMethod(isolate, channel_wrap, "queryTxt", Query<QueryTxtWrap>);
1934
1278
  SetProtoMethod(isolate, channel_wrap, "querySrv", Query<QuerySrvWrap>);
1935
1278
  SetProtoMethod(isolate, channel_wrap, "queryPtr", Query<QueryPtrWrap>);
1936
1278
  SetProtoMethod(isolate, channel_wrap, "queryNaptr", Query<QueryNaptrWrap>);
1937
1278
  SetProtoMethod(isolate, channel_wrap, "querySoa", Query<QuerySoaWrap>);
1938
1278
  SetProtoMethod(
1939
      isolate, channel_wrap, "getHostByAddr", Query<GetHostByAddrWrap>);
1940
1941
1278
  SetProtoMethodNoSideEffect(isolate, channel_wrap, "getServers", GetServers);
1942
1278
  SetProtoMethod(isolate, channel_wrap, "setServers", SetServers);
1943
1278
  SetProtoMethod(isolate, channel_wrap, "setLocalAddress", SetLocalAddress);
1944
1278
  SetProtoMethod(isolate, channel_wrap, "cancel", Cancel);
1945
1946
1278
  SetConstructorFunction(context, target, "ChannelWrap", channel_wrap);
1947
1278
}
1948
1949
5588
void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
1950
5588
  registry->Register(GetAddrInfo);
1951
5588
  registry->Register(GetNameInfo);
1952
5588
  registry->Register(CanonicalizeIP);
1953
5588
  registry->Register(StrError);
1954
5588
  registry->Register(ChannelWrap::New);
1955
1956
5588
  registry->Register(Query<QueryAnyWrap>);
1957
5588
  registry->Register(Query<QueryAWrap>);
1958
5588
  registry->Register(Query<QueryAaaaWrap>);
1959
5588
  registry->Register(Query<QueryCaaWrap>);
1960
5588
  registry->Register(Query<QueryCnameWrap>);
1961
5588
  registry->Register(Query<QueryMxWrap>);
1962
5588
  registry->Register(Query<QueryNsWrap>);
1963
5588
  registry->Register(Query<QueryTxtWrap>);
1964
5588
  registry->Register(Query<QuerySrvWrap>);
1965
5588
  registry->Register(Query<QueryPtrWrap>);
1966
5588
  registry->Register(Query<QueryNaptrWrap>);
1967
5588
  registry->Register(Query<QuerySoaWrap>);
1968
5588
  registry->Register(Query<GetHostByAddrWrap>);
1969
1970
5588
  registry->Register(GetServers);
1971
5588
  registry->Register(SetServers);
1972
5588
  registry->Register(SetLocalAddress);
1973
5588
  registry->Register(Cancel);
1974
5588
}
1975
1976
}  // namespace cares_wrap
1977
}  // namespace node
1978
1979
5659
NODE_MODULE_CONTEXT_AWARE_INTERNAL(cares_wrap, node::cares_wrap::Initialize)
1980
5588
NODE_MODULE_EXTERNAL_REFERENCE(cares_wrap,
1981
                               node::cares_wrap::RegisterExternalReferences)