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: 88 344 25.6 %
Date: 2021-02-19 04:08:54 Branches: 35 193 18.1 %

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::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
15
bool SocketAddress::ToSockAddr(
37
    int32_t family,
38
    const char* host,
39
    uint32_t port,
40
    sockaddr_storage* addr) {
41
15
  switch (family) {
42
    case AF_INET:
43
10
      return uv_ip4_addr(
44
          host,
45
          port,
46
10
          reinterpret_cast<sockaddr_in*>(addr)) == 0;
47
    case AF_INET6:
48
5
      return uv_ip6_addr(
49
          host,
50
          port,
51
5
          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
33
size_t SocketAddress::Hash::operator()(const SocketAddress& addr) const {
74
33
  size_t hash = 0;
75
33
  switch (addr.family()) {
76
    case AF_INET: {
77
      const sockaddr_in* ipv4 =
78
33
          reinterpret_cast<const sockaddr_in*>(addr.raw());
79
33
      hash_combine(&hash, ipv4->sin_port, ipv4->sin_addr.s_addr);
80
33
      break;
81
    }
82
    case AF_INET6: {
83
      const sockaddr_in6* ipv6 =
84
          reinterpret_cast<const sockaddr_in6*>(addr.raw());
85
      const uint64_t* a =
86
          reinterpret_cast<const uint64_t*>(&ipv6->sin6_addr);
87
      hash_combine(&hash, ipv6->sin6_port, a[0], a[1]);
88
      break;
89
    }
90
    default:
91
      UNREACHABLE();
92
  }
93
33
  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
5
bool is_match_ipv4(
116
    const SocketAddress& one,
117
    const SocketAddress& two) {
118
  const sockaddr_in* one_in =
119
5
      reinterpret_cast<const sockaddr_in*>(one.data());
120
  const sockaddr_in* two_in =
121
5
      reinterpret_cast<const sockaddr_in*>(two.data());
122
5
  return memcmp(&one_in->sin_addr, &two_in->sin_addr, sizeof(uint32_t)) == 0;
123
}
124
125
bool is_match_ipv6(
126
    const SocketAddress& one,
127
    const SocketAddress& two) {
128
  const sockaddr_in6* one_in =
129
      reinterpret_cast<const sockaddr_in6*>(one.data());
130
  const sockaddr_in6* two_in =
131
      reinterpret_cast<const sockaddr_in6*>(two.data());
132
  return memcmp(&one_in->sin6_addr, &two_in->sin6_addr, 16) == 0;
133
}
134
135
bool is_match_ipv4_ipv6(
136
    const SocketAddress& ipv4,
137
    const SocketAddress& ipv6) {
138
  const sockaddr_in* check_ipv4 =
139
      reinterpret_cast<const sockaddr_in*>(ipv4.data());
140
  const sockaddr_in6* check_ipv6 =
141
      reinterpret_cast<const sockaddr_in6*>(ipv6.data());
142
143
  const uint8_t* ptr =
144
      reinterpret_cast<const uint8_t*>(&check_ipv6->sin6_addr);
145
146
  return memcmp(ptr, mask, sizeof(mask)) == 0 &&
147
         memcmp(ptr + sizeof(mask),
148
                &check_ipv4->sin_addr,
149
                sizeof(uint32_t)) == 0;
150
}
151
152
9
SocketAddress::CompareResult compare_ipv4(
153
    const SocketAddress& one,
154
    const SocketAddress& two) {
155
  const sockaddr_in* one_in =
156
9
      reinterpret_cast<const sockaddr_in*>(one.data());
157
  const sockaddr_in* two_in =
158
9
      reinterpret_cast<const sockaddr_in*>(two.data());
159
160
9
  if (one_in->sin_addr.s_addr < two_in->sin_addr.s_addr)
161
3
    return SocketAddress::CompareResult::LESS_THAN;
162
6
  else if (one_in->sin_addr.s_addr == two_in->sin_addr.s_addr)
163
3
    return SocketAddress::CompareResult::SAME;
164
  else
165
3
    return SocketAddress::CompareResult::GREATER_THAN;
166
}
167
168
9
SocketAddress::CompareResult compare_ipv6(
169
    const SocketAddress& one,
170
    const SocketAddress& two) {
171
  const sockaddr_in6* one_in =
172
9
      reinterpret_cast<const sockaddr_in6*>(one.data());
173
  const sockaddr_in6* two_in =
174
9
      reinterpret_cast<const sockaddr_in6*>(two.data());
175
9
  int ret = memcmp(&one_in->sin6_addr, &two_in->sin6_addr, 16);
176
9
  if (ret < 0)
177
3
    return SocketAddress::CompareResult::LESS_THAN;
178
6
  else if (ret > 0)
179
3
    return SocketAddress::CompareResult::GREATER_THAN;
180
3
  return SocketAddress::CompareResult::SAME;
181
}
182
183
21
SocketAddress::CompareResult compare_ipv4_ipv6(
184
    const SocketAddress& ipv4,
185
    const SocketAddress& ipv6) {
186
  const sockaddr_in* ipv4_in =
187
21
      reinterpret_cast<const sockaddr_in*>(ipv4.data());
188
  const sockaddr_in6 * ipv6_in =
189
21
      reinterpret_cast<const sockaddr_in6*>(ipv6.data());
190
191
  const uint8_t* ptr =
192
21
      reinterpret_cast<const uint8_t*>(&ipv6_in->sin6_addr);
193
194
21
  if (memcmp(ptr, mask, sizeof(mask)) != 0)
195
10
    return SocketAddress::CompareResult::NOT_COMPARABLE;
196
197
  int ret = memcmp(
198
11
      &ipv4_in->sin_addr,
199
11
      ptr + sizeof(mask),
200
11
      sizeof(uint32_t));
201
202
11
  if (ret < 0)
203
6
    return SocketAddress::CompareResult::LESS_THAN;
204
5
  else if (ret > 0)
205
1
    return SocketAddress::CompareResult::GREATER_THAN;
206
4
  return SocketAddress::CompareResult::SAME;
207
}
208
209
bool in_network_ipv4(
210
    const SocketAddress& ip,
211
    const SocketAddress& net,
212
    int prefix) {
213
  uint32_t mask = ((1 << prefix) - 1) << (32 - prefix);
214
215
  const sockaddr_in* ip_in =
216
      reinterpret_cast<const sockaddr_in*>(ip.data());
217
  const sockaddr_in* net_in =
218
      reinterpret_cast<const sockaddr_in*>(net.data());
219
220
  return (htonl(ip_in->sin_addr.s_addr) & mask) ==
221
         (htonl(net_in->sin_addr.s_addr) & mask);
222
}
223
224
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
  if (prefix == 128)
231
    return compare_ipv6(ip, net) == SocketAddress::CompareResult::SAME;
232
233
  uint8_t r = prefix % 8;
234
  int len = (prefix - r) / 8;
235
  uint8_t mask = ((1 << r) - 1) << (8 - r);
236
237
  const sockaddr_in6* ip_in =
238
      reinterpret_cast<const sockaddr_in6*>(ip.data());
239
  const sockaddr_in6* net_in =
240
      reinterpret_cast<const sockaddr_in6*>(net.data());
241
242
  if (memcmp(&ip_in->sin6_addr, &net_in->sin6_addr, len) != 0)
243
    return false;
244
245
  const uint8_t* p1 = reinterpret_cast<const uint8_t*>(
246
      ip_in->sin6_addr.s6_addr);
247
  const uint8_t* p2 = reinterpret_cast<const uint8_t*>(
248
      net_in->sin6_addr.s6_addr);
249
250
  return (p1[len] & mask) == (p2[len] & mask);
251
}
252
253
bool in_network_ipv4_ipv6(
254
    const SocketAddress& ip,
255
    const SocketAddress& net,
256
    int prefix) {
257
258
  if (prefix == 128)
259
    return compare_ipv4_ipv6(ip, net) == SocketAddress::CompareResult::SAME;
260
261
  uint8_t r = prefix % 8;
262
  int len = (prefix - r) / 8;
263
  uint8_t mask = ((1 << r) - 1) << (8 - r);
264
265
  const sockaddr_in* ip_in =
266
      reinterpret_cast<const sockaddr_in*>(ip.data());
267
  const sockaddr_in6* net_in =
268
      reinterpret_cast<const sockaddr_in6*>(net.data());
269
270
  uint8_t ip_mask[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0, 0, 0, 0};
271
  uint8_t* ptr = ip_mask;
272
  memcpy(ptr + 12, &ip_in->sin_addr, 4);
273
274
  if (memcmp(ptr, &net_in->sin6_addr, len) != 0)
275
    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
bool in_network_ipv6_ipv4(
285
    const SocketAddress& ip,
286
    const SocketAddress& net,
287
    int prefix) {
288
  if (prefix == 32)
289
    return compare_ipv4_ipv6(net, ip) == SocketAddress::CompareResult::SAME;
290
291
  uint32_t m = ((1 << prefix) - 1) << (32 - prefix);
292
293
  const sockaddr_in6* ip_in =
294
      reinterpret_cast<const sockaddr_in6*>(ip.data());
295
  const sockaddr_in* net_in =
296
      reinterpret_cast<const sockaddr_in*>(net.data());
297
298
  const uint8_t* ptr =
299
      reinterpret_cast<const uint8_t*>(&ip_in->sin6_addr);
300
301
  if (memcmp(ptr, mask, sizeof(mask)) != 0)
302
    return false;
303
304
  ptr += sizeof(mask);
305
  uint32_t check = ReadUint32BE(ptr);
306
307
  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
5
bool SocketAddress::is_match(const SocketAddress& other) const {
316
5
  switch (family()) {
317
    case AF_INET:
318
5
      switch (other.family()) {
319
5
        case AF_INET: return is_match_ipv4(*this, other);
320
        case AF_INET6: return is_match_ipv4_ipv6(*this, other);
321
      }
322
      break;
323
    case AF_INET6:
324
      switch (other.family()) {
325
        case AF_INET: return is_match_ipv4_ipv6(other, *this);
326
        case AF_INET6: return is_match_ipv6(*this, other);
327
      }
328
      break;
329
  }
330
  return false;
331
}
332
333
39
SocketAddress::CompareResult SocketAddress::compare(
334
    const SocketAddress& other) const {
335
39
  switch (family()) {
336
    case AF_INET:
337
22
      switch (other.family()) {
338
9
        case AF_INET: return compare_ipv4(*this, other);
339
13
        case AF_INET6: return compare_ipv4_ipv6(*this, other);
340
      }
341
      break;
342
    case AF_INET6:
343
17
      switch (other.family()) {
344
        case AF_INET: {
345
8
          CompareResult c = compare_ipv4_ipv6(other, *this);
346

8
          switch (c) {
347
            case SocketAddress::CompareResult::NOT_COMPARABLE:
348
              // Fall through
349
            case SocketAddress::CompareResult::SAME:
350
5
              return c;
351
            case SocketAddress::CompareResult::GREATER_THAN:
352
              return SocketAddress::CompareResult::LESS_THAN;
353
            case SocketAddress::CompareResult::LESS_THAN:
354
3
              return SocketAddress::CompareResult::GREATER_THAN;
355
          }
356
          break;
357
        }
358
9
        case AF_INET6: return compare_ipv6(*this, other);
359
      }
360
      break;
361
  }
362
  return SocketAddress::CompareResult::NOT_COMPARABLE;
363
}
364
365
bool SocketAddress::is_in_network(
366
    const SocketAddress& other,
367
    int prefix) const {
368
369
  switch (family()) {
370
    case AF_INET:
371
      switch (other.family()) {
372
        case AF_INET: return in_network_ipv4(*this, other, prefix);
373
        case AF_INET6: return in_network_ipv4_ipv6(*this, other, prefix);
374
      }
375
      break;
376
    case AF_INET6:
377
      switch (other.family()) {
378
        case AF_INET: return in_network_ipv6_ipv4(*this, other, prefix);
379
        case AF_INET6: return in_network_ipv6(*this, other, prefix);
380
      }
381
      break;
382
  }
383
384
  return false;
385
}
386
387
1
SocketAddressBlockList::SocketAddressBlockList(
388
1
    std::shared_ptr<SocketAddressBlockList> parent)
389
1
    : parent_(parent) {}
390
391
2
void SocketAddressBlockList::AddSocketAddress(
392
    const SocketAddress& address) {
393
  std::unique_ptr<Rule> rule =
394
4
      std::make_unique<SocketAddressRule>(address);
395
2
  rules_.emplace_front(std::move(rule));
396
2
  address_rules_[address] = rules_.begin();
397
2
}
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
void SocketAddressBlockList::AddSocketAddressRange(
409
    const SocketAddress& start,
410
    const SocketAddress& end) {
411
  std::unique_ptr<Rule> rule =
412
      std::make_unique<SocketAddressRangeRule>(start, end);
413
  rules_.emplace_front(std::move(rule));
414
}
415
416
void SocketAddressBlockList::AddSocketAddressMask(
417
    const SocketAddress& network,
418
    int prefix) {
419
  std::unique_ptr<Rule> rule =
420
      std::make_unique<SocketAddressMaskRule>(network, prefix);
421
  rules_.emplace_front(std::move(rule));
422
}
423
424
4
bool SocketAddressBlockList::Apply(const SocketAddress& address) {
425
6
  for (const auto& rule : rules_) {
426
5
    if (rule->Apply(address))
427
3
      return true;
428
  }
429
1
  return parent_ ? parent_->Apply(address) : false;
430
}
431
432
2
SocketAddressBlockList::SocketAddressRule::SocketAddressRule(
433
2
    const SocketAddress& address_)
434
2
    : address(address_) {}
435
436
SocketAddressBlockList::SocketAddressRangeRule::SocketAddressRangeRule(
437
    const SocketAddress& start_,
438
    const SocketAddress& end_)
439
    : start(start_),
440
      end(end_) {}
441
442
SocketAddressBlockList::SocketAddressMaskRule::SocketAddressMaskRule(
443
    const SocketAddress& network_,
444
    int prefix_)
445
    : network(network_),
446
      prefix(prefix_) {}
447
448
5
bool SocketAddressBlockList::SocketAddressRule::Apply(
449
    const SocketAddress& address) {
450
5
  return this->address.is_match(address);
451
}
452
453
std::string SocketAddressBlockList::SocketAddressRule::ToString() {
454
  std::string ret = "Address: ";
455
  ret += address.family() == AF_INET ? "IPv4" : "IPv6";
456
  ret += " ";
457
  ret += address.address();
458
  return ret;
459
}
460
461
bool SocketAddressBlockList::SocketAddressRangeRule::Apply(
462
    const SocketAddress& address) {
463
  return address >= start && address <= end;
464
}
465
466
std::string SocketAddressBlockList::SocketAddressRangeRule::ToString() {
467
  std::string ret = "Range: ";
468
  ret += start.family() == AF_INET ? "IPv4" : "IPv6";
469
  ret += " ";
470
  ret += start.address();
471
  ret += "-";
472
  ret += end.address();
473
  return ret;
474
}
475
476
bool SocketAddressBlockList::SocketAddressMaskRule::Apply(
477
    const SocketAddress& address) {
478
  return address.is_in_network(network, prefix);
479
}
480
481
std::string SocketAddressBlockList::SocketAddressMaskRule::ToString() {
482
  std::string ret = "Subnet: ";
483
  ret += network.family() == AF_INET ? "IPv4" : "IPv6";
484
  ret += " ";
485
  ret += network.address();
486
  ret += "/" + std::to_string(prefix);
487
  return ret;
488
}
489
490
MaybeLocal<Array> SocketAddressBlockList::ListRules(Environment* env) {
491
  std::vector<Local<Value>> rules;
492
  for (const auto& rule : rules_) {
493
    Local<Value> str;
494
    if (!rule->ToV8String(env).ToLocal(&str))
495
      return MaybeLocal<Array>();
496
    rules.push_back(str);
497
  }
498
  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
SocketAddressBlockListWrap::SocketAddressBlockListWrap(
522
    Environment* env, Local<Object> wrap)
523
    : BaseObject(env, wrap) {
524
  MakeWeak();
525
}
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
void SocketAddressBlockListWrap::New(
541
    const FunctionCallbackInfo<Value>& args) {
542
  CHECK(args.IsConstructCall());
543
  Environment* env = Environment::GetCurrent(args);
544
  new SocketAddressBlockListWrap(env, args.This());
545
}
546
547
void SocketAddressBlockListWrap::AddAddress(
548
    const FunctionCallbackInfo<Value>& args) {
549
  Environment* env = Environment::GetCurrent(args);
550
  SocketAddressBlockListWrap* wrap;
551
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
552
553
  CHECK(args[0]->IsString());
554
  CHECK(args[1]->IsInt32());
555
556
  sockaddr_storage address;
557
  Utf8Value value(args.GetIsolate(), args[0]);
558
  int32_t family;
559
  if (!args[1]->Int32Value(env->context()).To(&family))
560
    return;
561
562
  if (!SocketAddress::ToSockAddr(family, *value, 0, &address))
563
    return;
564
565
  wrap->AddSocketAddress(
566
      SocketAddress(reinterpret_cast<const sockaddr*>(&address)));
567
568
  args.GetReturnValue().Set(true);
569
}
570
571
void SocketAddressBlockListWrap::AddRange(
572
    const FunctionCallbackInfo<Value>& args) {
573
  Environment* env = Environment::GetCurrent(args);
574
  SocketAddressBlockListWrap* wrap;
575
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
576
577
  CHECK(args[0]->IsString());
578
  CHECK(args[1]->IsString());
579
  CHECK(args[2]->IsInt32());
580
581
  sockaddr_storage address[2];
582
  Utf8Value start(args.GetIsolate(), args[0]);
583
  Utf8Value end(args.GetIsolate(), args[1]);
584
  int32_t family;
585
  if (!args[2]->Int32Value(env->context()).To(&family))
586
    return;
587
588
  if (!SocketAddress::ToSockAddr(family, *start, 0, &address[0]) ||
589
      !SocketAddress::ToSockAddr(family, *end, 0, &address[1])) {
590
    return;
591
  }
592
593
  SocketAddress start_addr(reinterpret_cast<const sockaddr*>(&address[0]));
594
  SocketAddress end_addr(reinterpret_cast<const sockaddr*>(&address[1]));
595
596
  // Starting address must come before the end address
597
  if (start_addr > end_addr)
598
    return args.GetReturnValue().Set(false);
599
600
  wrap->AddSocketAddressRange(start_addr, end_addr);
601
602
  args.GetReturnValue().Set(true);
603
}
604
605
void SocketAddressBlockListWrap::AddSubnet(
606
    const FunctionCallbackInfo<Value>& args) {
607
  Environment* env = Environment::GetCurrent(args);
608
  SocketAddressBlockListWrap* wrap;
609
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
610
611
  CHECK(args[0]->IsString());
612
  CHECK(args[1]->IsInt32());
613
  CHECK(args[2]->IsInt32());
614
615
  sockaddr_storage address;
616
  Utf8Value network(args.GetIsolate(), args[0]);
617
  int32_t family;
618
  int32_t prefix;
619
  if (!args[1]->Int32Value(env->context()).To(&family) ||
620
      !args[2]->Int32Value(env->context()).To(&prefix)) {
621
    return;
622
  }
623
624
  if (!SocketAddress::ToSockAddr(family, *network, 0, &address))
625
    return;
626
627
  CHECK_IMPLIES(family == AF_INET, prefix <= 32);
628
  CHECK_IMPLIES(family == AF_INET6, prefix <= 128);
629
  CHECK_GE(prefix, 0);
630
631
  wrap->AddSocketAddressMask(
632
      SocketAddress(reinterpret_cast<const sockaddr*>(&address)),
633
      prefix);
634
635
  args.GetReturnValue().Set(true);
636
}
637
638
void SocketAddressBlockListWrap::Check(
639
    const FunctionCallbackInfo<Value>& args) {
640
  Environment* env = Environment::GetCurrent(args);
641
  SocketAddressBlockListWrap* wrap;
642
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
643
644
  CHECK(args[0]->IsString());
645
  CHECK(args[1]->IsInt32());
646
647
  sockaddr_storage address;
648
  Utf8Value value(args.GetIsolate(), args[0]);
649
  int32_t family;
650
  if (!args[1]->Int32Value(env->context()).To(&family))
651
    return;
652
653
  if (!SocketAddress::ToSockAddr(family, *value, 0, &address))
654
    return;
655
656
  args.GetReturnValue().Set(
657
      wrap->Apply(SocketAddress(reinterpret_cast<const sockaddr*>(&address))));
658
}
659
660
void SocketAddressBlockListWrap::GetRules(
661
    const FunctionCallbackInfo<Value>& args) {
662
  Environment* env = Environment::GetCurrent(args);
663
  SocketAddressBlockListWrap* wrap;
664
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
665
  Local<Array> rules;
666
  if (wrap->ListRules(env).ToLocal(&rules))
667
    args.GetReturnValue().Set(rules);
668
}
669
670
void SocketAddressBlockListWrap::Initialize(
671
    Local<Object> target,
672
    Local<Value> unused,
673
    Local<Context> context,
674
    void* priv) {
675
  Environment* env = Environment::GetCurrent(context);
676
677
  Local<FunctionTemplate> t =
678
      env->NewFunctionTemplate(SocketAddressBlockListWrap::New);
679
  t->InstanceTemplate()->SetInternalFieldCount(BaseObject::kInternalFieldCount);
680
681
  env->SetProtoMethod(t, "addAddress", SocketAddressBlockListWrap::AddAddress);
682
  env->SetProtoMethod(t, "addRange", SocketAddressBlockListWrap::AddRange);
683
  env->SetProtoMethod(t, "addSubnet", SocketAddressBlockListWrap::AddSubnet);
684
  env->SetProtoMethod(t, "check", SocketAddressBlockListWrap::Check);
685
  env->SetProtoMethod(t, "getRules", SocketAddressBlockListWrap::GetRules);
686
687
  env->set_blocklist_instance_template(t->InstanceTemplate());
688
  env->SetConstructorFunction(target, "BlockList", t);
689
690
  NODE_DEFINE_CONSTANT(target, AF_INET);
691
  NODE_DEFINE_CONSTANT(target, AF_INET6);
692
}
693
694
}  // namespace node
695
696

481
NODE_MODULE_CONTEXT_AWARE_INTERNAL(
697
    block_list,
698
    node::SocketAddressBlockListWrap::Initialize)