Home | History | Annotate | Download | only in impl
      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