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

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

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

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

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

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

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

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

17887
NODE_MODULE_CONTEXT_AWARE_INTERNAL(
700
    block_list,
701
    node::SocketAddressBlockListWrap::Initialize)