From: g0dil Date: Mon, 6 Aug 2007 14:44:13 +0000 (+0000) Subject: Socket/Protocols/INet: Implemented INet4Network X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=c75c285e1d33a5394c7f7d3cb437bd01da7d888e;p=senf.git Socket/Protocols/INet: Implemented INet4Network git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@379 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/Socket/Protocols/INet/INet4Address.cc b/Socket/Protocols/INet/INet4Address.cc index ad51600..f6b5362 100644 --- a/Socket/Protocols/INet/INet4Address.cc +++ b/Socket/Protocols/INet/INet4Address.cc @@ -30,6 +30,7 @@ #include #include #include +#include #ifdef _REENTRANT #include #endif @@ -118,6 +119,21 @@ senf::INet4Address const senf::INet4Address::None; senf::INet4Address const senf::INet4Address::Loopback (0x7F000001u); senf::INet4Address const senf::INet4Address::Broadcast (0xFFFFFFFFu); +/////////////////////////////////////////////////////////////////////////// +// senf::INet4Network + +prefix_ senf::INet4Network::INet4Network(std::string s) +{ + std::string::size_type i (s.find('/')); + if (i == std::string::npos) + throw INet4Address::SyntaxException(); + try { + prefix_len_ = boost::lexical_cast(std::string(s,i+1)); + } catch (boost::bad_lexical_cast const &) { + throw INet4Address::SyntaxException(); + } + address_ = INet4Address(INet4Address::from_string(std::string(s, 0, i)).address() & mask()); +} /////////////////////////////////////////////////////////////////////////// // namespace members diff --git a/Socket/Protocols/INet/INet4Address.cci b/Socket/Protocols/INet/INet4Address.cci index 61b328f..ebf5615 100644 --- a/Socket/Protocols/INet/INet4Address.cci +++ b/Socket/Protocols/INet/INet4Address.cci @@ -78,6 +78,73 @@ prefix_ senf::INet4Address::inaddr_type senf::INet4Address::iref() return *reinterpret_cast(&(*this)[0]); } +/////////////////////////////////////////////////////////////////////////// +// senf::INet4Network + +prefix_ senf::INet4Network::INet4Network() + : prefix_len_(), address_() +{} + +prefix_ senf::INet4Network::INet4Network(INet4Address address, unsigned prefix_len) + : prefix_len_(prefix_len), address_(INet4Address(address.address() & mask())) +{} + +prefix_ senf::INet4Address const & senf::INet4Network::address() + const +{ + return address_; +} + +prefix_ unsigned senf::INet4Network::prefix_len() + const +{ + return prefix_len_; +} + +prefix_ bool senf::INet4Network::boolean_test() + const +{ + return address() || prefix_len(); +} + +prefix_ bool senf::INet4Network::operator==(INet4Network const & other) + const +{ + return address() == other.address() && prefix_len() == other.prefix_len(); +} + +prefix_ bool senf::INet4Network::match(INet4Address addr) + const +{ + return (addr.address() & mask()) == address_.address(); +} + +prefix_ bool senf::INet4Network::match(INet4Network net) + const +{ + return net.prefix_len() >= prefix_len() && + (net.address().address() & mask()) == address_.address(); +} + +//////////////////////////////////////// +// private members + +prefix_ boost::uint32_t senf::INet4Network::mask() + const +{ + // This is correct as long as the system is using 2-complement arithmetic ... + return (~((boost::uint32_t(1u)<<(32u-prefix_len()))-1u)) & 0xFFFFFFFFu; +} + +/////////////////////////////////////////////////////////////////////////// +// namespace members + +prefix_ std::ostream & senf::operator<<(std::ostream & os, INet4Network const & addr) +{ + os << addr.address() << '/' << addr.prefix_len(); + return os; +} + ///////////////////////////////cci.e/////////////////////////////////////// #undef prefix_ diff --git a/Socket/Protocols/INet/INet4Address.hh b/Socket/Protocols/INet/INet4Address.hh index 1ed57e8..818ffbe 100644 --- a/Socket/Protocols/INet/INet4Address.hh +++ b/Socket/Protocols/INet/INet4Address.hh @@ -32,6 +32,7 @@ #include #include #include +#include #include "Utils/SafeBool.hh" //#include "INet4Address.mpp" @@ -58,7 +59,6 @@ namespace senf { class INet4Address : public boost::array, public ComparableSafeBool - { public: /////////////////////////////////////////////////////////////////////////// @@ -195,6 +195,56 @@ namespace senf { static bool match(INet4Address const & addr); }; + /** \brief IpV4 network prefix + + This class represents an IpV4 network prefix in CIDR notation. + */ + class INet4Network + : public boost::equality_comparable, + public ComparableSafeBool + { + public: + /////////////////////////////////////////////////////////////////////////// + // Types + + /////////////////////////////////////////////////////////////////////////// + ///\name Structors and default members + ///@{ + + INet4Network(); ///< Construct empty (0.0.0.0/0) network + INet4Network(INet4Address address, unsigned prefix_len); + ///< Construct network from given address and prefix length + explicit INet4Network(std::string s); ///< Construct network from CIDR notation + + ///@} + /////////////////////////////////////////////////////////////////////////// + + INet4Address const & address() const; ///< Get the networks address + unsigned prefix_len() const; ///< Get the networks prefix length + + bool boolean_test() const; ///< \c true, if INet4Network is non-empty + bool operator==(INet4Network const & other) const; + ///< Compare to networks for equality + + bool match(INet4Address addr) const; ///< \c true, if the network includes \a addr + bool match(INet4Network net) const; ///< \c true, if the network includes \a net + /**< The is true, if \a net is sub-network (or the same as) + \c this. */ + + protected: + + private: + boost::uint32_t mask() const; + + unsigned prefix_len_; + INet4Address address_; + }; + + /** \brief Output INet4Network instance as it's string representation + \related INet4Network + */ + std::ostream & operator<<(std::ostream & os, INet4Network const & addr); + } ///////////////////////////////hh.e//////////////////////////////////////// diff --git a/Socket/Protocols/INet/INet4Address.test.cc b/Socket/Protocols/INet/INet4Address.test.cc index 6b7f84a..c1a8211 100644 --- a/Socket/Protocols/INet/INet4Address.test.cc +++ b/Socket/Protocols/INet/INet4Address.test.cc @@ -28,6 +28,7 @@ // Custom includes #include +#include #include #include "INet4Address.hh" @@ -68,6 +69,28 @@ BOOST_AUTO_UNIT_TEST(inet4Address) BOOST_CHECK_EQUAL( str.str(), "128.129.130.131" ); } +BOOST_AUTO_UNIT_TEST(inet4Network) +{ + senf::INet4Network net (senf::INet4Address::Loopback,8); + BOOST_CHECK_EQUAL( net.address().address(), 0x7F000000u ); + BOOST_CHECK_EQUAL( net.prefix_len(), 8u ); + BOOST_CHECK( net ); + BOOST_CHECK( ! senf::INet4Network() ); + + senf::INet4Network net2 ("192.0.111.222/16"); + BOOST_CHECK_EQUAL( net2.address(), senf::INet4Address::from_string("192.0.0.0") ); + BOOST_CHECK_EQUAL( net2.prefix_len(), 16u ); + + BOOST_CHECK( net != net2 ); + BOOST_CHECK( net.match(senf::INet4Address::from_string("127.0.0.1")) ); + BOOST_CHECK( ! net2.match(senf::INet4Address::from_string("127.0.0.1")) ); + BOOST_CHECK( ! net.match(net2) ); + BOOST_CHECK( net2.match(senf::INet4Network("192.0.111.0/24")) ); + BOOST_CHECK( ! net2.match(senf::INet4Network("192.0.0.0/15")) ); + + BOOST_CHECK_EQUAL( boost::lexical_cast(net2), "192.0.0.0/16" ); +} + ///////////////////////////////cc.e//////////////////////////////////////// #undef prefix_ diff --git a/Socket/Protocols/INet/INetAddressing.test.cc b/Socket/Protocols/INet/INetAddressing.test.cc index ee68de8..61cc302 100644 --- a/Socket/Protocols/INet/INetAddressing.test.cc +++ b/Socket/Protocols/INet/INetAddressing.test.cc @@ -45,7 +45,7 @@ BOOST_AUTO_UNIT_TEST(inet4SocketAddress) BOOST_CHECK( ! addr ); addr = INet4SocketAddress("127.0.0.1:12345"); - BOOST_CHECK ( addr != INet4SocketAddress() ); + BOOST_CHECK ( addr != INet4SocketAddress("127.0.0.2:12345") ); } {