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