// $Id$ // // Copyright (C) 2007 // Fraunhofer Institute for Open Communication Systems (FOKUS) // // The contents of this file are subject to the Fraunhofer FOKUS Public License // Version 1.0 (the "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // http://senf.berlios.de/license.html // // The Fraunhofer FOKUS Public License Version 1.0 is based on, // but modifies the Mozilla Public License Version 1.1. // See the full license text for the amendments. // // Software distributed under the License is distributed on an "AS IS" basis, // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License // for the specific language governing rights and limitations under the License. // // The Original Code is Fraunhofer FOKUS code. // // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V. // (registered association), Hansastraße 27 c, 80686 Munich, Germany. // All Rights Reserved. // // Contributor(s): // Stefan Bund /** \file \brief INet6Address inline non-template implementation */ #include "INet6Address.ih" // Custom includes #include #include #define prefix_ inline //-///////////////////////////////////////////////////////////////////////////////////////////////// prefix_ senf::INet6Address::INet6Address(senf::NoInit_t) {} prefix_ senf::INet6Address::INet6Address(boost::uint16_t a0, boost::uint16_t a1, boost::uint16_t a2, boost::uint16_t a3, boost::uint16_t a4, boost::uint16_t a5, boost::uint16_t a6, boost::uint16_t a7) { (*this)[ 0] = boost::uint8_t(a0>>8); (*this)[ 1] = boost::uint8_t(a0); (*this)[ 2] = boost::uint8_t(a1>>8); (*this)[ 3] = boost::uint8_t(a1); (*this)[ 4] = boost::uint8_t(a2>>8); (*this)[ 5] = boost::uint8_t(a2); (*this)[ 6] = boost::uint8_t(a3>>8); (*this)[ 7] = boost::uint8_t(a3); (*this)[ 8] = boost::uint8_t(a4>>8); (*this)[ 9] = boost::uint8_t(a4); (*this)[10] = boost::uint8_t(a5>>8); (*this)[11] = boost::uint8_t(a5); (*this)[12] = boost::uint8_t(a6>>8); (*this)[13] = boost::uint8_t(a6); (*this)[14] = boost::uint8_t(a7>>8); (*this)[15] = boost::uint8_t(a7); } prefix_ senf::INet6Address senf::INet6Address::from_in6addr(in6_addr const & in6addr) { return senf::INet6Address::from_data(&in6addr.s6_addr[0]); } prefix_ senf::INet6Address senf::INet6Address::from_inet4address(INet4Address const & addr4) { INet6Address addr; addr[10] = 0xffu; addr[11] = 0xffu; std::copy(addr4.begin(), addr4.end(), addr.begin()+12); return addr; } prefix_ senf::INet6Network senf::INet6Address::network() const { return senf::INet6Network(*this, 64); } prefix_ bool senf::INet6Address::universalId() const { return (*this)[8] & 2u; } prefix_ bool senf::INet6Address::groupId() const { return (*this)[8] & 1u; } prefix_ senf::INet4Address senf::INet6Address::inet4address() const { return INet4Address::from_data(&(*this)[12]); } prefix_ bool senf::INet6Address::inet4Mapped() const { return CheckINet6Network<0u,0u,0u,0u,0u,0xFFFFu,96>::match(*this); } prefix_ bool senf::INet6Address::multicast() const { return (*this)[0] == 0xFFu || (inet4Mapped() && inet4address().multicast()); } prefix_ senf::INet6Address::ScopeId senf::INet6Address::scope() const { static ScopeId const scopeMap[] = { ReservedScope, InterfaceScope, LinkScope, ReservedScope, AdminScope, SiteScope, UnassignedScope, UnassignedScope, OrganizationScope, UnassignedScope, UnassignedScope, UnassignedScope, UnassignedScope, UnassignedScope, GlobalScope, ReservedScope }; return multicast() ? scopeMap[(*this)[1] & 0x0Fu] : (*this)[0] == 0xFEu ? (((*this)[1]&0xC0) == 0x80 ? LinkScope : ((*this)[1]&0xC0) == 0xC0 ? SiteScope : GlobalScope ) : GlobalScope; } prefix_ bool senf::INet6Address::unicast() const { return ! multicast(); } prefix_ bool senf::INet6Address::hasEUI64() const { return unicast() && ((*this)[0]&0xE0u) != 0u; } prefix_ bool senf::INet6Address::globalScope() const { return scope() == GlobalScope; } prefix_ bool senf::INet6Address::linkScope() const { return scope() == LinkScope; } prefix_ bool senf::INet6Address::inet4Compatible() const { return CheckINet6Network<0u,96>::match(*this); } prefix_ bool senf::INet6Address::globalMulticastAddr() const { return multicast() && ! ((*this)[1] & 0x10u); } prefix_ bool senf::INet6Address::prefixMulticastAddr() const { return multicast() && ((*this)[1] & 0x20u); } prefix_ bool senf::INet6Address::embeddedRpAddr() const { return multicast() && ((*this)[1] & 0x40u); } prefix_ bool senf::INet6Address::boolean_test() const { using boost::lambda::_1; return std::find_if(begin(),end(), _1 != 0x00) != end(); } prefix_ void senf::INet6Address::network(boost::uint64_t net) { (*this)[ 0] = net >> 56; (*this)[ 1] = net >> 48; (*this)[ 2] = net >> 40; (*this)[ 3] = net >> 32; (*this)[ 4] = net >> 24; (*this)[ 5] = net >> 16; (*this)[ 6] = net >> 8; (*this)[ 7] = net ; } prefix_ void senf::INet6Address::id(boost::uint64_t id) { (*this)[ 8] = id >> 56; (*this)[ 9] = id >> 48; (*this)[10] = id >> 40; (*this)[11] = id >> 32; (*this)[12] = id >> 24; (*this)[13] = id >> 16; (*this)[14] = id >> 8; (*this)[15] = id ; } //-///////////////////////////////////////////////////////////////////////////////////////////////// // senf::INet6Network prefix_ senf::INet6Network::INet6Network() : prefix_len_(), address_() {} prefix_ senf::INet6Network::INet6Network(INet6Address const & address, unsigned prefix_len) : prefix_len_( prefix_len_checked(prefix_len)), address_(address) { using boost::lambda::_1; using boost::lambda::_2; detail::apply_mask(prefix_len_, address_.begin(), address_.end(), _1 &= _2); } prefix_ senf::INet6Address const & senf::INet6Network::address() const { return address_; } prefix_ unsigned senf::INet6Network::prefix_len() const { return prefix_len_; } prefix_ bool senf::INet6Network::boolean_test() const { return prefix_len() && address(); } prefix_ bool senf::INet6Network::operator==(INet6Network const & other) const { return prefix_len() == other.prefix_len() && address() == other.address(); } prefix_ bool senf::INet6Network::match(INet6Address const & addr) const { using boost::lambda::_1; using boost::lambda::_2; using boost::lambda::_3; return detail::find_if_mask(prefix_len_, address_.begin(), address_.end(), addr.begin(), _1 != (_2 & _3)) == address_.end(); } prefix_ bool senf::INet6Network::match(INet6Network const & net) const { return net.prefix_len() >= prefix_len() && match(net.address()); } prefix_ senf::INet6Address senf::INet6Network::host(boost::uint64_t id) { INet6Address addr (address()); addr.id(id); return addr; } prefix_ senf::INet6Network senf::INet6Network::subnet(boost::uint64_t net, unsigned prefix_len) { using boost::lambda::_1; using boost::lambda::_2; using boost::lambda::var; using boost::lambda::ret; INet6Address addr (address()); net <<= (64-prefix_len); detail::apply_mask(prefix_len, addr.begin(), addr.end(), ( ( _1 |= ret((var(net) >> 56) & _2) ), ( var(net) <<= 8 ) )); return INet6Network(addr, prefix_len); } prefix_ unsigned senf::INet6Network::prefix_len_checked(unsigned prefix_len) const { if (prefix_len > 128) throw AddressSyntaxException("invalid INet6 prefix length: " + boost::lexical_cast(prefix_len)); return prefix_len; } prefix_ std::ostream & senf::operator<<(std::ostream & os, INet6Network const & addr) { os << addr.address() << '/' << addr.prefix_len(); return os; } //-///////////////////////////////////////////////////////////////////////////////////////////////// // namespace senf::detail members prefix_ boost::uint8_t senf::detail::low_bits_mask(unsigned bits) { return ((1<