• 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 addres 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 
128   static SocketAddress FromSockName(const uv_udp_t& handle);
129   static SocketAddress FromSockName(const uv_tcp_t& handle);
130   static SocketAddress FromPeerName(const uv_udp_t& handle);
131   static SocketAddress FromPeerName(const uv_tcp_t& handle);
132 
133   inline v8::Local<v8::Object> ToJS(
134       Environment* env,
135       v8::Local<v8::Object> obj = v8::Local<v8::Object>()) const;
136 
137   inline std::string ToString() const;
138 
139   SET_NO_MEMORY_INFO()
140   SET_MEMORY_INFO_NAME(SocketAddress)
141   SET_SELF_SIZE(SocketAddress)
142 
143   template <typename T>
144   using Map = std::unordered_map<SocketAddress, T, Hash>;
145 
146  private:
147   sockaddr_storage address_;
148 };
149 
150 class SocketAddressBase : public BaseObject {
151  public:
152   static bool HasInstance(Environment* env, v8::Local<v8::Value> value);
153   static v8::Local<v8::FunctionTemplate> GetConstructorTemplate(
154       Environment* env);
155   static void Initialize(Environment* env, v8::Local<v8::Object> target);
156   static BaseObjectPtr<SocketAddressBase> Create(
157       Environment* env,
158       std::shared_ptr<SocketAddress> address);
159 
160   static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
161   static void Detail(const v8::FunctionCallbackInfo<v8::Value>& args);
162   static void LegacyDetail(const v8::FunctionCallbackInfo<v8::Value>& args);
163   static void GetFlowLabel(const v8::FunctionCallbackInfo<v8::Value>& args);
164 
165   SocketAddressBase(
166     Environment* env,
167     v8::Local<v8::Object> wrap,
168     std::shared_ptr<SocketAddress> address);
169 
address()170   inline const std::shared_ptr<SocketAddress>& address() const {
171     return address_;
172   }
173 
174   void MemoryInfo(MemoryTracker* tracker) const override;
175   SET_MEMORY_INFO_NAME(SocketAddressBase)
SET_SELF_SIZE(SocketAddressBase)176   SET_SELF_SIZE(SocketAddressBase)
177 
178   TransferMode GetTransferMode() const override {
179     return TransferMode::kCloneable;
180   }
181   std::unique_ptr<worker::TransferData> CloneForMessaging() const override;
182 
183   class TransferData : public worker::TransferData {
184    public:
TransferData(const SocketAddressBase * wrap)185     inline explicit TransferData(const SocketAddressBase* wrap)
186         : address_(wrap->address_) {}
187 
TransferData(std::shared_ptr<SocketAddress> address)188     inline explicit TransferData(std::shared_ptr<SocketAddress> address)
189         : address_(std::move(address)) {}
190 
191     BaseObjectPtr<BaseObject> Deserialize(
192         Environment* env,
193         v8::Local<v8::Context> context,
194         std::unique_ptr<worker::TransferData> self) override;
195 
196     void MemoryInfo(MemoryTracker* tracker) const override;
197     SET_MEMORY_INFO_NAME(SocketAddressBase::TransferData)
198     SET_SELF_SIZE(TransferData)
199 
200    private:
201     std::shared_ptr<SocketAddress> address_;
202   };
203 
204  private:
205   std::shared_ptr<SocketAddress> address_;
206 };
207 
208 template <typename T>
209 class SocketAddressLRU : public MemoryRetainer {
210  public:
211   using Type = typename T::Type;
212 
213   inline explicit SocketAddressLRU(size_t max_size);
214 
215   // If the item already exists, returns a reference to
216   // the existing item, adjusting items position in the
217   // LRU. If the item does not exist, emplaces the item
218   // and returns the new item.
219   Type* Upsert(const SocketAddress& address);
220 
221   // Returns a reference to the item if it exists, or
222   // nullptr. The position in the LRU is not modified.
223   Type* Peek(const SocketAddress& address) const;
224 
size()225   size_t size() const { return map_.size(); }
max_size()226   size_t max_size() const { return max_size_; }
227 
228   void MemoryInfo(MemoryTracker* tracker) const override;
229   SET_MEMORY_INFO_NAME(SocketAddressLRU)
230   SET_SELF_SIZE(SocketAddressLRU)
231 
232  private:
233   using Pair = std::pair<SocketAddress, Type>;
234   using Iterator = typename std::list<Pair>::iterator;
235 
236   void CheckExpired();
237 
238   std::list<Pair> list_;
239   SocketAddress::Map<Iterator> map_;
240   size_t max_size_;
241 };
242 
243 // A BlockList is used to evaluate whether a given
244 // SocketAddress should be accepted for inbound or
245 // outbound network activity.
246 class SocketAddressBlockList : public MemoryRetainer {
247  public:
248   explicit SocketAddressBlockList(
249       std::shared_ptr<SocketAddressBlockList> parent = {});
250   ~SocketAddressBlockList() = default;
251 
252   void AddSocketAddress(const std::shared_ptr<SocketAddress>& address);
253 
254   void RemoveSocketAddress(const std::shared_ptr<SocketAddress>& address);
255 
256   void AddSocketAddressRange(
257       const std::shared_ptr<SocketAddress>& start,
258       const std::shared_ptr<SocketAddress>& end);
259 
260   void AddSocketAddressMask(
261       const std::shared_ptr<SocketAddress>& address,
262       int prefix);
263 
264   bool Apply(const std::shared_ptr<SocketAddress>& address);
265 
size()266   size_t size() const { return rules_.size(); }
267 
268   v8::MaybeLocal<v8::Array> ListRules(Environment* env);
269 
270   struct Rule : public MemoryRetainer {
271     virtual bool Apply(const std::shared_ptr<SocketAddress>& address) = 0;
272     inline v8::MaybeLocal<v8::Value> ToV8String(Environment* env);
273     virtual std::string ToString() = 0;
274   };
275 
276   struct SocketAddressRule final : Rule {
277     std::shared_ptr<SocketAddress> address;
278 
279     explicit SocketAddressRule(const std::shared_ptr<SocketAddress>& address);
280 
281     bool Apply(const std::shared_ptr<SocketAddress>& address) override;
282     std::string ToString() override;
283 
284     void MemoryInfo(node::MemoryTracker* tracker) const override;
285     SET_MEMORY_INFO_NAME(SocketAddressRule)
286     SET_SELF_SIZE(SocketAddressRule)
287   };
288 
289   struct SocketAddressRangeRule final : Rule {
290     std::shared_ptr<SocketAddress> start;
291     std::shared_ptr<SocketAddress> end;
292 
293     SocketAddressRangeRule(
294         const std::shared_ptr<SocketAddress>& start,
295         const std::shared_ptr<SocketAddress>& end);
296 
297     bool Apply(const std::shared_ptr<SocketAddress>& address) override;
298     std::string ToString() override;
299 
300     void MemoryInfo(node::MemoryTracker* tracker) const override;
301     SET_MEMORY_INFO_NAME(SocketAddressRangeRule)
302     SET_SELF_SIZE(SocketAddressRangeRule)
303   };
304 
305   struct SocketAddressMaskRule final : Rule {
306     std::shared_ptr<SocketAddress> network;
307     int prefix;
308 
309     SocketAddressMaskRule(
310         const std::shared_ptr<SocketAddress>& address,
311         int prefix);
312 
313     bool Apply(const std::shared_ptr<SocketAddress>& address) override;
314     std::string ToString() override;
315 
316     void MemoryInfo(node::MemoryTracker* tracker) const override;
317     SET_MEMORY_INFO_NAME(SocketAddressMaskRule)
318     SET_SELF_SIZE(SocketAddressMaskRule)
319   };
320 
321   void MemoryInfo(node::MemoryTracker* tracker) const override;
322   SET_MEMORY_INFO_NAME(SocketAddressBlockList)
323   SET_SELF_SIZE(SocketAddressBlockList)
324 
325  private:
326   bool ListRules(
327       Environment* env,
328       std::vector<v8::Local<v8::Value>>* vec);
329 
330   std::shared_ptr<SocketAddressBlockList> parent_;
331   std::list<std::unique_ptr<Rule>> rules_;
332   SocketAddress::Map<std::list<std::unique_ptr<Rule>>::iterator> address_rules_;
333 
334   Mutex mutex_;
335 };
336 
337 class SocketAddressBlockListWrap : public BaseObject {
338  public:
339   static bool HasInstance(Environment* env, v8::Local<v8::Value> value);
340   static v8::Local<v8::FunctionTemplate> GetConstructorTemplate(
341       Environment* env);
342   static void Initialize(v8::Local<v8::Object> target,
343                          v8::Local<v8::Value> unused,
344                          v8::Local<v8::Context> context,
345                          void* priv);
346 
347   static BaseObjectPtr<SocketAddressBlockListWrap> New(Environment* env);
348   static BaseObjectPtr<SocketAddressBlockListWrap> New(
349       Environment* env,
350       std::shared_ptr<SocketAddressBlockList> blocklist);
351 
352   static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
353   static void AddAddress(const v8::FunctionCallbackInfo<v8::Value>& args);
354   static void AddRange(const v8::FunctionCallbackInfo<v8::Value>& args);
355   static void AddSubnet(const v8::FunctionCallbackInfo<v8::Value>& args);
356   static void Check(const v8::FunctionCallbackInfo<v8::Value>& args);
357   static void GetRules(const v8::FunctionCallbackInfo<v8::Value>& args);
358 
359   SocketAddressBlockListWrap(
360       Environment* env,
361       v8::Local<v8::Object> wrap,
362       std::shared_ptr<SocketAddressBlockList> blocklist =
363           std::make_shared<SocketAddressBlockList>());
364 
365   void MemoryInfo(node::MemoryTracker* tracker) const override;
366   SET_MEMORY_INFO_NAME(SocketAddressBlockListWrap)
SET_SELF_SIZE(SocketAddressBlockListWrap)367   SET_SELF_SIZE(SocketAddressBlockListWrap)
368 
369   TransferMode GetTransferMode() const override {
370     return TransferMode::kCloneable;
371   }
372   std::unique_ptr<worker::TransferData> CloneForMessaging() const override;
373 
374   class TransferData : public worker::TransferData {
375    public:
TransferData(const SocketAddressBlockListWrap * wrap)376     inline explicit TransferData(const SocketAddressBlockListWrap* wrap)
377         : blocklist_(wrap->blocklist_) {}
378 
TransferData(std::shared_ptr<SocketAddressBlockList> blocklist)379     inline explicit TransferData(
380         std::shared_ptr<SocketAddressBlockList> blocklist)
381         : blocklist_(std::move(blocklist)) {}
382 
383     BaseObjectPtr<BaseObject> Deserialize(
384         Environment* env,
385         v8::Local<v8::Context> context,
386         std::unique_ptr<worker::TransferData> self) override;
387 
388     void MemoryInfo(MemoryTracker* tracker) const override;
389     SET_MEMORY_INFO_NAME(SocketAddressBlockListWrap::TransferData)
390     SET_SELF_SIZE(TransferData)
391 
392    private:
393     std::shared_ptr<SocketAddressBlockList> blocklist_;
394   };
395 
396  private:
397   std::shared_ptr<SocketAddressBlockList> blocklist_;
398 };
399 
400 }  // namespace node
401 
402 #endif  // NOE_WANT_INTERNALS
403 
404 #endif  // SRC_NODE_SOCKADDR_H_
405