GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: node_sockaddr.cc Lines: 395 462 85.5 %
Date: 2022-12-07 04:23:16 Branches: 115 199 57.8 %

Line Branch Exec Source
1
#include "node_sockaddr-inl.h"  // NOLINT(build/include)
2
#include "env-inl.h"
3
#include "base64-inl.h"
4
#include "base_object-inl.h"
5
#include "memory_tracker-inl.h"
6
#include "node_errors.h"
7
#include "uv.h"
8
9
#include <memory>
10
#include <string>
11
#include <vector>
12
13
namespace node {
14
15
using v8::Array;
16
using v8::Context;
17
using v8::FunctionCallbackInfo;
18
using v8::FunctionTemplate;
19
using v8::Int32;
20
using v8::Isolate;
21
using v8::Local;
22
using v8::MaybeLocal;
23
using v8::Object;
24
using v8::Uint32;
25
using v8::Value;
26
27
namespace {
28
template <typename T, typename F>
29
SocketAddress FromUVHandle(F fn, const T& handle) {
30
  SocketAddress addr;
31
  int len = sizeof(sockaddr_storage);
32
  if (fn(&handle, addr.storage(), &len) == 0)
33
    CHECK_EQ(static_cast<size_t>(len), addr.length());
34
  else
35
    addr.storage()->sa_family = 0;
36
  return addr;
37
}
38
}  // namespace
39
40
19398
bool SocketAddress::ToSockAddr(
41
    int32_t family,
42
    const char* host,
43
    uint32_t port,
44
    sockaddr_storage* addr) {
45
19398
  switch (family) {
46
12908
    case AF_INET:
47
12908
      return uv_ip4_addr(
48
          host,
49
          port,
50
12908
          reinterpret_cast<sockaddr_in*>(addr)) == 0;
51
6490
    case AF_INET6:
52
6490
      return uv_ip6_addr(
53
          host,
54
          port,
55
6490
          reinterpret_cast<sockaddr_in6*>(addr)) == 0;
56
    default:
57
      UNREACHABLE();
58
  }
59
}
60
61
bool SocketAddress::New(
62
    const char* host,
63
    uint32_t port,
64
    SocketAddress* addr) {
65
  return New(AF_INET, host, port, addr) || New(AF_INET6, host, port, addr);
66
}
67
68
19383
bool SocketAddress::New(
69
    int32_t family,
70
    const char* host,
71
    uint32_t port,
72
    SocketAddress* addr) {
73
19383
  return ToSockAddr(family, host, port,
74
38766
                    reinterpret_cast<sockaddr_storage*>(addr->storage()));
75
}
76
77
6423
size_t SocketAddress::Hash::operator()(const SocketAddress& addr) const {
78
6423
  size_t hash = 0;
79
6423
  switch (addr.family()) {
80
38
    case AF_INET: {
81
      const sockaddr_in* ipv4 =
82
38
          reinterpret_cast<const sockaddr_in*>(addr.raw());
83
38
      hash_combine(&hash, ipv4->sin_port, ipv4->sin_addr.s_addr);
84
38
      break;
85
    }
86
6385
    case AF_INET6: {
87
      const sockaddr_in6* ipv6 =
88
6385
          reinterpret_cast<const sockaddr_in6*>(addr.raw());
89
6385
      const uint64_t* a =
90
          reinterpret_cast<const uint64_t*>(&ipv6->sin6_addr);
91
6385
      hash_combine(&hash, ipv6->sin6_port, a[0], a[1]);
92
6385
      break;
93
    }
94
    default:
95
      UNREACHABLE();
96
  }
97
6423
  return hash;
98
}
99
100
SocketAddress SocketAddress::FromSockName(const uv_tcp_t& handle) {
101
  return FromUVHandle(uv_tcp_getsockname, handle);
102
}
103
104
SocketAddress SocketAddress::FromSockName(const uv_udp_t& handle) {
105
  return FromUVHandle(uv_udp_getsockname, handle);
106
}
107
108
SocketAddress SocketAddress::FromPeerName(const uv_tcp_t& handle) {
109
  return FromUVHandle(uv_tcp_getpeername, handle);
110
}
111
112
SocketAddress SocketAddress::FromPeerName(const uv_udp_t& handle) {
113
  return FromUVHandle(uv_udp_getpeername, handle);
114
}
115
116
namespace {
117
constexpr uint8_t mask[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
118
119
16
bool is_match_ipv4(
120
    const SocketAddress& one,
121
    const SocketAddress& two) {
122
  const sockaddr_in* one_in =
123
16
      reinterpret_cast<const sockaddr_in*>(one.data());
124
  const sockaddr_in* two_in =
125
16
      reinterpret_cast<const sockaddr_in*>(two.data());
126
16
  return memcmp(&one_in->sin_addr, &two_in->sin_addr, sizeof(uint32_t)) == 0;
127
}
128
129
42
bool is_match_ipv6(
130
    const SocketAddress& one,
131
    const SocketAddress& two) {
132
  const sockaddr_in6* one_in =
133
42
      reinterpret_cast<const sockaddr_in6*>(one.data());
134
  const sockaddr_in6* two_in =
135
42
      reinterpret_cast<const sockaddr_in6*>(two.data());
136
42
  return memcmp(&one_in->sin6_addr, &two_in->sin6_addr, 16) == 0;
137
}
138
139
23
bool is_match_ipv4_ipv6(
140
    const SocketAddress& ipv4,
141
    const SocketAddress& ipv6) {
142
  const sockaddr_in* check_ipv4 =
143
23
      reinterpret_cast<const sockaddr_in*>(ipv4.data());
144
  const sockaddr_in6* check_ipv6 =
145
23
      reinterpret_cast<const sockaddr_in6*>(ipv6.data());
146
147
23
  const uint8_t* ptr =
148
      reinterpret_cast<const uint8_t*>(&check_ipv6->sin6_addr);
149
150
36
  return memcmp(ptr, mask, sizeof(mask)) == 0 &&
151
13
         memcmp(ptr + sizeof(mask),
152
13
                &check_ipv4->sin_addr,
153
23
                sizeof(uint32_t)) == 0;
154
}
155
156
6481
SocketAddress::CompareResult compare_ipv4(
157
    const SocketAddress& one,
158
    const SocketAddress& two) {
159
  const sockaddr_in* one_in =
160
6481
      reinterpret_cast<const sockaddr_in*>(one.data());
161
  const sockaddr_in* two_in =
162
6481
      reinterpret_cast<const sockaddr_in*>(two.data());
163
6481
  const uint32_t s_addr_one = ntohl(one_in->sin_addr.s_addr);
164
6481
  const uint32_t s_addr_two = ntohl(two_in->sin_addr.s_addr);
165
166
6481
  if (s_addr_one < s_addr_two)
167
6426
    return SocketAddress::CompareResult::LESS_THAN;
168
55
  else if (s_addr_one == s_addr_two)
169
21
    return SocketAddress::CompareResult::SAME;
170
  else
171
34
    return SocketAddress::CompareResult::GREATER_THAN;
172
}
173
174
77
SocketAddress::CompareResult compare_ipv6(
175
    const SocketAddress& one,
176
    const SocketAddress& two) {
177
  const sockaddr_in6* one_in =
178
77
      reinterpret_cast<const sockaddr_in6*>(one.data());
179
  const sockaddr_in6* two_in =
180
77
      reinterpret_cast<const sockaddr_in6*>(two.data());
181
77
  int ret = memcmp(&one_in->sin6_addr, &two_in->sin6_addr, 16);
182
77
  if (ret < 0)
183
35
    return SocketAddress::CompareResult::LESS_THAN;
184
42
  else if (ret > 0)
185
35
    return SocketAddress::CompareResult::GREATER_THAN;
186
7
  return SocketAddress::CompareResult::SAME;
187
}
188
189
87
SocketAddress::CompareResult compare_ipv4_ipv6(
190
    const SocketAddress& ipv4,
191
    const SocketAddress& ipv6) {
192
  const sockaddr_in* ipv4_in =
193
87
      reinterpret_cast<const sockaddr_in*>(ipv4.data());
194
  const sockaddr_in6 * ipv6_in =
195
87
      reinterpret_cast<const sockaddr_in6*>(ipv6.data());
196
197
87
  const uint8_t* ptr =
198
      reinterpret_cast<const uint8_t*>(&ipv6_in->sin6_addr);
199
200
87
  if (memcmp(ptr, mask, sizeof(mask)) != 0)
201
63
    return SocketAddress::CompareResult::NOT_COMPARABLE;
202
203
24
  int ret = memcmp(
204
24
      &ipv4_in->sin_addr,
205
24
      ptr + sizeof(mask),
206
      sizeof(uint32_t));
207
208
24
  if (ret < 0)
209
14
    return SocketAddress::CompareResult::LESS_THAN;
210
10
  else if (ret > 0)
211
4
    return SocketAddress::CompareResult::GREATER_THAN;
212
6
  return SocketAddress::CompareResult::SAME;
213
}
214
215
42
bool in_network_ipv4(
216
    const SocketAddress& ip,
217
    const SocketAddress& net,
218
    int prefix) {
219
42
  uint32_t mask = ((1ull << prefix) - 1) << (32 - prefix);
220
221
  const sockaddr_in* ip_in =
222
42
      reinterpret_cast<const sockaddr_in*>(ip.data());
223
  const sockaddr_in* net_in =
224
42
      reinterpret_cast<const sockaddr_in*>(net.data());
225
226
84
  return (htonl(ip_in->sin_addr.s_addr) & mask) ==
227
42
         (htonl(net_in->sin_addr.s_addr) & mask);
228
}
229
230
15
bool in_network_ipv6(
231
    const SocketAddress& ip,
232
    const SocketAddress& net,
233
    int prefix) {
234
  // Special case, if prefix == 128, then just do a
235
  // straight comparison.
236
15
  if (prefix == 128)
237
    return compare_ipv6(ip, net) == SocketAddress::CompareResult::SAME;
238
239
15
  uint8_t r = prefix % 8;
240
15
  int len = (prefix - r) / 8;
241
15
  uint8_t mask = ((1 << r) - 1) << (8 - r);
242
243
  const sockaddr_in6* ip_in =
244
15
      reinterpret_cast<const sockaddr_in6*>(ip.data());
245
  const sockaddr_in6* net_in =
246
15
      reinterpret_cast<const sockaddr_in6*>(net.data());
247
248
15
  if (memcmp(&ip_in->sin6_addr, &net_in->sin6_addr, len) != 0)
249
7
    return false;
250
251
8
  const uint8_t* p1 = reinterpret_cast<const uint8_t*>(
252
      ip_in->sin6_addr.s6_addr);
253
8
  const uint8_t* p2 = reinterpret_cast<const uint8_t*>(
254
      net_in->sin6_addr.s6_addr);
255
256
8
  return (p1[len] & mask) == (p2[len] & mask);
257
}
258
259
42
bool in_network_ipv4_ipv6(
260
    const SocketAddress& ip,
261
    const SocketAddress& net,
262
    int prefix) {
263
264
42
  if (prefix == 128)
265
    return compare_ipv4_ipv6(ip, net) == SocketAddress::CompareResult::SAME;
266
267
42
  uint8_t r = prefix % 8;
268
42
  int len = (prefix - r) / 8;
269
42
  uint8_t mask = ((1 << r) - 1) << (8 - r);
270
271
  const sockaddr_in* ip_in =
272
42
      reinterpret_cast<const sockaddr_in*>(ip.data());
273
  const sockaddr_in6* net_in =
274
42
      reinterpret_cast<const sockaddr_in6*>(net.data());
275
276
42
  uint8_t ip_mask[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0, 0, 0, 0};
277
42
  uint8_t* ptr = ip_mask;
278
42
  memcpy(ptr + 12, &ip_in->sin_addr, 4);
279
280
42
  if (memcmp(ptr, &net_in->sin6_addr, len) != 0)
281
42
    return false;
282
283
  ptr += len;
284
  const uint8_t* p2 = reinterpret_cast<const uint8_t*>(
285
      net_in->sin6_addr.s6_addr);
286
287
  return (ptr[0] & mask) == (p2[len] & mask);
288
}
289
290
5
bool in_network_ipv6_ipv4(
291
    const SocketAddress& ip,
292
    const SocketAddress& net,
293
    int prefix) {
294
5
  if (prefix == 32)
295
    return compare_ipv4_ipv6(net, ip) == SocketAddress::CompareResult::SAME;
296
297
5
  uint32_t m = ((1ull << prefix) - 1) << (32 - prefix);
298
299
  const sockaddr_in6* ip_in =
300
5
      reinterpret_cast<const sockaddr_in6*>(ip.data());
301
  const sockaddr_in* net_in =
302
5
      reinterpret_cast<const sockaddr_in*>(net.data());
303
304
5
  const uint8_t* ptr =
305
      reinterpret_cast<const uint8_t*>(&ip_in->sin6_addr);
306
307
5
  if (memcmp(ptr, mask, sizeof(mask)) != 0)
308
3
    return false;
309
310
2
  ptr += sizeof(mask);
311
2
  uint32_t check = ReadUint32BE(ptr);
312
313
2
  return (check & m) == (htonl(net_in->sin_addr.s_addr) & m);
314
}
315
}  // namespace
316
317
// TODO(@jasnell): The implementations of is_match, compare, and
318
// is_in_network have not been performance optimized and could
319
// likely benefit from work on more performant approaches.
320
321
81
bool SocketAddress::is_match(const SocketAddress& other) const {
322
81
  switch (family()) {
323
24
    case AF_INET:
324
24
      switch (other.family()) {
325
16
        case AF_INET: return is_match_ipv4(*this, other);
326
8
        case AF_INET6: return is_match_ipv4_ipv6(*this, other);
327
      }
328
      break;
329
57
    case AF_INET6:
330
57
      switch (other.family()) {
331
15
        case AF_INET: return is_match_ipv4_ipv6(other, *this);
332
42
        case AF_INET6: return is_match_ipv6(*this, other);
333
      }
334
      break;
335
  }
336
  return false;
337
}
338
339
6645
SocketAddress::CompareResult SocketAddress::compare(
340
    const SocketAddress& other) const {
341
6645
  switch (family()) {
342
6518
    case AF_INET:
343
6518
      switch (other.family()) {
344
6481
        case AF_INET: return compare_ipv4(*this, other);
345
37
        case AF_INET6: return compare_ipv4_ipv6(*this, other);
346
      }
347
      break;
348
127
    case AF_INET6:
349
127
      switch (other.family()) {
350
50
        case AF_INET: {
351
50
          CompareResult c = compare_ipv4_ipv6(other, *this);
352
          switch (c) {
353
36
            case SocketAddress::CompareResult::NOT_COMPARABLE:
354
              // Fall through
355
            case SocketAddress::CompareResult::SAME:
356
36
              return c;
357
3
            case SocketAddress::CompareResult::GREATER_THAN:
358
3
              return SocketAddress::CompareResult::LESS_THAN;
359
11
            case SocketAddress::CompareResult::LESS_THAN:
360
11
              return SocketAddress::CompareResult::GREATER_THAN;
361
          }
362
          break;
363
        }
364
77
        case AF_INET6: return compare_ipv6(*this, other);
365
      }
366
      break;
367
  }
368
  return SocketAddress::CompareResult::NOT_COMPARABLE;
369
}
370
371
104
bool SocketAddress::is_in_network(
372
    const SocketAddress& other,
373
    int prefix) const {
374
375
104
  switch (family()) {
376
84
    case AF_INET:
377
84
      switch (other.family()) {
378
42
        case AF_INET: return in_network_ipv4(*this, other, prefix);
379
42
        case AF_INET6: return in_network_ipv4_ipv6(*this, other, prefix);
380
      }
381
      break;
382
20
    case AF_INET6:
383
20
      switch (other.family()) {
384
5
        case AF_INET: return in_network_ipv6_ipv4(*this, other, prefix);
385
15
        case AF_INET6: return in_network_ipv6(*this, other, prefix);
386
      }
387
      break;
388
  }
389
390
  return false;
391
}
392
393
6399
SocketAddressBlockList::SocketAddressBlockList(
394
6399
    std::shared_ptr<SocketAddressBlockList> parent)
395
6399
    : parent_(parent) {}
396
397
6392
void SocketAddressBlockList::AddSocketAddress(
398
    const std::shared_ptr<SocketAddress>& address) {
399
12784
  Mutex::ScopedLock lock(mutex_);
400
  std::unique_ptr<Rule> rule =
401
6392
      std::make_unique<SocketAddressRule>(address);
402
6392
  rules_.emplace_front(std::move(rule));
403
6392
  address_rules_[*address.get()] = rules_.begin();
404
6392
}
405
406
1
void SocketAddressBlockList::RemoveSocketAddress(
407
    const std::shared_ptr<SocketAddress>& address) {
408
2
  Mutex::ScopedLock lock(mutex_);
409
1
  auto it = address_rules_.find(*address.get());
410
1
  if (it != std::end(address_rules_)) {
411
1
    rules_.erase(it->second);
412
1
    address_rules_.erase(it);
413
  }
414
1
}
415
416
6387
void SocketAddressBlockList::AddSocketAddressRange(
417
    const std::shared_ptr<SocketAddress>& start,
418
    const std::shared_ptr<SocketAddress>& end) {
419
12774
  Mutex::ScopedLock lock(mutex_);
420
  std::unique_ptr<Rule> rule =
421
12774
      std::make_unique<SocketAddressRangeRule>(start, end);
422
6387
  rules_.emplace_front(std::move(rule));
423
6387
}
424
425
8
void SocketAddressBlockList::AddSocketAddressMask(
426
    const std::shared_ptr<SocketAddress>& network,
427
    int prefix) {
428
16
  Mutex::ScopedLock lock(mutex_);
429
  std::unique_ptr<Rule> rule =
430
16
      std::make_unique<SocketAddressMaskRule>(network, prefix);
431
8
  rules_.emplace_front(std::move(rule));
432
8
}
433
434
191
bool SocketAddressBlockList::Apply(
435
    const std::shared_ptr<SocketAddress>& address) {
436
382
  Mutex::ScopedLock lock(mutex_);
437
358
  for (const auto& rule : rules_) {
438
325
    if (rule->Apply(address))
439
158
      return true;
440
  }
441
33
  return parent_ ? parent_->Apply(address) : false;
442
}
443
444
6392
SocketAddressBlockList::SocketAddressRule::SocketAddressRule(
445
6392
    const std::shared_ptr<SocketAddress>& address_)
446
6392
    : address(address_) {}
447
448
6387
SocketAddressBlockList::SocketAddressRangeRule::SocketAddressRangeRule(
449
    const std::shared_ptr<SocketAddress>& start_,
450
6387
    const std::shared_ptr<SocketAddress>& end_)
451
    : start(start_),
452
6387
      end(end_) {}
453
454
8
SocketAddressBlockList::SocketAddressMaskRule::SocketAddressMaskRule(
455
    const std::shared_ptr<SocketAddress>& network_,
456
8
    int prefix_)
457
    : network(network_),
458
8
      prefix(prefix_) {}
459
460
81
bool SocketAddressBlockList::SocketAddressRule::Apply(
461
    const std::shared_ptr<SocketAddress>& address) {
462
81
  return this->address->is_match(*address.get());
463
}
464
465
1
std::string SocketAddressBlockList::SocketAddressRule::ToString() {
466
1
  std::string ret = "Address: ";
467
1
  ret += address->family() == AF_INET ? "IPv4" : "IPv6";
468
1
  ret += " ";
469
1
  ret += address->address();
470
1
  return ret;
471
}
472
473
140
bool SocketAddressBlockList::SocketAddressRangeRule::Apply(
474
    const std::shared_ptr<SocketAddress>& address) {
475

218
  return *address.get() >= *start.get() &&
476
218
         *address.get() <= *end.get();
477
}
478
479
1
std::string SocketAddressBlockList::SocketAddressRangeRule::ToString() {
480
1
  std::string ret = "Range: ";
481
1
  ret += start->family() == AF_INET ? "IPv4" : "IPv6";
482
1
  ret += " ";
483
1
  ret += start->address();
484
1
  ret += "-";
485
1
  ret += end->address();
486
1
  return ret;
487
}
488
489
104
bool SocketAddressBlockList::SocketAddressMaskRule::Apply(
490
    const std::shared_ptr<SocketAddress>& address) {
491
104
  return address->is_in_network(*network.get(), prefix);
492
}
493
494
1
std::string SocketAddressBlockList::SocketAddressMaskRule::ToString() {
495
1
  std::string ret = "Subnet: ";
496
1
  ret += network->family() == AF_INET ? "IPv4" : "IPv6";
497
1
  ret += " ";
498
1
  ret += network->address();
499
1
  ret += "/" + std::to_string(prefix);
500
1
  return ret;
501
}
502
503
2
MaybeLocal<Array> SocketAddressBlockList::ListRules(Environment* env) {
504
4
  Mutex::ScopedLock lock(mutex_);
505
4
  std::vector<Local<Value>> rules;
506
2
  if (!ListRules(env, &rules))
507
    return MaybeLocal<Array>();
508
4
  return Array::New(env->isolate(), rules.data(), rules.size());
509
}
510
511
2
bool SocketAddressBlockList::ListRules(
512
    Environment* env,
513
    std::vector<v8::Local<v8::Value>>* rules) {
514

2
  if (parent_ && !parent_->ListRules(env, rules))
515
    return false;
516
5
  for (const auto& rule : rules_) {
517
    Local<Value> str;
518
6
    if (!rule->ToV8String(env).ToLocal(&str))
519
      return false;
520
3
    rules->push_back(str);
521
  }
522
2
  return true;
523
}
524
525
37
void SocketAddressBlockList::MemoryInfo(node::MemoryTracker* tracker) const {
526
37
  tracker->TrackField("rules", rules_);
527
37
}
528
529
37
void SocketAddressBlockList::SocketAddressRule::MemoryInfo(
530
    node::MemoryTracker* tracker) const {
531
37
  tracker->TrackField("address", address);
532
37
}
533
534
37
void SocketAddressBlockList::SocketAddressRangeRule::MemoryInfo(
535
    node::MemoryTracker* tracker) const {
536
37
  tracker->TrackField("start", start);
537
37
  tracker->TrackField("end", end);
538
37
}
539
540
void SocketAddressBlockList::SocketAddressMaskRule::MemoryInfo(
541
    node::MemoryTracker* tracker) const {
542
  tracker->TrackField("network", network);
543
}
544
545
6399
SocketAddressBlockListWrap::SocketAddressBlockListWrap(
546
    Environment* env,
547
    Local<Object> wrap,
548
6399
    std::shared_ptr<SocketAddressBlockList> blocklist)
549
    : BaseObject(env, wrap),
550
6399
      blocklist_(std::move(blocklist)) {
551
6399
  MakeWeak();
552
6399
}
553
554
BaseObjectPtr<SocketAddressBlockListWrap> SocketAddressBlockListWrap::New(
555
    Environment* env) {
556
  Local<Object> obj;
557
  if (!env->blocklist_constructor_template()
558
          ->InstanceTemplate()
559
          ->NewInstance(env->context()).ToLocal(&obj)) {
560
    return BaseObjectPtr<SocketAddressBlockListWrap>();
561
  }
562
  BaseObjectPtr<SocketAddressBlockListWrap> wrap =
563
      MakeBaseObject<SocketAddressBlockListWrap>(env, obj);
564
  CHECK(wrap);
565
  return wrap;
566
}
567
568
1
BaseObjectPtr<SocketAddressBlockListWrap> SocketAddressBlockListWrap::New(
569
    Environment* env,
570
    std::shared_ptr<SocketAddressBlockList> blocklist) {
571
  Local<Object> obj;
572
1
  if (!env->blocklist_constructor_template()
573
1
          ->InstanceTemplate()
574
2
          ->NewInstance(env->context()).ToLocal(&obj)) {
575
    return BaseObjectPtr<SocketAddressBlockListWrap>();
576
  }
577
  BaseObjectPtr<SocketAddressBlockListWrap> wrap =
578
      MakeBaseObject<SocketAddressBlockListWrap>(
579
          env,
580
          obj,
581
2
          std::move(blocklist));
582
1
  CHECK(wrap);
583
1
  return wrap;
584
}
585
586
6398
void SocketAddressBlockListWrap::New(
587
    const FunctionCallbackInfo<Value>& args) {
588
6398
  CHECK(args.IsConstructCall());
589
6398
  Environment* env = Environment::GetCurrent(args);
590
6398
  new SocketAddressBlockListWrap(env, args.This());
591
6398
}
592
593
6390
void SocketAddressBlockListWrap::AddAddress(
594
    const FunctionCallbackInfo<Value>& args) {
595
6390
  Environment* env = Environment::GetCurrent(args);
596
  SocketAddressBlockListWrap* wrap;
597
6390
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
598
599
6390
  CHECK(SocketAddressBase::HasInstance(env, args[0]));
600
  SocketAddressBase* addr;
601
6390
  ASSIGN_OR_RETURN_UNWRAP(&addr, args[0]);
602
603
6390
  wrap->blocklist_->AddSocketAddress(addr->address());
604
605
12780
  args.GetReturnValue().Set(true);
606
}
607
608
6388
void SocketAddressBlockListWrap::AddRange(
609
    const FunctionCallbackInfo<Value>& args) {
610
6388
  Environment* env = Environment::GetCurrent(args);
611
  SocketAddressBlockListWrap* wrap;
612
6389
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
613
614
6388
  CHECK(SocketAddressBase::HasInstance(env, args[0]));
615
6388
  CHECK(SocketAddressBase::HasInstance(env, args[1]));
616
617
  SocketAddressBase* start_addr;
618
  SocketAddressBase* end_addr;
619
6388
  ASSIGN_OR_RETURN_UNWRAP(&start_addr, args[0]);
620
6388
  ASSIGN_OR_RETURN_UNWRAP(&end_addr, args[1]);
621
622
  // Starting address must come before the end address
623
6388
  if (*start_addr->address().get() > *end_addr->address().get())
624
2
    return args.GetReturnValue().Set(false);
625
626
6387
  wrap->blocklist_->AddSocketAddressRange(
627
      start_addr->address(),
628
      end_addr->address());
629
630
12774
  args.GetReturnValue().Set(true);
631
}
632
633
8
void SocketAddressBlockListWrap::AddSubnet(
634
    const FunctionCallbackInfo<Value>& args) {
635
8
  Environment* env = Environment::GetCurrent(args);
636
  SocketAddressBlockListWrap* wrap;
637
8
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
638
639
8
  CHECK(SocketAddressBase::HasInstance(env, args[0]));
640
8
  CHECK(args[1]->IsInt32());
641
642
  SocketAddressBase* addr;
643
8
  ASSIGN_OR_RETURN_UNWRAP(&addr, args[0]);
644
645
  int32_t prefix;
646
16
  if (!args[1]->Int32Value(env->context()).To(&prefix)) {
647
    return;
648
  }
649
650

8
  CHECK_IMPLIES(addr->address()->family() == AF_INET, prefix <= 32);
651

8
  CHECK_IMPLIES(addr->address()->family() == AF_INET6, prefix <= 128);
652
8
  CHECK_GE(prefix, 0);
653
654
8
  wrap->blocklist_->AddSocketAddressMask(addr->address(), prefix);
655
656
16
  args.GetReturnValue().Set(true);
657
}
658
659
187
void SocketAddressBlockListWrap::Check(
660
    const FunctionCallbackInfo<Value>& args) {
661
187
  Environment* env = Environment::GetCurrent(args);
662
  SocketAddressBlockListWrap* wrap;
663
187
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
664
665
187
  CHECK(SocketAddressBase::HasInstance(env, args[0]));
666
  SocketAddressBase* addr;
667
187
  ASSIGN_OR_RETURN_UNWRAP(&addr, args[0]);
668
669
374
  args.GetReturnValue().Set(wrap->blocklist_->Apply(addr->address()));
670
}
671
672
2
void SocketAddressBlockListWrap::GetRules(
673
    const FunctionCallbackInfo<Value>& args) {
674
2
  Environment* env = Environment::GetCurrent(args);
675
  SocketAddressBlockListWrap* wrap;
676
2
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
677
  Local<Array> rules;
678
4
  if (wrap->blocklist_->ListRules(env).ToLocal(&rules))
679
4
    args.GetReturnValue().Set(rules);
680
}
681
682
37
void SocketAddressBlockListWrap::MemoryInfo(MemoryTracker* tracker) const {
683
37
  blocklist_->MemoryInfo(tracker);
684
37
}
685
686
std::unique_ptr<worker::TransferData>
687
1
SocketAddressBlockListWrap::CloneForMessaging() const {
688
1
  return std::make_unique<TransferData>(this);
689
}
690
691
bool SocketAddressBlockListWrap::HasInstance(
692
    Environment* env,
693
    Local<Value> value) {
694
  return GetConstructorTemplate(env)->HasInstance(value);
695
}
696
697
6381
Local<FunctionTemplate> SocketAddressBlockListWrap::GetConstructorTemplate(
698
    Environment* env) {
699
6381
  Local<FunctionTemplate> tmpl = env->blocklist_constructor_template();
700
6381
  if (tmpl.IsEmpty()) {
701
6381
    Isolate* isolate = env->isolate();
702
6381
    tmpl = NewFunctionTemplate(isolate, SocketAddressBlockListWrap::New);
703
6381
    tmpl->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "BlockList"));
704
6381
    tmpl->Inherit(BaseObject::GetConstructorTemplate(env));
705
12762
    tmpl->InstanceTemplate()->SetInternalFieldCount(kInternalFieldCount);
706
6381
    SetProtoMethod(isolate, tmpl, "addAddress", AddAddress);
707
6381
    SetProtoMethod(isolate, tmpl, "addRange", AddRange);
708
6381
    SetProtoMethod(isolate, tmpl, "addSubnet", AddSubnet);
709
6381
    SetProtoMethod(isolate, tmpl, "check", Check);
710
6381
    SetProtoMethod(isolate, tmpl, "getRules", GetRules);
711
6381
    env->set_blocklist_constructor_template(tmpl);
712
  }
713
6381
  return tmpl;
714
}
715
716
6381
void SocketAddressBlockListWrap::Initialize(
717
    Local<Object> target,
718
    Local<Value> unused,
719
    Local<Context> context,
720
    void* priv) {
721
6381
  Environment* env = Environment::GetCurrent(context);
722
723
6381
  SetConstructorFunction(context,
724
                         target,
725
                         "BlockList",
726
                         GetConstructorTemplate(env),
727
                         SetConstructorFunctionFlag::NONE);
728
729
6381
  SocketAddressBase::Initialize(env, target);
730
731
19143
  NODE_DEFINE_CONSTANT(target, AF_INET);
732
12762
  NODE_DEFINE_CONSTANT(target, AF_INET6);
733
6381
}
734
735
1
BaseObjectPtr<BaseObject> SocketAddressBlockListWrap::TransferData::Deserialize(
736
    Environment* env,
737
    Local<Context> context,
738
    std::unique_ptr<worker::TransferData> self) {
739
1
  return New(env, std::move(blocklist_));
740
}
741
742
void SocketAddressBlockListWrap::TransferData::MemoryInfo(
743
    MemoryTracker* tracker) const {
744
  blocklist_->MemoryInfo(tracker);
745
}
746
747
19361
bool SocketAddressBase::HasInstance(Environment* env, Local<Value> value) {
748
38722
  return GetConstructorTemplate(env)->HasInstance(value);
749
}
750
751
25743
Local<FunctionTemplate> SocketAddressBase::GetConstructorTemplate(
752
    Environment* env) {
753
25743
  Local<FunctionTemplate> tmpl = env->socketaddress_constructor_template();
754
25743
  if (tmpl.IsEmpty()) {
755
6381
    Isolate* isolate = env->isolate();
756
6381
    tmpl = NewFunctionTemplate(isolate, New);
757
6381
    tmpl->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "SocketAddress"));
758
12762
    tmpl->InstanceTemplate()->SetInternalFieldCount(
759
        SocketAddressBase::kInternalFieldCount);
760
6381
    tmpl->Inherit(BaseObject::GetConstructorTemplate(env));
761
6381
    SetProtoMethod(isolate, tmpl, "detail", Detail);
762
6381
    SetProtoMethod(isolate, tmpl, "legacyDetail", LegacyDetail);
763
6381
    SetProtoMethodNoSideEffect(isolate, tmpl, "flowlabel", GetFlowLabel);
764
6381
    env->set_socketaddress_constructor_template(tmpl);
765
  }
766
25743
  return tmpl;
767
}
768
769
6381
void SocketAddressBase::Initialize(Environment* env, Local<Object> target) {
770
6381
  SetConstructorFunction(env->context(),
771
                         target,
772
                         "SocketAddress",
773
                         GetConstructorTemplate(env),
774
                         SetConstructorFunctionFlag::NONE);
775
6381
}
776
777
1
BaseObjectPtr<SocketAddressBase> SocketAddressBase::Create(
778
    Environment* env,
779
    std::shared_ptr<SocketAddress> address) {
780
  Local<Object> obj;
781
1
  if (!GetConstructorTemplate(env)
782
1
          ->InstanceTemplate()
783
2
          ->NewInstance(env->context()).ToLocal(&obj)) {
784
    return BaseObjectPtr<SocketAddressBase>();
785
  }
786
787
1
  return MakeBaseObject<SocketAddressBase>(env, obj, std::move(address));
788
}
789
790
19383
void SocketAddressBase::New(const FunctionCallbackInfo<Value>& args) {
791
19383
  Environment* env = Environment::GetCurrent(args);
792
19383
  CHECK(args.IsConstructCall());
793
38766
  CHECK(args[0]->IsString());  // address
794
19383
  CHECK(args[1]->IsInt32());  // port
795
19383
  CHECK(args[2]->IsInt32());  // family
796
19383
  CHECK(args[3]->IsUint32());  // flow label
797
798
19383
  Utf8Value address(env->isolate(), args[0]);
799
38766
  int32_t port = args[1].As<Int32>()->Value();
800
38766
  int32_t family = args[2].As<Int32>()->Value();
801
38766
  uint32_t flow_label = args[3].As<Uint32>()->Value();
802
803
19383
  std::shared_ptr<SocketAddress> addr = std::make_shared<SocketAddress>();
804
805
19383
  if (!SocketAddress::New(family, *address, port, addr.get()))
806
4
    return THROW_ERR_INVALID_ADDRESS(env);
807
808
19379
  addr->set_flow_label(flow_label);
809
810
19379
  new SocketAddressBase(env, args.This(), std::move(addr));
811
}
812
813
19380
void SocketAddressBase::Detail(const FunctionCallbackInfo<Value>& args) {
814
19380
  Environment* env = Environment::GetCurrent(args);
815
19380
  CHECK(args[0]->IsObject());
816
38760
  Local<Object> detail = args[0].As<Object>();
817
818
  SocketAddressBase* base;
819
19380
  ASSIGN_OR_RETURN_UNWRAP(&base, args.Holder());
820
821
  Local<Value> address;
822
38760
  if (!ToV8Value(env->context(), base->address_->address()).ToLocal(&address))
823
    return;
824
825
38760
  if (detail->Set(env->context(), env->address_string(), address).IsJust() &&
826
19380
      detail->Set(
827
          env->context(),
828
          env->port_string(),
829
77520
          Int32::New(env->isolate(), base->address_->port())).IsJust() &&
830
19380
      detail->Set(
831
          env->context(),
832
          env->family_string(),
833

116280
          Int32::New(env->isolate(), base->address_->family())).IsJust() &&
834
19380
      detail->Set(
835
          env->context(),
836
          env->flowlabel_string(),
837
77520
          Uint32::New(env->isolate(), base->address_->flow_label()))
838
19380
              .IsJust()) {
839
38760
    args.GetReturnValue().Set(detail);
840
  }
841
}
842
843
9
void SocketAddressBase::GetFlowLabel(const FunctionCallbackInfo<Value>& args) {
844
  SocketAddressBase* base;
845
9
  ASSIGN_OR_RETURN_UNWRAP(&base, args.Holder());
846
18
  args.GetReturnValue().Set(base->address_->flow_label());
847
}
848
849
void SocketAddressBase::LegacyDetail(const FunctionCallbackInfo<Value>& args) {
850
  Environment* env = Environment::GetCurrent(args);
851
  SocketAddressBase* base;
852
  ASSIGN_OR_RETURN_UNWRAP(&base, args.Holder());
853
  Local<Object> address;
854
  if (!base->address_->ToJS(env).ToLocal(&address)) return;
855
  args.GetReturnValue().Set(address);
856
}
857
858
19380
SocketAddressBase::SocketAddressBase(
859
    Environment* env,
860
    Local<Object> wrap,
861
19380
    std::shared_ptr<SocketAddress> address)
862
    : BaseObject(env, wrap),
863
19380
      address_(std::move(address)) {
864
19380
  MakeWeak();
865
19380
}
866
867
void SocketAddressBase::MemoryInfo(MemoryTracker* tracker) const {
868
  tracker->TrackField("address", address_);
869
}
870
871
std::unique_ptr<worker::TransferData>
872
1
SocketAddressBase::CloneForMessaging() const {
873
1
  return std::make_unique<TransferData>(this);
874
}
875
876
void SocketAddressBase::TransferData::MemoryInfo(MemoryTracker* tracker) const {
877
  tracker->TrackField("address", address_);
878
}
879
880
1
BaseObjectPtr<BaseObject> SocketAddressBase::TransferData::Deserialize(
881
    Environment* env,
882
    v8::Local<v8::Context> context,
883
    std::unique_ptr<worker::TransferData> self) {
884
1
  return SocketAddressBase::Create(env, std::move(address_));
885
}
886
887
}  // namespace node
888
889
5710
NODE_BINDING_CONTEXT_AWARE_INTERNAL(
890
    block_list, node::SocketAddressBlockListWrap::Initialize)