1 //
2 // ip/address_v6.hpp
3 // ~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6 //
7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9 //
10 
11 #ifndef BOOST_ASIO_IP_ADDRESS_V6_HPP
12 #define BOOST_ASIO_IP_ADDRESS_V6_HPP
13 
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
15 # pragma once
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
17 
18 #include <boost/asio/detail/config.hpp>
19 #include <string>
20 #include <boost/asio/detail/array.hpp>
21 #include <boost/asio/detail/cstdint.hpp>
22 #include <boost/asio/detail/socket_types.hpp>
23 #include <boost/asio/detail/string_view.hpp>
24 #include <boost/asio/detail/winsock_init.hpp>
25 #include <boost/system/error_code.hpp>
26 #include <boost/asio/ip/address_v4.hpp>
27 
28 #if defined(BOOST_ASIO_HAS_STD_HASH)
29 # include <functional>
30 #endif // defined(BOOST_ASIO_HAS_STD_HASH)
31 
32 #if !defined(BOOST_ASIO_NO_IOSTREAM)
33 # include <iosfwd>
34 #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
35 
36 #include <boost/asio/detail/push_options.hpp>
37 
38 namespace boost {
39 namespace asio {
40 namespace ip {
41 
42 template <typename> class basic_address_iterator;
43 
44 /// Type used for storing IPv6 scope IDs.
45 typedef uint_least32_t scope_id_type;
46 
47 /// Implements IP version 6 style addresses.
48 /**
49  * The boost::asio::ip::address_v6 class provides the ability to use and
50  * manipulate IP version 6 addresses.
51  *
52  * @par Thread Safety
53  * @e Distinct @e objects: Safe.@n
54  * @e Shared @e objects: Unsafe.
55  */
56 class address_v6
57 {
58 public:
59   /// The type used to represent an address as an array of bytes.
60   /**
61    * @note This type is defined in terms of the C++0x template @c std::array
62    * when it is available. Otherwise, it uses @c boost:array.
63    */
64 #if defined(GENERATING_DOCUMENTATION)
65   typedef array<unsigned char, 16> bytes_type;
66 #else
67   typedef boost::asio::detail::array<unsigned char, 16> bytes_type;
68 #endif
69 
70   /// Default constructor.
71   BOOST_ASIO_DECL address_v6() BOOST_ASIO_NOEXCEPT;
72 
73   /// Construct an address from raw bytes and scope ID.
74   BOOST_ASIO_DECL explicit address_v6(const bytes_type& bytes,
75       scope_id_type scope_id = 0);
76 
77   /// Copy constructor.
78   BOOST_ASIO_DECL address_v6(const address_v6& other) BOOST_ASIO_NOEXCEPT;
79 
80 #if defined(BOOST_ASIO_HAS_MOVE)
81   /// Move constructor.
82   BOOST_ASIO_DECL address_v6(address_v6&& other) BOOST_ASIO_NOEXCEPT;
83 #endif // defined(BOOST_ASIO_HAS_MOVE)
84 
85   /// Assign from another address.
86   BOOST_ASIO_DECL address_v6& operator=(
87       const address_v6& other) BOOST_ASIO_NOEXCEPT;
88 
89 #if defined(BOOST_ASIO_HAS_MOVE)
90   /// Move-assign from another address.
91   BOOST_ASIO_DECL address_v6& operator=(address_v6&& other) BOOST_ASIO_NOEXCEPT;
92 #endif // defined(BOOST_ASIO_HAS_MOVE)
93 
94   /// The scope ID of the address.
95   /**
96    * Returns the scope ID associated with the IPv6 address.
97    */
scope_id() const98   scope_id_type scope_id() const BOOST_ASIO_NOEXCEPT
99   {
100     return scope_id_;
101   }
102 
103   /// The scope ID of the address.
104   /**
105    * Modifies the scope ID associated with the IPv6 address.
106    */
scope_id(scope_id_type id)107   void scope_id(scope_id_type id) BOOST_ASIO_NOEXCEPT
108   {
109     scope_id_ = id;
110   }
111 
112   /// Get the address in bytes, in network byte order.
113   BOOST_ASIO_DECL bytes_type to_bytes() const BOOST_ASIO_NOEXCEPT;
114 
115   /// Get the address as a string.
116   BOOST_ASIO_DECL std::string to_string() const;
117 
118 #if !defined(BOOST_ASIO_NO_DEPRECATED)
119   /// (Deprecated: Use other overload.) Get the address as a string.
120   BOOST_ASIO_DECL std::string to_string(boost::system::error_code& ec) const;
121 
122   /// (Deprecated: Use make_address_v6().) Create an IPv6 address from an IP
123   /// address string.
124   static address_v6 from_string(const char* str);
125 
126   /// (Deprecated: Use make_address_v6().) Create an IPv6 address from an IP
127   /// address string.
128   static address_v6 from_string(
129       const char* str, boost::system::error_code& ec);
130 
131   /// (Deprecated: Use make_address_v6().) Create an IPv6 address from an IP
132   /// address string.
133   static address_v6 from_string(const std::string& str);
134 
135   /// (Deprecated: Use make_address_v6().) Create an IPv6 address from an IP
136   /// address string.
137   static address_v6 from_string(
138       const std::string& str, boost::system::error_code& ec);
139 
140   /// (Deprecated: Use make_address_v4().) Converts an IPv4-mapped or
141   /// IPv4-compatible address to an IPv4 address.
142   BOOST_ASIO_DECL address_v4 to_v4() const;
143 #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
144 
145   /// Determine whether the address is a loopback address.
146   BOOST_ASIO_DECL bool is_loopback() const BOOST_ASIO_NOEXCEPT;
147 
148   /// Determine whether the address is unspecified.
149   BOOST_ASIO_DECL bool is_unspecified() const BOOST_ASIO_NOEXCEPT;
150 
151   /// Determine whether the address is link local.
152   BOOST_ASIO_DECL bool is_link_local() const BOOST_ASIO_NOEXCEPT;
153 
154   /// Determine whether the address is site local.
155   BOOST_ASIO_DECL bool is_site_local() const BOOST_ASIO_NOEXCEPT;
156 
157   /// Determine whether the address is a mapped IPv4 address.
158   BOOST_ASIO_DECL bool is_v4_mapped() const BOOST_ASIO_NOEXCEPT;
159 
160 #if !defined(BOOST_ASIO_NO_DEPRECATED)
161   /// (Deprecated: No replacement.) Determine whether the address is an
162   /// IPv4-compatible address.
163   BOOST_ASIO_DECL bool is_v4_compatible() const;
164 #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
165 
166   /// Determine whether the address is a multicast address.
167   BOOST_ASIO_DECL bool is_multicast() const BOOST_ASIO_NOEXCEPT;
168 
169   /// Determine whether the address is a global multicast address.
170   BOOST_ASIO_DECL bool is_multicast_global() const BOOST_ASIO_NOEXCEPT;
171 
172   /// Determine whether the address is a link-local multicast address.
173   BOOST_ASIO_DECL bool is_multicast_link_local() const BOOST_ASIO_NOEXCEPT;
174 
175   /// Determine whether the address is a node-local multicast address.
176   BOOST_ASIO_DECL bool is_multicast_node_local() const BOOST_ASIO_NOEXCEPT;
177 
178   /// Determine whether the address is a org-local multicast address.
179   BOOST_ASIO_DECL bool is_multicast_org_local() const BOOST_ASIO_NOEXCEPT;
180 
181   /// Determine whether the address is a site-local multicast address.
182   BOOST_ASIO_DECL bool is_multicast_site_local() const BOOST_ASIO_NOEXCEPT;
183 
184   /// Compare two addresses for equality.
185   BOOST_ASIO_DECL friend bool operator==(const address_v6& a1,
186       const address_v6& a2) BOOST_ASIO_NOEXCEPT;
187 
188   /// Compare two addresses for inequality.
operator !=(const address_v6 & a1,const address_v6 & a2)189   friend bool operator!=(const address_v6& a1,
190       const address_v6& a2) BOOST_ASIO_NOEXCEPT
191   {
192     return !(a1 == a2);
193   }
194 
195   /// Compare addresses for ordering.
196   BOOST_ASIO_DECL friend bool operator<(const address_v6& a1,
197       const address_v6& a2) BOOST_ASIO_NOEXCEPT;
198 
199   /// Compare addresses for ordering.
operator >(const address_v6 & a1,const address_v6 & a2)200   friend bool operator>(const address_v6& a1,
201       const address_v6& a2) BOOST_ASIO_NOEXCEPT
202   {
203     return a2 < a1;
204   }
205 
206   /// Compare addresses for ordering.
operator <=(const address_v6 & a1,const address_v6 & a2)207   friend bool operator<=(const address_v6& a1,
208       const address_v6& a2) BOOST_ASIO_NOEXCEPT
209   {
210     return !(a2 < a1);
211   }
212 
213   /// Compare addresses for ordering.
operator >=(const address_v6 & a1,const address_v6 & a2)214   friend bool operator>=(const address_v6& a1,
215       const address_v6& a2) BOOST_ASIO_NOEXCEPT
216   {
217     return !(a1 < a2);
218   }
219 
220   /// Obtain an address object that represents any address.
any()221   static address_v6 any() BOOST_ASIO_NOEXCEPT
222   {
223     return address_v6();
224   }
225 
226   /// Obtain an address object that represents the loopback address.
227   BOOST_ASIO_DECL static address_v6 loopback() BOOST_ASIO_NOEXCEPT;
228 
229 #if !defined(BOOST_ASIO_NO_DEPRECATED)
230   /// (Deprecated: Use make_address_v6().) Create an IPv4-mapped IPv6 address.
231   BOOST_ASIO_DECL static address_v6 v4_mapped(const address_v4& addr);
232 
233   /// (Deprecated: No replacement.) Create an IPv4-compatible IPv6 address.
234   BOOST_ASIO_DECL static address_v6 v4_compatible(const address_v4& addr);
235 #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
236 
237 private:
238   friend class basic_address_iterator<address_v6>;
239 
240   // The underlying IPv6 address.
241   boost::asio::detail::in6_addr_type addr_;
242 
243   // The scope ID associated with the address.
244   scope_id_type scope_id_;
245 };
246 
247 /// Create an IPv6 address from raw bytes and scope ID.
248 /**
249  * @relates address_v6
250  */
make_address_v6(const address_v6::bytes_type & bytes,scope_id_type scope_id=0)251 inline address_v6 make_address_v6(const address_v6::bytes_type& bytes,
252     scope_id_type scope_id = 0)
253 {
254   return address_v6(bytes, scope_id);
255 }
256 
257 /// Create an IPv6 address from an IP address string.
258 /**
259  * @relates address_v6
260  */
261 BOOST_ASIO_DECL address_v6 make_address_v6(const char* str);
262 
263 /// Create an IPv6 address from an IP address string.
264 /**
265  * @relates address_v6
266  */
267 BOOST_ASIO_DECL address_v6 make_address_v6(const char* str,
268     boost::system::error_code& ec) BOOST_ASIO_NOEXCEPT;
269 
270 /// Createan IPv6 address from an IP address string.
271 /**
272  * @relates address_v6
273  */
274 BOOST_ASIO_DECL address_v6 make_address_v6(const std::string& str);
275 
276 /// Create an IPv6 address from an IP address string.
277 /**
278  * @relates address_v6
279  */
280 BOOST_ASIO_DECL address_v6 make_address_v6(const std::string& str,
281     boost::system::error_code& ec) BOOST_ASIO_NOEXCEPT;
282 
283 #if defined(BOOST_ASIO_HAS_STRING_VIEW) \
284   || defined(GENERATING_DOCUMENTATION)
285 
286 /// Create an IPv6 address from an IP address string.
287 /**
288  * @relates address_v6
289  */
290 BOOST_ASIO_DECL address_v6 make_address_v6(string_view str);
291 
292 /// Create an IPv6 address from an IP address string.
293 /**
294  * @relates address_v6
295  */
296 BOOST_ASIO_DECL address_v6 make_address_v6(string_view str,
297     boost::system::error_code& ec) BOOST_ASIO_NOEXCEPT;
298 
299 #endif // defined(BOOST_ASIO_HAS_STRING_VIEW)
300        //  || defined(GENERATING_DOCUMENTATION)
301 
302 /// Tag type used for distinguishing overloads that deal in IPv4-mapped IPv6
303 /// addresses.
304 enum v4_mapped_t { v4_mapped };
305 
306 /// Create an IPv4 address from a IPv4-mapped IPv6 address.
307 /**
308  * @relates address_v4
309  */
310 BOOST_ASIO_DECL address_v4 make_address_v4(
311     v4_mapped_t, const address_v6& v6_addr);
312 
313 /// Create an IPv4-mapped IPv6 address from an IPv4 address.
314 /**
315  * @relates address_v6
316  */
317 BOOST_ASIO_DECL address_v6 make_address_v6(
318     v4_mapped_t, const address_v4& v4_addr);
319 
320 #if !defined(BOOST_ASIO_NO_IOSTREAM)
321 
322 /// Output an address as a string.
323 /**
324  * Used to output a human-readable string for a specified address.
325  *
326  * @param os The output stream to which the string will be written.
327  *
328  * @param addr The address to be written.
329  *
330  * @return The output stream.
331  *
332  * @relates boost::asio::ip::address_v6
333  */
334 template <typename Elem, typename Traits>
335 std::basic_ostream<Elem, Traits>& operator<<(
336     std::basic_ostream<Elem, Traits>& os, const address_v6& addr);
337 
338 #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
339 
340 } // namespace ip
341 } // namespace asio
342 } // namespace boost
343 
344 #if defined(BOOST_ASIO_HAS_STD_HASH)
345 namespace std {
346 
347 template <>
348 struct hash<boost::asio::ip::address_v6>
349 {
operator ()std::hash350   std::size_t operator()(const boost::asio::ip::address_v6& addr)
351     const BOOST_ASIO_NOEXCEPT
352   {
353     const boost::asio::ip::address_v6::bytes_type bytes = addr.to_bytes();
354     std::size_t result = static_cast<std::size_t>(addr.scope_id());
355     combine_4_bytes(result, &bytes[0]);
356     combine_4_bytes(result, &bytes[4]);
357     combine_4_bytes(result, &bytes[8]);
358     combine_4_bytes(result, &bytes[12]);
359     return result;
360   }
361 
362 private:
combine_4_bytesstd::hash363   static void combine_4_bytes(std::size_t& seed, const unsigned char* bytes)
364   {
365     const std::size_t bytes_hash =
366       (static_cast<std::size_t>(bytes[0]) << 24) |
367       (static_cast<std::size_t>(bytes[1]) << 16) |
368       (static_cast<std::size_t>(bytes[2]) << 8) |
369       (static_cast<std::size_t>(bytes[3]));
370     seed ^= bytes_hash + 0x9e3779b9 + (seed << 6) + (seed >> 2);
371   }
372 };
373 
374 } // namespace std
375 #endif // defined(BOOST_ASIO_HAS_STD_HASH)
376 
377 #include <boost/asio/detail/pop_options.hpp>
378 
379 #include <boost/asio/ip/impl/address_v6.hpp>
380 #if defined(BOOST_ASIO_HEADER_ONLY)
381 # include <boost/asio/ip/impl/address_v6.ipp>
382 #endif // defined(BOOST_ASIO_HEADER_ONLY)
383 
384 #endif // BOOST_ASIO_IP_ADDRESS_V6_HPP
385