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::Isolate;
21 using v8::Local;
22 using v8::MaybeLocal;
23 using v8::Object;
24 using v8::Uint32;
25 using v8::Value;
26
27 namespace {
28 template <typename T, typename F>
FromUVHandle(F fn,const T & handle)29 SocketAddress FromUVHandle(F fn, const T& handle) {
30 SocketAddress addr;
31 int len = sizeof(sockaddr_storage);
32 if (fn(&handle, addr.storage(), &len) == 0)
33 CHECK_EQ(static_cast<size_t>(len), addr.length());
34 else
35 addr.storage()->sa_family = 0;
36 return addr;
37 }
38 } // namespace
39
ToSockAddr(int32_t family,const char * host,uint32_t port,sockaddr_storage * addr)40 bool SocketAddress::ToSockAddr(
41 int32_t family,
42 const char* host,
43 uint32_t port,
44 sockaddr_storage* addr) {
45 switch (family) {
46 case AF_INET:
47 return uv_ip4_addr(
48 host,
49 port,
50 reinterpret_cast<sockaddr_in*>(addr)) == 0;
51 case AF_INET6:
52 return uv_ip6_addr(
53 host,
54 port,
55 reinterpret_cast<sockaddr_in6*>(addr)) == 0;
56 default:
57 UNREACHABLE();
58 }
59 }
60
New(const char * host,uint32_t port,SocketAddress * addr)61 bool SocketAddress::New(
62 const char* host,
63 uint32_t port,
64 SocketAddress* addr) {
65 return New(AF_INET, host, port, addr) || New(AF_INET6, host, port, addr);
66 }
67
New(int32_t family,const char * host,uint32_t port,SocketAddress * addr)68 bool SocketAddress::New(
69 int32_t family,
70 const char* host,
71 uint32_t port,
72 SocketAddress* addr) {
73 return ToSockAddr(family, host, port,
74 reinterpret_cast<sockaddr_storage*>(addr->storage()));
75 }
76
operator ()(const SocketAddress & addr) const77 size_t SocketAddress::Hash::operator()(const SocketAddress& addr) const {
78 size_t hash = 0;
79 switch (addr.family()) {
80 case AF_INET: {
81 const sockaddr_in* ipv4 =
82 reinterpret_cast<const sockaddr_in*>(addr.raw());
83 hash_combine(&hash, ipv4->sin_port, ipv4->sin_addr.s_addr);
84 break;
85 }
86 case AF_INET6: {
87 const sockaddr_in6* ipv6 =
88 reinterpret_cast<const sockaddr_in6*>(addr.raw());
89 const uint64_t* a =
90 reinterpret_cast<const uint64_t*>(&ipv6->sin6_addr);
91 hash_combine(&hash, ipv6->sin6_port, a[0], a[1]);
92 break;
93 }
94 default:
95 UNREACHABLE();
96 }
97 return hash;
98 }
99
FromSockName(const uv_tcp_t & handle)100 SocketAddress SocketAddress::FromSockName(const uv_tcp_t& handle) {
101 return FromUVHandle(uv_tcp_getsockname, handle);
102 }
103
FromSockName(const uv_udp_t & handle)104 SocketAddress SocketAddress::FromSockName(const uv_udp_t& handle) {
105 return FromUVHandle(uv_udp_getsockname, handle);
106 }
107
FromPeerName(const uv_tcp_t & handle)108 SocketAddress SocketAddress::FromPeerName(const uv_tcp_t& handle) {
109 return FromUVHandle(uv_tcp_getpeername, handle);
110 }
111
FromPeerName(const uv_udp_t & handle)112 SocketAddress SocketAddress::FromPeerName(const uv_udp_t& handle) {
113 return FromUVHandle(uv_udp_getpeername, handle);
114 }
115
116 namespace {
117 constexpr uint8_t mask[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
118
is_match_ipv4(const SocketAddress & one,const SocketAddress & two)119 bool is_match_ipv4(
120 const SocketAddress& one,
121 const SocketAddress& two) {
122 const sockaddr_in* one_in =
123 reinterpret_cast<const sockaddr_in*>(one.data());
124 const sockaddr_in* two_in =
125 reinterpret_cast<const sockaddr_in*>(two.data());
126 return memcmp(&one_in->sin_addr, &two_in->sin_addr, sizeof(uint32_t)) == 0;
127 }
128
is_match_ipv6(const SocketAddress & one,const SocketAddress & two)129 bool is_match_ipv6(
130 const SocketAddress& one,
131 const SocketAddress& two) {
132 const sockaddr_in6* one_in =
133 reinterpret_cast<const sockaddr_in6*>(one.data());
134 const sockaddr_in6* two_in =
135 reinterpret_cast<const sockaddr_in6*>(two.data());
136 return memcmp(&one_in->sin6_addr, &two_in->sin6_addr, 16) == 0;
137 }
138
is_match_ipv4_ipv6(const SocketAddress & ipv4,const SocketAddress & ipv6)139 bool is_match_ipv4_ipv6(
140 const SocketAddress& ipv4,
141 const SocketAddress& ipv6) {
142 const sockaddr_in* check_ipv4 =
143 reinterpret_cast<const sockaddr_in*>(ipv4.data());
144 const sockaddr_in6* check_ipv6 =
145 reinterpret_cast<const sockaddr_in6*>(ipv6.data());
146
147 const uint8_t* ptr =
148 reinterpret_cast<const uint8_t*>(&check_ipv6->sin6_addr);
149
150 return memcmp(ptr, mask, sizeof(mask)) == 0 &&
151 memcmp(ptr + sizeof(mask),
152 &check_ipv4->sin_addr,
153 sizeof(uint32_t)) == 0;
154 }
155
compare_ipv4(const SocketAddress & one,const SocketAddress & two)156 SocketAddress::CompareResult compare_ipv4(
157 const SocketAddress& one,
158 const SocketAddress& two) {
159 const sockaddr_in* one_in =
160 reinterpret_cast<const sockaddr_in*>(one.data());
161 const sockaddr_in* two_in =
162 reinterpret_cast<const sockaddr_in*>(two.data());
163 const uint32_t s_addr_one = ntohl(one_in->sin_addr.s_addr);
164 const uint32_t s_addr_two = ntohl(two_in->sin_addr.s_addr);
165
166 if (s_addr_one < s_addr_two)
167 return SocketAddress::CompareResult::LESS_THAN;
168 else if (s_addr_one == s_addr_two)
169 return SocketAddress::CompareResult::SAME;
170 else
171 return SocketAddress::CompareResult::GREATER_THAN;
172 }
173
compare_ipv6(const SocketAddress & one,const SocketAddress & two)174 SocketAddress::CompareResult compare_ipv6(
175 const SocketAddress& one,
176 const SocketAddress& two) {
177 const sockaddr_in6* one_in =
178 reinterpret_cast<const sockaddr_in6*>(one.data());
179 const sockaddr_in6* two_in =
180 reinterpret_cast<const sockaddr_in6*>(two.data());
181 int ret = memcmp(&one_in->sin6_addr, &two_in->sin6_addr, 16);
182 if (ret < 0)
183 return SocketAddress::CompareResult::LESS_THAN;
184 else if (ret > 0)
185 return SocketAddress::CompareResult::GREATER_THAN;
186 return SocketAddress::CompareResult::SAME;
187 }
188
compare_ipv4_ipv6(const SocketAddress & ipv4,const SocketAddress & ipv6)189 SocketAddress::CompareResult compare_ipv4_ipv6(
190 const SocketAddress& ipv4,
191 const SocketAddress& ipv6) {
192 const sockaddr_in* ipv4_in =
193 reinterpret_cast<const sockaddr_in*>(ipv4.data());
194 const sockaddr_in6 * ipv6_in =
195 reinterpret_cast<const sockaddr_in6*>(ipv6.data());
196
197 const uint8_t* ptr =
198 reinterpret_cast<const uint8_t*>(&ipv6_in->sin6_addr);
199
200 if (memcmp(ptr, mask, sizeof(mask)) != 0)
201 return SocketAddress::CompareResult::NOT_COMPARABLE;
202
203 int ret = memcmp(
204 &ipv4_in->sin_addr,
205 ptr + sizeof(mask),
206 sizeof(uint32_t));
207
208 if (ret < 0)
209 return SocketAddress::CompareResult::LESS_THAN;
210 else if (ret > 0)
211 return SocketAddress::CompareResult::GREATER_THAN;
212 return SocketAddress::CompareResult::SAME;
213 }
214
in_network_ipv4(const SocketAddress & ip,const SocketAddress & net,int prefix)215 bool in_network_ipv4(
216 const SocketAddress& ip,
217 const SocketAddress& net,
218 int prefix) {
219 uint32_t mask = ((1ull << prefix) - 1) << (32 - prefix);
220
221 const sockaddr_in* ip_in =
222 reinterpret_cast<const sockaddr_in*>(ip.data());
223 const sockaddr_in* net_in =
224 reinterpret_cast<const sockaddr_in*>(net.data());
225
226 return (htonl(ip_in->sin_addr.s_addr) & mask) ==
227 (htonl(net_in->sin_addr.s_addr) & mask);
228 }
229
in_network_ipv6(const SocketAddress & ip,const SocketAddress & net,int prefix)230 bool in_network_ipv6(
231 const SocketAddress& ip,
232 const SocketAddress& net,
233 int prefix) {
234 // Special case, if prefix == 128, then just do a
235 // straight comparison.
236 if (prefix == 128)
237 return compare_ipv6(ip, net) == SocketAddress::CompareResult::SAME;
238
239 uint8_t r = prefix % 8;
240 int len = (prefix - r) / 8;
241 uint8_t mask = ((1 << r) - 1) << (8 - r);
242
243 const sockaddr_in6* ip_in =
244 reinterpret_cast<const sockaddr_in6*>(ip.data());
245 const sockaddr_in6* net_in =
246 reinterpret_cast<const sockaddr_in6*>(net.data());
247
248 if (memcmp(&ip_in->sin6_addr, &net_in->sin6_addr, len) != 0)
249 return false;
250
251 const uint8_t* p1 = reinterpret_cast<const uint8_t*>(
252 ip_in->sin6_addr.s6_addr);
253 const uint8_t* p2 = reinterpret_cast<const uint8_t*>(
254 net_in->sin6_addr.s6_addr);
255
256 return (p1[len] & mask) == (p2[len] & mask);
257 }
258
in_network_ipv4_ipv6(const SocketAddress & ip,const SocketAddress & net,int prefix)259 bool in_network_ipv4_ipv6(
260 const SocketAddress& ip,
261 const SocketAddress& net,
262 int prefix) {
263
264 if (prefix == 128)
265 return compare_ipv4_ipv6(ip, net) == SocketAddress::CompareResult::SAME;
266
267 uint8_t r = prefix % 8;
268 int len = (prefix - r) / 8;
269 uint8_t mask = ((1 << r) - 1) << (8 - r);
270
271 const sockaddr_in* ip_in =
272 reinterpret_cast<const sockaddr_in*>(ip.data());
273 const sockaddr_in6* net_in =
274 reinterpret_cast<const sockaddr_in6*>(net.data());
275
276 uint8_t ip_mask[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0, 0, 0, 0};
277 uint8_t* ptr = ip_mask;
278 memcpy(ptr + 12, &ip_in->sin_addr, 4);
279
280 if (memcmp(ptr, &net_in->sin6_addr, len) != 0)
281 return false;
282
283 ptr += len;
284 const uint8_t* p2 = reinterpret_cast<const uint8_t*>(
285 net_in->sin6_addr.s6_addr);
286
287 return (ptr[0] & mask) == (p2[len] & mask);
288 }
289
in_network_ipv6_ipv4(const SocketAddress & ip,const SocketAddress & net,int prefix)290 bool in_network_ipv6_ipv4(
291 const SocketAddress& ip,
292 const SocketAddress& net,
293 int prefix) {
294 if (prefix == 32)
295 return compare_ipv4_ipv6(net, ip) == SocketAddress::CompareResult::SAME;
296
297 uint32_t m = ((1ull << prefix) - 1) << (32 - prefix);
298
299 const sockaddr_in6* ip_in =
300 reinterpret_cast<const sockaddr_in6*>(ip.data());
301 const sockaddr_in* net_in =
302 reinterpret_cast<const sockaddr_in*>(net.data());
303
304 const uint8_t* ptr =
305 reinterpret_cast<const uint8_t*>(&ip_in->sin6_addr);
306
307 if (memcmp(ptr, mask, sizeof(mask)) != 0)
308 return false;
309
310 ptr += sizeof(mask);
311 uint32_t check = ReadUint32BE(ptr);
312
313 return (check & m) == (htonl(net_in->sin_addr.s_addr) & m);
314 }
315 } // namespace
316
317 // TODO(@jasnell): The implementations of is_match, compare, and
318 // is_in_network have not been performance optimized and could
319 // likely benefit from work on more performant approaches.
320
is_match(const SocketAddress & other) const321 bool SocketAddress::is_match(const SocketAddress& other) const {
322 switch (family()) {
323 case AF_INET:
324 switch (other.family()) {
325 case AF_INET: return is_match_ipv4(*this, other);
326 case AF_INET6: return is_match_ipv4_ipv6(*this, other);
327 }
328 break;
329 case AF_INET6:
330 switch (other.family()) {
331 case AF_INET: return is_match_ipv4_ipv6(other, *this);
332 case AF_INET6: return is_match_ipv6(*this, other);
333 }
334 break;
335 }
336 return false;
337 }
338
compare(const SocketAddress & other) const339 SocketAddress::CompareResult SocketAddress::compare(
340 const SocketAddress& other) const {
341 switch (family()) {
342 case AF_INET:
343 switch (other.family()) {
344 case AF_INET: return compare_ipv4(*this, other);
345 case AF_INET6: return compare_ipv4_ipv6(*this, other);
346 }
347 break;
348 case AF_INET6:
349 switch (other.family()) {
350 case AF_INET: {
351 CompareResult c = compare_ipv4_ipv6(other, *this);
352 switch (c) {
353 case SocketAddress::CompareResult::NOT_COMPARABLE:
354 // Fall through
355 case SocketAddress::CompareResult::SAME:
356 return c;
357 case SocketAddress::CompareResult::GREATER_THAN:
358 return SocketAddress::CompareResult::LESS_THAN;
359 case SocketAddress::CompareResult::LESS_THAN:
360 return SocketAddress::CompareResult::GREATER_THAN;
361 }
362 break;
363 }
364 case AF_INET6: return compare_ipv6(*this, other);
365 }
366 break;
367 }
368 return SocketAddress::CompareResult::NOT_COMPARABLE;
369 }
370
is_in_network(const SocketAddress & other,int prefix) const371 bool SocketAddress::is_in_network(
372 const SocketAddress& other,
373 int prefix) const {
374
375 switch (family()) {
376 case AF_INET:
377 switch (other.family()) {
378 case AF_INET: return in_network_ipv4(*this, other, prefix);
379 case AF_INET6: return in_network_ipv4_ipv6(*this, other, prefix);
380 }
381 break;
382 case AF_INET6:
383 switch (other.family()) {
384 case AF_INET: return in_network_ipv6_ipv4(*this, other, prefix);
385 case AF_INET6: return in_network_ipv6(*this, other, prefix);
386 }
387 break;
388 }
389
390 return false;
391 }
392
SocketAddressBlockList(std::shared_ptr<SocketAddressBlockList> parent)393 SocketAddressBlockList::SocketAddressBlockList(
394 std::shared_ptr<SocketAddressBlockList> parent)
395 : parent_(parent) {}
396
AddSocketAddress(const std::shared_ptr<SocketAddress> & address)397 void SocketAddressBlockList::AddSocketAddress(
398 const std::shared_ptr<SocketAddress>& address) {
399 Mutex::ScopedLock lock(mutex_);
400 std::unique_ptr<Rule> rule =
401 std::make_unique<SocketAddressRule>(address);
402 rules_.emplace_front(std::move(rule));
403 address_rules_[*address.get()] = rules_.begin();
404 }
405
RemoveSocketAddress(const std::shared_ptr<SocketAddress> & address)406 void SocketAddressBlockList::RemoveSocketAddress(
407 const std::shared_ptr<SocketAddress>& address) {
408 Mutex::ScopedLock lock(mutex_);
409 auto it = address_rules_.find(*address.get());
410 if (it != std::end(address_rules_)) {
411 rules_.erase(it->second);
412 address_rules_.erase(it);
413 }
414 }
415
AddSocketAddressRange(const std::shared_ptr<SocketAddress> & start,const std::shared_ptr<SocketAddress> & end)416 void SocketAddressBlockList::AddSocketAddressRange(
417 const std::shared_ptr<SocketAddress>& start,
418 const std::shared_ptr<SocketAddress>& end) {
419 Mutex::ScopedLock lock(mutex_);
420 std::unique_ptr<Rule> rule =
421 std::make_unique<SocketAddressRangeRule>(start, end);
422 rules_.emplace_front(std::move(rule));
423 }
424
AddSocketAddressMask(const std::shared_ptr<SocketAddress> & network,int prefix)425 void SocketAddressBlockList::AddSocketAddressMask(
426 const std::shared_ptr<SocketAddress>& network,
427 int prefix) {
428 Mutex::ScopedLock lock(mutex_);
429 std::unique_ptr<Rule> rule =
430 std::make_unique<SocketAddressMaskRule>(network, prefix);
431 rules_.emplace_front(std::move(rule));
432 }
433
Apply(const std::shared_ptr<SocketAddress> & address)434 bool SocketAddressBlockList::Apply(
435 const std::shared_ptr<SocketAddress>& address) {
436 Mutex::ScopedLock lock(mutex_);
437 for (const auto& rule : rules_) {
438 if (rule->Apply(address))
439 return true;
440 }
441 return parent_ ? parent_->Apply(address) : false;
442 }
443
SocketAddressRule(const std::shared_ptr<SocketAddress> & address_)444 SocketAddressBlockList::SocketAddressRule::SocketAddressRule(
445 const std::shared_ptr<SocketAddress>& address_)
446 : address(address_) {}
447
SocketAddressRangeRule(const std::shared_ptr<SocketAddress> & start_,const std::shared_ptr<SocketAddress> & end_)448 SocketAddressBlockList::SocketAddressRangeRule::SocketAddressRangeRule(
449 const std::shared_ptr<SocketAddress>& start_,
450 const std::shared_ptr<SocketAddress>& end_)
451 : start(start_),
452 end(end_) {}
453
SocketAddressMaskRule(const std::shared_ptr<SocketAddress> & network_,int prefix_)454 SocketAddressBlockList::SocketAddressMaskRule::SocketAddressMaskRule(
455 const std::shared_ptr<SocketAddress>& network_,
456 int prefix_)
457 : network(network_),
458 prefix(prefix_) {}
459
Apply(const std::shared_ptr<SocketAddress> & address)460 bool SocketAddressBlockList::SocketAddressRule::Apply(
461 const std::shared_ptr<SocketAddress>& address) {
462 return this->address->is_match(*address.get());
463 }
464
ToString()465 std::string SocketAddressBlockList::SocketAddressRule::ToString() {
466 std::string ret = "Address: ";
467 ret += address->family() == AF_INET ? "IPv4" : "IPv6";
468 ret += " ";
469 ret += address->address();
470 return ret;
471 }
472
Apply(const std::shared_ptr<SocketAddress> & address)473 bool SocketAddressBlockList::SocketAddressRangeRule::Apply(
474 const std::shared_ptr<SocketAddress>& address) {
475 return *address.get() >= *start.get() &&
476 *address.get() <= *end.get();
477 }
478
ToString()479 std::string SocketAddressBlockList::SocketAddressRangeRule::ToString() {
480 std::string ret = "Range: ";
481 ret += start->family() == AF_INET ? "IPv4" : "IPv6";
482 ret += " ";
483 ret += start->address();
484 ret += "-";
485 ret += end->address();
486 return ret;
487 }
488
Apply(const std::shared_ptr<SocketAddress> & address)489 bool SocketAddressBlockList::SocketAddressMaskRule::Apply(
490 const std::shared_ptr<SocketAddress>& address) {
491 return address->is_in_network(*network.get(), prefix);
492 }
493
ToString()494 std::string SocketAddressBlockList::SocketAddressMaskRule::ToString() {
495 std::string ret = "Subnet: ";
496 ret += network->family() == AF_INET ? "IPv4" : "IPv6";
497 ret += " ";
498 ret += network->address();
499 ret += "/" + std::to_string(prefix);
500 return ret;
501 }
502
ListRules(Environment * env)503 MaybeLocal<Array> SocketAddressBlockList::ListRules(Environment* env) {
504 Mutex::ScopedLock lock(mutex_);
505 std::vector<Local<Value>> rules;
506 if (!ListRules(env, &rules))
507 return MaybeLocal<Array>();
508 return Array::New(env->isolate(), rules.data(), rules.size());
509 }
510
ListRules(Environment * env,std::vector<v8::Local<v8::Value>> * rules)511 bool SocketAddressBlockList::ListRules(
512 Environment* env,
513 std::vector<v8::Local<v8::Value>>* rules) {
514 if (parent_ && !parent_->ListRules(env, rules))
515 return false;
516 for (const auto& rule : rules_) {
517 Local<Value> str;
518 if (!rule->ToV8String(env).ToLocal(&str))
519 return false;
520 rules->push_back(str);
521 }
522 return true;
523 }
524
MemoryInfo(node::MemoryTracker * tracker) const525 void SocketAddressBlockList::MemoryInfo(node::MemoryTracker* tracker) const {
526 tracker->TrackField("rules", rules_);
527 }
528
MemoryInfo(node::MemoryTracker * tracker) const529 void SocketAddressBlockList::SocketAddressRule::MemoryInfo(
530 node::MemoryTracker* tracker) const {
531 tracker->TrackField("address", address);
532 }
533
MemoryInfo(node::MemoryTracker * tracker) const534 void SocketAddressBlockList::SocketAddressRangeRule::MemoryInfo(
535 node::MemoryTracker* tracker) const {
536 tracker->TrackField("start", start);
537 tracker->TrackField("end", end);
538 }
539
MemoryInfo(node::MemoryTracker * tracker) const540 void SocketAddressBlockList::SocketAddressMaskRule::MemoryInfo(
541 node::MemoryTracker* tracker) const {
542 tracker->TrackField("network", network);
543 }
544
SocketAddressBlockListWrap(Environment * env,Local<Object> wrap,std::shared_ptr<SocketAddressBlockList> blocklist)545 SocketAddressBlockListWrap::SocketAddressBlockListWrap(
546 Environment* env,
547 Local<Object> wrap,
548 std::shared_ptr<SocketAddressBlockList> blocklist)
549 : BaseObject(env, wrap),
550 blocklist_(std::move(blocklist)) {
551 MakeWeak();
552 }
553
New(Environment * env)554 BaseObjectPtr<SocketAddressBlockListWrap> SocketAddressBlockListWrap::New(
555 Environment* env) {
556 Local<Object> obj;
557 if (!env->blocklist_constructor_template()
558 ->InstanceTemplate()
559 ->NewInstance(env->context()).ToLocal(&obj)) {
560 return BaseObjectPtr<SocketAddressBlockListWrap>();
561 }
562 BaseObjectPtr<SocketAddressBlockListWrap> wrap =
563 MakeBaseObject<SocketAddressBlockListWrap>(env, obj);
564 CHECK(wrap);
565 return wrap;
566 }
567
New(Environment * env,std::shared_ptr<SocketAddressBlockList> blocklist)568 BaseObjectPtr<SocketAddressBlockListWrap> SocketAddressBlockListWrap::New(
569 Environment* env,
570 std::shared_ptr<SocketAddressBlockList> blocklist) {
571 Local<Object> obj;
572 if (!env->blocklist_constructor_template()
573 ->InstanceTemplate()
574 ->NewInstance(env->context()).ToLocal(&obj)) {
575 return BaseObjectPtr<SocketAddressBlockListWrap>();
576 }
577 BaseObjectPtr<SocketAddressBlockListWrap> wrap =
578 MakeBaseObject<SocketAddressBlockListWrap>(
579 env,
580 obj,
581 std::move(blocklist));
582 CHECK(wrap);
583 return wrap;
584 }
585
New(const FunctionCallbackInfo<Value> & args)586 void SocketAddressBlockListWrap::New(
587 const FunctionCallbackInfo<Value>& args) {
588 CHECK(args.IsConstructCall());
589 Environment* env = Environment::GetCurrent(args);
590 new SocketAddressBlockListWrap(env, args.This());
591 }
592
AddAddress(const FunctionCallbackInfo<Value> & args)593 void SocketAddressBlockListWrap::AddAddress(
594 const FunctionCallbackInfo<Value>& args) {
595 Environment* env = Environment::GetCurrent(args);
596 SocketAddressBlockListWrap* wrap;
597 ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
598
599 CHECK(SocketAddressBase::HasInstance(env, args[0]));
600 SocketAddressBase* addr;
601 ASSIGN_OR_RETURN_UNWRAP(&addr, args[0]);
602
603 wrap->blocklist_->AddSocketAddress(addr->address());
604
605 args.GetReturnValue().Set(true);
606 }
607
AddRange(const FunctionCallbackInfo<Value> & args)608 void SocketAddressBlockListWrap::AddRange(
609 const FunctionCallbackInfo<Value>& args) {
610 Environment* env = Environment::GetCurrent(args);
611 SocketAddressBlockListWrap* wrap;
612 ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
613
614 CHECK(SocketAddressBase::HasInstance(env, args[0]));
615 CHECK(SocketAddressBase::HasInstance(env, args[1]));
616
617 SocketAddressBase* start_addr;
618 SocketAddressBase* end_addr;
619 ASSIGN_OR_RETURN_UNWRAP(&start_addr, args[0]);
620 ASSIGN_OR_RETURN_UNWRAP(&end_addr, args[1]);
621
622 // Starting address must come before the end address
623 if (*start_addr->address().get() > *end_addr->address().get())
624 return args.GetReturnValue().Set(false);
625
626 wrap->blocklist_->AddSocketAddressRange(
627 start_addr->address(),
628 end_addr->address());
629
630 args.GetReturnValue().Set(true);
631 }
632
AddSubnet(const FunctionCallbackInfo<Value> & args)633 void SocketAddressBlockListWrap::AddSubnet(
634 const FunctionCallbackInfo<Value>& args) {
635 Environment* env = Environment::GetCurrent(args);
636 SocketAddressBlockListWrap* wrap;
637 ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
638
639 CHECK(SocketAddressBase::HasInstance(env, args[0]));
640 CHECK(args[1]->IsInt32());
641
642 SocketAddressBase* addr;
643 ASSIGN_OR_RETURN_UNWRAP(&addr, args[0]);
644
645 int32_t prefix;
646 if (!args[1]->Int32Value(env->context()).To(&prefix)) {
647 return;
648 }
649
650 CHECK_IMPLIES(addr->address()->family() == AF_INET, prefix <= 32);
651 CHECK_IMPLIES(addr->address()->family() == AF_INET6, prefix <= 128);
652 CHECK_GE(prefix, 0);
653
654 wrap->blocklist_->AddSocketAddressMask(addr->address(), prefix);
655
656 args.GetReturnValue().Set(true);
657 }
658
Check(const FunctionCallbackInfo<Value> & args)659 void SocketAddressBlockListWrap::Check(
660 const FunctionCallbackInfo<Value>& args) {
661 Environment* env = Environment::GetCurrent(args);
662 SocketAddressBlockListWrap* wrap;
663 ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
664
665 CHECK(SocketAddressBase::HasInstance(env, args[0]));
666 SocketAddressBase* addr;
667 ASSIGN_OR_RETURN_UNWRAP(&addr, args[0]);
668
669 args.GetReturnValue().Set(wrap->blocklist_->Apply(addr->address()));
670 }
671
GetRules(const FunctionCallbackInfo<Value> & args)672 void SocketAddressBlockListWrap::GetRules(
673 const FunctionCallbackInfo<Value>& args) {
674 Environment* env = Environment::GetCurrent(args);
675 SocketAddressBlockListWrap* wrap;
676 ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
677 Local<Array> rules;
678 if (wrap->blocklist_->ListRules(env).ToLocal(&rules))
679 args.GetReturnValue().Set(rules);
680 }
681
MemoryInfo(MemoryTracker * tracker) const682 void SocketAddressBlockListWrap::MemoryInfo(MemoryTracker* tracker) const {
683 blocklist_->MemoryInfo(tracker);
684 }
685
686 std::unique_ptr<worker::TransferData>
CloneForMessaging() const687 SocketAddressBlockListWrap::CloneForMessaging() const {
688 return std::make_unique<TransferData>(this);
689 }
690
HasInstance(Environment * env,Local<Value> value)691 bool SocketAddressBlockListWrap::HasInstance(
692 Environment* env,
693 Local<Value> value) {
694 return GetConstructorTemplate(env)->HasInstance(value);
695 }
696
GetConstructorTemplate(Environment * env)697 Local<FunctionTemplate> SocketAddressBlockListWrap::GetConstructorTemplate(
698 Environment* env) {
699 Local<FunctionTemplate> tmpl = env->blocklist_constructor_template();
700 if (tmpl.IsEmpty()) {
701 Isolate* isolate = env->isolate();
702 tmpl = NewFunctionTemplate(isolate, SocketAddressBlockListWrap::New);
703 tmpl->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "BlockList"));
704 tmpl->Inherit(BaseObject::GetConstructorTemplate(env));
705 tmpl->InstanceTemplate()->SetInternalFieldCount(kInternalFieldCount);
706 SetProtoMethod(isolate, tmpl, "addAddress", AddAddress);
707 SetProtoMethod(isolate, tmpl, "addRange", AddRange);
708 SetProtoMethod(isolate, tmpl, "addSubnet", AddSubnet);
709 SetProtoMethod(isolate, tmpl, "check", Check);
710 SetProtoMethod(isolate, tmpl, "getRules", GetRules);
711 env->set_blocklist_constructor_template(tmpl);
712 }
713 return tmpl;
714 }
715
Initialize(Local<Object> target,Local<Value> unused,Local<Context> context,void * priv)716 void SocketAddressBlockListWrap::Initialize(
717 Local<Object> target,
718 Local<Value> unused,
719 Local<Context> context,
720 void* priv) {
721 Environment* env = Environment::GetCurrent(context);
722
723 SetConstructorFunction(context,
724 target,
725 "BlockList",
726 GetConstructorTemplate(env),
727 SetConstructorFunctionFlag::NONE);
728
729 SocketAddressBase::Initialize(env, target);
730
731 NODE_DEFINE_CONSTANT(target, AF_INET);
732 NODE_DEFINE_CONSTANT(target, AF_INET6);
733 }
734
Deserialize(Environment * env,Local<Context> context,std::unique_ptr<worker::TransferData> self)735 BaseObjectPtr<BaseObject> SocketAddressBlockListWrap::TransferData::Deserialize(
736 Environment* env,
737 Local<Context> context,
738 std::unique_ptr<worker::TransferData> self) {
739 return New(env, std::move(blocklist_));
740 }
741
MemoryInfo(MemoryTracker * tracker) const742 void SocketAddressBlockListWrap::TransferData::MemoryInfo(
743 MemoryTracker* tracker) const {
744 blocklist_->MemoryInfo(tracker);
745 }
746
HasInstance(Environment * env,Local<Value> value)747 bool SocketAddressBase::HasInstance(Environment* env, Local<Value> value) {
748 return GetConstructorTemplate(env)->HasInstance(value);
749 }
750
GetConstructorTemplate(Environment * env)751 Local<FunctionTemplate> SocketAddressBase::GetConstructorTemplate(
752 Environment* env) {
753 Local<FunctionTemplate> tmpl = env->socketaddress_constructor_template();
754 if (tmpl.IsEmpty()) {
755 Isolate* isolate = env->isolate();
756 tmpl = NewFunctionTemplate(isolate, New);
757 tmpl->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "SocketAddress"));
758 tmpl->InstanceTemplate()->SetInternalFieldCount(
759 SocketAddressBase::kInternalFieldCount);
760 tmpl->Inherit(BaseObject::GetConstructorTemplate(env));
761 SetProtoMethod(isolate, tmpl, "detail", Detail);
762 SetProtoMethod(isolate, tmpl, "legacyDetail", LegacyDetail);
763 SetProtoMethodNoSideEffect(isolate, tmpl, "flowlabel", GetFlowLabel);
764 env->set_socketaddress_constructor_template(tmpl);
765 }
766 return tmpl;
767 }
768
Initialize(Environment * env,Local<Object> target)769 void SocketAddressBase::Initialize(Environment* env, Local<Object> target) {
770 SetConstructorFunction(env->context(),
771 target,
772 "SocketAddress",
773 GetConstructorTemplate(env),
774 SetConstructorFunctionFlag::NONE);
775 }
776
Create(Environment * env,std::shared_ptr<SocketAddress> address)777 BaseObjectPtr<SocketAddressBase> SocketAddressBase::Create(
778 Environment* env,
779 std::shared_ptr<SocketAddress> address) {
780 Local<Object> obj;
781 if (!GetConstructorTemplate(env)
782 ->InstanceTemplate()
783 ->NewInstance(env->context()).ToLocal(&obj)) {
784 return BaseObjectPtr<SocketAddressBase>();
785 }
786
787 return MakeBaseObject<SocketAddressBase>(env, obj, std::move(address));
788 }
789
New(const FunctionCallbackInfo<Value> & args)790 void SocketAddressBase::New(const FunctionCallbackInfo<Value>& args) {
791 Environment* env = Environment::GetCurrent(args);
792 CHECK(args.IsConstructCall());
793 CHECK(args[0]->IsString()); // address
794 CHECK(args[1]->IsInt32()); // port
795 CHECK(args[2]->IsInt32()); // family
796 CHECK(args[3]->IsUint32()); // flow label
797
798 Utf8Value address(env->isolate(), args[0]);
799 int32_t port = args[1].As<Int32>()->Value();
800 int32_t family = args[2].As<Int32>()->Value();
801 uint32_t flow_label = args[3].As<Uint32>()->Value();
802
803 std::shared_ptr<SocketAddress> addr = std::make_shared<SocketAddress>();
804
805 if (!SocketAddress::New(family, *address, port, addr.get()))
806 return THROW_ERR_INVALID_ADDRESS(env);
807
808 addr->set_flow_label(flow_label);
809
810 new SocketAddressBase(env, args.This(), std::move(addr));
811 }
812
Detail(const FunctionCallbackInfo<Value> & args)813 void SocketAddressBase::Detail(const FunctionCallbackInfo<Value>& args) {
814 Environment* env = Environment::GetCurrent(args);
815 CHECK(args[0]->IsObject());
816 Local<Object> detail = args[0].As<Object>();
817
818 SocketAddressBase* base;
819 ASSIGN_OR_RETURN_UNWRAP(&base, args.Holder());
820
821 Local<Value> address;
822 if (!ToV8Value(env->context(), base->address_->address()).ToLocal(&address))
823 return;
824
825 if (detail->Set(env->context(), env->address_string(), address).IsJust() &&
826 detail->Set(
827 env->context(),
828 env->port_string(),
829 Int32::New(env->isolate(), base->address_->port())).IsJust() &&
830 detail->Set(
831 env->context(),
832 env->family_string(),
833 Int32::New(env->isolate(), base->address_->family())).IsJust() &&
834 detail->Set(
835 env->context(),
836 env->flowlabel_string(),
837 Uint32::New(env->isolate(), base->address_->flow_label()))
838 .IsJust()) {
839 args.GetReturnValue().Set(detail);
840 }
841 }
842
GetFlowLabel(const FunctionCallbackInfo<Value> & args)843 void SocketAddressBase::GetFlowLabel(const FunctionCallbackInfo<Value>& args) {
844 SocketAddressBase* base;
845 ASSIGN_OR_RETURN_UNWRAP(&base, args.Holder());
846 args.GetReturnValue().Set(base->address_->flow_label());
847 }
848
LegacyDetail(const FunctionCallbackInfo<Value> & args)849 void SocketAddressBase::LegacyDetail(const FunctionCallbackInfo<Value>& args) {
850 Environment* env = Environment::GetCurrent(args);
851 SocketAddressBase* base;
852 ASSIGN_OR_RETURN_UNWRAP(&base, args.Holder());
853 Local<Object> address;
854 if (!base->address_->ToJS(env).ToLocal(&address)) return;
855 args.GetReturnValue().Set(address);
856 }
857
SocketAddressBase(Environment * env,Local<Object> wrap,std::shared_ptr<SocketAddress> address)858 SocketAddressBase::SocketAddressBase(
859 Environment* env,
860 Local<Object> wrap,
861 std::shared_ptr<SocketAddress> address)
862 : BaseObject(env, wrap),
863 address_(std::move(address)) {
864 MakeWeak();
865 }
866
MemoryInfo(MemoryTracker * tracker) const867 void SocketAddressBase::MemoryInfo(MemoryTracker* tracker) const {
868 tracker->TrackField("address", address_);
869 }
870
871 std::unique_ptr<worker::TransferData>
CloneForMessaging() const872 SocketAddressBase::CloneForMessaging() const {
873 return std::make_unique<TransferData>(this);
874 }
875
MemoryInfo(MemoryTracker * tracker) const876 void SocketAddressBase::TransferData::MemoryInfo(MemoryTracker* tracker) const {
877 tracker->TrackField("address", address_);
878 }
879
Deserialize(Environment * env,v8::Local<v8::Context> context,std::unique_ptr<worker::TransferData> self)880 BaseObjectPtr<BaseObject> SocketAddressBase::TransferData::Deserialize(
881 Environment* env,
882 v8::Local<v8::Context> context,
883 std::unique_ptr<worker::TransferData> self) {
884 return SocketAddressBase::Create(env, std::move(address_));
885 }
886
887 } // namespace node
888
889 NODE_BINDING_CONTEXT_AWARE_INTERNAL(
890 block_list, node::SocketAddressBlockListWrap::Initialize)
891