diff options
author | James M Snell <jasnell@gmail.com> | 2020-08-05 02:03:30 +0300 |
---|---|---|
committer | James M Snell <jasnell@gmail.com> | 2020-08-11 21:13:17 +0300 |
commit | 1f9b20b6376e0949807729ef46727a4fafad7f1d (patch) | |
tree | 3448933182ca47dd949e93ead90a25a65d8272df /src/node_sockaddr.h | |
parent | 6e1f6ec57398689740ab29acb6ce49bc94b95c79 (diff) |
net: introduce net.BlockList
`net.BlockList` provides an object intended to be used by net APIs to
specify rules for disallowing network activity with specific IP
addresses. This commit adds the basic mechanism but does not add the
specific uses.
PR-URL: https://github.com/nodejs/node/pull/34625
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Bradley Farias <bradley.meck@gmail.com>
Diffstat (limited to 'src/node_sockaddr.h')
-rw-r--r-- | src/node_sockaddr.h | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/src/node_sockaddr.h b/src/node_sockaddr.h index 5d20487f93d..f539cf6555f 100644 --- a/src/node_sockaddr.h +++ b/src/node_sockaddr.h @@ -3,11 +3,14 @@ #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS +#include "env.h" #include "memory_tracker.h" +#include "base_object.h" #include "node.h" #include "uv.h" #include "v8.h" +#include <memory> #include <string> #include <list> #include <unordered_map> @@ -18,6 +21,13 @@ class Environment; class SocketAddress : public MemoryRetainer { public: + enum class CompareResult { + NOT_COMPARABLE = -2, + LESS_THAN, + SAME, + GREATER_THAN + }; + struct Hash { size_t operator()(const SocketAddress& addr) const; }; @@ -25,6 +35,11 @@ class SocketAddress : public MemoryRetainer { inline bool operator==(const SocketAddress& other) const; inline bool operator!=(const SocketAddress& other) const; + inline bool operator<(const SocketAddress& other) const; + inline bool operator>(const SocketAddress& other) const; + inline bool operator<=(const SocketAddress& other) const; + inline bool operator>=(const SocketAddress& other) const; + inline static bool is_numeric_host(const char* hostname); inline static bool is_numeric_host(const char* hostname, int family); @@ -78,6 +93,20 @@ class SocketAddress : public MemoryRetainer { inline std::string address() const; inline int port() const; + // Returns true if the given other SocketAddress is a match + // for this one. The addresses are a match if: + // 1. They are the same family and match identically + // 2. They are different family but match semantically ( + // for instance, an IPv4 addres in IPv6 notation) + bool is_match(const SocketAddress& other) const; + + // Compares this SocketAddress to the given other SocketAddress. + CompareResult compare(const SocketAddress& other) const; + + // Returns true if this SocketAddress is within the subnet + // identified by the given network address and CIDR prefix. + bool is_in_network(const SocketAddress& network, int prefix) const; + // If the SocketAddress is an IPv6 address, returns the // current value of the IPv6 flow label, if set. Otherwise // returns 0. @@ -152,6 +181,123 @@ class SocketAddressLRU : public MemoryRetainer { size_t max_size_; }; +// A BlockList is used to evaluate whether a given +// SocketAddress should be accepted for inbound or +// outbound network activity. +class SocketAddressBlockList : public MemoryRetainer { + public: + explicit SocketAddressBlockList( + std::shared_ptr<SocketAddressBlockList> parent = {}); + ~SocketAddressBlockList() = default; + + void AddSocketAddress( + const SocketAddress& address); + + void RemoveSocketAddress( + const SocketAddress& address); + + void AddSocketAddressRange( + const SocketAddress& start, + const SocketAddress& end); + + void AddSocketAddressMask( + const SocketAddress& address, + int prefix); + + bool Apply(const SocketAddress& address); + + size_t size() const { return rules_.size(); } + + v8::MaybeLocal<v8::Array> ListRules(Environment* env); + + struct Rule : public MemoryRetainer { + virtual bool Apply(const SocketAddress& address) = 0; + inline v8::MaybeLocal<v8::Value> ToV8String(Environment* env); + virtual std::string ToString() = 0; + }; + + struct SocketAddressRule final : Rule { + SocketAddress address; + + explicit SocketAddressRule(const SocketAddress& address); + + bool Apply(const SocketAddress& address) override; + std::string ToString() override; + + void MemoryInfo(node::MemoryTracker* tracker) const override; + SET_MEMORY_INFO_NAME(SocketAddressRule) + SET_SELF_SIZE(SocketAddressRule) + }; + + struct SocketAddressRangeRule final : Rule { + SocketAddress start; + SocketAddress end; + + SocketAddressRangeRule( + const SocketAddress& start, + const SocketAddress& end); + + bool Apply(const SocketAddress& address) override; + std::string ToString() override; + + void MemoryInfo(node::MemoryTracker* tracker) const override; + SET_MEMORY_INFO_NAME(SocketAddressRangeRule) + SET_SELF_SIZE(SocketAddressRangeRule) + }; + + struct SocketAddressMaskRule final : Rule { + SocketAddress network; + int prefix; + + SocketAddressMaskRule( + const SocketAddress& address, + int prefix); + + bool Apply(const SocketAddress& address) override; + std::string ToString() override; + + void MemoryInfo(node::MemoryTracker* tracker) const override; + SET_MEMORY_INFO_NAME(SocketAddressMaskRule) + SET_SELF_SIZE(SocketAddressMaskRule) + }; + + void MemoryInfo(node::MemoryTracker* tracker) const override; + SET_MEMORY_INFO_NAME(SocketAddressBlockList) + SET_SELF_SIZE(SocketAddressBlockList) + + private: + std::shared_ptr<SocketAddressBlockList> parent_; + std::list<std::unique_ptr<Rule>> rules_; + SocketAddress::Map<std::list<std::unique_ptr<Rule>>::iterator> address_rules_; +}; + +class SocketAddressBlockListWrap : + public BaseObject, + public SocketAddressBlockList { + public: + static void Initialize(v8::Local<v8::Object> target, + v8::Local<v8::Value> unused, + v8::Local<v8::Context> context, + void* priv); + + static void New(const v8::FunctionCallbackInfo<v8::Value>& args); + static void AddAddress(const v8::FunctionCallbackInfo<v8::Value>& args); + static void AddRange(const v8::FunctionCallbackInfo<v8::Value>& args); + static void AddSubnet(const v8::FunctionCallbackInfo<v8::Value>& args); + static void Check(const v8::FunctionCallbackInfo<v8::Value>& args); + static void GetRules(const v8::FunctionCallbackInfo<v8::Value>& args); + + SocketAddressBlockListWrap( + Environment* env, + v8::Local<v8::Object> wrap); + + void MemoryInfo(node::MemoryTracker* tracker) const override { + SocketAddressBlockList::MemoryInfo(tracker); + } + SET_MEMORY_INFO_NAME(SocketAddressBlockListWrap) + SET_SELF_SIZE(SocketAddressBlockListWrap) +}; + } // namespace node #endif // NOE_WANT_INTERNALS |