1//
2// ip/impl/address_v6.ipp
3// ~~~~~~~~~~~~~~~~~~~~~~
4//
5// Copyright (c) 2003-2024 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_IMPL_ADDRESS_V6_IPP
12#define BOOST_ASIO_IP_IMPL_ADDRESS_V6_IPP
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 <cstring>
20#include <stdexcept>
21#include <typeinfo>
22#include <boost/asio/detail/socket_ops.hpp>
23#include <boost/asio/detail/throw_error.hpp>
24#include <boost/asio/detail/throw_exception.hpp>
25#include <boost/asio/error.hpp>
26#include <boost/asio/ip/address_v6.hpp>
27#include <boost/asio/ip/bad_address_cast.hpp>
28
29#include <boost/asio/detail/push_options.hpp>
30
31namespace boost {
32namespace asio {
33namespace ip {
34
35address_v6::address_v6() noexcept
36 : addr_(),
37 scope_id_(0)
38{
39}
40
41address_v6::address_v6(const address_v6::bytes_type& bytes,
42 scope_id_type scope)
43 : scope_id_(scope)
44{
45#if UCHAR_MAX > 0xFF
46 for (std::size_t i = 0; i < bytes.size(); ++i)
47 {
48 if (bytes[i] > 0xFF)
49 {
50 std::out_of_range ex("address_v6 from bytes_type");
51 boost::asio::detail::throw_exception(ex);
52 }
53 }
54#endif // UCHAR_MAX > 0xFF
55
56 using namespace std; // For memcpy.
57 memcpy(dest: addr_.s6_addr, src: bytes.data(), n: 16);
58}
59
60address_v6::address_v6(const address_v6& other) noexcept
61 : addr_(other.addr_),
62 scope_id_(other.scope_id_)
63{
64}
65
66address_v6::address_v6(address_v6&& other) noexcept
67 : addr_(other.addr_),
68 scope_id_(other.scope_id_)
69{
70}
71
72address_v6& address_v6::operator=(const address_v6& other) noexcept
73{
74 addr_ = other.addr_;
75 scope_id_ = other.scope_id_;
76 return *this;
77}
78
79address_v6& address_v6::operator=(address_v6&& other) noexcept
80{
81 addr_ = other.addr_;
82 scope_id_ = other.scope_id_;
83 return *this;
84}
85
86address_v6::bytes_type address_v6::to_bytes() const noexcept
87{
88 using namespace std; // For memcpy.
89 bytes_type bytes;
90 memcpy(dest: bytes.data(), src: addr_.s6_addr, n: 16);
91 return bytes;
92}
93
94std::string address_v6::to_string() const
95{
96 boost::system::error_code ec;
97 char addr_str[boost::asio::detail::max_addr_v6_str_len];
98 const char* addr =
99 boost::asio::detail::socket_ops::inet_ntop(
100 BOOST_ASIO_OS_DEF(AF_INET6), src: &addr_, dest: addr_str,
101 length: boost::asio::detail::max_addr_v6_str_len, scope_id: scope_id_, ec);
102 if (addr == 0)
103 boost::asio::detail::throw_error(err: ec);
104 return addr;
105}
106
107#if !defined(BOOST_ASIO_NO_DEPRECATED)
108std::string address_v6::to_string(boost::system::error_code& ec) const
109{
110 char addr_str[boost::asio::detail::max_addr_v6_str_len];
111 const char* addr =
112 boost::asio::detail::socket_ops::inet_ntop(
113 BOOST_ASIO_OS_DEF(AF_INET6), src: &addr_, dest: addr_str,
114 length: boost::asio::detail::max_addr_v6_str_len, scope_id: scope_id_, ec);
115 if (addr == 0)
116 return std::string();
117 return addr;
118}
119
120address_v4 address_v6::to_v4() const
121{
122 if (!is_v4_mapped() && !is_v4_compatible())
123 {
124 bad_address_cast ex;
125 boost::asio::detail::throw_exception(e: ex);
126 }
127
128 address_v4::bytes_type v4_bytes = { ._M_elems: { addr_.s6_addr[12],
129 addr_.s6_addr[13], addr_.s6_addr[14], addr_.s6_addr[15] } };
130 return address_v4(v4_bytes);
131}
132#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
133
134bool address_v6::is_loopback() const noexcept
135{
136 return ((addr_.s6_addr[0] == 0) && (addr_.s6_addr[1] == 0)
137 && (addr_.s6_addr[2] == 0) && (addr_.s6_addr[3] == 0)
138 && (addr_.s6_addr[4] == 0) && (addr_.s6_addr[5] == 0)
139 && (addr_.s6_addr[6] == 0) && (addr_.s6_addr[7] == 0)
140 && (addr_.s6_addr[8] == 0) && (addr_.s6_addr[9] == 0)
141 && (addr_.s6_addr[10] == 0) && (addr_.s6_addr[11] == 0)
142 && (addr_.s6_addr[12] == 0) && (addr_.s6_addr[13] == 0)
143 && (addr_.s6_addr[14] == 0) && (addr_.s6_addr[15] == 1));
144}
145
146bool address_v6::is_unspecified() const noexcept
147{
148 return ((addr_.s6_addr[0] == 0) && (addr_.s6_addr[1] == 0)
149 && (addr_.s6_addr[2] == 0) && (addr_.s6_addr[3] == 0)
150 && (addr_.s6_addr[4] == 0) && (addr_.s6_addr[5] == 0)
151 && (addr_.s6_addr[6] == 0) && (addr_.s6_addr[7] == 0)
152 && (addr_.s6_addr[8] == 0) && (addr_.s6_addr[9] == 0)
153 && (addr_.s6_addr[10] == 0) && (addr_.s6_addr[11] == 0)
154 && (addr_.s6_addr[12] == 0) && (addr_.s6_addr[13] == 0)
155 && (addr_.s6_addr[14] == 0) && (addr_.s6_addr[15] == 0));
156}
157
158bool address_v6::is_link_local() const noexcept
159{
160 return ((addr_.s6_addr[0] == 0xfe) && ((addr_.s6_addr[1] & 0xc0) == 0x80));
161}
162
163bool address_v6::is_site_local() const noexcept
164{
165 return ((addr_.s6_addr[0] == 0xfe) && ((addr_.s6_addr[1] & 0xc0) == 0xc0));
166}
167
168bool address_v6::is_v4_mapped() const noexcept
169{
170 return ((addr_.s6_addr[0] == 0) && (addr_.s6_addr[1] == 0)
171 && (addr_.s6_addr[2] == 0) && (addr_.s6_addr[3] == 0)
172 && (addr_.s6_addr[4] == 0) && (addr_.s6_addr[5] == 0)
173 && (addr_.s6_addr[6] == 0) && (addr_.s6_addr[7] == 0)
174 && (addr_.s6_addr[8] == 0) && (addr_.s6_addr[9] == 0)
175 && (addr_.s6_addr[10] == 0xff) && (addr_.s6_addr[11] == 0xff));
176}
177
178#if !defined(BOOST_ASIO_NO_DEPRECATED)
179bool address_v6::is_v4_compatible() const
180{
181 return ((addr_.s6_addr[0] == 0) && (addr_.s6_addr[1] == 0)
182 && (addr_.s6_addr[2] == 0) && (addr_.s6_addr[3] == 0)
183 && (addr_.s6_addr[4] == 0) && (addr_.s6_addr[5] == 0)
184 && (addr_.s6_addr[6] == 0) && (addr_.s6_addr[7] == 0)
185 && (addr_.s6_addr[8] == 0) && (addr_.s6_addr[9] == 0)
186 && (addr_.s6_addr[10] == 0) && (addr_.s6_addr[11] == 0)
187 && !((addr_.s6_addr[12] == 0)
188 && (addr_.s6_addr[13] == 0)
189 && (addr_.s6_addr[14] == 0)
190 && ((addr_.s6_addr[15] == 0) || (addr_.s6_addr[15] == 1))));
191}
192#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
193
194bool address_v6::is_multicast() const noexcept
195{
196 return (addr_.s6_addr[0] == 0xff);
197}
198
199bool address_v6::is_multicast_global() const noexcept
200{
201 return ((addr_.s6_addr[0] == 0xff) && ((addr_.s6_addr[1] & 0x0f) == 0x0e));
202}
203
204bool address_v6::is_multicast_link_local() const noexcept
205{
206 return ((addr_.s6_addr[0] == 0xff) && ((addr_.s6_addr[1] & 0x0f) == 0x02));
207}
208
209bool address_v6::is_multicast_node_local() const noexcept
210{
211 return ((addr_.s6_addr[0] == 0xff) && ((addr_.s6_addr[1] & 0x0f) == 0x01));
212}
213
214bool address_v6::is_multicast_org_local() const noexcept
215{
216 return ((addr_.s6_addr[0] == 0xff) && ((addr_.s6_addr[1] & 0x0f) == 0x08));
217}
218
219bool address_v6::is_multicast_site_local() const noexcept
220{
221 return ((addr_.s6_addr[0] == 0xff) && ((addr_.s6_addr[1] & 0x0f) == 0x05));
222}
223
224bool operator==(const address_v6& a1, const address_v6& a2) noexcept
225{
226 using namespace std; // For memcmp.
227 return memcmp(s1: &a1.addr_, s2: &a2.addr_,
228 n: sizeof(boost::asio::detail::in6_addr_type)) == 0
229 && a1.scope_id_ == a2.scope_id_;
230}
231
232bool operator<(const address_v6& a1, const address_v6& a2) noexcept
233{
234 using namespace std; // For memcmp.
235 int memcmp_result = memcmp(s1: &a1.addr_, s2: &a2.addr_,
236 n: sizeof(boost::asio::detail::in6_addr_type));
237 if (memcmp_result < 0)
238 return true;
239 if (memcmp_result > 0)
240 return false;
241 return a1.scope_id_ < a2.scope_id_;
242}
243
244address_v6 address_v6::loopback() noexcept
245{
246 address_v6 tmp;
247 tmp.addr_.s6_addr[15] = 1;
248 return tmp;
249}
250
251#if !defined(BOOST_ASIO_NO_DEPRECATED)
252address_v6 address_v6::v4_mapped(const address_v4& addr)
253{
254 address_v4::bytes_type v4_bytes = addr.to_bytes();
255 bytes_type v6_bytes = { ._M_elems: { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF,
256 v4_bytes[0], v4_bytes[1], v4_bytes[2], v4_bytes[3] } };
257 return address_v6(v6_bytes);
258}
259
260address_v6 address_v6::v4_compatible(const address_v4& addr)
261{
262 address_v4::bytes_type v4_bytes = addr.to_bytes();
263 bytes_type v6_bytes = { ._M_elems: { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
264 v4_bytes[0], v4_bytes[1], v4_bytes[2], v4_bytes[3] } };
265 return address_v6(v6_bytes);
266}
267#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
268
269address_v6 make_address_v6(const char* str)
270{
271 boost::system::error_code ec;
272 address_v6 addr = make_address_v6(str, ec);
273 boost::asio::detail::throw_error(err: ec);
274 return addr;
275}
276
277address_v6 make_address_v6(const char* str,
278 boost::system::error_code& ec) noexcept
279{
280 address_v6::bytes_type bytes;
281 unsigned long scope_id = 0;
282 if (boost::asio::detail::socket_ops::inet_pton(
283 BOOST_ASIO_OS_DEF(AF_INET6), src: str, dest: &bytes[0], scope_id: &scope_id, ec) <= 0)
284 return address_v6();
285 return address_v6(bytes, scope_id);
286}
287
288address_v6 make_address_v6(const std::string& str)
289{
290 return make_address_v6(str: str.c_str());
291}
292
293address_v6 make_address_v6(const std::string& str,
294 boost::system::error_code& ec) noexcept
295{
296 return make_address_v6(str: str.c_str(), ec);
297}
298
299#if defined(BOOST_ASIO_HAS_STRING_VIEW)
300
301address_v6 make_address_v6(string_view str)
302{
303 return make_address_v6(str: static_cast<std::string>(str));
304}
305
306address_v6 make_address_v6(string_view str,
307 boost::system::error_code& ec) noexcept
308{
309 return make_address_v6(str: static_cast<std::string>(str), ec);
310}
311
312#endif // defined(BOOST_ASIO_HAS_STRING_VIEW)
313
314address_v4 make_address_v4(
315 v4_mapped_t, const address_v6& v6_addr)
316{
317 if (!v6_addr.is_v4_mapped())
318 {
319 bad_address_cast ex;
320 boost::asio::detail::throw_exception(e: ex);
321 }
322
323 address_v6::bytes_type v6_bytes = v6_addr.to_bytes();
324 address_v4::bytes_type v4_bytes = { ._M_elems: { v6_bytes[12],
325 v6_bytes[13], v6_bytes[14], v6_bytes[15] } };
326 return address_v4(v4_bytes);
327}
328
329address_v6 make_address_v6(
330 v4_mapped_t, const address_v4& v4_addr)
331{
332 address_v4::bytes_type v4_bytes = v4_addr.to_bytes();
333 address_v6::bytes_type v6_bytes = { ._M_elems: { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
334 0xFF, 0xFF, v4_bytes[0], v4_bytes[1], v4_bytes[2], v4_bytes[3] } };
335 return address_v6(v6_bytes);
336}
337
338} // namespace ip
339} // namespace asio
340} // namespace boost
341
342#include <boost/asio/detail/pop_options.hpp>
343
344#endif // BOOST_ASIO_IP_IMPL_ADDRESS_V6_IPP
345

source code of boost/libs/asio/include/boost/asio/ip/impl/address_v6.ipp