GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: node_sockaddr.cc Lines: 393 460 85.4 %
Date: 2022-04-05 04:14:57 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::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
16939
bool SocketAddress::ToSockAddr(
40
    int32_t family,
41
    const char* host,
42
    uint32_t port,
43
    sockaddr_storage* addr) {
44
16939
  switch (family) {
45
11267
    case AF_INET:
46
11267
      return uv_ip4_addr(
47
          host,
48
          port,
49
11267
          reinterpret_cast<sockaddr_in*>(addr)) == 0;
50
5672
    case AF_INET6:
51
5672
      return uv_ip6_addr(
52
          host,
53
          port,
54
5672
          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
16924
bool SocketAddress::New(
68
    int32_t family,
69
    const char* host,
70
    uint32_t port,
71
    SocketAddress* addr) {
72
16924
  return ToSockAddr(family, host, port,
73
33848
                    reinterpret_cast<sockaddr_storage*>(addr->storage()));
74
}
75
76
5605
size_t SocketAddress::Hash::operator()(const SocketAddress& addr) const {
77
5605
  size_t hash = 0;
78
5605
  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
5567
    case AF_INET6: {
86
      const sockaddr_in6* ipv6 =
87
5567
          reinterpret_cast<const sockaddr_in6*>(addr.raw());
88
5567
      const uint64_t* a =
89
          reinterpret_cast<const uint64_t*>(&ipv6->sin6_addr);
90
5567
      hash_combine(&hash, ipv6->sin6_port, a[0], a[1]);
91
5567
      break;
92
    }
93
    default:
94
      UNREACHABLE();
95
  }
96
5605
  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
42
bool is_match_ipv6(
129
    const SocketAddress& one,
130
    const SocketAddress& two) {
131
  const sockaddr_in6* one_in =
132
42
      reinterpret_cast<const sockaddr_in6*>(one.data());
133
  const sockaddr_in6* two_in =
134
42
      reinterpret_cast<const sockaddr_in6*>(two.data());
135
42
  return memcmp(&one_in->sin6_addr, &two_in->sin6_addr, 16) == 0;
136
}
137
138
23
bool is_match_ipv4_ipv6(
139
    const SocketAddress& ipv4,
140
    const SocketAddress& ipv6) {
141
  const sockaddr_in* check_ipv4 =
142
23
      reinterpret_cast<const sockaddr_in*>(ipv4.data());
143
  const sockaddr_in6* check_ipv6 =
144
23
      reinterpret_cast<const sockaddr_in6*>(ipv6.data());
145
146
23
  const uint8_t* ptr =
147
      reinterpret_cast<const uint8_t*>(&check_ipv6->sin6_addr);
148
149
36
  return memcmp(ptr, mask, sizeof(mask)) == 0 &&
150
13
         memcmp(ptr + sizeof(mask),
151
13
                &check_ipv4->sin_addr,
152
23
                sizeof(uint32_t)) == 0;
153
}
154
155
5663
SocketAddress::CompareResult compare_ipv4(
156
    const SocketAddress& one,
157
    const SocketAddress& two) {
158
  const sockaddr_in* one_in =
159
5663
      reinterpret_cast<const sockaddr_in*>(one.data());
160
  const sockaddr_in* two_in =
161
5663
      reinterpret_cast<const sockaddr_in*>(two.data());
162
5663
  const uint32_t s_addr_one = ntohl(one_in->sin_addr.s_addr);
163
5663
  const uint32_t s_addr_two = ntohl(two_in->sin_addr.s_addr);
164
165
5663
  if (s_addr_one < s_addr_two)
166
5608
    return SocketAddress::CompareResult::LESS_THAN;
167
55
  else if (s_addr_one == s_addr_two)
168
21
    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
87
SocketAddress::CompareResult compare_ipv4_ipv6(
189
    const SocketAddress& ipv4,
190
    const SocketAddress& ipv6) {
191
  const sockaddr_in* ipv4_in =
192
87
      reinterpret_cast<const sockaddr_in*>(ipv4.data());
193
  const sockaddr_in6 * ipv6_in =
194
87
      reinterpret_cast<const sockaddr_in6*>(ipv6.data());
195
196
87
  const uint8_t* ptr =
197
      reinterpret_cast<const uint8_t*>(&ipv6_in->sin6_addr);
198
199
87
  if (memcmp(ptr, mask, sizeof(mask)) != 0)
200
63
    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
81
bool SocketAddress::is_match(const SocketAddress& other) const {
321
81
  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
57
    case AF_INET6:
329
57
      switch (other.family()) {
330
15
        case AF_INET: return is_match_ipv4_ipv6(other, *this);
331
42
        case AF_INET6: return is_match_ipv6(*this, other);
332
      }
333
      break;
334
  }
335
  return false;
336
}
337
338
5827
SocketAddress::CompareResult SocketAddress::compare(
339
    const SocketAddress& other) const {
340
5827
  switch (family()) {
341
5700
    case AF_INET:
342
5700
      switch (other.family()) {
343
5663
        case AF_INET: return compare_ipv4(*this, other);
344
37
        case AF_INET6: return compare_ipv4_ipv6(*this, other);
345
      }
346
      break;
347
127
    case AF_INET6:
348
127
      switch (other.family()) {
349
50
        case AF_INET: {
350
50
          CompareResult c = compare_ipv4_ipv6(other, *this);
351
          switch (c) {
352
36
            case SocketAddress::CompareResult::NOT_COMPARABLE:
353
              // Fall through
354
            case SocketAddress::CompareResult::SAME:
355
36
              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
5580
SocketAddressBlockList::SocketAddressBlockList(
393
5580
    std::shared_ptr<SocketAddressBlockList> parent)
394
5580
    : parent_(parent) {}
395
396
5574
void SocketAddressBlockList::AddSocketAddress(
397
    const std::shared_ptr<SocketAddress>& address) {
398
11148
  Mutex::ScopedLock lock(mutex_);
399
  std::unique_ptr<Rule> rule =
400
5574
      std::make_unique<SocketAddressRule>(address);
401
5574
  rules_.emplace_front(std::move(rule));
402
5574
  address_rules_[*address.get()] = rules_.begin();
403
5574
}
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
5569
void SocketAddressBlockList::AddSocketAddressRange(
416
    const std::shared_ptr<SocketAddress>& start,
417
    const std::shared_ptr<SocketAddress>& end) {
418
11138
  Mutex::ScopedLock lock(mutex_);
419
  std::unique_ptr<Rule> rule =
420
11138
      std::make_unique<SocketAddressRangeRule>(start, end);
421
5569
  rules_.emplace_front(std::move(rule));
422
5569
}
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
188
bool SocketAddressBlockList::Apply(
434
    const std::shared_ptr<SocketAddress>& address) {
435
376
  Mutex::ScopedLock lock(mutex_);
436
353
  for (const auto& rule : rules_) {
437
322
    if (rule->Apply(address))
438
157
      return true;
439
  }
440
31
  return parent_ ? parent_->Apply(address) : false;
441
}
442
443
5574
SocketAddressBlockList::SocketAddressRule::SocketAddressRule(
444
5574
    const std::shared_ptr<SocketAddress>& address_)
445
5574
    : address(address_) {}
446
447
5569
SocketAddressBlockList::SocketAddressRangeRule::SocketAddressRangeRule(
448
    const std::shared_ptr<SocketAddress>& start_,
449
5569
    const std::shared_ptr<SocketAddress>& end_)
450
    : start(start_),
451
5569
      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
81
bool SocketAddressBlockList::SocketAddressRule::Apply(
460
    const std::shared_ptr<SocketAddress>& address) {
461
81
  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
140
bool SocketAddressBlockList::SocketAddressRangeRule::Apply(
473
    const std::shared_ptr<SocketAddress>& address) {
474

218
  return *address.get() >= *start.get() &&
475
218
         *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
23
void SocketAddressBlockList::MemoryInfo(node::MemoryTracker* tracker) const {
525
23
  tracker->TrackField("rules", rules_);
526
23
}
527
528
23
void SocketAddressBlockList::SocketAddressRule::MemoryInfo(
529
    node::MemoryTracker* tracker) const {
530
23
  tracker->TrackField("address", address);
531
23
}
532
533
23
void SocketAddressBlockList::SocketAddressRangeRule::MemoryInfo(
534
    node::MemoryTracker* tracker) const {
535
23
  tracker->TrackField("start", start);
536
23
  tracker->TrackField("end", end);
537
23
}
538
539
void SocketAddressBlockList::SocketAddressMaskRule::MemoryInfo(
540
    node::MemoryTracker* tracker) const {
541
  tracker->TrackField("network", network);
542
}
543
544
5580
SocketAddressBlockListWrap::SocketAddressBlockListWrap(
545
    Environment* env,
546
    Local<Object> wrap,
547
5580
    std::shared_ptr<SocketAddressBlockList> blocklist)
548
    : BaseObject(env, wrap),
549
5580
      blocklist_(std::move(blocklist)) {
550
5580
  MakeWeak();
551
5580
}
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
5579
void SocketAddressBlockListWrap::New(
586
    const FunctionCallbackInfo<Value>& args) {
587
5579
  CHECK(args.IsConstructCall());
588
5579
  Environment* env = Environment::GetCurrent(args);
589
5579
  new SocketAddressBlockListWrap(env, args.This());
590
5579
}
591
592
5572
void SocketAddressBlockListWrap::AddAddress(
593
    const FunctionCallbackInfo<Value>& args) {
594
5572
  Environment* env = Environment::GetCurrent(args);
595
  SocketAddressBlockListWrap* wrap;
596
5572
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
597
598
5572
  CHECK(SocketAddressBase::HasInstance(env, args[0]));
599
  SocketAddressBase* addr;
600
5572
  ASSIGN_OR_RETURN_UNWRAP(&addr, args[0]);
601
602
5572
  wrap->blocklist_->AddSocketAddress(addr->address());
603
604
11144
  args.GetReturnValue().Set(true);
605
}
606
607
5570
void SocketAddressBlockListWrap::AddRange(
608
    const FunctionCallbackInfo<Value>& args) {
609
5570
  Environment* env = Environment::GetCurrent(args);
610
  SocketAddressBlockListWrap* wrap;
611
5571
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
612
613
5570
  CHECK(SocketAddressBase::HasInstance(env, args[0]));
614
5570
  CHECK(SocketAddressBase::HasInstance(env, args[1]));
615
616
  SocketAddressBase* start_addr;
617
  SocketAddressBase* end_addr;
618
5570
  ASSIGN_OR_RETURN_UNWRAP(&start_addr, args[0]);
619
5570
  ASSIGN_OR_RETURN_UNWRAP(&end_addr, args[1]);
620
621
  // Starting address must come before the end address
622
5570
  if (*start_addr->address().get() > *end_addr->address().get())
623
2
    return args.GetReturnValue().Set(false);
624
625
5569
  wrap->blocklist_->AddSocketAddressRange(
626
      start_addr->address(),
627
      end_addr->address());
628
629
11138
  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
184
void SocketAddressBlockListWrap::Check(
659
    const FunctionCallbackInfo<Value>& args) {
660
184
  Environment* env = Environment::GetCurrent(args);
661
  SocketAddressBlockListWrap* wrap;
662
184
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
663
664
184
  CHECK(SocketAddressBase::HasInstance(env, args[0]));
665
  SocketAddressBase* addr;
666
184
  ASSIGN_OR_RETURN_UNWRAP(&addr, args[0]);
667
668
368
  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
23
void SocketAddressBlockListWrap::MemoryInfo(MemoryTracker* tracker) const {
682
23
  blocklist_->MemoryInfo(tracker);
683
23
}
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
5563
Local<FunctionTemplate> SocketAddressBlockListWrap::GetConstructorTemplate(
697
    Environment* env) {
698
5563
  Local<FunctionTemplate> tmpl = env->blocklist_constructor_template();
699
5563
  if (tmpl.IsEmpty()) {
700
5563
    tmpl = env->NewFunctionTemplate(SocketAddressBlockListWrap::New);
701
5563
    tmpl->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "BlockList"));
702
5563
    tmpl->Inherit(BaseObject::GetConstructorTemplate(env));
703
11126
    tmpl->InstanceTemplate()->SetInternalFieldCount(kInternalFieldCount);
704
5563
    env->SetProtoMethod(tmpl, "addAddress", AddAddress);
705
5563
    env->SetProtoMethod(tmpl, "addRange", AddRange);
706
5563
    env->SetProtoMethod(tmpl, "addSubnet", AddSubnet);
707
5563
    env->SetProtoMethod(tmpl, "check", Check);
708
5563
    env->SetProtoMethod(tmpl, "getRules", GetRules);
709
5563
    env->set_blocklist_constructor_template(tmpl);
710
  }
711
5563
  return tmpl;
712
}
713
714
5563
void SocketAddressBlockListWrap::Initialize(
715
    Local<Object> target,
716
    Local<Value> unused,
717
    Local<Context> context,
718
    void* priv) {
719
5563
  Environment* env = Environment::GetCurrent(context);
720
721
5563
  env->SetConstructorFunction(
722
      target,
723
      "BlockList",
724
      GetConstructorTemplate(env),
725
      Environment::SetConstructorFunctionFlag::NONE);
726
727
5563
  SocketAddressBase::Initialize(env, target);
728
729
16689
  NODE_DEFINE_CONSTANT(target, AF_INET);
730
11126
  NODE_DEFINE_CONSTANT(target, AF_INET6);
731
5563
}
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
16903
bool SocketAddressBase::HasInstance(Environment* env, Local<Value> value) {
746
33806
  return GetConstructorTemplate(env)->HasInstance(value);
747
}
748
749
22467
Local<FunctionTemplate> SocketAddressBase::GetConstructorTemplate(
750
    Environment* env) {
751
22467
  Local<FunctionTemplate> tmpl = env->socketaddress_constructor_template();
752
22467
  if (tmpl.IsEmpty()) {
753
5563
    tmpl = env->NewFunctionTemplate(New);
754
5563
    tmpl->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "SocketAddress"));
755
11126
    tmpl->InstanceTemplate()->SetInternalFieldCount(
756
        SocketAddressBase::kInternalFieldCount);
757
5563
    tmpl->Inherit(BaseObject::GetConstructorTemplate(env));
758
5563
    env->SetProtoMethod(tmpl, "detail", Detail);
759
5563
    env->SetProtoMethod(tmpl, "legacyDetail", LegacyDetail);
760
5563
    env->SetProtoMethodNoSideEffect(tmpl, "flowlabel", GetFlowLabel);
761
5563
    env->set_socketaddress_constructor_template(tmpl);
762
  }
763
22467
  return tmpl;
764
}
765
766
5563
void SocketAddressBase::Initialize(Environment* env, Local<Object> target) {
767
5563
  env->SetConstructorFunction(
768
      target,
769
      "SocketAddress",
770
      GetConstructorTemplate(env),
771
      Environment::SetConstructorFunctionFlag::NONE);
772
5563
}
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
16924
void SocketAddressBase::New(const FunctionCallbackInfo<Value>& args) {
788
16924
  Environment* env = Environment::GetCurrent(args);
789
16924
  CHECK(args.IsConstructCall());
790
33848
  CHECK(args[0]->IsString());  // address
791
16924
  CHECK(args[1]->IsInt32());  // port
792
16924
  CHECK(args[2]->IsInt32());  // family
793
16924
  CHECK(args[3]->IsUint32());  // flow label
794
795
16924
  Utf8Value address(env->isolate(), args[0]);
796
33848
  int32_t port = args[1].As<Int32>()->Value();
797
33848
  int32_t family = args[2].As<Int32>()->Value();
798
33848
  uint32_t flow_label = args[3].As<Uint32>()->Value();
799
800
16924
  std::shared_ptr<SocketAddress> addr = std::make_shared<SocketAddress>();
801
802
16924
  if (!SocketAddress::New(family, *address, port, addr.get()))
803
4
    return THROW_ERR_INVALID_ADDRESS(env);
804
805
16920
  addr->set_flow_label(flow_label);
806
807
16920
  new SocketAddressBase(env, args.This(), std::move(addr));
808
}
809
810
16921
void SocketAddressBase::Detail(const FunctionCallbackInfo<Value>& args) {
811
16921
  Environment* env = Environment::GetCurrent(args);
812
16921
  CHECK(args[0]->IsObject());
813
33842
  Local<Object> detail = args[0].As<Object>();
814
815
  SocketAddressBase* base;
816
16921
  ASSIGN_OR_RETURN_UNWRAP(&base, args.Holder());
817
818
  Local<Value> address;
819
33842
  if (!ToV8Value(env->context(), base->address_->address()).ToLocal(&address))
820
    return;
821
822
33842
  if (detail->Set(env->context(), env->address_string(), address).IsJust() &&
823
16921
      detail->Set(
824
          env->context(),
825
          env->port_string(),
826
67684
          Int32::New(env->isolate(), base->address_->port())).IsJust() &&
827
16921
      detail->Set(
828
          env->context(),
829
          env->family_string(),
830

101526
          Int32::New(env->isolate(), base->address_->family())).IsJust() &&
831
16921
      detail->Set(
832
          env->context(),
833
          env->flowlabel_string(),
834
67684
          Uint32::New(env->isolate(), base->address_->flow_label()))
835
16921
              .IsJust()) {
836
33842
    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
  Local<Object> address;
851
  if (!base->address_->ToJS(env).ToLocal(&address)) return;
852
  args.GetReturnValue().Set(address);
853
}
854
855
16921
SocketAddressBase::SocketAddressBase(
856
    Environment* env,
857
    Local<Object> wrap,
858
16921
    std::shared_ptr<SocketAddress> address)
859
    : BaseObject(env, wrap),
860
16921
      address_(std::move(address)) {
861
16921
  MakeWeak();
862
16921
}
863
864
void SocketAddressBase::MemoryInfo(MemoryTracker* tracker) const {
865
  tracker->TrackField("address", address_);
866
}
867
868
std::unique_ptr<worker::TransferData>
869
1
SocketAddressBase::CloneForMessaging() const {
870
1
  return std::make_unique<TransferData>(this);
871
}
872
873
void SocketAddressBase::TransferData::MemoryInfo(MemoryTracker* tracker) const {
874
  tracker->TrackField("address", address_);
875
}
876
877
1
BaseObjectPtr<BaseObject> SocketAddressBase::TransferData::Deserialize(
878
    Environment* env,
879
    v8::Local<v8::Context> context,
880
    std::unique_ptr<worker::TransferData> self) {
881
1
  return SocketAddressBase::Create(env, std::move(address_));
882
}
883
884
}  // namespace node
885
886
5042
NODE_MODULE_CONTEXT_AWARE_INTERNAL(
887
    block_list,
888
    node::SocketAddressBlockListWrap::Initialize)