• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #ifndef SRC_NODE_SOCKADDR_H_
2 #define SRC_NODE_SOCKADDR_H_
3 
4 #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
5 
6 #include "env.h"
7 #include "memory_tracker.h"
8 #include "base_object.h"
9 #include "node.h"
10 #include "node_worker.h"
11 #include "uv.h"
12 #include "v8.h"
13 
14 #include <memory>
15 #include <string>
16 #include <list>
17 #include <unordered_map>
18 
19 namespace node {
20 
21 class Environment;
22 
23 class SocketAddress : public MemoryRetainer {
24  public:
25   enum class CompareResult {
26     NOT_COMPARABLE = -2,
27     LESS_THAN,
28     SAME,
29     GREATER_THAN
30   };
31 
32   struct Hash {
33     size_t operator()(const SocketAddress& addr) const;
34   };
35 
36   inline bool operator==(const SocketAddress& other) const;
37   inline bool operator!=(const SocketAddress& other) const;
38 
39   inline bool operator<(const SocketAddress& other) const;
40   inline bool operator>(const SocketAddress& other) const;
41   inline bool operator<=(const SocketAddress& other) const;
42   inline bool operator>=(const SocketAddress& other) const;
43 
44   inline static bool is_numeric_host(const char* hostname);
45   inline static bool is_numeric_host(const char* hostname, int family);
46 
47   // Returns true if converting {family, host, port} to *addr succeeded.
48   static bool ToSockAddr(
49       int32_t family,
50       const char* host,
51       uint32_t port,
52       sockaddr_storage* addr);
53 
54   // Returns true if converting {family, host, port} to *addr succeeded.
55   static bool New(
56       int32_t family,
57       const char* host,
58       uint32_t port,
59       SocketAddress* addr);
60 
61   static bool New(
62       const char* host,
63       uint32_t port,
64       SocketAddress* addr);
65 
66   // Returns the port for an IPv4 or IPv6 address.
67   inline static int GetPort(const sockaddr* addr);
68   inline static int GetPort(const sockaddr_storage* addr);
69 
70   // Returns the numeric host as a string for an IPv4 or IPv6 address.
71   inline static std::string GetAddress(const sockaddr* addr);
72   inline static std::string GetAddress(const sockaddr_storage* addr);
73 
74   // Returns the struct length for an IPv4, IPv6 or UNIX domain.
75   inline static size_t GetLength(const sockaddr* addr);
76   inline static size_t GetLength(const sockaddr_storage* addr);
77 
78   SocketAddress() = default;
79 
80   inline explicit SocketAddress(const sockaddr* addr);
81   inline SocketAddress(const SocketAddress& addr);
82   inline SocketAddress& operator=(const sockaddr* other);
83   inline SocketAddress& operator=(const SocketAddress& other);
84 
85   inline const sockaddr& operator*() const;
86   inline const sockaddr* operator->() const;
87 
88   inline const sockaddr* data() const;
89   inline const uint8_t* raw() const;
90   inline sockaddr* storage();
91   inline size_t length() const;
92 
93   inline int family() const;
94   inline std::string address() const;
95   inline int port() const;
96 
97   // Returns true if the given other SocketAddress is a match
98   // for this one. The addresses are a match if:
99   // 1. They are the same family and match identically
100   // 2. They are different family but match semantically (
101   //     for instance, an IPv4 address in IPv6 notation)
102   bool is_match(const SocketAddress& other) const;
103 
104   // Compares this SocketAddress to the given other SocketAddress.
105   CompareResult compare(const SocketAddress& other) const;
106 
107   // Returns true if this SocketAddress is within the subnet
108   // identified by the given network address and CIDR prefix.
109   bool is_in_network(const SocketAddress& network, int prefix) const;
110 
111   // If the SocketAddress is an IPv6 address, returns the
112   // current value of the IPv6 flow label, if set. Otherwise
113   // returns 0.
114   inline uint32_t flow_label() const;
115 
116   // If the SocketAddress is an IPv6 address, sets the
117   // current value of the IPv6 flow label. If not an
118   // IPv6 address, set_flow_label is a non-op. It
119   // is important to note that the flow label,
120   // while represented as an uint32_t, the flow
121   // label is strictly limited to 20 bits, and
122   // this will assert if any value larger than
123   // 20-bits is specified.
124   inline void set_flow_label(uint32_t label = 0);
125 
126   inline void Update(uint8_t* data, size_t len);
127   inline void Update(const sockaddr* data, size_t len);
128 
129   static SocketAddress FromSockName(const uv_udp_t& handle);
130   static SocketAddress FromSockName(const uv_tcp_t& handle);
131   static SocketAddress FromPeerName(const uv_udp_t& handle);
132   static SocketAddress FromPeerName(const uv_tcp_t& handle);
133 
134   inline v8::MaybeLocal<v8::Object> ToJS(
135       Environment* env,
136       v8::Local<v8::Object> obj = v8::Local<v8::Object>()) const;
137 
138   inline std::string ToString() const;
139 
140   SET_NO_MEMORY_INFO()
141   SET_MEMORY_INFO_NAME(SocketAddress)
142   SET_SELF_SIZE(SocketAddress)
143 
144   template <typename T>
145   using Map = std::unordered_map<SocketAddress, T, Hash>;
146 
147  private:
148   sockaddr_storage address_;
149 };
150 
151 class SocketAddressBase : public BaseObject {
152  public:
153   static bool HasInstance(Environment* env, v8::Local<v8::Value> value);
154   static v8::Local<v8::FunctionTemplate> GetConstructorTemplate(
155       Environment* env);
156   static void Initialize(Environment* env, v8::Local<v8::Object> target);
157   static BaseObjectPtr<SocketAddressBase> Create(
158       Environment* env,
159       std::shared_ptr<SocketAddress> address);
160 
161   static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
162   static void Detail(const v8::FunctionCallbackInfo<v8::Value>& args);
163   static void LegacyDetail(const v8::FunctionCallbackInfo<v8::Value>& args);
164   static void GetFlowLabel(const v8::FunctionCallbackInfo<v8::Value>& args);
165 
166   SocketAddressBase(
167     Environment* env,
168     v8::Local<v8::Object> wrap,
169     std::shared_ptr<SocketAddress> address);
170 
address()171   inline const std::shared_ptr<SocketAddress>& address() const {
172     return address_;
173   }
174 
175   void MemoryInfo(MemoryTracker* tracker) const override;
176   SET_MEMORY_INFO_NAME(SocketAddressBase)
SET_SELF_SIZE(SocketAddressBase)177   SET_SELF_SIZE(SocketAddressBase)
178 
179   TransferMode GetTransferMode() const override {
180     return TransferMode::kCloneable;
181   }
182   std::unique_ptr<worker::TransferData> CloneForMessaging() const override;
183 
184   class TransferData : public worker::TransferData {
185    public:
TransferData(const SocketAddressBase * wrap)186     inline explicit TransferData(const SocketAddressBase* wrap)
187         : address_(wrap->address_) {}
188 
TransferData(std::shared_ptr<SocketAddress> address)189     inline explicit TransferData(std::shared_ptr<SocketAddress> address)
190         : address_(std::move(address)) {}
191 
192     BaseObjectPtr<BaseObject> Deserialize(
193         Environment* env,
194         v8::Local<v8::Context> context,
195         std::unique_ptr<worker::TransferData> self) override;
196 
197     void MemoryInfo(MemoryTracker* tracker) const override;
198     SET_MEMORY_INFO_NAME(SocketAddressBase::TransferData)
199     SET_SELF_SIZE(TransferData)
200 
201    private:
202     std::shared_ptr<SocketAddress> address_;
203   };
204 
205  private:
206   std::shared_ptr<SocketAddress> address_;
207 };
208 
209 template <typename T>
210 class SocketAddressLRU : public MemoryRetainer {
211  public:
212   using Type = typename T::Type;
213 
214   inline explicit SocketAddressLRU(size_t max_size);
215 
216   // If the item already exists, returns a reference to
217   // the existing item, adjusting items position in the
218   // LRU. If the item does not exist, emplaces the item
219   // and returns the new item.
220   Type* Upsert(const SocketAddress& address);
221 
222   // Returns a reference to the item if it exists, or
223   // nullptr. The position in the LRU is not modified.
224   Type* Peek(const SocketAddress& address) const;
225 
size()226   size_t size() const { return map_.size(); }
max_size()227   size_t max_size() const { return max_size_; }
228 
229   void MemoryInfo(MemoryTracker* tracker) const override;
230   SET_MEMORY_INFO_NAME(SocketAddressLRU)
231   SET_SELF_SIZE(SocketAddressLRU)
232 
233  private:
234   using Pair = std::pair<SocketAddress, Type>;
235   using Iterator = typename std::list<Pair>::iterator;
236 
237   void CheckExpired();
238 
239   std::list<Pair> list_;
240   SocketAddress::Map<Iterator> map_;
241   size_t max_size_;
242 };
243 
244 // A BlockList is used to evaluate whether a given
245 // SocketAddress should be accepted for inbound or
246 // outbound network activity.
247 class SocketAddressBlockList : public MemoryRetainer {
248  public:
249   explicit SocketAddressBlockList(
250       std::shared_ptr<SocketAddressBlockList> parent = {});
251   ~SocketAddressBlockList() = default;
252 
253   void AddSocketAddress(const std::shared_ptr<SocketAddress>& address);
254 
255   void RemoveSocketAddress(const std::shared_ptr<SocketAddress>& address);
256 
257   void AddSocketAddressRange(
258       const std::shared_ptr<SocketAddress>& start,
259       const std::shared_ptr<SocketAddress>& end);
260 
261   void AddSocketAddressMask(
262       const std::shared_ptr<SocketAddress>& address,
263       int prefix);
264 
265   bool Apply(const std::shared_ptr<SocketAddress>& address);
266 
size()267   size_t size() const { return rules_.size(); }
268 
269   v8::MaybeLocal<v8::Array> ListRules(Environment* env);
270 
271   struct Rule : public MemoryRetainer {
272     virtual bool Apply(const std::shared_ptr<SocketAddress>& address) = 0;
273     inline v8::MaybeLocal<v8::Value> ToV8String(Environment* env);
274     virtual std::string ToString() = 0;
275   };
276 
277   struct SocketAddressRule final : Rule {
278     std::shared_ptr<SocketAddress> address;
279 
280     explicit SocketAddressRule(const std::shared_ptr<SocketAddress>& address);
281 
282     bool Apply(const std::shared_ptr<SocketAddress>& address) override;
283     std::string ToString() override;
284 
285     void MemoryInfo(node::MemoryTracker* tracker) const override;
286     SET_MEMORY_INFO_NAME(SocketAddressRule)
287     SET_SELF_SIZE(SocketAddressRule)
288   };
289 
290   struct SocketAddressRangeRule final : Rule {
291     std::shared_ptr<SocketAddress> start;
292     std::shared_ptr<SocketAddress> end;
293 
294     SocketAddressRangeRule(
295         const std::shared_ptr<SocketAddress>& start,
296         const std::shared_ptr<SocketAddress>& end);
297 
298     bool Apply(const std::shared_ptr<SocketAddress>& address) override;
299     std::string ToString() override;
300 
301     void MemoryInfo(node::MemoryTracker* tracker) const override;
302     SET_MEMORY_INFO_NAME(SocketAddressRangeRule)
303     SET_SELF_SIZE(SocketAddressRangeRule)
304   };
305 
306   struct SocketAddressMaskRule final : Rule {
307     std::shared_ptr<SocketAddress> network;
308     int prefix;
309 
310     SocketAddressMaskRule(
311         const std::shared_ptr<SocketAddress>& address,
312         int prefix);
313 
314     bool Apply(const std::shared_ptr<SocketAddress>& address) override;
315     std::string ToString() override;
316 
317     void MemoryInfo(node::MemoryTracker* tracker) const override;
318     SET_MEMORY_INFO_NAME(SocketAddressMaskRule)
319     SET_SELF_SIZE(SocketAddressMaskRule)
320   };
321 
322   void MemoryInfo(node::MemoryTracker* tracker) const override;
323   SET_MEMORY_INFO_NAME(SocketAddressBlockList)
324   SET_SELF_SIZE(SocketAddressBlockList)
325 
326  private:
327   bool ListRules(
328       Environment* env,
329       std::vector<v8::Local<v8::Value>>* vec);
330 
331   std::shared_ptr<SocketAddressBlockList> parent_;
332   std::list<std::unique_ptr<Rule>> rules_;
333   SocketAddress::Map<std::list<std::unique_ptr<Rule>>::iterator> address_rules_;
334 
335   Mutex mutex_;
336 };
337 
338 class SocketAddressBlockListWrap : public BaseObject {
339  public:
340   static bool HasInstance(Environment* env, v8::Local<v8::Value> value);
341   static v8::Local<v8::FunctionTemplate> GetConstructorTemplate(
342       Environment* env);
343   static void Initialize(v8::Local<v8::Object> target,
344                          v8::Local<v8::Value> unused,
345                          v8::Local<v8::Context> context,
346                          void* priv);
347 
348   static BaseObjectPtr<SocketAddressBlockListWrap> New(Environment* env);
349   static BaseObjectPtr<SocketAddressBlockListWrap> New(
350       Environment* env,
351       std::shared_ptr<SocketAddressBlockList> blocklist);
352 
353   static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
354   static void AddAddress(const v8::FunctionCallbackInfo<v8::Value>& args);
355   static void AddRange(const v8::FunctionCallbackInfo<v8::Value>& args);
356   static void AddSubnet(const v8::FunctionCallbackInfo<v8::Value>& args);
357   static void Check(const v8::FunctionCallbackInfo<v8::Value>& args);
358   static void GetRules(const v8::FunctionCallbackInfo<v8::Value>& args);
359 
360   SocketAddressBlockListWrap(
361       Environment* env,
362       v8::Local<v8::Object> wrap,
363       std::shared_ptr<SocketAddressBlockList> blocklist =
364           std::make_shared<SocketAddressBlockList>());
365 
366   void MemoryInfo(node::MemoryTracker* tracker) const override;
367   SET_MEMORY_INFO_NAME(SocketAddressBlockListWrap)
SET_SELF_SIZE(SocketAddressBlockListWrap)368   SET_SELF_SIZE(SocketAddressBlockListWrap)
369 
370   TransferMode GetTransferMode() const override {
371     return TransferMode::kCloneable;
372   }
373   std::unique_ptr<worker::TransferData> CloneForMessaging() const override;
374 
375   class TransferData : public worker::TransferData {
376    public:
TransferData(const SocketAddressBlockListWrap * wrap)377     inline explicit TransferData(const SocketAddressBlockListWrap* wrap)
378         : blocklist_(wrap->blocklist_) {}
379 
TransferData(std::shared_ptr<SocketAddressBlockList> blocklist)380     inline explicit TransferData(
381         std::shared_ptr<SocketAddressBlockList> blocklist)
382         : blocklist_(std::move(blocklist)) {}
383 
384     BaseObjectPtr<BaseObject> Deserialize(
385         Environment* env,
386         v8::Local<v8::Context> context,
387         std::unique_ptr<worker::TransferData> self) override;
388 
389     void MemoryInfo(MemoryTracker* tracker) const override;
390     SET_MEMORY_INFO_NAME(SocketAddressBlockListWrap::TransferData)
391     SET_SELF_SIZE(TransferData)
392 
393    private:
394     std::shared_ptr<SocketAddressBlockList> blocklist_;
395   };
396 
397  private:
398   std::shared_ptr<SocketAddressBlockList> blocklist_;
399 };
400 
401 }  // namespace node
402 
403 #endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
404 
405 #endif  // SRC_NODE_SOCKADDR_H_
406