GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/cares_wrap.cc Lines: 778 1051 74.0 %
Date: 2021-06-02 04:11:51 Branches: 289 615 47.0 %

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::Local;
67
using v8::Null;
68
using v8::Object;
69
using v8::String;
70
using v8::Value;
71
72
namespace {
73
74
4840
Mutex ares_library_mutex;
75
76
56
inline uint16_t cares_get_16bit(const unsigned char* p) {
77
56
  return static_cast<uint32_t>(p[0] << 8U) | (static_cast<uint32_t>(p[1]));
78
}
79
80
16
void ares_poll_cb(uv_poll_t* watcher, int status, int events) {
81
16
  NodeAresTask* task = ContainerOf(&NodeAresTask::poll_watcher, watcher);
82
16
  ChannelWrap* channel = task->channel;
83
84
  /* Reset the idle timer */
85
16
  uv_timer_again(channel->timer_handle());
86
87
16
  if (status < 0) {
88
    /* An error happened. Just pretend that the socket is both readable and */
89
    /* writable. */
90
    ares_process_fd(channel->cares_channel(), task->sock, task->sock);
91
    return;
92
  }
93
94
  /* Process DNS responses */
95

32
  ares_process_fd(channel->cares_channel(),
96
16
                  events & UV_READABLE ? task->sock : ARES_SOCKET_BAD,
97
32
                  events & UV_WRITABLE ? task->sock : ARES_SOCKET_BAD);
98
}
99
100
101
29
void ares_poll_close_cb(uv_poll_t* watcher) {
102
  std::unique_ptr<NodeAresTask> free_me(
103
29
        ContainerOf(&NodeAresTask::poll_watcher, watcher));
104
29
}
105
106
107
/* Callback from ares when socket operation is started */
108
58
void ares_sockstate_cb(void* data, ares_socket_t sock, int read, int write) {
109
58
  ChannelWrap* channel = static_cast<ChannelWrap*>(data);
110
  NodeAresTask* task;
111
112
116
  NodeAresTask lookup_task;
113
58
  lookup_task.sock = sock;
114
58
  auto it = channel->task_list()->find(&lookup_task);
115
116
58
  task = (it == channel->task_list()->end()) ? nullptr : *it;
117
118

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

29
                  (read ? UV_READABLE : 0) | (write ? UV_WRITABLE : 0),
138
29
                  ares_poll_cb);
139
140
  } else {
141
    /* read == 0 and write == 0 this is c-ares's way of notifying us that */
142
    /* the socket is now closed. We must free the data associated with */
143
    /* socket. */
144
29
    CHECK(task &&
145
          "When an ares socket is closed we should have a handle for it");
146
147
29
    channel->task_list()->erase(it);
148
29
    channel->env()->CloseHandle(&task->poll_watcher, ares_poll_close_cb);
149
150
29
    if (channel->task_list()->empty()) {
151
29
      channel->CloseTimer();
152
    }
153
  }
154
}
155
156
2
Local<Array> HostentToNames(Environment* env, struct hostent* host) {
157
2
  EscapableHandleScope scope(env->isolate());
158
159
4
  std::vector<Local<Value>> names;
160
161
2
  for (uint32_t i = 0; host->h_aliases[i] != nullptr; ++i)
162
    names.emplace_back(OneByteString(env->isolate(), host->h_aliases[i]));
163
164
2
  Local<Array> ret = Array::New(env->isolate(), names.data(), names.size());
165
166
2
  return scope.Escape(ret);
167
}
168
169
4
Local<Array> HostentToNames(Environment* env,
170
                            struct hostent* host,
171
                            Local<Array> names) {
172
4
  size_t offset = names->Length();
173
174
8
  for (uint32_t i = 0; host->h_aliases[i] != nullptr; ++i) {
175
8
    names->Set(
176
        env->context(),
177
        i + offset,
178
12
        OneByteString(env->isolate(), host->h_aliases[i])).Check();
179
  }
180
181
4
  return names;
182
}
183
184
template <typename T>
185
9
Local<Array> AddrTTLToArray(
186
    Environment* env,
187
    const T* addrttls,
188
    size_t naddrttls) {
189
18
  MaybeStackBuffer<Local<Value>, 8> ttls(naddrttls);
190

18
  for (size_t i = 0; i < naddrttls; i++)
191
18
    ttls[i] = Integer::NewFromUnsigned(env->isolate(), addrttls[i].ttl);
192
193
18
  return Array::New(env->isolate(), ttls.out(), naddrttls);
194
}
195
196
27
int ParseGeneralReply(
197
    Environment* env,
198
    const unsigned char* buf,
199
    int len,
200
    int* type,
201
    Local<Array> ret,
202
    void* addrttls = nullptr,
203
    int* naddrttls = nullptr) {
204
54
  HandleScope handle_scope(env->isolate());
205
  hostent* host;
206
207
  int status;
208

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


50
  if ((*type == ns_t_cname_or_a && ptr->h_name && ptr->h_aliases[0]) ||
246
25
      *type == ns_t_cname) {
247
    // A cname lookup always returns a single record but we follow the
248
    // common API here.
249
    *type = ns_t_cname;
250
    ret->Set(env->context(),
251
             ret->Length(),
252
             OneByteString(env->isolate(), ptr->h_name)).Check();
253
    return ARES_SUCCESS;
254
  }
255
256
25
  if (*type == ns_t_cname_or_a)
257
4
    *type = ns_t_a;
258
259
25
  if (*type == ns_t_ns) {
260
4
    HostentToNames(env, ptr.get(), ret);
261
21
  } else if (*type == ns_t_ptr) {
262
4
    uint32_t offset = ret->Length();
263
8
    for (uint32_t i = 0; ptr->h_aliases[i] != nullptr; i++) {
264
4
      auto alias = OneByteString(env->isolate(), ptr->h_aliases[i]);
265
12
      ret->Set(env->context(), i + offset, alias).Check();
266
    }
267
  } else {
268
17
    uint32_t offset = ret->Length();
269
    char ip[INET6_ADDRSTRLEN];
270
34
    for (uint32_t i = 0; ptr->h_addr_list[i] != nullptr; ++i) {
271
17
      uv_inet_ntop(ptr->h_addrtype, ptr->h_addr_list[i], ip, sizeof(ip));
272
17
      auto address = OneByteString(env->isolate(), ip);
273
51
      ret->Set(env->context(), i + offset, address).Check();
274
    }
275
  }
276
277
25
  return ARES_SUCCESS;
278
}
279
280
4
int ParseMxReply(
281
    Environment* env,
282
    const unsigned char* buf,
283
    int len,
284
    Local<Array> ret,
285
    bool need_type = false) {
286
8
  HandleScope handle_scope(env->isolate());
287
288
  struct ares_mx_reply* mx_start;
289
4
  int status = ares_parse_mx_reply(buf, len, &mx_start);
290
4
  if (status != ARES_SUCCESS)
291
    return status;
292
293
4
  uint32_t offset = ret->Length();
294
4
  ares_mx_reply* current = mx_start;
295
8
  for (uint32_t i = 0; current != nullptr; ++i, current = current->next) {
296
4
    Local<Object> mx_record = Object::New(env->isolate());
297
8
    mx_record->Set(env->context(),
298
                   env->exchange_string(),
299
20
                   OneByteString(env->isolate(), current->host)).Check();
300
8
    mx_record->Set(env->context(),
301
                   env->priority_string(),
302
20
                   Integer::New(env->isolate(), current->priority)).Check();
303
4
    if (need_type)
304
8
      mx_record->Set(env->context(),
305
                     env->type_string(),
306
20
                     env->dns_mx_string()).Check();
307
308
12
    ret->Set(env->context(), i + offset, mx_record).Check();
309
  }
310
311
4
  ares_free_data(mx_start);
312
4
  return ARES_SUCCESS;
313
}
314
315
4
int ParseCaaReply(
316
    Environment* env,
317
    const unsigned char* buf,
318
    int len,
319
    Local<Array> ret,
320
    bool need_type = false) {
321
8
  HandleScope handle_scope(env->isolate());
322
323
  struct ares_caa_reply* caa_start;
324
4
  int status = ares_parse_caa_reply(buf, len, &caa_start);
325
4
  if (status != ARES_SUCCESS)
326
    return status;
327
328
4
  uint32_t offset = ret->Length();
329
4
  ares_caa_reply* current = caa_start;
330
6
  for (uint32_t i = 0; current != nullptr; ++i, current = current->next) {
331
2
    Local<Object> caa_record = Object::New(env->isolate());
332
333
4
    caa_record->Set(env->context(),
334
                    env->dns_critical_string(),
335
10
                    Integer::New(env->isolate(), current->critical)).Check();
336
4
    caa_record->Set(env->context(),
337
2
                    OneByteString(env->isolate(), current->property),
338
10
                    OneByteString(env->isolate(), current->value)).Check();
339
2
    if (need_type)
340
4
      caa_record->Set(env->context(),
341
                      env->type_string(),
342
10
                      env->dns_caa_string()).Check();
343
344
6
    ret->Set(env->context(), i + offset, caa_record).Check();
345
  }
346
347
4
  ares_free_data(caa_start);
348
4
  return ARES_SUCCESS;
349
}
350
351
4
int ParseTxtReply(
352
    Environment* env,
353
    const unsigned char* buf,
354
    int len,
355
    Local<Array> ret,
356
    bool need_type = false) {
357
8
  HandleScope handle_scope(env->isolate());
358
359
  struct ares_txt_ext* txt_out;
360
361
4
  int status = ares_parse_txt_reply_ext(buf, len, &txt_out);
362
4
  if (status != ARES_SUCCESS)
363
    return status;
364
365
  Local<Array> txt_chunk;
366
367
4
  struct ares_txt_ext* current = txt_out;
368
4
  uint32_t i = 0, j;
369
4
  uint32_t offset = ret->Length();
370
8
  for (j = 0; current != nullptr; current = current->next) {
371
    Local<String> txt =
372
4
        OneByteString(env->isolate(), current->txt, current->length);
373
374
    // New record found - write out the current chunk
375
4
    if (current->record_start) {
376
2
      if (!txt_chunk.IsEmpty()) {
377
        if (need_type) {
378
          Local<Object> elem = Object::New(env->isolate());
379
          elem->Set(env->context(), env->entries_string(), txt_chunk).Check();
380
          elem->Set(env->context(),
381
                    env->type_string(),
382
                    env->dns_txt_string()).Check();
383
          ret->Set(env->context(), offset + i++, elem).Check();
384
        } else {
385
          ret->Set(env->context(), offset + i++, txt_chunk).Check();
386
        }
387
      }
388
389
2
      txt_chunk = Array::New(env->isolate());
390
2
      j = 0;
391
    }
392
393
12
    txt_chunk->Set(env->context(), j++, txt).Check();
394
  }
395
396
  // Push last chunk if it isn't empty
397
4
  if (!txt_chunk.IsEmpty()) {
398
2
    if (need_type) {
399
2
      Local<Object> elem = Object::New(env->isolate());
400
8
      elem->Set(env->context(), env->entries_string(), txt_chunk).Check();
401
4
      elem->Set(env->context(),
402
                env->type_string(),
403
10
                env->dns_txt_string()).Check();
404
6
      ret->Set(env->context(), offset + i, elem).Check();
405
    } else {
406
      ret->Set(env->context(), offset + i, txt_chunk).Check();
407
    }
408
  }
409
410
4
  ares_free_data(txt_out);
411
4
  return ARES_SUCCESS;
412
}
413
414
415
4
int ParseSrvReply(
416
    Environment* env,
417
    const unsigned char* buf,
418
    int len,
419
    Local<Array> ret,
420
    bool need_type = false) {
421
8
  HandleScope handle_scope(env->isolate());
422
423
  struct ares_srv_reply* srv_start;
424
4
  int status = ares_parse_srv_reply(buf, len, &srv_start);
425
4
  if (status != ARES_SUCCESS)
426
    return status;
427
428
4
  ares_srv_reply* current = srv_start;
429
4
  int offset = ret->Length();
430
4
  for (uint32_t i = 0; current != nullptr; ++i, current = current->next) {
431
    Local<Object> srv_record = Object::New(env->isolate());
432
    srv_record->Set(env->context(),
433
                    env->name_string(),
434
                    OneByteString(env->isolate(), current->host)).Check();
435
    srv_record->Set(env->context(),
436
                    env->port_string(),
437
                    Integer::New(env->isolate(), current->port)).Check();
438
    srv_record->Set(env->context(),
439
                    env->priority_string(),
440
                    Integer::New(env->isolate(), current->priority)).Check();
441
    srv_record->Set(env->context(),
442
                    env->weight_string(),
443
                    Integer::New(env->isolate(), current->weight)).Check();
444
    if (need_type)
445
      srv_record->Set(env->context(),
446
                      env->type_string(),
447
                      env->dns_srv_string()).Check();
448
449
    ret->Set(env->context(), i + offset, srv_record).Check();
450
  }
451
452
4
  ares_free_data(srv_start);
453
4
  return ARES_SUCCESS;
454
}
455
456
457
4
int ParseNaptrReply(
458
    Environment* env,
459
    const unsigned char* buf,
460
    int len,
461
    Local<Array> ret,
462
    bool need_type = false) {
463
8
  HandleScope handle_scope(env->isolate());
464
465
  ares_naptr_reply* naptr_start;
466
4
  int status = ares_parse_naptr_reply(buf, len, &naptr_start);
467
468
4
  if (status != ARES_SUCCESS)
469
    return status;
470
471
4
  ares_naptr_reply* current = naptr_start;
472
4
  int offset = ret->Length();
473
4
  for (uint32_t i = 0; current != nullptr; ++i, current = current->next) {
474
    Local<Object> naptr_record = Object::New(env->isolate());
475
    naptr_record->Set(env->context(),
476
                      env->flags_string(),
477
                      OneByteString(env->isolate(), current->flags)).Check();
478
    naptr_record->Set(env->context(),
479
                      env->service_string(),
480
                      OneByteString(env->isolate(),
481
                                    current->service)).Check();
482
    naptr_record->Set(env->context(),
483
                      env->regexp_string(),
484
                      OneByteString(env->isolate(),
485
                                    current->regexp)).Check();
486
    naptr_record->Set(env->context(),
487
                      env->replacement_string(),
488
                      OneByteString(env->isolate(),
489
                                    current->replacement)).Check();
490
    naptr_record->Set(env->context(),
491
                      env->order_string(),
492
                      Integer::New(env->isolate(), current->order)).Check();
493
    naptr_record->Set(env->context(),
494
                      env->preference_string(),
495
                      Integer::New(env->isolate(),
496
                                   current->preference)).Check();
497
    if (need_type)
498
      naptr_record->Set(env->context(),
499
                        env->type_string(),
500
                        env->dns_naptr_string()).Check();
501
502
    ret->Set(env->context(), i + offset, naptr_record).Check();
503
  }
504
505
4
  ares_free_data(naptr_start);
506
4
  return ARES_SUCCESS;
507
}
508
509
510
4
int ParseSoaReply(
511
    Environment* env,
512
    unsigned char* buf,
513
    int len,
514
    Local<Object>* ret) {
515
4
  EscapableHandleScope handle_scope(env->isolate());
516
517
  // Manage memory using standardard smart pointer std::unique_tr
518
  struct AresDeleter {
519
38
    void operator()(char* ptr) const noexcept { ares_free_string(ptr); }
520
  };
521
  using ares_unique_ptr = std::unique_ptr<char[], AresDeleter>;
522
523
  // Can't use ares_parse_soa_reply() here which can only parse single record
524
4
  const unsigned int ancount = cares_get_16bit(buf + 6);
525
4
  unsigned char* ptr = buf + NS_HFIXEDSZ;
526
4
  char* name_temp = nullptr;
527
  long temp_len;  // NOLINT(runtime/int)
528
4
  int status = ares_expand_name(ptr, buf, len, &name_temp, &temp_len);
529
4
  if (status != ARES_SUCCESS) {
530
    // returns EBADRESP in case of invalid input
531
    return status == ARES_EBADNAME ? ARES_EBADRESP : status;
532
  }
533
534
8
  const ares_unique_ptr name(name_temp);
535
536
4
  if (ptr + temp_len + NS_QFIXEDSZ > buf + len) {
537
    return ARES_EBADRESP;
538
  }
539
4
  ptr += temp_len + NS_QFIXEDSZ;
540
541
26
  for (unsigned int i = 0; i < ancount; i++) {
542
26
    char* rr_name_temp = nullptr;
543
    long rr_temp_len;  // NOLINT(runtime/int)
544
26
    int status2 = ares_expand_name(ptr, buf, len, &rr_name_temp, &rr_temp_len);
545
546
26
    if (status2 != ARES_SUCCESS)
547
      return status2 == ARES_EBADNAME ? ARES_EBADRESP : status2;
548
549
48
    const ares_unique_ptr rr_name(rr_name_temp);
550
551
26
    ptr += rr_temp_len;
552
26
    if (ptr + NS_RRFIXEDSZ > buf + len) {
553
      return ARES_EBADRESP;
554
    }
555
556
26
    const int rr_type = cares_get_16bit(ptr);
557
26
    const int rr_len = cares_get_16bit(ptr + 8);
558
26
    ptr += NS_RRFIXEDSZ;
559
560
    // only need SOA
561
26
    if (rr_type == ns_t_soa) {
562
4
      char* nsname_temp = nullptr;
563
      long nsname_temp_len;  // NOLINT(runtime/int)
564
565
      int status3 = ares_expand_name(ptr, buf, len,
566
                                     &nsname_temp,
567
4
                                     &nsname_temp_len);
568
4
      if (status3 != ARES_SUCCESS) {
569
        return status3 == ARES_EBADNAME ? ARES_EBADRESP : status3;
570
      }
571
4
      const ares_unique_ptr nsname(nsname_temp);
572
4
      ptr += nsname_temp_len;
573
574
4
      char* hostmaster_temp = nullptr;
575
      long hostmaster_temp_len;  // NOLINT(runtime/int)
576
      int status4 = ares_expand_name(ptr, buf, len,
577
                                     &hostmaster_temp,
578
4
                                     &hostmaster_temp_len);
579
4
      if (status4 != ARES_SUCCESS) {
580
        return status4 == ARES_EBADNAME ? ARES_EBADRESP : status4;
581
      }
582
4
      const ares_unique_ptr hostmaster(hostmaster_temp);
583
4
      ptr += hostmaster_temp_len;
584
585
4
      if (ptr + 5 * 4 > buf + len) {
586
        return ARES_EBADRESP;
587
      }
588
589
4
      const unsigned int serial = ReadUint32BE(ptr + 0 * 4);
590
4
      const unsigned int refresh = ReadUint32BE(ptr + 1 * 4);
591
4
      const unsigned int retry = ReadUint32BE(ptr + 2 * 4);
592
4
      const unsigned int expire = ReadUint32BE(ptr + 3 * 4);
593
4
      const unsigned int minttl = ReadUint32BE(ptr + 4 * 4);
594
595
4
      Local<Object> soa_record = Object::New(env->isolate());
596
8
      soa_record->Set(env->context(),
597
                      env->nsname_string(),
598
20
                      OneByteString(env->isolate(), nsname.get())).Check();
599
8
      soa_record->Set(env->context(),
600
                      env->hostmaster_string(),
601
                      OneByteString(env->isolate(),
602
20
                                    hostmaster.get())).Check();
603
8
      soa_record->Set(env->context(),
604
                      env->serial_string(),
605
20
                      Integer::NewFromUnsigned(env->isolate(), serial)).Check();
606
8
      soa_record->Set(env->context(),
607
                      env->refresh_string(),
608
20
                      Integer::New(env->isolate(), refresh)).Check();
609
8
      soa_record->Set(env->context(),
610
                      env->retry_string(),
611
20
                      Integer::New(env->isolate(), retry)).Check();
612
8
      soa_record->Set(env->context(),
613
                      env->expire_string(),
614
20
                      Integer::New(env->isolate(), expire)).Check();
615
8
      soa_record->Set(env->context(),
616
                      env->minttl_string(),
617
20
                      Integer::NewFromUnsigned(env->isolate(), minttl)).Check();
618
8
      soa_record->Set(env->context(),
619
                      env->type_string(),
620
20
                      env->dns_soa_string()).Check();
621
622
623
4
      *ret = handle_scope.Escape(soa_record);
624

4
      break;
625
    }
626
627
22
    ptr += rr_len;
628
  }
629
630
4
  return ARES_SUCCESS;
631
}
632
}  // anonymous namespace
633
634
1109
ChannelWrap::ChannelWrap(Environment* env, Local<Object> object, int timeout)
635
    : AsyncWrap(env, object, PROVIDER_DNSCHANNEL),
636
1109
      timeout_(timeout) {
637
1109
  MakeWeak();
638
639
1109
  Setup();
640
1109
}
641
642
4
void ChannelWrap::MemoryInfo(MemoryTracker* tracker) const {
643
4
  if (timer_handle_ != nullptr)
644
    tracker->TrackField("timer_handle", *timer_handle_);
645
4
  tracker->TrackField("task_list", task_list_, "NodeAresTask::List");
646
4
}
647
648
1109
void ChannelWrap::New(const FunctionCallbackInfo<Value>& args) {
649
1109
  CHECK(args.IsConstructCall());
650
1109
  CHECK_EQ(args.Length(), 1);
651
2218
  CHECK(args[0]->IsInt32());
652
3327
  const int timeout = args[0].As<Int32>()->Value();
653
1109
  Environment* env = Environment::GetCurrent(args);
654
1109
  new ChannelWrap(env, args.This(), timeout);
655
1109
}
656
657
5401
GetAddrInfoReqWrap::GetAddrInfoReqWrap(
658
    Environment* env,
659
    Local<Object> req_wrap_obj,
660
5401
    bool verbatim)
661
    : ReqWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_GETADDRINFOREQWRAP),
662
5401
      verbatim_(verbatim) {}
663
664
4
GetNameInfoReqWrap::GetNameInfoReqWrap(
665
    Environment* env,
666
4
    Local<Object> req_wrap_obj)
667
4
    : ReqWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_GETNAMEINFOREQWRAP) {}
668
669
/* This is called once per second by loop->timer. It is used to constantly */
670
/* call back into c-ares for possibly processing timeouts. */
671
73
void ChannelWrap::AresTimeout(uv_timer_t* handle) {
672
73
  ChannelWrap* channel = static_cast<ChannelWrap*>(handle->data);
673
73
  CHECK_EQ(channel->timer_handle(), handle);
674
73
  CHECK_EQ(false, channel->task_list()->empty());
675
73
  ares_process_fd(channel->cares_channel(), ARES_SOCKET_BAD, ARES_SOCKET_BAD);
676
73
}
677
678
679
void NodeAresTask::MemoryInfo(MemoryTracker* tracker) const {
680
  tracker->TrackField("channel", channel);
681
}
682
683
/* Allocates and returns a new NodeAresTask */
684
29
NodeAresTask* NodeAresTask::Create(ChannelWrap* channel, ares_socket_t sock) {
685
29
  auto task = new NodeAresTask();
686
687
29
  task->channel = channel;
688
29
  task->sock = sock;
689
690
29
  if (uv_poll_init_socket(channel->env()->event_loop(),
691
                          &task->poll_watcher, sock) < 0) {
692
    /* This should never happen. */
693
    delete task;
694
    return nullptr;
695
  }
696
697
29
  return task;
698
}
699
700
1109
void ChannelWrap::Setup() {
701
  struct ares_options options;
702
1109
  memset(&options, 0, sizeof(options));
703
1109
  options.flags = ARES_FLAG_NOCHECKRESP;
704
1109
  options.sock_state_cb = ares_sockstate_cb;
705
1109
  options.sock_state_cb_data = this;
706
1109
  options.timeout = timeout_;
707
708
  int r;
709
1109
  if (!library_inited_) {
710
2218
    Mutex::ScopedLock lock(ares_library_mutex);
711
    // Multiple calls to ares_library_init() increase a reference counter,
712
    // so this is a no-op except for the first call to it.
713
1109
    r = ares_library_init(ARES_LIB_INIT_ALL);
714
1109
    if (r != ARES_SUCCESS)
715
      return env()->ThrowError(ToErrorCodeString(r));
716
  }
717
718
  /* We do the call to ares_init_option for caller. */
719
  const int optmask =
720
1109
      ARES_OPT_FLAGS | ARES_OPT_TIMEOUTMS | ARES_OPT_SOCK_STATE_CB;
721
1109
  r = ares_init_options(&channel_, &options, optmask);
722
723
1109
  if (r != ARES_SUCCESS) {
724
    Mutex::ScopedLock lock(ares_library_mutex);
725
    ares_library_cleanup();
726
    return env()->ThrowError(ToErrorCodeString(r));
727
  }
728
729
1109
  library_inited_ = true;
730
}
731
732
29
void ChannelWrap::StartTimer() {
733
29
  if (timer_handle_ == nullptr) {
734
29
    timer_handle_ = new uv_timer_t();
735
29
    timer_handle_->data = static_cast<void*>(this);
736
29
    uv_timer_init(env()->event_loop(), timer_handle_);
737
  } else if (uv_is_active(reinterpret_cast<uv_handle_t*>(timer_handle_))) {
738
    return;
739
  }
740
29
  int timeout = timeout_;
741
29
  if (timeout == 0) timeout = 1;
742

29
  if (timeout < 0 || timeout > 1000) timeout = 1000;
743
29
  uv_timer_start(timer_handle_, AresTimeout, timeout, timeout);
744
}
745
746
1109
void ChannelWrap::CloseTimer() {
747
1109
  if (timer_handle_ == nullptr)
748
1080
    return;
749
750
58
  env()->CloseHandle(timer_handle_, [](uv_timer_t* handle) { delete handle; });
751
29
  timer_handle_ = nullptr;
752
}
753
754
3240
ChannelWrap::~ChannelWrap() {
755
1080
  ares_destroy(channel_);
756
757
1080
  if (library_inited_) {
758
2160
    Mutex::ScopedLock lock(ares_library_mutex);
759
    // This decreases the reference counter increased by ares_library_init().
760
1080
    ares_library_cleanup();
761
  }
762
763
1080
  CloseTimer();
764
2160
}
765
766
767
101
void ChannelWrap::ModifyActivityQueryCount(int count) {
768
101
  active_query_count_ += count;
769
101
  CHECK_GE(active_query_count_, 0);
770
101
}
771
772
773
/**
774
 * This function is to check whether current servers are fallback servers
775
 * when cares initialized.
776
 *
777
 * The fallback servers of cares is [ "127.0.0.1" ] with no user additional
778
 * setting.
779
 */
780
48
void ChannelWrap::EnsureServers() {
781
  /* if last query is OK or servers are set by user self, do not check */
782

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

6
  if (status != ARES_SUCCESS && status != ARES_ENODATA)
908
2
    return status;
909
910
4
  if (type == ns_t_a) {
911
4
    CHECK_EQ(static_cast<uint32_t>(naddrttls), a_count);
912
8
    for (uint32_t i = 0; i < a_count; i++) {
913
4
      Local<Object> obj = Object::New(env->isolate());
914
8
      obj->Set(env->context(),
915
                env->address_string(),
916
24
                ret->Get(env->context(), i).ToLocalChecked()).Check();
917
8
      obj->Set(env->context(),
918
                env->ttl_string(),
919
                Integer::NewFromUnsigned(
920
20
                  env->isolate(), addrttls[i].ttl)).Check();
921
8
      obj->Set(env->context(),
922
                env->type_string(),
923
20
                env->dns_a_string()).Check();
924
12
      ret->Set(env->context(), i, obj).Check();
925
    }
926
  } else {
927
    for (uint32_t i = 0; i < a_count; i++) {
928
      Local<Object> obj = Object::New(env->isolate());
929
      obj->Set(env->context(),
930
                env->value_string(),
931
                ret->Get(env->context(), i).ToLocalChecked()).Check();
932
      obj->Set(env->context(),
933
                env->type_string(),
934
                env->dns_cname_string()).Check();
935
      ret->Set(env->context(), i, obj).Check();
936
    }
937
  }
938
939
  /* Parse AAAA records */
940
  ares_addr6ttl addr6ttls[256];
941
4
  int naddr6ttls = arraysize(addr6ttls);
942
943
4
  type = ns_t_aaaa;
944
  status = ParseGeneralReply(env,
945
                             buf,
946
                             len,
947
                             &type,
948
                             ret,
949
                             addr6ttls,
950
4
                             &naddr6ttls);
951
4
  uint32_t aaaa_count = ret->Length() - a_count;
952

4
  if (status != ARES_SUCCESS && status != ARES_ENODATA)
953
    return status;
954
955
4
  CHECK_EQ(aaaa_count, static_cast<uint32_t>(naddr6ttls));
956
4
  CHECK_EQ(ret->Length(), a_count + aaaa_count);
957
16
  for (uint32_t i = a_count; i < ret->Length(); i++) {
958
4
    Local<Object> obj = Object::New(env->isolate());
959
8
    obj->Set(env->context(),
960
              env->address_string(),
961
24
              ret->Get(env->context(), i).ToLocalChecked()).Check();
962
8
    obj->Set(env->context(),
963
              env->ttl_string(),
964
              Integer::NewFromUnsigned(
965
20
                env->isolate(), addr6ttls[i - a_count].ttl)).Check();
966
8
    obj->Set(env->context(),
967
              env->type_string(),
968
20
              env->dns_aaaa_string()).Check();
969
12
    ret->Set(env->context(), i, obj).Check();
970
  }
971
972
  /* Parse MX records */
973
4
  status = ParseMxReply(env, buf, len, ret, true);
974

4
  if (status != ARES_SUCCESS && status != ARES_ENODATA)
975
    return status;
976
977
  /* Parse NS records */
978
4
  type = ns_t_ns;
979
4
  old_count = ret->Length();
980
4
  status = ParseGeneralReply(env, buf, len, &type, ret);
981

4
  if (status != ARES_SUCCESS && status != ARES_ENODATA)
982
    return status;
983
984
16
  for (uint32_t i = old_count; i < ret->Length(); i++) {
985
4
    Local<Object> obj = Object::New(env->isolate());
986
8
    obj->Set(env->context(),
987
             env->value_string(),
988
24
             ret->Get(env->context(), i).ToLocalChecked()).Check();
989
8
    obj->Set(env->context(),
990
              env->type_string(),
991
20
              env->dns_ns_string()).Check();
992
12
    ret->Set(env->context(), i, obj).Check();
993
  }
994
995
  /* Parse TXT records */
996
4
  status = ParseTxtReply(env, buf, len, ret, true);
997

4
  if (status != ARES_SUCCESS && status != ARES_ENODATA)
998
    return status;
999
1000
  /* Parse SRV records */
1001
4
  status = ParseSrvReply(env, buf, len, ret, true);
1002

4
  if (status != ARES_SUCCESS && status != ARES_ENODATA)
1003
    return status;
1004
1005
  /* Parse PTR records */
1006
4
  type = ns_t_ptr;
1007
4
  old_count = ret->Length();
1008
4
  status = ParseGeneralReply(env, buf, len, &type, ret);
1009

4
  if (status != ARES_SUCCESS && status != ARES_ENODATA)
1010
    return status;
1011
16
  for (uint32_t i = old_count; i < ret->Length(); i++) {
1012
4
    Local<Object> obj = Object::New(env->isolate());
1013
8
    obj->Set(env->context(),
1014
              env->value_string(),
1015
24
              ret->Get(env->context(), i).ToLocalChecked()).Check();
1016
8
    obj->Set(env->context(),
1017
              env->type_string(),
1018
20
              env->dns_ptr_string()).Check();
1019
12
    ret->Set(env->context(), i, obj).Check();
1020
  }
1021
1022
  /* Parse NAPTR records */
1023
4
  status = ParseNaptrReply(env, buf, len, ret, true);
1024

4
  if (status != ARES_SUCCESS && status != ARES_ENODATA)
1025
    return status;
1026
1027
  /* Parse SOA records */
1028
  Local<Object> soa_record = Local<Object>();
1029
4
  status = ParseSoaReply(env, buf, len, &soa_record);
1030

4
  if (status != ARES_SUCCESS && status != ARES_ENODATA)
1031
    return status;
1032
1033
4
  if (!soa_record.IsEmpty())
1034
12
    ret->Set(env->context(), ret->Length(), soa_record).Check();
1035
1036
  /* Parse CAA records */
1037
4
  status = ParseCaaReply(env, buf, len, ret, true);
1038

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






51
  ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
1395
1396






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






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






153
  CHECK(args[1]->IsString());
1399
1400
102
  Local<Object> req_wrap_obj = args[0].As<Object>();
1401
102
  Local<String> string = args[1].As<String>();
1402
102
  auto wrap = std::make_unique<Wrap>(channel, req_wrap_obj);
1403
1404
102
  node::Utf8Value name(env->isolate(), string);
1405
51
  channel->ModifyActivityQueryCount(1);
1406
51
  int err = wrap->Send(*name);
1407






51
  if (err) {
1408
    channel->ModifyActivityQueryCount(-1);
1409
  } else {
1410
    // Release ownership of the pointer allowing the ownership to be transferred
1411
51
    USE(wrap.release());
1412
  }
1413
1414
102
  args.GetReturnValue().Set(err);
1415
}
1416
1417
1418
5400
void AfterGetAddrInfo(uv_getaddrinfo_t* req, int status, struct addrinfo* res) {
1419
  std::unique_ptr<GetAddrInfoReqWrap> req_wrap {
1420
10800
      static_cast<GetAddrInfoReqWrap*>(req->data)};
1421
5400
  Environment* env = req_wrap->env();
1422
1423
10800
  HandleScope handle_scope(env->isolate());
1424
5400
  Context::Scope context_scope(env->context());
1425
1426
  Local<Value> argv[] = {
1427
    Integer::New(env->isolate(), status),
1428
    Null(env->isolate())
1429
16200
  };
1430
1431
5400
  uint32_t n = 0;
1432
5400
  const bool verbatim = req_wrap->verbatim();
1433
1434
5400
  if (status == 0) {
1435
5391
    Local<Array> results = Array::New(env->isolate());
1436
1437
10782
    auto add = [&] (bool want_ipv4, bool want_ipv6) {
1438
43824
      for (auto p = res; p != nullptr; p = p->ai_next) {
1439
33042
        CHECK_EQ(p->ai_socktype, SOCK_STREAM);
1440
1441
        const char* addr;
1442

33042
        if (want_ipv4 && p->ai_family == AF_INET) {
1443
5602
          addr = reinterpret_cast<char*>(
1444
11204
              &(reinterpret_cast<struct sockaddr_in*>(p->ai_addr)->sin_addr));
1445

27440
        } else if (want_ipv6 && p->ai_family == AF_INET6) {
1446
10919
          addr = reinterpret_cast<char*>(
1447
21838
              &(reinterpret_cast<struct sockaddr_in6*>(p->ai_addr)->sin6_addr));
1448
        } else {
1449
33042
          continue;
1450
        }
1451
1452
        char ip[INET6_ADDRSTRLEN];
1453
16521
        if (uv_inet_ntop(p->ai_family, addr, ip, sizeof(ip)))
1454
          continue;
1455
1456
33042
        Local<String> s = OneByteString(env->isolate(), ip);
1457
66084
        results->Set(env->context(), n, s).Check();
1458
16521
        n++;
1459
      }
1460
16173
    };
1461
1462
5391
    add(true, verbatim);
1463
5391
    if (verbatim == false)
1464
5391
      add(false, true);
1465
1466
    // No responses were found to return
1467
5391
    if (n == 0) {
1468
      argv[0] = Integer::New(env->isolate(), UV_EAI_NODATA);
1469
    }
1470
1471
5391
    argv[1] = results;
1472
  }
1473
1474
5400
  uv_freeaddrinfo(res);
1475
1476
  TRACE_EVENT_NESTABLE_ASYNC_END2(
1477
5400
      TRACING_CATEGORY_NODE2(dns, native), "lookup", req_wrap.get(),
1478
5400
      "count", n, "verbatim", verbatim);
1479
793
1480
11593
  // Make the callback into JavaScript
1481
10800
  req_wrap->MakeCallback(env->oncomplete_string(), arraysize(argv), argv);
1482
5400
}
1483
1484
1485
4
void AfterGetNameInfo(uv_getnameinfo_t* req,
1486
                      int status,
1487
                      const char* hostname,
1488
                      const char* service) {
1489
  std::unique_ptr<GetNameInfoReqWrap> req_wrap {
1490
8
      static_cast<GetNameInfoReqWrap*>(req->data)};
1491
4
  Environment* env = req_wrap->env();
1492
1493
8
  HandleScope handle_scope(env->isolate());
1494
4
  Context::Scope context_scope(env->context());
1495
1496
  Local<Value> argv[] = {
1497
    Integer::New(env->isolate(), status),
1498
    Null(env->isolate()),
1499
    Null(env->isolate())
1500
16
  };
1501
1502
4
  if (status == 0) {
1503
    // Success
1504
3
    Local<String> js_hostname = OneByteString(env->isolate(), hostname);
1505
3
    Local<String> js_service = OneByteString(env->isolate(), service);
1506
3
    argv[1] = js_hostname;
1507
3
    argv[2] = js_service;
1508
  }
1509
1510
  TRACE_EVENT_NESTABLE_ASYNC_END2(
1511
4
      TRACING_CATEGORY_NODE2(dns, native), "lookupService", req_wrap.get(),
1512
4
      "hostname", TRACE_STR_COPY(hostname),
1513
3
      "service", TRACE_STR_COPY(service));
1514
11
1515
4
  // Make the callback into JavaScript
1516
4
  req_wrap->MakeCallback(env->oncomplete_string(), arraysize(argv), argv);
1517
4
}
1518
1519
using ParseIPResult =
1520
    decltype(static_cast<ares_addr_port_node*>(nullptr)->addr);
1521
1522
26
int ParseIP(const char* ip, ParseIPResult* result = nullptr) {
1523
  ParseIPResult tmp;
1524
26
  if (result == nullptr) result = &tmp;
1525
26
  if (0 == uv_inet_pton(AF_INET, ip, result)) return 4;
1526
10
  if (0 == uv_inet_pton(AF_INET6, ip, result)) return 6;
1527
1
  return 0;
1528
}
1529
1530
26
void CanonicalizeIP(const FunctionCallbackInfo<Value>& args) {
1531
26
  Isolate* isolate = args.GetIsolate();
1532
51
  node::Utf8Value ip(isolate, args[0]);
1533
1534
  ParseIPResult result;
1535
26
  const int rc = ParseIP(*ip, &result);
1536
26
  if (rc == 0) return;
1537
1538
  char canonical_ip[INET6_ADDRSTRLEN];
1539
25
  const int af = (rc == 4 ? AF_INET : AF_INET6);
1540
25
  CHECK_EQ(0, uv_inet_ntop(af, &result, canonical_ip, sizeof(canonical_ip)));
1541
50
  Local<String> val = String::NewFromUtf8(isolate, canonical_ip)
1542
25
      .ToLocalChecked();
1543
50
  args.GetReturnValue().Set(val);
1544
}
1545
1546
5401
void GetAddrInfo(const FunctionCallbackInfo<Value>& args) {
1547
5401
  Environment* env = Environment::GetCurrent(args);
1548
1549
10802
  CHECK(args[0]->IsObject());
1550
16203
  CHECK(args[1]->IsString());
1551
10802
  CHECK(args[2]->IsInt32());
1552
10802
  CHECK(args[4]->IsBoolean());
1553
10802
  Local<Object> req_wrap_obj = args[0].As<Object>();
1554
10802
  node::Utf8Value hostname(env->isolate(), args[1]);
1555
1556
5401
  int32_t flags = 0;
1557
10802
  if (args[3]->IsInt32()) {
1558
16203
    flags = args[3].As<Int32>()->Value();
1559
  }
1560
1561
  int family;
1562
1563

16203
  switch (args[2].As<Int32>()->Value()) {
1564
    case 0:
1565
5385
      family = AF_UNSPEC;
1566
5385
      break;
1567
    case 4:
1568
14
      family = AF_INET;
1569
14
      break;
1570
    case 6:
1571
2
      family = AF_INET6;
1572
2
      break;
1573
    default:
1574
      CHECK(0 && "bad address family");
1575
  }
1576
1577
  auto req_wrap = std::make_unique<GetAddrInfoReqWrap>(env,
1578
                                                       req_wrap_obj,
1579
16203
                                                       args[4]->IsTrue());
1580
1581
  struct addrinfo hints;
1582
5401
  memset(&hints, 0, sizeof(hints));
1583
5401
  hints.ai_family = family;
1584
5401
  hints.ai_socktype = SOCK_STREAM;
1585
5401
  hints.ai_flags = flags;
1586
1587
  TRACE_EVENT_NESTABLE_ASYNC_BEGIN2(
1588
5401
      TRACING_CATEGORY_NODE2(dns, native), "lookup", req_wrap.get(),
1589
5401
      "hostname", TRACE_STR_COPY(*hostname),
1590
794
      "family",
1591
11596
      family == AF_INET ? "ipv4" : family == AF_INET6 ? "ipv6" : "unspec");
1592
5401
1593
5401
  int err = req_wrap->Dispatch(uv_getaddrinfo,
1594
                               AfterGetAddrInfo,
1595
                               *hostname,
1596
                               nullptr,
1597
5401
                               &hints);
1598
5401
  if (err == 0)
1599
    // Release ownership of the pointer allowing the ownership to be transferred
1600
5401
    USE(req_wrap.release());
1601
1602
10802
  args.GetReturnValue().Set(err);
1603
5401
}
1604
1605
1606
4
void GetNameInfo(const FunctionCallbackInfo<Value>& args) {
1607
4
  Environment* env = Environment::GetCurrent(args);
1608
1609
8
  CHECK(args[0]->IsObject());
1610
12
  CHECK(args[1]->IsString());
1611
8
  CHECK(args[2]->IsUint32());
1612
8
  Local<Object> req_wrap_obj = args[0].As<Object>();
1613
8
  node::Utf8Value ip(env->isolate(), args[1]);
1614
16
  const unsigned port = args[2]->Uint32Value(env->context()).FromJust();
1615
  struct sockaddr_storage addr;
1616
1617

4
  CHECK(uv_ip4_addr(*ip, port, reinterpret_cast<sockaddr_in*>(&addr)) == 0 ||
1618
        uv_ip6_addr(*ip, port, reinterpret_cast<sockaddr_in6*>(&addr)) == 0);
1619
1620
8
  auto req_wrap = std::make_unique<GetNameInfoReqWrap>(env, req_wrap_obj);
1621
1622
4
  TRACE_EVENT_NESTABLE_ASYNC_BEGIN2(
1623
      TRACING_CATEGORY_NODE2(dns, native), "lookupService", req_wrap.get(),
1624
4
      "ip", TRACE_STR_COPY(*ip), "port", port);
1625
3
1626
15
  int err = req_wrap->Dispatch(uv_getnameinfo,
1627
4
                               AfterGetNameInfo,
1628
                               reinterpret_cast<struct sockaddr*>(&addr),
1629
4
                               NI_NAMEREQD);
1630
4
  if (err == 0)
1631
    // Release ownership of the pointer allowing the ownership to be transferred
1632
4
    USE(req_wrap.release());
1633
1634
8
  args.GetReturnValue().Set(err);
1635
4
}
1636
1637
1638
65
void GetServers(const FunctionCallbackInfo<Value>& args) {
1639
65
  Environment* env = Environment::GetCurrent(args);
1640
  ChannelWrap* channel;
1641
65
  ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
1642
1643
65
  Local<Array> server_array = Array::New(env->isolate());
1644
1645
  ares_addr_port_node* servers;
1646
1647
65
  int r = ares_get_servers_ports(channel->cares_channel(), &servers);
1648
65
  CHECK_EQ(r, ARES_SUCCESS);
1649
195
  auto cleanup = OnScopeLeave([&]() { ares_free_data(servers); });
1650
1651
65
  ares_addr_port_node* cur = servers;
1652
1653
141
  for (uint32_t i = 0; cur != nullptr; ++i, cur = cur->next) {
1654
    char ip[INET6_ADDRSTRLEN];
1655
1656
76
    const void* caddr = static_cast<const void*>(&cur->addr);
1657
76
    int err = uv_inet_ntop(cur->family, caddr, ip, sizeof(ip));
1658
76
    CHECK_EQ(err, 0);
1659
1660
    Local<Value> ret[] = {
1661
      OneByteString(env->isolate(), ip),
1662
      Integer::New(env->isolate(), cur->udp_port)
1663
228
    };
1664
1665
228
    if (server_array->Set(env->context(), i,
1666
228
                          Array::New(env->isolate(), ret, arraysize(ret)))
1667
          .IsNothing()) {
1668
      return;
1669
    }
1670
  }
1671
1672
130
  args.GetReturnValue().Set(server_array);
1673
}
1674
1675
1676
28
void SetServers(const FunctionCallbackInfo<Value>& args) {
1677
28
  Environment* env = Environment::GetCurrent(args);
1678
  ChannelWrap* channel;
1679
32
  ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
1680
1681
28
  if (channel->active_query_count()) {
1682
4
    return args.GetReturnValue().Set(DNS_ESETSRVPENDING);
1683
  }
1684
1685
52
  CHECK(args[0]->IsArray());
1686
1687
26
  Local<Array> arr = Local<Array>::Cast(args[0]);
1688
1689
26
  uint32_t len = arr->Length();
1690
1691
26
  if (len == 0) {
1692
2
    int rv = ares_set_servers(channel->cares_channel(), nullptr);
1693
4
    return args.GetReturnValue().Set(rv);
1694
  }
1695
1696
48
  std::vector<ares_addr_port_node> servers(len);
1697
24
  ares_addr_port_node* last = nullptr;
1698
1699
  int err;
1700
1701
59
  for (uint32_t i = 0; i < len; i++) {
1702
140
    CHECK(arr->Get(env->context(), i).ToLocalChecked()->IsArray());
1703
1704
    Local<Array> elm =
1705
105
        Local<Array>::Cast(arr->Get(env->context(), i).ToLocalChecked());
1706
1707
175
    CHECK(elm->Get(env->context(),
1708
                   0).ToLocalChecked()->Int32Value(env->context()).FromJust());
1709
175
    CHECK(elm->Get(env->context(), 1).ToLocalChecked()->IsString());
1710
175
    CHECK(elm->Get(env->context(),
1711
                   2).ToLocalChecked()->Int32Value(env->context()).FromJust());
1712
1713
105
    int fam = elm->Get(env->context(), 0)
1714
140
        .ToLocalChecked()->Int32Value(env->context()).FromJust();
1715
    node::Utf8Value ip(env->isolate(),
1716
140
                       elm->Get(env->context(), 1).ToLocalChecked());
1717
105
    int port = elm->Get(env->context(), 2)
1718
140
        .ToLocalChecked()->Int32Value(env->context()).FromJust();
1719
1720
35
    ares_addr_port_node* cur = &servers[i];
1721
1722
35
    cur->tcp_port = cur->udp_port = port;
1723
35
    switch (fam) {
1724
      case 4:
1725
28
        cur->family = AF_INET;
1726
28
        err = uv_inet_pton(AF_INET, *ip, &cur->addr);
1727
28
        break;
1728
      case 6:
1729
7
        cur->family = AF_INET6;
1730
7
        err = uv_inet_pton(AF_INET6, *ip, &cur->addr);
1731
7
        break;
1732
      default:
1733
        CHECK(0 && "Bad address family.");
1734
    }
1735
1736
35
    if (err)
1737
      break;
1738
1739
35
    cur->next = nullptr;
1740
1741
35
    if (last != nullptr)
1742
11
      last->next = cur;
1743
1744
35
    last = cur;
1745
  }
1746
1747
24
  if (err == 0)
1748
24
    err = ares_set_servers_ports(channel->cares_channel(), &servers[0]);
1749
  else
1750
    err = ARES_EBADSTR;
1751
1752
24
  if (err == ARES_SUCCESS)
1753
24
    channel->set_is_servers_default(false);
1754
1755
48
  args.GetReturnValue().Set(err);
1756
}
1757
1758
7
void SetLocalAddress(const FunctionCallbackInfo<Value>& args) {
1759
7
  Environment* env = Environment::GetCurrent(args);
1760
  ChannelWrap* channel;
1761
10
  ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
1762
1763
7
  CHECK_EQ(args.Length(), 2);
1764
21
  CHECK(args[0]->IsString());
1765
1766
7
  Isolate* isolate = args.GetIsolate();
1767
11
  node::Utf8Value ip0(isolate, args[0]);
1768
1769
  unsigned char addr0[sizeof(struct in6_addr)];
1770
  unsigned char addr1[sizeof(struct in6_addr)];
1771
7
  int type0 = 0;
1772
1773
  // This function accepts 2 arguments.  The first may be either an IPv4
1774
  // address or an IPv6 address.  If present, the second argument must be the
1775
  // other type of address.  Otherwise, the unspecified type of IP is set
1776
  // to 0 (any).
1777
1778
7
  if (uv_inet_pton(AF_INET, *ip0, &addr0) == 0) {
1779
4
    ares_set_local_ip4(channel->cares_channel(), ReadUint32BE(addr0));
1780
4
    type0 = 4;
1781
3
  } else if (uv_inet_pton(AF_INET6, *ip0, &addr0) == 0) {
1782
2
    ares_set_local_ip6(channel->cares_channel(), addr0);
1783
2
    type0 = 6;
1784
  } else {
1785
1
    THROW_ERR_INVALID_ARG_VALUE(env, "Invalid IP address.");
1786
1
    return;
1787
  }
1788
1789
18
  if (!args[1]->IsUndefined()) {
1790
12
    CHECK(args[1]->IsString());
1791
6
    node::Utf8Value ip1(isolate, args[1]);
1792
1793
4
    if (uv_inet_pton(AF_INET, *ip1, &addr1) == 0) {
1794
1
      if (type0 == 4) {
1795
1
        THROW_ERR_INVALID_ARG_VALUE(env, "Cannot specify two IPv4 addresses.");
1796
1
        return;
1797
      } else {
1798
        ares_set_local_ip4(channel->cares_channel(), ReadUint32BE(addr1));
1799
      }
1800
3
    } else if (uv_inet_pton(AF_INET6, *ip1, &addr1) == 0) {
1801
3
      if (type0 == 6) {
1802
1
        THROW_ERR_INVALID_ARG_VALUE(env, "Cannot specify two IPv6 addresses.");
1803
1
        return;
1804
      } else {
1805
2
        ares_set_local_ip6(channel->cares_channel(), addr1);
1806
      }
1807
    } else {
1808
      THROW_ERR_INVALID_ARG_VALUE(env, "Invalid IP address.");
1809
      return;
1810
    }
1811
  } else {
1812
    // No second arg specified
1813
2
    if (type0 == 4) {
1814
1
      memset(&addr1, 0, sizeof(addr1));
1815
1
      ares_set_local_ip6(channel->cares_channel(), addr1);
1816
    } else {
1817
1
      ares_set_local_ip4(channel->cares_channel(), 0);
1818
    }
1819
  }
1820
}
1821
1822
6
void Cancel(const FunctionCallbackInfo<Value>& args) {
1823
  ChannelWrap* channel;
1824
6
  ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
1825
1826
6
  TRACE_EVENT_INSTANT0(TRACING_CATEGORY_NODE2(dns, native),
1827
      "cancel", TRACE_EVENT_SCOPE_THREAD);
1828
6
1829
10
  ares_cancel(channel->cares_channel());
1830
16
}
1831
6
1832
const char EMSG_ESETSRVPENDING[] = "There are pending queries.";
1833
1
void StrError(const FunctionCallbackInfo<Value>& args) {
1834
1
  Environment* env = Environment::GetCurrent(args);
1835
4
  int code = args[0]->Int32Value(env->context()).FromJust();
1836
1
  const char* errmsg = (code == DNS_ESETSRVPENDING) ?
1837
    EMSG_ESETSRVPENDING :
1838
1
    ares_strerror(code);
1839
3
  args.GetReturnValue().Set(OneByteString(env->isolate(), errmsg));
1840
1
}
1841
1842
}  // namespace
1843
1844
2
inline void safe_free_hostent(struct hostent* host) {
1845
  int idx;
1846
1847
2
  if (host->h_addr_list != nullptr) {
1848
2
    idx = 0;
1849
6
    while (host->h_addr_list[idx]) {
1850
2
      free(host->h_addr_list[idx++]);
1851
    }
1852
2
    free(host->h_addr_list);
1853
2
    host->h_addr_list = nullptr;
1854
  }
1855
1856
2
  if (host->h_aliases != nullptr) {
1857
2
    idx = 0;
1858
2
    while (host->h_aliases[idx]) {
1859
      free(host->h_aliases[idx++]);
1860
    }
1861
2
    free(host->h_aliases);
1862
2
    host->h_aliases = nullptr;
1863
  }
1864
1865
2
  free(host->h_name);
1866
2
  free(host);
1867
2
}
1868
1869
1157
void Initialize(Local<Object> target,
1870
                Local<Value> unused,
1871
                Local<Context> context,
1872
                void* priv) {
1873
1157
  Environment* env = Environment::GetCurrent(context);
1874
1875
1157
  env->SetMethod(target, "getaddrinfo", GetAddrInfo);
1876
1157
  env->SetMethod(target, "getnameinfo", GetNameInfo);
1877
1157
  env->SetMethodNoSideEffect(target, "canonicalizeIP", CanonicalizeIP);
1878
1879
1157
  env->SetMethod(target, "strerror", StrError);
1880
1881
2314
  target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(), "AF_INET"),
1882
5785
              Integer::New(env->isolate(), AF_INET)).Check();
1883
2314
  target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(), "AF_INET6"),
1884
5785
              Integer::New(env->isolate(), AF_INET6)).Check();
1885
2314
  target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(),
1886
                                                    "AF_UNSPEC"),
1887
5785
              Integer::New(env->isolate(), AF_UNSPEC)).Check();
1888
2314
  target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(),
1889
                                                    "AI_ADDRCONFIG"),
1890
5785
              Integer::New(env->isolate(), AI_ADDRCONFIG)).Check();
1891
2314
  target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(),
1892
                                                    "AI_ALL"),
1893
5785
              Integer::New(env->isolate(), AI_ALL)).Check();
1894
2314
  target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(),
1895
                                                    "AI_V4MAPPED"),
1896
5785
              Integer::New(env->isolate(), AI_V4MAPPED)).Check();
1897
1898
  Local<FunctionTemplate> aiw =
1899
1157
      BaseObject::MakeLazilyInitializedJSTemplate(env);
1900
2314
  aiw->Inherit(AsyncWrap::GetConstructorTemplate(env));
1901
1157
  env->SetConstructorFunction(target, "GetAddrInfoReqWrap", aiw);
1902
1903
  Local<FunctionTemplate> niw =
1904
1157
      BaseObject::MakeLazilyInitializedJSTemplate(env);
1905
2314
  niw->Inherit(AsyncWrap::GetConstructorTemplate(env));
1906
1157
  env->SetConstructorFunction(target, "GetNameInfoReqWrap", niw);
1907
1908
  Local<FunctionTemplate> qrw =
1909
1157
      BaseObject::MakeLazilyInitializedJSTemplate(env);
1910
2314
  qrw->Inherit(AsyncWrap::GetConstructorTemplate(env));
1911
1157
  env->SetConstructorFunction(target, "QueryReqWrap", qrw);
1912
1913
  Local<FunctionTemplate> channel_wrap =
1914
1157
      env->NewFunctionTemplate(ChannelWrap::New);
1915
3471
  channel_wrap->InstanceTemplate()->SetInternalFieldCount(
1916
1157
      ChannelWrap::kInternalFieldCount);
1917
2314
  channel_wrap->Inherit(AsyncWrap::GetConstructorTemplate(env));
1918
1919
1157
  env->SetProtoMethod(channel_wrap, "queryAny", Query<QueryAnyWrap>);
1920
1157
  env->SetProtoMethod(channel_wrap, "queryA", Query<QueryAWrap>);
1921
1157
  env->SetProtoMethod(channel_wrap, "queryAaaa", Query<QueryAaaaWrap>);
1922
1157
  env->SetProtoMethod(channel_wrap, "queryCaa", Query<QueryCaaWrap>);
1923
1157
  env->SetProtoMethod(channel_wrap, "queryCname", Query<QueryCnameWrap>);
1924
1157
  env->SetProtoMethod(channel_wrap, "queryMx", Query<QueryMxWrap>);
1925
1157
  env->SetProtoMethod(channel_wrap, "queryNs", Query<QueryNsWrap>);
1926
1157
  env->SetProtoMethod(channel_wrap, "queryTxt", Query<QueryTxtWrap>);
1927
1157
  env->SetProtoMethod(channel_wrap, "querySrv", Query<QuerySrvWrap>);
1928
1157
  env->SetProtoMethod(channel_wrap, "queryPtr", Query<QueryPtrWrap>);
1929
1157
  env->SetProtoMethod(channel_wrap, "queryNaptr", Query<QueryNaptrWrap>);
1930
1157
  env->SetProtoMethod(channel_wrap, "querySoa", Query<QuerySoaWrap>);
1931
1157
  env->SetProtoMethod(channel_wrap, "getHostByAddr", Query<GetHostByAddrWrap>);
1932
1933
1157
  env->SetProtoMethodNoSideEffect(channel_wrap, "getServers", GetServers);
1934
1157
  env->SetProtoMethod(channel_wrap, "setServers", SetServers);
1935
1157
  env->SetProtoMethod(channel_wrap, "setLocalAddress", SetLocalAddress);
1936
1157
  env->SetProtoMethod(channel_wrap, "cancel", Cancel);
1937
1938
1157
  env->SetConstructorFunction(target, "ChannelWrap", channel_wrap);
1939
1157
}
1940
1941
}  // namespace cares_wrap
1942
}  // namespace node
1943
1944

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