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