return addr;
}
-prefix_ boost::uint64_t senf::INet6Address::network()
+prefix_ senf::INet6Address senf::INet6Address::from_eui64(senf::EUI64 const & eui)
+{
+ INet6Address addr;
+ addr[0] = 0xfe;
+ addr[1] = 0x80;
+ std::copy(eui.begin(), eui.end(), addr.begin()+8);
+ return addr;
+}
+
+prefix_ senf::INet6Network 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) );
+ return senf::INet6Network(*this, 64);
}
-prefix_ boost::uint64_t senf::INet6Address::id()
+prefix_ senf::EUI64 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) );
+ return senf::EUI64::from_data(begin()+8);
}
prefix_ bool senf::INet6Address::universalId()
return ! multicast();
}
-prefix_ bool senf::INet6Address::hasEuid64()
+prefix_ bool senf::INet6Address::hasEUI64()
const
{
return unicast() && ((*this)[0]&0xE0u) != 0u;
#include "INet4Address.hh"
#include "../AddressExceptions.hh"
#include "../Raw/MACAddress.hh"
+#include "../Raw/EUI64.hh"
//#include "INet6Address.mpp"
#include "INet6Address.ih"
namespace senf {
+ class INet6Network;
+
/** \brief INet6 network address
This implementation of an INet6 address is based strictly on
///< Construct a link-local INet6 address
/**< This will construct a link local address of the form
<tt>fe80::xxxx:xxff:fexx:xxxx</tt>. */
+
+ static INet6Address from_eui64(senf::EUI64 const & eui);
+ ///< Construct link-local INet6 address
+ /**< This will construct a link local address of the form
+ <tt>fe80::xxxx:xxxx:xxxx:xxxx</tt>. */
in6_addr toin6_addr() const; ///< get the linux in6_addr struct (convinience only)
///\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)
+ INet6Network network() const; ///< Return <tt>/64</tt> Network of this address
+ bool hasEUI64() const; ///< \c true, if address is based on an EUID-64
+ EUI64 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
{
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_EQUAL( addr.network(), senf::INet6Network(
+ senf::INet6Address(0x2001u,0xdeadu, 0xbeef),64) );
+ BOOST_CHECK_EQUAL( addr.id(), senf::EUI64(0x0000000010023004llu) );
+ BOOST_CHECK( addr.hasEUI64() );
+ BOOST_CHECK( ! INet6Address::from_inet4address(INet4Address(0x01020304)).hasEUI64() );
BOOST_CHECK( ! addr.universalId() );
BOOST_CHECK( ! addr.groupId() );
BOOST_CHECK( addr.unicast() );
return (*this)[3] == 0xffu && (*this)[4] == 0xfeu;
}
+prefix_ bool senf::EUI64::local()
+ const
+{
+ return (*this)[0]&0x02;
+}
+
+prefix_ bool senf::EUI64::group()
+ const
+{
+ return (*this)[0]&0x01;
+}
+
prefix_ bool senf::EUI64::boolean_test()
const
{
<tr><td><tt>std::string</tt></td>
<td><tt>senf::EUI64::from_string("1a:2b:3c:4d-5f:60:71:82")</tt><br/>
<tt>senf::str(</tt><i>eui64</i><tt>)</tt></td></tr>
- <tr><td><i>raw data</i></td>
+ <tr><td><i>raw data</i><br/> (8 bytes)</td>
<td><tt>senf::EUI64::from_data(</tt><i>iterator</i><tt>)</tt><br/>
<i>eui64</i><tt>.begin()</tt></td></tr>
<tr><td>senf::MACAddress<br/> (aka EUI-48)</td>
<tt>senf::MACAddress::from_eui64(</tt><i>eui64</i><tt>)</tt></td></tr>
</table>
- Additionally, a senf::MACAddress can be converted into an EUI64 and vice versa.
+ Since senf::EUI64 is based on \c boost::array, you can access the raw data bytes of the
+ address using \c begin(), \c end() or \c operator[]:
+ \code
+ senf::EUI64 eui64 (...);
+ std::vector<char> data;
+ data.resize(8);
+ std::copy(eui64.begin(), eui64.end(), data.begin()); // Copy 8 bytes
+ \endcode
+
+ \see <a href="http://tools.ietf.org/html/rfc4291">RFC 4291</a>
\ingroup addr_group
*/
static EUI64 from_string(std::string const & s);
///< Construct EUI-64 from string representation
/**< The string representation consists of 8 octets in
- hexadecimal notation spearated by ':' or '-' */
+ hexadecimal notation spearated by ':' or '-'
+ \throws senf::AddressSyntaxException */
template <class InputIterator>
static EUI64 from_data(InputIterator i);
///< Construct EUI-64 from 8 data octets
bool isMACCompatible() const; ///< \c true, if EUI64 is MAC compatible, \c false otherwise
/**< An EUI64 is MAC compatible if bytes 4th and 5th byte
(in network byte order) are 0xfffe. */
+ bool local() const; ///< \c true if the \e local bit is set, \c false otherwise
+ /**< The \e local bit is the second least significant bit of
+ the first octet (bit 6 in standard RFC bit numbering).
+ */
+ bool group() const; ///< \c true if the \e group bit is set, \c false otherwise
+ /**< The \e group bit is the least significant bit of the
+ first octed (bit 7 in standard RFC bit numbering). */
bool boolean_test() const; ///< \c true, if EUI64 is != 0, \c false otherwise
boost::uint64_t uint64() const; ///< Return EUI64 as integer number
};
BOOST_CHECK_EQUAL_COLLECTIONS( eui.begin(), eui.end(), data, data+sizeof(data)/sizeof(data[0]) );
BOOST_CHECK( eui );
BOOST_CHECK( eui.isMACCompatible() );
+ BOOST_CHECK( ! eui.local() );
+ BOOST_CHECK( ! eui.group() );
BOOST_CHECK_EQUAL( eui.uint64(), 0x102030fffe405060ull );
BOOST_CHECK_EQUAL( eui, senf::EUI64::from_data(data) );
#include <sstream>
#include <boost/io/ios_state.hpp>
#include "ParseString.hh"
+#include "EUI64.hh"
//#include "MACAddress.mpp"
#define prefix_
return mac;
}
-prefix_ senf::MACAddress senf::MACAddress::from_eui64(boost::uint64_t v)
+prefix_ senf::MACAddress senf::MACAddress::from_eui64(senf::EUI64 const & eui)
{
- if ( boost::uint16_t(v>>24) != 0xfffe )
+ if (eui[3] != 0xffu || eui[4] != 0xfeu)
throw AddressSyntaxException();
MACAddress mac (senf::noinit);
- mac[0] = boost::uint8_t( v>>56 );
- mac[1] = boost::uint8_t( v>>48 );
- mac[2] = boost::uint8_t( v>>40 );
- mac[3] = boost::uint8_t( v>>16 );
- mac[4] = boost::uint8_t( v>> 8 );
- mac[5] = boost::uint8_t( v );
+ mac[0] = eui[0];
+ mac[1] = eui[1];
+ mac[2] = eui[2];
+ mac[3] = eui[5];
+ mac[4] = eui[6];
+ mac[5] = eui[7];
return mac;
}
namespace senf {
+ class EUI64;
+
/** \brief Ethernet MAC address
- The Ethernet MAC is modelled as a fixed-size container/sequence of 6 bytes.
-
- The following statements all create the same MAC address <code>00:1A:2B:3C:4D:5F</code>
- \code
- // Used to construct constant MAC addresses
- MACAddress(0x001A2B3C4D5Full)
-
- // Construct a MAC address from it's string representation:
- MACAddress::from_string("00:1a:2b:3c:4d:5f") // case is ignored
- MACAddress::from_string("00-1A-2B-3C-4D-5F") // '-' as separator is allowed too
-
- // Construct a MAC address from raw data. 'from_data' takes an arbitrary iterator (e.g. a
- // pointer) as argument. Here we use a fixed array but normally you will need this to build
- // a MAC address in a packet parser
- char rawBytes[] = { 0x00, 0x1A, 0x2B, 0x3C, 0x4D, 0x5F };
- MACAddress::from_data(rawBytes)
-
- // Construct a MAC from the EUID64 as used by INet6 interfaces. The eui64 will come from an
- // INet6 address:
- MACAddress::from_eui64(0x001A2BFFFE3C4D5Full)
- MACAddress::from_eui64(
- INet6Address(0x2001u,0xDB8u,0x1u,0x0u,0x001Au,0x2BFFu,0xFE3Cu,0x3D5Fu).id())
- \endcode
+ The Ethernet MAC is modelled as a fixed-size container/sequence of 6 bytes. A MACAddress can
+ be converted from/to the following representations
+
+ <table class="senf">
+ <tr><td><tt>boost::uint64_t</tt></td>
+ <td><tt>senf::MACAddress(0x112233445566ull)</tt><br/>
+ <i>mac</i><tt>.uint64()</tt></td></tr>
+ <tr><td><tt>std::string</tt></td>
+ <td><tt>senf::MACAddress::from_string("11:22:33:44:55:66")</tt><br/>
+ <tt>senf::str(</tt><i>mac</i><tt>)</tt></td></tr>
+ <tr><td><i>raw data</i><br/> (6 bytes)</td>
+ <td><tt>senf::MACAddress::from_data(</tt><i>iterator</i><tt>)</tt><br/>
+ <i>mac</i><tt>.begin()</tt></td></tr>
+ <tr><td>senf::EUI64</td>
+ <td><tt>senf::MACAddress::from_eui64(</tt><i>eui64</i><tt>)</tt><br/>
+ <tt>senf::EUI64::from_mac(</tt><i>mac</i><tt>)</tt></td></tr>
+ </table>
Since MACAddress is based on \c boost::array, you can access the raw data bytes of the
address using \c begin(), \c end() or \c operator[]:
\code
- MACAddress mac = ...;
- Packet::iterator i = ...;
-
- std::copy(mac.begin(), mac.end(), i); // Copies 6 bytes
+ senf::MACAddress mac (...);
+ std::vector<char> data;
+ data.resize(6);
+ std::copy(mac.begin(), mac.end(), data.begin()); // Copy 6 bytes
\endcode
\implementation We awkwardly need to use static named constructors (<tt>from_</tt> members)
\pre The input range at \a i must have a size of at
least 6 elements. */
- static MACAddress from_eui64(boost::uint64_t v);
+ static MACAddress from_eui64(senf::EUI64 const & eui);
///< Construct address from EUI-64
/**< This constructor takes an EUI-64 value and converts it
to a MAC address. This conversion is only possible, if
compatible EUI-64. */
bool local() const; ///< \c true, if address is locally administered
- bool multicast() const; ///< \c true, if address is a group/multicast address
+ bool multicast() const; ///< \c true, if address is a group/multicast address
bool broadcast() const; ///< \c true, if address is the broadcast address
bool boolean_test() const; ///< \c true, if address is not the zero address
#include <sstream>
#include "MACAddress.hh"
#include "../../../Utils/String.hh"
+#include "EUI64.hh"
#include "../../../Utils/auto_unit_test.hh"
#include <boost/test/test_tools.hpp>
BOOST_CHECK_THROW( MACAddress::from_string("01:02:03:04:05:@6"), AddressSyntaxException );
BOOST_CHECK_THROW( MACAddress::from_string("01:02:03:04:05:[6"), AddressSyntaxException );
- BOOST_CHECK_EQUAL( mac, MACAddress::from_eui64(0xa1b2c3fffed4e5f6llu) );
- BOOST_CHECK_THROW( MACAddress::from_eui64(0u), AddressSyntaxException );
+ BOOST_CHECK_EQUAL( mac, MACAddress::from_eui64(senf::EUI64(0xa1b2c3fffed4e5f6llu)) );
+ BOOST_CHECK_THROW( MACAddress::from_eui64(senf::EUI64(0ull)),
+ AddressSyntaxException );
BOOST_CHECK_EQUAL( MACAddress(0x1a2b3c4d5e6fULL).uint64(), 0x1a2b3c4d5e6fULL);
}