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