GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: node_sockaddr.cc Lines: 380 455 83.5 %
Date: 2021-08-24 04:12:49 Branches: 115 197 58.4 %

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

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

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

7
  CHECK_IMPLIES(addr->address()->family() == AF_INET, prefix <= 32);
650

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

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