GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/node_sockaddr.cc Lines: 290 352 82.4 %
Date: 2020-11-21 04:10:54 Branches: 115 193 59.6 %

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 "uv.h"
7
8
#include <memory>
9
#include <string>
10
#include <vector>
11
12
namespace node {
13
14
using v8::Array;
15
using v8::Context;
16
using v8::FunctionCallbackInfo;
17
using v8::FunctionTemplate;
18
using v8::Local;
19
using v8::MaybeLocal;
20
using v8::Object;
21
using v8::String;
22
using v8::Value;
23
24
namespace {
25
template <typename T, typename F>
26
SocketAddress FromUVHandle(F fn, const T& handle) {
27
  SocketAddress addr;
28
  int len = sizeof(sockaddr_storage);
29
  if (fn(&handle, addr.storage(), &len) == 0)
30
    CHECK_EQ(static_cast<size_t>(len), addr.length());
31
  else
32
    addr.storage()->sa_family = 0;
33
  return addr;
34
}
35
}  // namespace
36
37
118
bool SocketAddress::ToSockAddr(
38
    int32_t family,
39
    const char* host,
40
    uint32_t port,
41
    sockaddr_storage* addr) {
42
118
  switch (family) {
43
    case AF_INET:
44
73
      return uv_ip4_addr(
45
          host,
46
          port,
47
73
          reinterpret_cast<sockaddr_in*>(addr)) == 0;
48
    case AF_INET6:
49
45
      return uv_ip6_addr(
50
          host,
51
          port,
52
45
          reinterpret_cast<sockaddr_in6*>(addr)) == 0;
53
    default:
54
      UNREACHABLE();
55
  }
56
}
57
58
bool SocketAddress::New(
59
    const char* host,
60
    uint32_t port,
61
    SocketAddress* addr) {
62
  return New(AF_INET, host, port, addr) || New(AF_INET6, host, port, addr);
63
}
64
65
bool SocketAddress::New(
66
    int32_t family,
67
    const char* host,
68
    uint32_t port,
69
    SocketAddress* addr) {
70
  return ToSockAddr(family, host, port,
71
                    reinterpret_cast<sockaddr_storage*>(addr->storage()));
72
}
73
74
37
size_t SocketAddress::Hash::operator()(const SocketAddress& addr) const {
75
37
  size_t hash = 0;
76
37
  switch (addr.family()) {
77
    case AF_INET: {
78
      const sockaddr_in* ipv4 =
79
35
          reinterpret_cast<const sockaddr_in*>(addr.raw());
80
35
      hash_combine(&hash, ipv4->sin_port, ipv4->sin_addr.s_addr);
81
35
      break;
82
    }
83
    case AF_INET6: {
84
      const sockaddr_in6* ipv6 =
85
2
          reinterpret_cast<const sockaddr_in6*>(addr.raw());
86
      const uint64_t* a =
87
2
          reinterpret_cast<const uint64_t*>(&ipv6->sin6_addr);
88
2
      hash_combine(&hash, ipv6->sin6_port, a[0], a[1]);
89
2
      break;
90
    }
91
    default:
92
      UNREACHABLE();
93
  }
94
37
  return hash;
95
}
96
97
SocketAddress SocketAddress::FromSockName(const uv_tcp_t& handle) {
98
  return FromUVHandle(uv_tcp_getsockname, handle);
99
}
100
101
SocketAddress SocketAddress::FromSockName(const uv_udp_t& handle) {
102
  return FromUVHandle(uv_udp_getsockname, handle);
103
}
104
105
SocketAddress SocketAddress::FromPeerName(const uv_tcp_t& handle) {
106
  return FromUVHandle(uv_tcp_getpeername, handle);
107
}
108
109
SocketAddress SocketAddress::FromPeerName(const uv_udp_t& handle) {
110
  return FromUVHandle(uv_udp_getpeername, handle);
111
}
112
113
namespace {
114
constexpr uint8_t mask[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
115
116
8
bool is_match_ipv4(
117
    const SocketAddress& one,
118
    const SocketAddress& two) {
119
  const sockaddr_in* one_in =
120
8
      reinterpret_cast<const sockaddr_in*>(one.data());
121
  const sockaddr_in* two_in =
122
8
      reinterpret_cast<const sockaddr_in*>(two.data());
123
8
  return memcmp(&one_in->sin_addr, &two_in->sin_addr, sizeof(uint32_t)) == 0;
124
}
125
126
8
bool is_match_ipv6(
127
    const SocketAddress& one,
128
    const SocketAddress& two) {
129
  const sockaddr_in6* one_in =
130
8
      reinterpret_cast<const sockaddr_in6*>(one.data());
131
  const sockaddr_in6* two_in =
132
8
      reinterpret_cast<const sockaddr_in6*>(two.data());
133
8
  return memcmp(&one_in->sin6_addr, &two_in->sin6_addr, 16) == 0;
134
}
135
136
10
bool is_match_ipv4_ipv6(
137
    const SocketAddress& ipv4,
138
    const SocketAddress& ipv6) {
139
  const sockaddr_in* check_ipv4 =
140
10
      reinterpret_cast<const sockaddr_in*>(ipv4.data());
141
  const sockaddr_in6* check_ipv6 =
142
10
      reinterpret_cast<const sockaddr_in6*>(ipv6.data());
143
144
  const uint8_t* ptr =
145
10
      reinterpret_cast<const uint8_t*>(&check_ipv6->sin6_addr);
146
147

16
  return memcmp(ptr, mask, sizeof(mask)) == 0 &&
148
6
         memcmp(ptr + sizeof(mask),
149
6
                &check_ipv4->sin_addr,
150
10
                sizeof(uint32_t)) == 0;
151
}
152
153
40
SocketAddress::CompareResult compare_ipv4(
154
    const SocketAddress& one,
155
    const SocketAddress& two) {
156
  const sockaddr_in* one_in =
157
40
      reinterpret_cast<const sockaddr_in*>(one.data());
158
  const sockaddr_in* two_in =
159
40
      reinterpret_cast<const sockaddr_in*>(two.data());
160
161
40
  if (one_in->sin_addr.s_addr < two_in->sin_addr.s_addr)
162
17
    return SocketAddress::CompareResult::LESS_THAN;
163
23
  else if (one_in->sin_addr.s_addr == two_in->sin_addr.s_addr)
164
5
    return SocketAddress::CompareResult::SAME;
165
  else
166
18
    return SocketAddress::CompareResult::GREATER_THAN;
167
}
168
169
43
SocketAddress::CompareResult compare_ipv6(
170
    const SocketAddress& one,
171
    const SocketAddress& two) {
172
  const sockaddr_in6* one_in =
173
43
      reinterpret_cast<const sockaddr_in6*>(one.data());
174
  const sockaddr_in6* two_in =
175
43
      reinterpret_cast<const sockaddr_in6*>(two.data());
176
43
  int ret = memcmp(&one_in->sin6_addr, &two_in->sin6_addr, 16);
177
43
  if (ret < 0)
178
19
    return SocketAddress::CompareResult::LESS_THAN;
179
24
  else if (ret > 0)
180
19
    return SocketAddress::CompareResult::GREATER_THAN;
181
5
  return SocketAddress::CompareResult::SAME;
182
}
183
184
40
SocketAddress::CompareResult compare_ipv4_ipv6(
185
    const SocketAddress& ipv4,
186
    const SocketAddress& ipv6) {
187
  const sockaddr_in* ipv4_in =
188
40
      reinterpret_cast<const sockaddr_in*>(ipv4.data());
189
  const sockaddr_in6 * ipv6_in =
190
40
      reinterpret_cast<const sockaddr_in6*>(ipv6.data());
191
192
  const uint8_t* ptr =
193
40
      reinterpret_cast<const uint8_t*>(&ipv6_in->sin6_addr);
194
195
40
  if (memcmp(ptr, mask, sizeof(mask)) != 0)
196
25
    return SocketAddress::CompareResult::NOT_COMPARABLE;
197
198
  int ret = memcmp(
199
15
      &ipv4_in->sin_addr,
200
15
      ptr + sizeof(mask),
201
15
      sizeof(uint32_t));
202
203
15
  if (ret < 0)
204
9
    return SocketAddress::CompareResult::LESS_THAN;
205
6
  else if (ret > 0)
206
2
    return SocketAddress::CompareResult::GREATER_THAN;
207
4
  return SocketAddress::CompareResult::SAME;
208
}
209
210
36
bool in_network_ipv4(
211
    const SocketAddress& ip,
212
    const SocketAddress& net,
213
    int prefix) {
214
36
  uint32_t mask = ((1 << prefix) - 1) << (32 - prefix);
215
216
  const sockaddr_in* ip_in =
217
36
      reinterpret_cast<const sockaddr_in*>(ip.data());
218
  const sockaddr_in* net_in =
219
36
      reinterpret_cast<const sockaddr_in*>(net.data());
220
221
72
  return (htonl(ip_in->sin_addr.s_addr) & mask) ==
222
72
         (htonl(net_in->sin_addr.s_addr) & mask);
223
}
224
225
11
bool in_network_ipv6(
226
    const SocketAddress& ip,
227
    const SocketAddress& net,
228
    int prefix) {
229
  // Special case, if prefix == 128, then just do a
230
  // straight comparison.
231
11
  if (prefix == 128)
232
    return compare_ipv6(ip, net) == SocketAddress::CompareResult::SAME;
233
234
11
  uint8_t r = prefix % 8;
235
11
  int len = (prefix - r) / 8;
236
11
  uint8_t mask = ((1 << r) - 1) << (8 - r);
237
238
  const sockaddr_in6* ip_in =
239
11
      reinterpret_cast<const sockaddr_in6*>(ip.data());
240
  const sockaddr_in6* net_in =
241
11
      reinterpret_cast<const sockaddr_in6*>(net.data());
242
243
11
  if (memcmp(&ip_in->sin6_addr, &net_in->sin6_addr, len) != 0)
244
5
    return false;
245
246
  const uint8_t* p1 = reinterpret_cast<const uint8_t*>(
247
6
      ip_in->sin6_addr.s6_addr);
248
  const uint8_t* p2 = reinterpret_cast<const uint8_t*>(
249
6
      net_in->sin6_addr.s6_addr);
250
251
6
  return (p1[len] & mask) == (p2[len] & mask);
252
}
253
254
39
bool in_network_ipv4_ipv6(
255
    const SocketAddress& ip,
256
    const SocketAddress& net,
257
    int prefix) {
258
259
39
  if (prefix == 128)
260
    return compare_ipv4_ipv6(ip, net) == SocketAddress::CompareResult::SAME;
261
262
39
  uint8_t r = prefix % 8;
263
39
  int len = (prefix - r) / 8;
264
39
  uint8_t mask = ((1 << r) - 1) << (8 - r);
265
266
  const sockaddr_in* ip_in =
267
39
      reinterpret_cast<const sockaddr_in*>(ip.data());
268
  const sockaddr_in6* net_in =
269
39
      reinterpret_cast<const sockaddr_in6*>(net.data());
270
271
39
  uint8_t ip_mask[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0, 0, 0, 0};
272
39
  uint8_t* ptr = ip_mask;
273
39
  memcpy(ptr + 12, &ip_in->sin_addr, 4);
274
275
39
  if (memcmp(ptr, &net_in->sin6_addr, len) != 0)
276
39
    return false;
277
278
  ptr += len;
279
  const uint8_t* p2 = reinterpret_cast<const uint8_t*>(
280
      net_in->sin6_addr.s6_addr);
281
282
  return (ptr[0] & mask) == (p2[len] & mask);
283
}
284
285
3
bool in_network_ipv6_ipv4(
286
    const SocketAddress& ip,
287
    const SocketAddress& net,
288
    int prefix) {
289
3
  if (prefix == 32)
290
    return compare_ipv4_ipv6(net, ip) == SocketAddress::CompareResult::SAME;
291
292
3
  uint32_t m = ((1 << prefix) - 1) << (32 - prefix);
293
294
  const sockaddr_in6* ip_in =
295
3
      reinterpret_cast<const sockaddr_in6*>(ip.data());
296
  const sockaddr_in* net_in =
297
3
      reinterpret_cast<const sockaddr_in*>(net.data());
298
299
  const uint8_t* ptr =
300
3
      reinterpret_cast<const uint8_t*>(&ip_in->sin6_addr);
301
302
3
  if (memcmp(ptr, mask, sizeof(mask)) != 0)
303
2
    return false;
304
305
1
  ptr += sizeof(mask);
306
1
  uint32_t check = ReadUint32BE(ptr);
307
308
1
  return (check & m) == (htonl(net_in->sin_addr.s_addr) & m);
309
}
310
}  // namespace
311
312
// TODO(@jasnell): The implementations of is_match, compare, and
313
// is_in_network have not been performance optimized and could
314
// likely benefit from work on more performant approaches.
315
316
26
bool SocketAddress::is_match(const SocketAddress& other) const {
317
26
  switch (family()) {
318
    case AF_INET:
319
13
      switch (other.family()) {
320
8
        case AF_INET: return is_match_ipv4(*this, other);
321
5
        case AF_INET6: return is_match_ipv4_ipv6(*this, other);
322
      }
323
      break;
324
    case AF_INET6:
325
13
      switch (other.family()) {
326
5
        case AF_INET: return is_match_ipv4_ipv6(other, *this);
327
8
        case AF_INET6: return is_match_ipv6(*this, other);
328
      }
329
      break;
330
  }
331
  return false;
332
}
333
334
123
SocketAddress::CompareResult SocketAddress::compare(
335
    const SocketAddress& other) const {
336
123
  switch (family()) {
337
    case AF_INET:
338
65
      switch (other.family()) {
339
40
        case AF_INET: return compare_ipv4(*this, other);
340
25
        case AF_INET6: return compare_ipv4_ipv6(*this, other);
341
      }
342
      break;
343
    case AF_INET6:
344
58
      switch (other.family()) {
345
        case AF_INET: {
346
15
          CompareResult c = compare_ipv4_ipv6(other, *this);
347

15
          switch (c) {
348
            case SocketAddress::CompareResult::NOT_COMPARABLE:
349
              // Fall through
350
            case SocketAddress::CompareResult::SAME:
351
8
              return c;
352
            case SocketAddress::CompareResult::GREATER_THAN:
353
1
              return SocketAddress::CompareResult::LESS_THAN;
354
            case SocketAddress::CompareResult::LESS_THAN:
355
6
              return SocketAddress::CompareResult::GREATER_THAN;
356
          }
357
          break;
358
        }
359
43
        case AF_INET6: return compare_ipv6(*this, other);
360
      }
361
      break;
362
  }
363
  return SocketAddress::CompareResult::NOT_COMPARABLE;
364
}
365
366
89
bool SocketAddress::is_in_network(
367
    const SocketAddress& other,
368
    int prefix) const {
369
370
89
  switch (family()) {
371
    case AF_INET:
372
75
      switch (other.family()) {
373
36
        case AF_INET: return in_network_ipv4(*this, other, prefix);
374
39
        case AF_INET6: return in_network_ipv4_ipv6(*this, other, prefix);
375
      }
376
      break;
377
    case AF_INET6:
378
14
      switch (other.family()) {
379
3
        case AF_INET: return in_network_ipv6_ipv4(*this, other, prefix);
380
11
        case AF_INET6: return in_network_ipv6(*this, other, prefix);
381
      }
382
      break;
383
  }
384
385
  return false;
386
}
387
388
7
SocketAddressBlockList::SocketAddressBlockList(
389
7
    std::shared_ptr<SocketAddressBlockList> parent)
390
7
    : parent_(parent) {}
391
392
6
void SocketAddressBlockList::AddSocketAddress(
393
    const SocketAddress& address) {
394
  std::unique_ptr<Rule> rule =
395
12
      std::make_unique<SocketAddressRule>(address);
396
6
  rules_.emplace_front(std::move(rule));
397
6
  address_rules_[address] = rules_.begin();
398
6
}
399
400
1
void SocketAddressBlockList::RemoveSocketAddress(
401
    const SocketAddress& address) {
402
1
  auto it = address_rules_.find(address);
403
1
  if (it != std::end(address_rules_)) {
404
1
    rules_.erase(it->second);
405
1
    address_rules_.erase(it);
406
  }
407
1
}
408
409
3
void SocketAddressBlockList::AddSocketAddressRange(
410
    const SocketAddress& start,
411
    const SocketAddress& end) {
412
  std::unique_ptr<Rule> rule =
413
6
      std::make_unique<SocketAddressRangeRule>(start, end);
414
3
  rules_.emplace_front(std::move(rule));
415
3
}
416
417
5
void SocketAddressBlockList::AddSocketAddressMask(
418
    const SocketAddress& network,
419
    int prefix) {
420
  std::unique_ptr<Rule> rule =
421
10
      std::make_unique<SocketAddressMaskRule>(network, prefix);
422
5
  rules_.emplace_front(std::move(rule));
423
5
}
424
425
90
bool SocketAddressBlockList::Apply(const SocketAddress& address) {
426
178
  for (const auto& rule : rules_) {
427
164
    if (rule->Apply(address))
428
76
      return true;
429
  }
430
14
  return parent_ ? parent_->Apply(address) : false;
431
}
432
433
6
SocketAddressBlockList::SocketAddressRule::SocketAddressRule(
434
6
    const SocketAddress& address_)
435
6
    : address(address_) {}
436
437
3
SocketAddressBlockList::SocketAddressRangeRule::SocketAddressRangeRule(
438
    const SocketAddress& start_,
439
3
    const SocketAddress& end_)
440
    : start(start_),
441
3
      end(end_) {}
442
443
5
SocketAddressBlockList::SocketAddressMaskRule::SocketAddressMaskRule(
444
    const SocketAddress& network_,
445
5
    int prefix_)
446
    : network(network_),
447
5
      prefix(prefix_) {}
448
449
26
bool SocketAddressBlockList::SocketAddressRule::Apply(
450
    const SocketAddress& address) {
451
26
  return this->address.is_match(address);
452
}
453
454
2
std::string SocketAddressBlockList::SocketAddressRule::ToString() {
455
2
  std::string ret = "Address: ";
456
2
  ret += address.family() == AF_INET ? "IPv4" : "IPv6";
457
2
  ret += " ";
458
2
  ret += address.address();
459
2
  return ret;
460
}
461
462
49
bool SocketAddressBlockList::SocketAddressRangeRule::Apply(
463
    const SocketAddress& address) {
464

49
  return address >= start && address <= end;
465
}
466
467
2
std::string SocketAddressBlockList::SocketAddressRangeRule::ToString() {
468
2
  std::string ret = "Range: ";
469
2
  ret += start.family() == AF_INET ? "IPv4" : "IPv6";
470
2
  ret += " ";
471
2
  ret += start.address();
472
2
  ret += "-";
473
2
  ret += end.address();
474
2
  return ret;
475
}
476
477
89
bool SocketAddressBlockList::SocketAddressMaskRule::Apply(
478
    const SocketAddress& address) {
479
89
  return address.is_in_network(network, prefix);
480
}
481
482
2
std::string SocketAddressBlockList::SocketAddressMaskRule::ToString() {
483
2
  std::string ret = "Subnet: ";
484
2
  ret += network.family() == AF_INET ? "IPv4" : "IPv6";
485
2
  ret += " ";
486
2
  ret += network.address();
487
2
  ret += "/" + std::to_string(prefix);
488
2
  return ret;
489
}
490
491
2
MaybeLocal<Array> SocketAddressBlockList::ListRules(Environment* env) {
492
4
  std::vector<Local<Value>> rules;
493
8
  for (const auto& rule : rules_) {
494
    Local<Value> str;
495
12
    if (!rule->ToV8String(env).ToLocal(&str))
496
      return MaybeLocal<Array>();
497
6
    rules.push_back(str);
498
  }
499
4
  return Array::New(env->isolate(), rules.data(), rules.size());
500
}
501
502
void SocketAddressBlockList::MemoryInfo(node::MemoryTracker* tracker) const {
503
  tracker->TrackField("rules", rules_);
504
}
505
506
void SocketAddressBlockList::SocketAddressRule::MemoryInfo(
507
    node::MemoryTracker* tracker) const {
508
  tracker->TrackField("address", address);
509
}
510
511
void SocketAddressBlockList::SocketAddressRangeRule::MemoryInfo(
512
    node::MemoryTracker* tracker) const {
513
  tracker->TrackField("start", start);
514
  tracker->TrackField("end", end);
515
}
516
517
void SocketAddressBlockList::SocketAddressMaskRule::MemoryInfo(
518
    node::MemoryTracker* tracker) const {
519
  tracker->TrackField("network", network);
520
}
521
522
6
SocketAddressBlockListWrap::SocketAddressBlockListWrap(
523
6
    Environment* env, Local<Object> wrap)
524
6
    : BaseObject(env, wrap) {
525
6
  MakeWeak();
526
6
}
527
528
BaseObjectPtr<SocketAddressBlockListWrap> SocketAddressBlockListWrap::New(
529
    Environment* env) {
530
  Local<Object> obj;
531
  if (!env->blocklist_instance_template()
532
          ->NewInstance(env->context()).ToLocal(&obj)) {
533
    return {};
534
  }
535
  BaseObjectPtr<SocketAddressBlockListWrap> wrap =
536
      MakeDetachedBaseObject<SocketAddressBlockListWrap>(env, obj);
537
  CHECK(wrap);
538
  return wrap;
539
}
540
541
6
void SocketAddressBlockListWrap::New(
542
    const FunctionCallbackInfo<Value>& args) {
543
6
  CHECK(args.IsConstructCall());
544
6
  Environment* env = Environment::GetCurrent(args);
545
6
  new SocketAddressBlockListWrap(env, args.This());
546
6
}
547
548
4
void SocketAddressBlockListWrap::AddAddress(
549
    const FunctionCallbackInfo<Value>& args) {
550
4
  Environment* env = Environment::GetCurrent(args);
551
  SocketAddressBlockListWrap* wrap;
552
4
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
553
554
12
  CHECK(args[0]->IsString());
555
8
  CHECK(args[1]->IsInt32());
556
557
  sockaddr_storage address;
558
8
  Utf8Value value(args.GetIsolate(), args[0]);
559
  int32_t family;
560
16
  if (!args[1]->Int32Value(env->context()).To(&family))
561
    return;
562
563
4
  if (!SocketAddress::ToSockAddr(family, *value, 0, &address))
564
    return;
565
566
4
  wrap->AddSocketAddress(
567
8
      SocketAddress(reinterpret_cast<const sockaddr*>(&address)));
568
569
8
  args.GetReturnValue().Set(true);
570
}
571
572
3
void SocketAddressBlockListWrap::AddRange(
573
    const FunctionCallbackInfo<Value>& args) {
574
3
  Environment* env = Environment::GetCurrent(args);
575
  SocketAddressBlockListWrap* wrap;
576
3
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
577
578
9
  CHECK(args[0]->IsString());
579
9
  CHECK(args[1]->IsString());
580
6
  CHECK(args[2]->IsInt32());
581
582
  sockaddr_storage address[2];
583
6
  Utf8Value start(args.GetIsolate(), args[0]);
584
6
  Utf8Value end(args.GetIsolate(), args[1]);
585
  int32_t family;
586
12
  if (!args[2]->Int32Value(env->context()).To(&family))
587
    return;
588
589

6
  if (!SocketAddress::ToSockAddr(family, *start, 0, &address[0]) ||
590
3
      !SocketAddress::ToSockAddr(family, *end, 0, &address[1])) {
591
    return;
592
  }
593
594
6
  SocketAddress start_addr(reinterpret_cast<const sockaddr*>(&address[0]));
595
6
  SocketAddress end_addr(reinterpret_cast<const sockaddr*>(&address[1]));
596
597
  // Starting address must come before the end address
598
3
  if (start_addr > end_addr)
599
    return args.GetReturnValue().Set(false);
600
601
3
  wrap->AddSocketAddressRange(start_addr, end_addr);
602
603
6
  args.GetReturnValue().Set(true);
604
}
605
606
5
void SocketAddressBlockListWrap::AddSubnet(
607
    const FunctionCallbackInfo<Value>& args) {
608
5
  Environment* env = Environment::GetCurrent(args);
609
  SocketAddressBlockListWrap* wrap;
610
5
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
611
612
15
  CHECK(args[0]->IsString());
613
10
  CHECK(args[1]->IsInt32());
614
10
  CHECK(args[2]->IsInt32());
615
616
  sockaddr_storage address;
617
10
  Utf8Value network(args.GetIsolate(), args[0]);
618
  int32_t family;
619
  int32_t prefix;
620

30
  if (!args[1]->Int32Value(env->context()).To(&family) ||
621
25
      !args[2]->Int32Value(env->context()).To(&prefix)) {
622
    return;
623
  }
624
625
5
  if (!SocketAddress::ToSockAddr(family, *network, 0, &address))
626
    return;
627
628

5
  CHECK_IMPLIES(family == AF_INET, prefix <= 32);
629

5
  CHECK_IMPLIES(family == AF_INET6, prefix <= 128);
630
5
  CHECK_GE(prefix, 0);
631
632
5
  wrap->AddSocketAddressMask(
633
10
      SocketAddress(reinterpret_cast<const sockaddr*>(&address)),
634
10
      prefix);
635
636
10
  args.GetReturnValue().Set(true);
637
}
638
639
88
void SocketAddressBlockListWrap::Check(
640
    const FunctionCallbackInfo<Value>& args) {
641
88
  Environment* env = Environment::GetCurrent(args);
642
  SocketAddressBlockListWrap* wrap;
643
90
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
644
645
264
  CHECK(args[0]->IsString());
646
176
  CHECK(args[1]->IsInt32());
647
648
  sockaddr_storage address;
649
174
  Utf8Value value(args.GetIsolate(), args[0]);
650
  int32_t family;
651
352
  if (!args[1]->Int32Value(env->context()).To(&family))
652
    return;
653
654
88
  if (!SocketAddress::ToSockAddr(family, *value, 0, &address))
655
2
    return;
656
657
258
  args.GetReturnValue().Set(
658
172
      wrap->Apply(SocketAddress(reinterpret_cast<const sockaddr*>(&address))));
659
}
660
661
2
void SocketAddressBlockListWrap::GetRules(
662
    const FunctionCallbackInfo<Value>& args) {
663
2
  Environment* env = Environment::GetCurrent(args);
664
  SocketAddressBlockListWrap* wrap;
665
2
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
666
  Local<Array> rules;
667
4
  if (wrap->ListRules(env).ToLocal(&rules))
668
4
    args.GetReturnValue().Set(rules);
669
}
670
671
447
void SocketAddressBlockListWrap::Initialize(
672
    Local<Object> target,
673
    Local<Value> unused,
674
    Local<Context> context,
675
    void* priv) {
676
447
  Environment* env = Environment::GetCurrent(context);
677
678
447
  Local<String> name = FIXED_ONE_BYTE_STRING(env->isolate(), "BlockList");
679
  Local<FunctionTemplate> t =
680
447
      env->NewFunctionTemplate(SocketAddressBlockListWrap::New);
681
894
  t->InstanceTemplate()->SetInternalFieldCount(BaseObject::kInternalFieldCount);
682
447
  t->SetClassName(name);
683
684
447
  env->SetProtoMethod(t, "addAddress", SocketAddressBlockListWrap::AddAddress);
685
447
  env->SetProtoMethod(t, "addRange", SocketAddressBlockListWrap::AddRange);
686
447
  env->SetProtoMethod(t, "addSubnet", SocketAddressBlockListWrap::AddSubnet);
687
447
  env->SetProtoMethod(t, "check", SocketAddressBlockListWrap::Check);
688
447
  env->SetProtoMethod(t, "getRules", SocketAddressBlockListWrap::GetRules);
689
690
447
  env->set_blocklist_instance_template(t->InstanceTemplate());
691
894
  target->Set(env->context(), name,
692
2235
              t->GetFunction(env->context()).ToLocalChecked()).FromJust();
693
694
1788
  NODE_DEFINE_CONSTANT(target, AF_INET);
695
1788
  NODE_DEFINE_CONSTANT(target, AF_INET6);
696
447
}
697
698
}  // namespace node
699
700

18704
NODE_MODULE_CONTEXT_AWARE_INTERNAL(
701
    block_list,
702
    node::SocketAddressBlockListWrap::Initialize)