From: g0dil Date: Mon, 30 Jul 2007 22:59:09 +0000 (+0000) Subject: Socket/Protocols/INet: Completely new implementation of INet6Address X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=6b6681bb03aac52a523b2ff8417e09be55dd446c;p=senf.git Socket/Protocols/INet: Completely new implementation of INet6Address git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@362 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/Packets/DefaultBundle/IpV6Extensions.test.cc b/Packets/DefaultBundle/IpV6Extensions.test.cc index 728d9fe..457597b 100644 --- a/Packets/DefaultBundle/IpV6Extensions.test.cc +++ b/Packets/DefaultBundle/IpV6Extensions.test.cc @@ -69,8 +69,10 @@ BOOST_AUTO_UNIT_TEST(ipv6Extension_Fragment_packet) BOOST_CHECK_EQUAL( p->version(), 6u ); BOOST_CHECK_EQUAL( p->length(), 20u ); BOOST_CHECK_EQUAL( p->nextHeader(), 44u ); - BOOST_CHECK_EQUAL( senf::INet6Address(p->source()), "2001::1" ); - BOOST_CHECK_EQUAL( senf::INet6Address(p->destination()), "2001::2" ); + BOOST_CHECK_EQUAL( senf::INet6Address::from_data(p->source().i()), + senf::INet6Address::from_string("2001::1") ); + BOOST_CHECK_EQUAL( senf::INet6Address::from_data(p->destination().i()), + senf::INet6Address::from_string("2001::2") ); BOOST_CHECK( p.next().is() ); senf::IpV6Extension_Fragment f (p.next().as()); diff --git a/Packets/DefaultBundle/IpV6Packet.cc b/Packets/DefaultBundle/IpV6Packet.cc index 63c341a..520772e 100644 --- a/Packets/DefaultBundle/IpV6Packet.cc +++ b/Packets/DefaultBundle/IpV6Packet.cc @@ -52,8 +52,8 @@ prefix_ void senf::IpV6PacketType::dump(packet p, std::ostream & os) << " length : " << std::dec << unsigned(p->length()) << "\n" << " next header : " << unsigned(p->nextHeader()) << "\n" << " hop limit : " << unsigned(p->hopLimit()) << "\n" - << " source : " << INet6Address(p->source()) << "\n" - << " destination : " << INet6Address(p->destination()) << "\n"; + << " source : " << INet6Address::from_data(p->source().i()) << "\n" + << " destination : " << INet6Address::from_data(p->destination().i()) << "\n"; } ///////////////////////////////cc.e//////////////////////////////////////// diff --git a/Packets/DefaultBundle/IpV6Packet.test.cc b/Packets/DefaultBundle/IpV6Packet.test.cc index 9882ab5..c65b062 100644 --- a/Packets/DefaultBundle/IpV6Packet.test.cc +++ b/Packets/DefaultBundle/IpV6Packet.test.cc @@ -54,10 +54,10 @@ BOOST_AUTO_UNIT_TEST(ipV6Packet_packet) BOOST_CHECK_EQUAL( p->length(), 0x0102u ); BOOST_CHECK_EQUAL( p->nextHeader(), 0x03u ); BOOST_CHECK_EQUAL( p->hopLimit(), 0x04u ); - BOOST_CHECK_EQUAL( senf::INet6Address(p->source()).address() , - "1011:1213:1415:1617:1819:1a1b:1c1d:1e1f" ); - BOOST_CHECK_EQUAL( senf::INet6Address(p->destination()).address() , - "2021:2223:2425:2627:2829:2a2b:2c2d:2e2f" ); + BOOST_CHECK_EQUAL( senf::INet6Address::from_data(p->source().i()), + senf::INet6Address::from_string("1011:1213:1415:1617:1819:1a1b:1c1d:1e1f") ); + BOOST_CHECK_EQUAL( senf::INet6Address::from_data(p->destination().i()), + senf::INet6Address::from_string("2021:2223:2425:2627:2829:2a2b:2c2d:2e2f") ); BOOST_CHECK( p.next() ); BOOST_CHECK( p.next().is() ); diff --git a/Socket/Protocols/INet/INet4Address.cc b/Socket/Protocols/INet/INet4Address.cc index 5495e32..4d29a1d 100644 --- a/Socket/Protocols/INet/INet4Address.cc +++ b/Socket/Protocols/INet/INet4Address.cc @@ -113,8 +113,8 @@ prefix_ senf::INet4Address::address_type senf::INet4Address::address() } senf::INet4Address const senf::INet4Address::None; -senf::INet4Address const senf::INet4Address::Loopback = senf::INet4Address(0x7F000001u); -senf::INet4Address const senf::INet4Address::Broadcast = senf::INet4Address(0xFFFFFFFFu); +senf::INet4Address const senf::INet4Address::Loopback (0x7F000001u); +senf::INet4Address const senf::INet4Address::Broadcast (0xFFFFFFFFu); /////////////////////////////////////////////////////////////////////////// diff --git a/Socket/Protocols/INet/INet4Address.hh b/Socket/Protocols/INet/INet4Address.hh index f075555..d7b13a1 100644 --- a/Socket/Protocols/INet/INet4Address.hh +++ b/Socket/Protocols/INet/INet4Address.hh @@ -50,6 +50,9 @@ namespace senf { { public: + /////////////////////////////////////////////////////////////////////////// + // Types + typedef uint32_t address_type; ///< Address representation as number in host byte order typedef uint32_t inaddr_type; ///< Legacy address representation in network byte order typedef boost::function Callback; @@ -61,8 +64,12 @@ namespace senf { enum NoInit_t { noinit }; + /////////////////////////////////////////////////////////////////////////// + ///\name Structors and default members + ///@{ + INet4Address(); ///< Construct an empty address - INet4Address(NoInit_t); ///< Construct uninitialized (!) address + explicit INet4Address(NoInit_t); ///< Construct uninitialized (!) address explicit INet4Address(address_type value); ///< Construct an address constant @@ -104,6 +111,11 @@ namespace senf { code to convert a network byte order address in an integer number into an INet4Address. */ + ///@} + /////////////////////////////////////////////////////////////////////////// + ///\name Accessors + ///@{ + bool local() const; ///< \c true, if address is locally administered /**< This call checks, if the address is within one of the IANA private ranges. */ @@ -125,6 +137,8 @@ namespace senf { host byte order. This representation allows simple network math operations. */ + ////@} + struct SyntaxException : public std::exception { virtual char const * what() const throw() { return "invalid INet4 address syntax"; } }; diff --git a/Socket/Protocols/INet/INet6Address.cc b/Socket/Protocols/INet/INet6Address.cc new file mode 100644 index 0000000..0def041 --- /dev/null +++ b/Socket/Protocols/INet/INet6Address.cc @@ -0,0 +1,109 @@ +// Copyright (C) 2007 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +/** \file + \brief INet6Address non-inline non-template implementation */ + +#include "INet6Address.hh" +#include "INet6Address.ih" + +// Custom includes +#include +#include +#include +#include +#include + +//#include "INet6Address.mpp" +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////// +// senf::INet6Address + +prefix_ senf::INet6Address senf::INet6Address::from_string(std::string const & s) +{ + struct in6_addr ina; + if (::inet_pton(AF_INET6,s.c_str(),&ina) > 0) + return senf::INet6Address::from_data(&ina.s6_addr[0]); + int herr (0); + + // If available, we use the reentrant GNU variant. This has the additional advantage, that we + // can explicitly ask for IpV4 addresses + +# ifdef __GLIBC__ + + struct hostent entbuf; + char buffer[4096]; + struct hostent * ent (0); + ::gethostbyname2_r(s.c_str(), AF_INET6, &entbuf, buffer, sizeof(buffer), &ent, &herr); + +# else // ! __GLIBC__ + +# ifdef _REENTRANT + static boost::mutex mutex; + boost::mutex::scoped_lock lock(mutex); +# endif + struct hostent * ent (::gethostbyname(s.c_str())); + herr = h_errno; + +# endif // __GLIBC__ + + if (!ent) + ///\fixme Need to give better exception here + throw SyntaxException(); + if (ent->h_addrtype != AF_INET6) + throw SyntaxException(); + + // We are only interested in the first address ... + return senf::INet6Address::from_data( + &reinterpret_cast(*(ent->h_addr_list))->s6_addr[0]); +} + +prefix_ std::ostream & senf::operator<<(std::ostream & os, INet6Address const & addr) +{ + ::in6_addr ina; + char buffer[5*8]; + std::copy(addr.begin(),addr.end(),&ina.s6_addr[0]); + ::inet_ntop(AF_INET6,&ina,buffer,sizeof(buffer)); + buffer[5*8] = 0; + os << buffer; + return os; +} + +senf::INet6Address const senf::INet6Address::None; +senf::INet6Address const senf::INet6Address::Loopback (0u,0u,0u,0u,0u,0u,0u,1u); +senf::INet6Address const senf::INet6Address::AllNodes (0xFF02u,0u,0u,0u,0u,0u,0u,1u); +senf::INet6Address const senf::INet6Address::AllRouters (0xFF02u,0u,0u,0u,0u,0u,0u,2u); + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ +//#include "INet6Address.mpp" + + +// Local Variables: +// mode: c++ +// fill-column: 100 +// comment-column: 40 +// c-file-style: "senf" +// indent-tabs-mode: nil +// ispell-local-dictionary: "american" +// compile-command: "scons -u test" +// End: diff --git a/Socket/Protocols/INet/INet6Address.cci b/Socket/Protocols/INet/INet6Address.cci new file mode 100644 index 0000000..029c4e8 --- /dev/null +++ b/Socket/Protocols/INet/INet6Address.cci @@ -0,0 +1,229 @@ +// Copyright (C) 2007 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +/** \file + \brief INet6Address inline non-template implementation */ + +// Custom includes +#include +#include + +#define prefix_ inline +///////////////////////////////cci.p/////////////////////////////////////// + +prefix_ senf::INet6Address::INet6Address(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_inet4address(INet4Address addr4) +{ + INet6Address addr; + addr[10] = 0xffu; + addr[11] = 0xffu; + std::copy(addr4.begin(), addr4.end(), addr.begin()+12); + return addr; +} + +prefix_ boost::uint64_t senf::INet6Address::network() + const +{ + return + ((boost::uint64_t((*this)[0]) & 0xff) << 56 ) | + ((boost::uint64_t((*this)[1]) & 0xff) << 48 ) | + ((boost::uint64_t((*this)[2]) & 0xff) << 40 ) | + ((boost::uint64_t((*this)[3]) & 0xff) << 32 ) | + ((boost::uint64_t((*this)[4]) & 0xff) << 24 ) | + ((boost::uint64_t((*this)[5]) & 0xff) << 16 ) | + ((boost::uint64_t((*this)[6]) & 0xff) << 8 ) | + ((boost::uint64_t((*this)[7]) & 0xff) ); +} + +prefix_ bool senf::INet6Address::hasEuid64() + const +{ + return unicast() && ((*this)[0]&0xE0u) != 0u; +} + +prefix_ boost::uint64_t senf::INet6Address::id() + const +{ + return + ((boost::uint64_t((*this)[ 8]) & 0xff) << 56 ) | + ((boost::uint64_t((*this)[ 9]) & 0xff) << 48 ) | + ((boost::uint64_t((*this)[10]) & 0xff) << 40 ) | + ((boost::uint64_t((*this)[11]) & 0xff) << 32 ) | + ((boost::uint64_t((*this)[12]) & 0xff) << 24 ) | + ((boost::uint64_t((*this)[13]) & 0xff) << 16 ) | + ((boost::uint64_t((*this)[14]) & 0xff) << 8 ) | + ((boost::uint64_t((*this)[15]) & 0xff) ); +} + +prefix_ bool senf::INet6Address::universalId() + const +{ + return (*this)[8] & 2u; +} + +prefix_ bool senf::INet6Address::groupId() + const +{ + return (*this)[8] & 1u; +} + +prefix_ bool senf::INet6Address::unicast() + const +{ + return ! multicast(); +} + +prefix_ bool senf::INet6Address::multicast() + const +{ + return (*this)[0] == 0xFFu; +} + +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::globalScope() + const +{ + return scope() == GlobalScope; +} + +prefix_ bool senf::INet6Address::linkScope() + const +{ + return scope() == LinkScope; +} + +prefix_ senf::INet4Address senf::INet6Address::inet4address() + const +{ + return INet4Address::from_data(&(*this)[12]); +} + +prefix_ bool senf::INet6Address::ipv4Compatible() + const +{ + return CheckINet6Network<0u,96>::match(*this); +} + +prefix_ bool senf::INet6Address::ipv4Mapped() + const +{ + return CheckINet6Network<0u,0u,0u,0u,0u,0xFFFFu,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 ; +} + +///////////////////////////////cci.e/////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// fill-column: 100 +// comment-column: 40 +// c-file-style: "senf" +// indent-tabs-mode: nil +// ispell-local-dictionary: "american" +// compile-command: "scons -u test" +// End: diff --git a/Socket/Protocols/INet/INetAddressing.ct b/Socket/Protocols/INet/INet6Address.ct similarity index 67% rename from Socket/Protocols/INet/INetAddressing.ct rename to Socket/Protocols/INet/INet6Address.ct index d2782a0..a93e78a 100644 --- a/Socket/Protocols/INet/INetAddressing.ct +++ b/Socket/Protocols/INet/INet6Address.ct @@ -1,4 +1,4 @@ -// Copyright (C) 2007 +// Copyright (C) 2007 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) // Kompetenzzentrum fuer Satelitenkommunikation (SatCom) // Stefan Bund @@ -19,27 +19,27 @@ // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. /** \file - \brief INetAddressing non-inline template implementation */ + \brief INet6Address non-inline template implementation */ -//#include "INetAddressing.ih" +#include "INet6Address.ih" // Custom includes -#include #define prefix_ ///////////////////////////////ct.p//////////////////////////////////////// -template -prefix_ senf::INet6Address::INet6Address(Range const & range) +/////////////////////////////////////////////////////////////////////////// +// senf::INet6Address + +template +prefix_ senf::INet6Address senf::INet6Address::from_data(InputIterator i) { - typename boost::range_const_iterator::type i ( boost::const_begin(range) ); - typename boost::range_const_iterator::type const i_end ( boost::const_end(range) ); - unsigned char * p (&addr_.s6_addr[0]); - unsigned char * p_end (p+sizeof(addr_.s6_addr)); - for (; p!=p_end && i!=i_end; ++p, ++i) - *p = *i; - if (p!=p_end || i!=i_end) - throw SyntaxException(); + INet6Address addr (INet6Address::noinit); + iterator j (addr.begin()); + iterator const j_end (addr.end()); + for (;j!=j_end;++j,++i) + *j = *i; + return addr; } ///////////////////////////////ct.e//////////////////////////////////////// @@ -49,9 +49,9 @@ prefix_ senf::INet6Address::INet6Address(Range const & range) // Local Variables: // mode: c++ // fill-column: 100 +// comment-column: 40 // c-file-style: "senf" // indent-tabs-mode: nil // ispell-local-dictionary: "american" // compile-command: "scons -u test" -// comment-column: 40 // End: diff --git a/Socket/Protocols/INet/INet6Address.cti b/Socket/Protocols/INet/INet6Address.cti new file mode 100644 index 0000000..9ab78ba --- /dev/null +++ b/Socket/Protocols/INet/INet6Address.cti @@ -0,0 +1,174 @@ +// Copyright (C) 2007 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +/** \file + \brief INet6Address inline template implementation */ + +#include "INet6Address.ih" + +// Custom includes +#include + +#define prefix_ inline +///////////////////////////////cti.p/////////////////////////////////////// + +template +prefix_ bool senf::detail::CheckINet6Network_impl5::match(boost::uint8_t v0, + boost::uint8_t v1) +{ + return true; +} + +template +prefix_ bool senf::detail::CheckINet6Network_impl5::match(boost::uint8_t v0, + boost::uint8_t v1) +{ + return v0 & ~boost::low_bits_mask_t<8-restbits>::sig_bits + == boost::uint8_t(a>>8) & ~boost::low_bits_mask_t<8-restbits>::sig_bits; +} + +template +prefix_ bool senf::detail::CheckINet6Network_impl5::match(boost::uint8_t v0, + boost::uint8_t v1) +{ + return v0 == boost::uint8_t(a>>8); +} + +template +prefix_ bool senf::detail::CheckINet6Network_impl5::match(boost::uint8_t v0, + boost::uint8_t v1) +{ + return v0 == boost::uint8_t(a>>8) && + v1 & ~boost::low_bits_mask_t<8-restbits>::sig_bits + == boost::uint8_t(a) & ~boost::low_bits_mask_t<8-restbits>::sig_bits; +} + +template +prefix_ bool senf::detail::CheckINet6Network_impl3:: +match(INet6Address const & addr) +{ + return CheckINet6Network_impl4::match(addr[0],addr[1]); +} + +template +prefix_ bool senf::detail::CheckINet6Network_impl3:: +match(INet6Address const & addr) +{ + return + addr[0] == boost::uint8_t(a0>>8) && addr[1] == boost::uint8_t(a0) && + CheckINet6Network_impl4::match(addr[2],addr[3]); +} + +template +prefix_ bool senf::detail::CheckINet6Network_impl3:: +match(INet6Address const & addr) +{ + return + addr[0] == boost::uint8_t(a0>>8) && addr[1] == boost::uint8_t(a0) && + addr[2] == boost::uint8_t(a1>>8) && addr[3] == boost::uint8_t(a1) && + CheckINet6Network_impl4::match(addr[4],addr[5]); +} + +template +prefix_ bool senf::detail::CheckINet6Network_impl3:: +match(INet6Address const & addr) +{ + return + addr[0] == boost::uint8_t(a0>>8) && addr[1] == boost::uint8_t(a0) && + addr[2] == boost::uint8_t(a1>>8) && addr[3] == boost::uint8_t(a1) && + addr[4] == boost::uint8_t(a2>>8) && addr[5] == boost::uint8_t(a2) && + CheckINet6Network_impl4::match(addr[6],addr[7]); +} + +template +prefix_ bool senf::detail::CheckINet6Network_impl3:: +match(INet6Address const & addr) +{ + return + addr[0] == boost::uint8_t(a0>>8) && addr[1] == boost::uint8_t(a0) && + addr[2] == boost::uint8_t(a1>>8) && addr[3] == boost::uint8_t(a1) && + addr[4] == boost::uint8_t(a2>>8) && addr[5] == boost::uint8_t(a2) && + addr[6] == boost::uint8_t(a3>>8) && addr[7] == boost::uint8_t(a3) && + CheckINet6Network_impl4::match(addr[8],addr[9]); +} + +template +prefix_ bool senf::detail::CheckINet6Network_impl3:: +match(INet6Address const & addr) +{ + return + addr[0] == boost::uint8_t(a0>>8) && addr[1] == boost::uint8_t(a0) && + addr[2] == boost::uint8_t(a1>>8) && addr[3] == boost::uint8_t(a1) && + addr[4] == boost::uint8_t(a2>>8) && addr[5] == boost::uint8_t(a2) && + addr[6] == boost::uint8_t(a3>>8) && addr[7] == boost::uint8_t(a3) && + addr[8] == boost::uint8_t(a4>>8) && addr[9] == boost::uint8_t(a4) && + CheckINet6Network_impl4::match(addr[10],addr[11]); +} + +template +prefix_ bool senf::detail::CheckINet6Network_impl3:: +match(INet6Address const & addr) +{ + return + addr[0] == boost::uint8_t(a0>>8) && addr[1] == boost::uint8_t(a0) && + addr[2] == boost::uint8_t(a1>>8) && addr[3] == boost::uint8_t(a1) && + addr[4] == boost::uint8_t(a2>>8) && addr[5] == boost::uint8_t(a2) && + addr[6] == boost::uint8_t(a3>>8) && addr[7] == boost::uint8_t(a3) && + addr[8] == boost::uint8_t(a4>>8) && addr[9] == boost::uint8_t(a4) && + addr[10] == boost::uint8_t(a5>>8) && addr[11] == boost::uint8_t(a5) && + CheckINet6Network_impl4::match(addr[12],addr[13]); +} + +template +prefix_ bool senf::detail::CheckINet6Network_impl3:: +match(INet6Address const & addr) +{ + return + addr[0] == boost::uint8_t(a0>>8) && addr[1] == boost::uint8_t(a0) && + addr[2] == boost::uint8_t(a1>>8) && addr[3] == boost::uint8_t(a1) && + addr[4] == boost::uint8_t(a2>>8) && addr[5] == boost::uint8_t(a2) && + addr[6] == boost::uint8_t(a3>>8) && addr[7] == boost::uint8_t(a3) && + addr[8] == boost::uint8_t(a4>>8) && addr[9] == boost::uint8_t(a4) && + addr[10] == boost::uint8_t(a5>>8) && addr[11] == boost::uint8_t(a5) && + addr[12] == boost::uint8_t(a6>>8) && addr[13] == boost::uint8_t(a6) && + CheckINet6Network_impl4::match(addr[14],addr[15]); +} + +///////////////////////////////cti.e/////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// fill-column: 100 +// comment-column: 40 +// c-file-style: "senf" +// indent-tabs-mode: nil +// ispell-local-dictionary: "american" +// compile-command: "scons -u test" +// End: diff --git a/Socket/Protocols/INet/INet6Address.hh b/Socket/Protocols/INet/INet6Address.hh new file mode 100644 index 0000000..48a2906 --- /dev/null +++ b/Socket/Protocols/INet/INet6Address.hh @@ -0,0 +1,276 @@ +// Copyright (C) 2007 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +/** \file + \brief INet6Address public header */ + +#ifndef HH_INet6Address_ +#define HH_INet6Address_ 1 + +// Custom includes +#include +#include +#include +#include +#include +#include "Utils/SafeBool.hh" +#include "INet4Address.hh" + +//#include "INet6Address.mpp" +#include "INet6Address.ih" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace senf { + + /** \brief IpV6 network address + + This implementation of an IpV6 address is based strictly on RFC 4291: Internet Protocol + Version 6 (IPv6) Addressing Architecture. This class provides accessors to all the + information fields defined in this document. + + The IpV6 addressing architecture however has several other components defined in other + RFC's. These RFC's should be implemented in additional modules: + + \li RFC4193: Unique Local Addresses (ULA). Defines the fc00::/7 prefix + \li RFC3306: Unicast-Prefix-based IPv6 Multicast Addresses. Defines the ff30::/12 prefix + \li RFC3956: Embedding the Rendezvous Point (RP) Address in an IPv6 Multicast + Address. Defines the ff70::/12 prefix + \li RFC3056: Connection of IPv6 Domains via IPv4 Clouds. Defines 6to4 tunneling and the + 2002::/16 prefix + \li RFC3849: IPv6 Address Prefix Reserved for Documentation. Defines the 2001:db8::/32 + prefix + + Here an overview of well-known prefixes: + + + + + + + + + + + + + + + + +
Prefix Description Definition Note
::/96 IpV4 compatible IpV6 address RFC4291 deprecated
::ffff:0:0/96 IpV6 mapped IpV4 address RFC4291
2000::/3 Global unicast addresses RFC3587 only noted, not defined
2001:db8::/32 Documentation-only prefix RFC3849
2002::/16 6to4 addressing RFC3056
fc00::/7 ULA RFC4193
fe80::/64 Link-local addresses RFC4291
fec0::/10 Site-local addresses RFC4291 deprecated
ff00::/8 Multicast RFC4291
ff00::/12 Globally allocated multicast RFC4291
ff10::/12 Locally allocated multicast RFC4291
ff30::/12 Unicast prefic based multicast RFC3306
ff70::/12 Multicast address with embedded RP RFC3956
+ + The INet6Address class is based on \c boost::array and is built as a fixed-size sequence of + 16 bytes. + */ + class INet6Address + : public boost::array, + public ComparableSafeBool + { + public: + /////////////////////////////////////////////////////////////////////////// + // Types + + typedef boost::function Callback; + ///< Callback for asynchronous from_string call + + static INet6Address const None; ///< The empty (::0) address + static INet6Address const Loopback; ///< The loopback (::1) address + static INet6Address const AllNodes; ///< The 'all nodes' link-local multicast address + static INet6Address const AllRouters; ///< The 'all routers' link-local multicast address + + enum NoInit_t { noinit }; + + /** \brief Possible scope values + + List of all possible scope values. This list includes all scope values defined for + multicast addresses in RFC4291. The values \ref LinkScope, \ref SiteScope and \ref + GlobalScope are also used with unicast addresses. + */ + enum ScopeId { + InterfaceScope = 1 /**< Interface only scope */ + , LinkScope = 2 /**< Link-local scope */ + , AdminScope = 4 /**< Administration defined local scope */ + , SiteScope = 5 /**< Site-local scope */ + , OrganizationScope = 8 /**< Scope covering multiple sites of an organization */ + , GlobalScope = 14 /**< Global Internet scope */ + + , ReservedScope = 0 /**< Reserved scope value */ + , UnassignedScope = 6 /**< Unassigned scope, may be defined locally */ + }; + + /////////////////////////////////////////////////////////////////////////// + ///\name Structors and default members + ///@{ + + explicit INet6Address(NoInit_t); ///< Construct uninitialized (!) address + INet6Address(boost::uint16_t a0=0u, boost::uint16_t a1=0u, boost::uint16_t a2=0u, + boost::uint16_t a3=0u, boost::uint16_t a4=0u, boost::uint16_t a5=0u, + boost::uint16_t a6=0u, boost::uint16_t a7=0u); + ///< Construct an address constant + + static INet6Address from_string(std::string const & s); + ///< Convert string to address + /**< This member will try to convert the given string into + an IP address. from_string() supports all standard IP + literal representations as well es hostnames. + \attention This call may block if \a s represents a + hostname which must be looked up via some network + protocol like DNS or NIS + \throws SyntaxException if the address cannot be + converted for some reason + \param[in] s Address literal or hostname */ + + static void from_string(std::string const & s, Callback const & cb); + ///< Convert string to address (async/non-blocking) + /**< This member works like + from_string(std::string const &). However unlike + from_string(std::string const &), this call will not + block. Instead it will call \a cb passing the + INet6Address instance as soon as the address has been + resolved (which may be immediate if the address + represents an IP literal). \par + On error, the address passed to \a cb will be empty. + \param[in] s Address literal or hostname + \param[in] cb Callback to pass the address to + \fixme Implement */ + + template + static INet6Address from_data(InputIterator i); + ///< Construct address from 16 bytes of raw data + /**< from_data will build an address from 16 bytes of raw + data as accessed by the iterator. The data must be in + network byte order. */ + + static INet6Address from_inet4address(INet4Address addr); + ///< Construct an IpV6-mapped IpV4 address + /**< This will construct an address of the form + ::FFFF::w.x.y.z where w.x.y.z is + the INet4Address value. This kind of address is called + an IpV6-mapped IpV4 address (see RFC4291). \par + IpV4 compatible IpV6 addresses are not directly + supported, they are deprecated in the RFC. */ + ///@} + /////////////////////////////////////////////////////////////////////////// + ///\name Accessors + ///@{ + + boost::uint64_t network() const; ///< Return 64bit network part + bool hasEuid64() const; ///< \c true, if address is based on an EUID-64 + boost::uint64_t id() const; ///< Return interface id (EUID-64) + bool universalId() const; ///< \c true, if the id() is universally assigned + bool groupId() const; ///< \c true, if the id()'s \a group bit is set + + bool unicast() const; ///< \c true, if address is unicast + bool multicast() const; ///< \c true, if address is multicast + + ScopeId scope() const; ///< Get address's scope + /**< The scope of an address is one of the \ref ScopeId + values. We need to differentiate between unicast and + multicast addresses: unicast addresses only have local, + site or global scope (where site scope is deprecated), + multicast address can have a number of scope values of + which local, site and global are a few. See the \ref + ScopeId enumerators. */ + bool globalScope() const; ///< \c true, if address is global unicast or multicast + bool linkScope() const; ///< \c true, if address is link-local unicast or multicast + + INet4Address inet4address() const; ///< Return embedded IpV4 address + /**< Returns the IpV4 address embedded within an IpV4 + compatible or IpV4 mapped unicast address. This address + is given by the last 32 bits of the IpV6 address. \par + The value returned is only a valid IpV4 address if + either ipv4Compatible() or ipv4Mapped() return \c + true. */ + bool ipv4Compatible() const; ///< \c true, if address is IpV4 compatible + /**< IpV4 compatible IpV6 addresses are deprecated. */ + bool ipv4Mapped() const; ///< \c true, if address is IpV4 mapped + + bool globalMulticastAddr() const; ///< \c true, if T bit is \e not set + /**< Any multicast address with a cleared T bit must be + globally assigned. See RFC4291. */ + bool prefixMulticastAddr() const; ///< \c true, if P bit is set + /**< In RFC4291, the P bit is specified as defining a + unicast prefix based multicast address. See RFC3306. */ + bool embeddedRpAddr() const; ///< \c true, if R bit is set + /** In RFC4291, the R bit is specified as defining a + multicast address with embedded rendezvous point. See + RFC3956. */ + + bool boolean_test() const; ///< \c true, if address != '::' (None) + + ///@} + ///\name Mutators + ///@{ + + void network(boost::uint64_t net); ///< Set network part of address + void id(boost::uint64_t id); ///< Set interface id part of address + + ///@} + + /** \brief Invalid IpV6 address syntax */ + struct SyntaxException : public std::exception + { virtual char const * what() const throw() { return "Invalid IpV6 address syntax"; } }; + }; + + /** \brief Output INet6Address instance as it's string representation + \related INet6Address + */ + std::ostream & operator<<(std::ostream & os, INet6Address const & addr); + + /** \brief Check address against a fixed network prefix + + This helper allows to easily and efficiently check an address against an arbitrary network + prefix: + \code + if (senf::CheckINet6Network<0x2000u,0xDB8u,32u>::match(addr)) { + // 'addr' is within in the 2001:db8::/32 documentation-only network + ... + } + \endcode + + The code generated by this call is highly optimized and as probably as efficient as it can + get. + + \related INet6Address + */ + template + struct CheckINet6Network + : public detail::CheckINet6Network_impl + {}; + +} + +///////////////////////////////hh.e//////////////////////////////////////// +#include "INet6Address.cci" +#include "INet6Address.ct" +#include "INet6Address.cti" +#endif + + +// Local Variables: +// mode: c++ +// fill-column: 100 +// comment-column: 40 +// c-file-style: "senf" +// indent-tabs-mode: nil +// ispell-local-dictionary: "american" +// compile-command: "scons -u test" +// End: diff --git a/Socket/Protocols/INet/INet6Address.ih b/Socket/Protocols/INet/INet6Address.ih new file mode 100644 index 0000000..1dc03ff --- /dev/null +++ b/Socket/Protocols/INet/INet6Address.ih @@ -0,0 +1,203 @@ +// Copyright (C) 2007 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +/** \file + \brief INet6Address internal header */ + +#ifndef IH_INet6Address_ +#define IH_INet6Address_ 1 + +// Custom includes + +///////////////////////////////ih.p//////////////////////////////////////// + +namespace senf { + + class INet6Address; + +namespace detail { + +# ifndef DOXYGEN + + template + struct CheckINet6Network_impl5 + {}; + + template + struct CheckINet6Network_impl5 + { + static bool match(boost::uint8_t v0, boost::uint8_t v1); + }; + + template + struct CheckINet6Network_impl5 + { + static bool match(boost::uint8_t v0, boost::uint8_t v1); + }; + + template + struct CheckINet6Network_impl5 + { + static bool match(boost::uint8_t v0, boost::uint8_t v1); + }; + + template + struct CheckINet6Network_impl5 + { + static bool match(boost::uint8_t v0, boost::uint8_t v1); + }; + + template + struct CheckINet6Network_impl4 + : public CheckINet6Network_impl5 + {}; + + template + struct CheckINet6Network_impl3 + {}; + + template + struct CheckINet6Network_impl3 + { + static bool match(INet6Address const & addr); + }; + + template + struct CheckINet6Network_impl3 + { + static bool match(INet6Address const & addr); + }; + + template + struct CheckINet6Network_impl3 + { + static bool match(INet6Address const & addr); + }; + + template + struct CheckINet6Network_impl3 + { + static bool match(INet6Address const & addr); + }; + + template + struct CheckINet6Network_impl3 + { + static bool match(INet6Address const & addr); + }; + + template + struct CheckINet6Network_impl3 + { + static bool match(INet6Address const & addr); + }; + + template + struct CheckINet6Network_impl3 + { + static bool match(INet6Address const & addr); + }; + + template + struct CheckINet6Network_impl3 + { + static bool match(INet6Address const & addr); + }; + + template + struct CheckINet6Network_impl2 + : public CheckINet6Network_impl3 + {}; + + template + struct CheckINet6Network_impl + : public CheckINet6Network_impl2 + {}; + + template + struct CheckINet6Network_impl + : public CheckINet6Network_impl2 + {}; + + template + struct CheckINet6Network_impl + : public CheckINet6Network_impl2 + {}; + + template + struct CheckINet6Network_impl + : public CheckINet6Network_impl2 + {}; + + template + struct CheckINet6Network_impl + : public CheckINet6Network_impl2 + {}; + + template + struct CheckINet6Network_impl + : public CheckINet6Network_impl2 + {}; + + template + struct CheckINet6Network_impl + : public CheckINet6Network_impl2 + {}; + + template + struct CheckINet6Network_impl + : public CheckINet6Network_impl2 + {}; + + template + struct IsINet6Network_impl + {}; + +# endif + +}} + +///////////////////////////////ih.e//////////////////////////////////////// +#endif + + +// Local Variables: +// mode: c++ +// fill-column: 100 +// comment-column: 40 +// c-file-style: "senf" +// indent-tabs-mode: nil +// ispell-local-dictionary: "american" +// compile-command: "scons -u test" +// End: diff --git a/Socket/Protocols/INet/INet6Address.test.cc b/Socket/Protocols/INet/INet6Address.test.cc new file mode 100644 index 0000000..562c8e6 --- /dev/null +++ b/Socket/Protocols/INet/INet6Address.test.cc @@ -0,0 +1,147 @@ +// Copyright (C) 2007 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +/** \file + \brief INet6Address.test unit tests */ + +//#include "INet6Address.test.hh" +//#include "INet6Address.test.ih" + +// Custom includes +#include +#include "INet6Address.hh" + +#include +#include + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +BOOST_AUTO_UNIT_TEST(inet6Address) +{ + using senf::INet6Address; + using senf::INet4Address; + + { + INet6Address addr1 (INet6Address::from_string("0102:0304:0506:0708:090A:0B0C:0D0E:0F00")); + BOOST_CHECK_EQUAL( addr1[0], 1 ); + BOOST_CHECK_EQUAL( addr1[1], 2 ); + BOOST_CHECK_EQUAL( addr1[2], 3 ); + BOOST_CHECK_EQUAL( addr1[3], 4 ); + BOOST_CHECK_EQUAL( addr1[4], 5 ); + BOOST_CHECK_EQUAL( addr1[5], 6 ); + BOOST_CHECK_EQUAL( addr1[6], 7 ); + BOOST_CHECK_EQUAL( addr1[7], 8 ); + BOOST_CHECK_EQUAL( addr1[8], 9 ); + BOOST_CHECK_EQUAL( addr1[9], 10 ); + BOOST_CHECK_EQUAL( addr1[10], 11 ); + BOOST_CHECK_EQUAL( addr1[11], 12 ); + BOOST_CHECK_EQUAL( addr1[12], 13 ); + BOOST_CHECK_EQUAL( addr1[13], 14 ); + BOOST_CHECK_EQUAL( addr1[14], 15 ); + BOOST_CHECK_EQUAL( addr1[15], 0 ); + BOOST_CHECK_EQUAL( INet6Address::from_string("ip6-localhost"), INet6Address::Loopback ); + INet6Address addr2; + BOOST_CHECK_EQUAL( boost::lexical_cast(addr2), "::" ); + addr2 = INet6Address::from_string("::1"); + BOOST_CHECK( addr1 != addr2 ); + addr1 =INet6Address::from_string("::1"); + BOOST_CHECK_EQUAL( addr1, addr2 ); + addr1 = INet6Address::None; + addr2 = INet6Address::from_string("::"); + BOOST_CHECK_EQUAL( addr1, addr2 ); + BOOST_CHECK_THROW( INet6Address::from_string(""), INet6Address::SyntaxException ); + BOOST_CHECK_EQUAL( boost::lexical_cast(addr1), "::" ); + unsigned char data[] = { 0x12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x21, 0 }; + INet6Address addr3 (INet6Address::from_data(data)); + BOOST_CHECK_EQUAL( addr3, INet6Address::from_string("1200::21") ); + BOOST_CHECK_EQUAL( INet6Address::from_inet4address(INet4Address(0x01020304)), + INet6Address::from_string("::ffff:1.2.3.4") ); + } + + { + INet6Address addr (INet6Address::from_string("2001:dead:beef::1002:3004")); + BOOST_CHECK_EQUAL( addr.network(), 0x2001deadbeef0000llu ); + BOOST_CHECK_EQUAL( addr.id(), 0x0000000010023004llu ); + BOOST_CHECK( addr.hasEuid64() ); + BOOST_CHECK( ! INet6Address::from_inet4address(INet4Address(0x01020304)).hasEuid64() ); + BOOST_CHECK( ! addr.universalId() ); + BOOST_CHECK( ! addr.groupId() ); + BOOST_CHECK( addr.unicast() ); + BOOST_CHECK( ! addr.multicast() ); + BOOST_CHECK( ! INet6Address::AllNodes.unicast() ); + BOOST_CHECK( INet6Address::AllNodes.multicast() ); + BOOST_CHECK_EQUAL( addr.scope(), INet6Address::GlobalScope ); + BOOST_CHECK( addr.globalScope() ); + BOOST_CHECK_EQUAL( INet6Address(0xfe80).scope(), INet6Address::LinkScope ); + BOOST_CHECK_EQUAL( INet6Address(0xfec0).scope(), INet6Address::SiteScope ); + BOOST_CHECK_EQUAL( INet6Address(0xff00).scope(), INet6Address::ReservedScope ); + BOOST_CHECK_EQUAL( INet6Address(0xff01).scope(), INet6Address::InterfaceScope ); + BOOST_CHECK_EQUAL( INet6Address(0xff02).scope(), INet6Address::LinkScope ); + BOOST_CHECK_EQUAL( INet6Address(0xff03).scope(), INet6Address::ReservedScope ); + BOOST_CHECK_EQUAL( INet6Address(0xff04).scope(), INet6Address::AdminScope ); + BOOST_CHECK_EQUAL( INet6Address(0xff05).scope(), INet6Address::SiteScope ); + BOOST_CHECK_EQUAL( INet6Address(0xff06).scope(), INet6Address::UnassignedScope ); + BOOST_CHECK_EQUAL( INet6Address(0xff07).scope(), INet6Address::UnassignedScope ); + BOOST_CHECK_EQUAL( INet6Address(0xff08).scope(), INet6Address::OrganizationScope ); + BOOST_CHECK_EQUAL( INet6Address(0xff09).scope(), INet6Address::UnassignedScope ); + BOOST_CHECK_EQUAL( INet6Address(0xff0a).scope(), INet6Address::UnassignedScope ); + BOOST_CHECK_EQUAL( INet6Address(0xff0b).scope(), INet6Address::UnassignedScope ); + BOOST_CHECK_EQUAL( INet6Address(0xff0c).scope(), INet6Address::UnassignedScope ); + BOOST_CHECK_EQUAL( INet6Address(0xff0d).scope(), INet6Address::UnassignedScope ); + BOOST_CHECK_EQUAL( INet6Address(0xff0e).scope(), INet6Address::GlobalScope ); + BOOST_CHECK_EQUAL( INet6Address(0xff0f).scope(), INet6Address::ReservedScope ); + BOOST_CHECK_EQUAL( INet6Address(0u,0u,0u,0u,0u,0xFFFF,0x0102u,0x0304).inet4address(), + INet4Address(0x01020304) ); + BOOST_CHECK( INet6Address(0u,0u,0u,0u,0u,0u,0x0102u,0x0304).ipv4Compatible() ); + BOOST_CHECK( INet6Address(0u,0u,0u,0u,0u,0xFFFF,0x0102,0x0304).ipv4Mapped() ); + BOOST_CHECK( ! addr.ipv4Compatible() ); + BOOST_CHECK( ! addr.ipv4Mapped() ); + + BOOST_CHECK( INet6Address::AllNodes.globalMulticastAddr() ); + BOOST_CHECK( ! INet6Address::AllNodes.prefixMulticastAddr() ); + BOOST_CHECK( ! INet6Address::AllNodes.embeddedRpAddr() ); + + BOOST_CHECK( INet6Address::Loopback ); + BOOST_CHECK( ! INet6Address::None ); + } + + { + INet6Address addr; + addr.network(0x2000010203040506ull); + BOOST_CHECK_EQUAL( addr, INet6Address(0x2000u,0x0102u,0x0304u,0x0506u) ); + addr.id(1u); + BOOST_CHECK_EQUAL( addr, INet6Address(0x2000u,0x0102u,0x0304u,0x0506u,0u,0u,0u,1u) ); + } +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// fill-column: 100 +// comment-column: 40 +// c-file-style: "senf" +// indent-tabs-mode: nil +// ispell-local-dictionary: "american" +// compile-command: "scons -u test" +// End: diff --git a/Socket/Protocols/INet/INetAddressing.cc b/Socket/Protocols/INet/INetAddressing.cc index d768c7d..9ef8c39 100644 --- a/Socket/Protocols/INet/INetAddressing.cc +++ b/Socket/Protocols/INet/INetAddressing.cc @@ -41,7 +41,7 @@ ///////////////////////////////cc.p//////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// -// senf::INet4Address +// senf::INet4SocketAddress prefix_ senf::INet4SocketAddress::INet4SocketAddress(std::string const & addr) { @@ -72,46 +72,6 @@ prefix_ void senf::INet4SocketAddress::clear() } /////////////////////////////////////////////////////////////////////////// -// senf::INet6Address - -prefix_ senf::INet6Address::INet6Address(std::string const & addr) -{ - if (inet_pton(AF_INET6,addr.c_str(),&addr_) <= 0) - throw SyntaxException(); -} - -prefix_ senf::INet6Address::INet6Address(char const * addr) -{ - if (inet_pton(AF_INET6,addr,&addr_) <= 0) - throw SyntaxException(); -} - -prefix_ void senf::INet6Address::clear() -{ - ::memset(&addr_,0,sizeof(addr_)); -} - -prefix_ std::string senf::INet6Address::address() - const -{ - char buffer[8*5]; - BOOST_ASSERT( inet_ntop(AF_INET6, &addr_, buffer, sizeof(buffer)) ); - return std::string(buffer); -} - -prefix_ bool senf::INet6Address::operator==(INet6Address const & other) - const -{ - return ::memcmp(&addr_,&other.addr_,sizeof(addr_))==0; -} - -prefix_ bool senf::INet6Address::operator!=(INet6Address const & other) - const -{ - return !operator==(other); -} - -/////////////////////////////////////////////////////////////////////////// // senf::INet6SocketAddress prefix_ bool senf::INet6SocketAddress::operator==(INet6SocketAddress const & other) diff --git a/Socket/Protocols/INet/INetAddressing.cci b/Socket/Protocols/INet/INetAddressing.cci index f0e039d..f053e1d 100644 --- a/Socket/Protocols/INet/INetAddressing.cci +++ b/Socket/Protocols/INet/INetAddressing.cci @@ -97,53 +97,6 @@ prefix_ std::ostream & senf::operator<<(std::ostream & os, INet4SocketAddress co } /////////////////////////////////////////////////////////////////////////// -// senf::INet6Address - -prefix_ senf::INet6Address::INet6Address() -{ - clear(); -} - -prefix_ senf::INet6Address::INet6Address(struct in6_addr const & addr) -{ - addr_ = addr; -} - -prefix_ struct in6_addr & senf::INet6Address::addr() -{ - return addr_; -} - -prefix_ struct in6_addr const & senf::INet6Address::addr() - const -{ - return addr_; -} - -prefix_ struct in6_addr * senf::INet6Address::addr_p() -{ - return & addr_; -} - -prefix_ struct in6_addr const * senf::INet6Address::addr_p() - const -{ - return & addr_; -} - -prefix_ unsigned senf::INet6Address::addr_len() - const -{ - return sizeof(addr_); -} - -prefix_ std::ostream & senf::operator<<(std::ostream & os, INet6Address const & addr) -{ - os << addr.address(); - return os; -} - -/////////////////////////////////////////////////////////////////////////// // senf::INet6SocketAddress prefix_ senf::INet6SocketAddress::INet6SocketAddress() @@ -166,7 +119,7 @@ prefix_ senf::INet6SocketAddress::INet6SocketAddress(char const * addr) prefix_ senf::INet6SocketAddress::INet6SocketAddress(INet6Address const & addr, unsigned port) { clear(); - sockaddr_.sin6_addr = addr.addr(); + std::copy(addr.begin(), addr.end(), &sockaddr_.sin6_addr.s6_addr[0]); sockaddr_.sin6_port = htons(port); } @@ -174,7 +127,7 @@ prefix_ senf::INet6SocketAddress::INet6SocketAddress(INet6Address const & addr, std::string const & iface) { clear(); - sockaddr_.sin6_addr = addr.addr(); + std::copy(addr.begin(), addr.end(), &sockaddr_.sin6_addr.s6_addr[0]); sockaddr_.sin6_port = htons(port); assignIface(iface); } @@ -190,12 +143,12 @@ prefix_ senf::INet6SocketAddress::INet6SocketAddress(std::string const & addr, prefix_ senf::INet6Address senf::INet6SocketAddress::host() const { - return INet6Address(sockaddr_.sin6_addr); + return INet6Address::from_data(&sockaddr_.sin6_addr.s6_addr[0]); } prefix_ void senf::INet6SocketAddress::host(INet6Address const & addr) { - sockaddr_.sin6_addr = addr.addr(); + std::copy(addr.begin(), addr.end(), &sockaddr_.sin6_addr.s6_addr[0]); } prefix_ unsigned senf::INet6SocketAddress::port() diff --git a/Socket/Protocols/INet/INetAddressing.hh b/Socket/Protocols/INet/INetAddressing.hh index 79ccb52..7d01b0a 100644 --- a/Socket/Protocols/INet/INetAddressing.hh +++ b/Socket/Protocols/INet/INetAddressing.hh @@ -37,6 +37,7 @@ #include "Socket/CommunicationPolicy.hh" #include "Socket/Protocols/GenericAddressingPolicy.hh" #include "INet4Address.hh" +#include "INet6Address.hh" //#include "INetAddressing.mpp" ///////////////////////////////hh.p//////////////////////////////////////// @@ -112,75 +113,6 @@ namespace senf { */ std::ostream & operator<<(std::ostream & os, INet4SocketAddress const & addr); - /** \brief IPv6 network address - - INet6Address represents a 128bit IPv6 network address. This class supports all standard - numeric string representations of IPv6 addresses. This class does not integrate with \c - gethostbyname() and so does not support host names. - - The conversion constructors allow the use of string constants wherever an INet6Address is - expected. Especially, it is possible to assign a string to an address to change it's value. - - \implementation The char const * constructor overload is needed to support - string-literals where an INet6Address is expected (the C++ standard does not allow - chaining conversion constructors like char const * -> std::string -> INet6Address) - */ - class INet6Address - { - public: - /////////////////////////////////////////////////////////////////////////// - // Types - - /////////////////////////////////////////////////////////////////////////// - ///\name Structors and default members - ///@{ - - INet6Address(); ///< Create empty address - INet6Address(std::string const & addr); ///< Create address from string representation - INet6Address(char const * addr); ///< Create address from string representation - INet6Address(struct in6_addr const & addr); ///< Create address from in6_addr - template - explicit INet6Address(Range const & range); ///< Create address from arbitrary raw data - /**< This constructor will copy 16 bytes from the given - range and interpret them as a IPv6 address in network - byte order. This constructor is used to read an - arbitrary address from it's binary representation. - - \param range arbitrary range, see Boost.Range - */ - - ///@} - /////////////////////////////////////////////////////////////////////////// - - void clear(); ///< Clear address - std::string address() const; ///< Return printable address representation - - bool operator==(INet6Address const & other) const; ///< Compare addresses for equality - bool operator!=(INet6Address const & other) const; ///< Inverse of above - - struct in6_addr & addr(); ///< Access internal address representation - struct in6_addr const & addr() const; - ///< Access internal address representation in const context - struct in6_addr * addr_p(); ///< Get pointer to internal address repr - struct in6_addr const * addr_p() const; - ///< Get const pointer to internal address repr - unsigned addr_len() const; ///< Size of an IPv6 address (16 bytes) - - struct SyntaxException : public std::exception - { virtual char const * what() const throw() { return "Invalid IpV6 address syntax"; } }; - - protected: - - private: - struct in6_addr addr_; - }; - - - /** \brief Output INet6Address instance as it's string representation - */ - std::ostream & operator<<(std::ostream & os, INet6Address const & addr); - /** \brief IPv6 socket address This class wraps the standard \c sockaddr_in6 structure. INet6SocketAddress provides access @@ -342,7 +274,7 @@ namespace senf { ///////////////////////////////hh.e//////////////////////////////////////// #include "INetAddressing.cci" -#include "INetAddressing.ct" +//#include "INetAddressing.ct" //#include "INetAddressing.cti" //#include "INetAddressing.mpp" #endif diff --git a/Socket/Protocols/INet/INetAddressing.test.cc b/Socket/Protocols/INet/INetAddressing.test.cc index c8c8024..102b95d 100644 --- a/Socket/Protocols/INet/INetAddressing.test.cc +++ b/Socket/Protocols/INet/INetAddressing.test.cc @@ -34,7 +34,7 @@ #define prefix_ ///////////////////////////////cc.p//////////////////////////////////////// -BOOST_AUTO_UNIT_TEST(inet4Address) +BOOST_AUTO_UNIT_TEST(inet4SocketAddress) { using senf::INet4SocketAddress; using senf::INet4Address; @@ -78,84 +78,45 @@ BOOST_AUTO_UNIT_TEST(inet4Address) } } -BOOST_AUTO_UNIT_TEST(inet6Address) +BOOST_AUTO_UNIT_TEST(inet6SocketAddress) { using senf::INet6Address; using senf::INet6SocketAddress; { - INet6Address addr1 ("0102:0304:0506:0708:090A:0B0C:0D0E:0F00"); - BOOST_CHECK_EQUAL( addr1.addr().s6_addr[0], 1 ); - BOOST_CHECK_EQUAL( addr1.addr().s6_addr[1], 2 ); - BOOST_CHECK_EQUAL( addr1.addr().s6_addr[2], 3 ); - BOOST_CHECK_EQUAL( addr1.addr().s6_addr[3], 4 ); - BOOST_CHECK_EQUAL( addr1.addr().s6_addr[4], 5 ); - BOOST_CHECK_EQUAL( addr1.addr().s6_addr[5], 6 ); - BOOST_CHECK_EQUAL( addr1.addr().s6_addr[6], 7 ); - BOOST_CHECK_EQUAL( addr1.addr().s6_addr[7], 8 ); - BOOST_CHECK_EQUAL( addr1.addr().s6_addr[8], 9 ); - BOOST_CHECK_EQUAL( addr1.addr().s6_addr[9], 10 ); - BOOST_CHECK_EQUAL( addr1.addr().s6_addr[10], 11 ); - BOOST_CHECK_EQUAL( addr1.addr().s6_addr[11], 12 ); - BOOST_CHECK_EQUAL( addr1.addr().s6_addr[12], 13 ); - BOOST_CHECK_EQUAL( addr1.addr().s6_addr[13], 14 ); - BOOST_CHECK_EQUAL( addr1.addr().s6_addr[14], 15 ); - BOOST_CHECK_EQUAL( addr1.addr().s6_addr[15], 0 ); - INet6Address addr2; - BOOST_CHECK_EQUAL( addr2, "::" ); - addr2 = "::1"; - BOOST_CHECK( addr1 != addr2 ); - addr1 ="::1"; - BOOST_CHECK_EQUAL( addr1, addr2 ); - BOOST_CHECK_EQUAL( addr1.address(),"::1" ); - addr1.clear(); - addr2 = "::"; - BOOST_CHECK_EQUAL( addr1, addr2 ); - BOOST_CHECK_THROW( addr1 = "", INet6Address::SyntaxException ); - BOOST_CHECK_EQUAL( boost::lexical_cast(addr1), "::" ); - unsigned char data[] = { 0x12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x21, 0 }; - INet6Address addr3 (std::make_pair(&data[0],&data[0]+sizeof(data)-1)); - BOOST_CHECK_EQUAL( addr3, "1200::21" ); - BOOST_CHECK_THROW( INet6Address(std::make_pair(&data[0],&data[0]+sizeof(data))), - INet6Address::SyntaxException ); - BOOST_CHECK_THROW( INet6Address(std::make_pair(&data[0],&data[0]+sizeof(data)-2)), - INet6Address::SyntaxException ); - } - - { INet6SocketAddress addr; - BOOST_CHECK_EQUAL( addr.host(), "::" ); + BOOST_CHECK_EQUAL( boost::lexical_cast(addr.host()), "::" ); BOOST_CHECK_EQUAL( addr.port(), 0u ); BOOST_CHECK_EQUAL( addr.iface(), "" ); addr = "[12::21]:12345"; - BOOST_CHECK_EQUAL( addr.host(), "12::21" ); + BOOST_CHECK_EQUAL( addr.host(), INet6Address::from_string("12::21") ); BOOST_CHECK_EQUAL( addr.port(), 12345u ); BOOST_CHECK_EQUAL( addr.iface(), "" ); BOOST_CHECK_EQUAL( addr, INet6SocketAddress("[12::21]:12345") ); } { - INet6SocketAddress addr ("::1", 1); + INet6SocketAddress addr (INet6Address::from_string("::1"), 1); BOOST_CHECK_EQUAL( addr, "[::1]:1" ); BOOST_CHECK_EQUAL( addr.iface(), "" ); } { - INet6SocketAddress addr ("::1", 1, "lo"); + INet6SocketAddress addr (INet6Address::Loopback, 1, "lo"); BOOST_CHECK_EQUAL( addr, "[::1@lo]:1" ); BOOST_CHECK_EQUAL( addr.iface(), "lo" ); addr.iface(""); BOOST_CHECK_EQUAL( addr.iface(), "" ); addr.port(100u); BOOST_CHECK_EQUAL( addr.port(), 100u ); - addr.host("::2"); - BOOST_CHECK_EQUAL( addr.host(), "::2" ); + addr.host(INet6Address::from_string("::2")); + BOOST_CHECK_EQUAL( addr.host(), INet6Address::from_string("::2") ); BOOST_CHECK_THROW( addr = "", INet6SocketAddress::SyntaxException ); BOOST_CHECK_THROW( addr = "[::1]", INet6SocketAddress::SyntaxException ); BOOST_CHECK_THROW( addr = "[::1]1234", INet6SocketAddress::SyntaxException ); addr = "[12::21@lo]:12345"; BOOST_CHECK_EQUAL( addr.address(), "[12::21@lo]:12345" ); - BOOST_CHECK_EQUAL( addr.host(), "12::21" ); + BOOST_CHECK_EQUAL( addr.host(), INet6Address::from_string("12::21") ); BOOST_CHECK_EQUAL( addr.port(), 12345u ); BOOST_CHECK_EQUAL( addr.iface(), "lo" ); BOOST_CHECK_EQUAL( boost::lexical_cast(addr), "[12::21@lo]:12345" ); diff --git a/senf.dict b/senf.dict index 2d56094..362d243 100644 --- a/senf.dict +++ b/senf.dict @@ -46,9 +46,11 @@ EthernetParser ethertype EthVLan EUI +EUID ExampleListPolicy ExampleVectorPolicy ExtendedParser +FFFF FileBody filebody FileHandle @@ -59,6 +61,7 @@ fokus FooParser fraunhofer fuer +GlobalScope hh hideinitializer Hmm @@ -83,11 +86,13 @@ IntField InvalidPacketChainException ip IpV +ipv iterator key Kommunikationssysteme Kompetenzzentrum li +LinkScope ListB ListN ListPolicy @@ -152,9 +157,12 @@ registerPacketType registerSomePacket RegistrationProxy rerference +RFC +RP SafePacketParser SatCom Satelitenkommunikation +ScopeId senf ServerSocketHandle setBegin @@ -162,6 +170,7 @@ setEnd setFromPosition SimplePacketType SimpleVectorSizer +SiteScope SizeParser skipline SocketHandle @@ -193,6 +202,7 @@ udp UDPPacket UInt UIntField +unicast VectorN vlanId VLanId