• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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