GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: cares_wrap.cc Lines: 768 1039 73.9 %
Date: 2022-09-07 04:19:57 Branches: 260 494 52.6 %

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

10
  TRACE_EVENT_NESTABLE_ASYNC_END2(
1527
      TRACING_CATEGORY_NODE2(dns, native), "lookupService", req_wrap.get(),
1528
      "hostname", TRACE_STR_COPY(hostname),
1529
      "service", TRACE_STR_COPY(service));
1530
1531
  // Make the callback into JavaScript
1532
6
  req_wrap->MakeCallback(env->oncomplete_string(), arraysize(argv), argv);
1533
6
}
1534
1535
using ParseIPResult =
1536
    decltype(static_cast<ares_addr_port_node*>(nullptr)->addr);
1537
1538
27
int ParseIP(const char* ip, ParseIPResult* result = nullptr) {
1539
  ParseIPResult tmp;
1540
27
  if (result == nullptr) result = &tmp;
1541
27
  if (0 == uv_inet_pton(AF_INET, ip, result)) return 4;
1542
10
  if (0 == uv_inet_pton(AF_INET6, ip, result)) return 6;
1543
1
  return 0;
1544
}
1545
1546
27
void CanonicalizeIP(const FunctionCallbackInfo<Value>& args) {
1547
27
  Isolate* isolate = args.GetIsolate();
1548
27
  node::Utf8Value ip(isolate, args[0]);
1549
1550
  ParseIPResult result;
1551
27
  const int rc = ParseIP(*ip, &result);
1552
27
  if (rc == 0) return;
1553
1554
  char canonical_ip[INET6_ADDRSTRLEN];
1555
26
  const int af = (rc == 4 ? AF_INET : AF_INET6);
1556
26
  CHECK_EQ(0, uv_inet_ntop(af, &result, canonical_ip, sizeof(canonical_ip)));
1557
26
  Local<String> val = String::NewFromUtf8(isolate, canonical_ip)
1558
26
      .ToLocalChecked();
1559
52
  args.GetReturnValue().Set(val);
1560
}
1561
1562
5294
void GetAddrInfo(const FunctionCallbackInfo<Value>& args) {
1563
5294
  Environment* env = Environment::GetCurrent(args);
1564
1565
5294
  CHECK(args[0]->IsObject());
1566
10588
  CHECK(args[1]->IsString());
1567
5294
  CHECK(args[2]->IsInt32());
1568
5294
  CHECK(args[4]->IsBoolean());
1569
10588
  Local<Object> req_wrap_obj = args[0].As<Object>();
1570
10588
  node::Utf8Value hostname(env->isolate(), args[1]);
1571
1572
5294
  int32_t flags = 0;
1573
5294
  if (args[3]->IsInt32()) {
1574
10588
    flags = args[3].As<Int32>()->Value();
1575
  }
1576
1577
  int family;
1578
1579

10588
  switch (args[2].As<Int32>()->Value()) {
1580
5031
    case 0:
1581
5031
      family = AF_UNSPEC;
1582
5031
      break;
1583
258
    case 4:
1584
258
      family = AF_INET;
1585
258
      break;
1586
5
    case 6:
1587
5
      family = AF_INET6;
1588
5
      break;
1589
    default:
1590
      CHECK(0 && "bad address family");
1591
  }
1592
1593
  auto req_wrap = std::make_unique<GetAddrInfoReqWrap>(env,
1594
                                                       req_wrap_obj,
1595
5294
                                                       args[4]->IsTrue());
1596
1597
  struct addrinfo hints;
1598
5294
  memset(&hints, 0, sizeof(hints));
1599
5294
  hints.ai_family = family;
1600
5294
  hints.ai_socktype = SOCK_STREAM;
1601
5294
  hints.ai_flags = flags;
1602
1603


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

6
  CHECK(uv_ip4_addr(*ip, port, reinterpret_cast<sockaddr_in*>(&addr)) == 0 ||
1634
        uv_ip6_addr(*ip, port, reinterpret_cast<sockaddr_in6*>(&addr)) == 0);
1635
1636
6
  auto req_wrap = std::make_unique<GetNameInfoReqWrap>(env, req_wrap_obj);
1637
1638

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

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