Move include files in debian packge into 'senf' subdirectory
[senf.git] / Socket / Protocols / INet / INet6Address.hh
index c40e7cc..1639ba3 100644 (file)
@@ -1,3 +1,5 @@
+// $Id$
+//
 // Copyright (C) 2007 
 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
 // Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
@@ -28,9 +30,9 @@
 #include <iostream>
 #include <string>
 #include <boost/cstdint.hpp>
-#include <boost/function.hpp>
 #include <boost/array.hpp>
-#include "Utils/SafeBool.hh"
+#include <boost/operators.hpp>
+#include "../../../Utils/SafeBool.hh"
 #include "INet4Address.hh"
 
 //#include "INet6Address.mpp"
@@ -41,21 +43,26 @@ namespace senf {
 
     /** \brief IpV6 network address
 
-        This implementation of an IpV6 address is based strictly on RFC 4291: Internet Protocol
+        This implementation of an IpV6 address is based strictly on 
+        <a href="http://tools.ietf.org/html/rfc4291">RFC 4291</a>: 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
+        \li <a href="http://tools.ietf.org/html/rfc4193">RFC 4193</a>:
+            Unique Local Addresses (ULA). Defines the fc00::/7 prefix
+        \li <a href="http://tools.ietf.org/html/rfc3306">RFC 3306</a>:
+            Unicast-Prefix-based IPv6 Multicast Addresses. Defines the ff30::/12 prefix
+        \li <a href="http://tools.ietf.org/html/rfc3956">RFC 3956</a>:
+            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
+        \li <a href="http://tools.ietf.org/html/rfc3056">RFC 3056</a>:
+            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
+        \li <a href="http://tools.ietf.org/html/rfc3849">RFC 3849</a>:
+            IPv6 Address Prefix Reserved for Documentation. Defines the 2001:db8::/32 prefix
         
         Here an overview of well-known prefixes:
 
@@ -79,8 +86,14 @@ namespace senf {
         The INet6Address class is based on \c boost::array and is built as a fixed-size sequence of
         16 bytes.
 
-        \see CheckINet6Network Helper to check address against an arbitrary fixed network prefix
+        \see CheckINet6Network \n INet6Network
         \ingroup addr_group
+
+        \implementation We awkwardly need to use static named constructors (<tt>from_</tt> members)
+            instead of ordinarily overloaded constructors for one simple reason: <tt>char *</tt>
+            doubles as string literal and as arbitrary data iterator. The iterator constructor can
+            therefore not be distinguished from initialization with a string literal. Therefore we
+            need to disambiguate using the named constructors.
      */
     class INet6Address
         : public boost::array<boost::uint8_t,16>,
@@ -90,21 +103,20 @@ namespace senf {
         ///////////////////////////////////////////////////////////////////////////
         // Types
 
-        typedef boost::function<void (INet6Address const &)> 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 };
+        enum Resolve_t { ResolveINet6, ResolveINet4 };
 
         /** \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.
+            multicast addresses in <a href="http://tools.ietf.org/html/rfc4291">RFC 4291</a>. 
+            The values \ref LinkScope, \ref SiteScope and \ref GlobalScope are also used with 
+            unicast addresses.
          */
         enum ScopeId {
               InterfaceScope    =  1    /**< Interface only scope */
@@ -128,7 +140,7 @@ namespace senf {
                      boost::uint16_t a6=0u, boost::uint16_t a7=0u);
                                         ///< Construct an address constant
 
-        static INet6Address from_string(std::string const & s);
+        static INet6Address from_string(std::string const & s, Resolve_t resolve = ResolveINet6);
                                         ///< Convert string to address
                                         /**< This member will try to convert the given string into
                                              an IP address. from_string() supports all standard IP
@@ -138,21 +150,12 @@ namespace senf {
                                                  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 */
+                                             \param[in] s Address literal or hostname 
+                                             \param[in] resolve If this is set to \c ResolveINet4,
+                                                 the call will additionally try to interpret \a s as
+                                                 an IpV4 address if no valid IpV6 address is
+                                                 found. The address will be returned as mapped IpV6
+                                                 address. */
 
         template <class InputIterator> 
         static INet6Address from_data(InputIterator i);
@@ -166,7 +169,9 @@ namespace senf {
                                         /**< This will construct an address of the form
                                              <tt>::FFFF::w.x.y.z</tt> where <tt>w.x.y.z</tt> is
                                              the INet4Address value. This kind of address is called
-                                             an IpV6-mapped IpV4 address (see RFC4291). \par
+                                             an IpV6-mapped IpV4 address (see 
+                                             <a href="http://tools.ietf.org/html/rfc4291">RFC 4291</a>).
+                                             \par 
                                              IpV4 compatible IpV6 addresses are not directly
                                              supported, they are deprecated in the RFC. */
         ///@}
@@ -207,14 +212,18 @@ namespace senf {
 
         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. */
+                                             globally assigned. See 
+                                             <a href="http://tools.ietf.org/html/rfc4291">RFC 4291</a>. */
         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. */ 
+                                        /**< In <a href="http://tools.ietf.org/html/rfc4291">RFC 4291</a>,
+                                             the P bit is specified as defining a
+                                             unicast prefix based multicast address. See 
+                                             <a href="http://tools.ietf.org/html/rfc3306">RFC 3306</a>. */ 
         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. */
+                                        /**< In <a href="http://tools.ietf.org/html/rfc4291">RFC 4291</a>,
+                                             the R bit is specified as defining a multicast address 
+                                             with embedded rendezvous point. See
+                                             <a href="http://tools.ietf.org/html/rfc3956">RFC 3956</a>. */
 
         bool boolean_test() const;      ///< \c true, if address != '::' (None)
 
@@ -227,9 +236,18 @@ namespace senf {
 
         ///@}
 
-        /** \brief Invalid IpV6 address syntax */
-        struct SyntaxException : public std::exception
-        { virtual char const * what() const throw() { return "Invalid IpV6 address syntax"; } };
+        /** \brief Base-class for INet6Address exceptions */
+        struct AddressException : public std::exception {};
+
+        /** \brief Invalid INet4 address syntax */
+        struct SyntaxException : public AddressException
+        { virtual char const * what() const throw() 
+                { return "invalid INet6 address syntax"; } };
+
+        /** \brief Resolver failure */
+        struct UnknownHostnameException : public AddressException
+        { virtual char const * what() const throw() 
+                { return "failed to resolve INet6 hostname"; } };
     };
 
     /** \brief Output INet6Address instance as it's string representation
@@ -237,10 +255,24 @@ namespace senf {
      */
     std::ostream & operator<<(std::ostream & os, INet6Address const & addr);
 
-    /** \brief Check address against a fixed network prefix
+    /** \brief Check INet6Address against a fixed network prefix
+        
+        This helper allows to easily and efficiently check an INet6Address against an arbitrary but
+        constant network prefix. It takes from 1 to 8 arguments for the network address and an
+        additional last argument providing the prefix length. So
+
+        \par ""
+            <tt>senf::CheckINet6Network<</tt> <i>addr_1</i> <tt>,</tt> <i>addr_2</i> <tt>,</tt>
+            ... <tt>,</tt> <i>prefix_len</i> <tt>></tt>
+
+        represents the network
+        
+        \par ""
+            <i>addr_1</i> <tt>:</tt> <i>addr_2</i> <tt>:</tt> ... <tt>::/</tt> <i>prefix_len</i> .
+
+        The class exposes a single static member <tt>match(</tt> <i>addr</i> <tt>)</tt> which
+        matches the INet6Address \a addr against the 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
@@ -248,10 +280,7 @@ namespace senf {
         }
         \endcode
 
-        The code generated by this call is highly optimized and as probably as efficient as it can
-        get.
-
-        \related INet6Address
+        The code generated by this call is highly optimized and probably as efficient as it can get.
      */
     template <unsigned a0, unsigned a1, unsigned a2=0u, unsigned a3=0u, unsigned a4=0u,
               unsigned a5=0u, unsigned a6=0u, unsigned a7=0u, unsigned a8=0u>
@@ -259,6 +288,66 @@ namespace senf {
         : public detail::CheckINet6Network_impl<a0,a1,a2,a3,a4,a5,a6,a7,a8>
     {};
 
+    /** \brief IpV6 network prefix
+
+        This class represents an IpV6 network prefix in CIDR notation. 
+      */
+    class INet6Network
+        : public boost::equality_comparable<INet6Network>, 
+          public ComparableSafeBool<INet6Network>
+    {
+    public:
+        ///////////////////////////////////////////////////////////////////////////
+        ///\name Structors and default members
+        ///@{
+
+        INet6Network();                 ///< Construct empty (::/0) network
+        INet6Network(INet6Address address, unsigned prefix_len);
+                                        ///< Construct network from given address and prefix length
+        explicit INet6Network(std::string s); ///< Construct network from CIDR notation
+
+        ///@}
+        ///////////////////////////////////////////////////////////////////////////
+
+        INet6Address const & address() const; ///< Get the network address
+        unsigned prefix_len() const;    ///< Get the network prefix length
+
+        bool boolean_test() const;      ///< \c true, if INet6Network is non-empty
+        bool operator==(INet6Network const & other) const;
+                                        ///< Compare two networks for equality
+        
+        bool match(INet6Address addr) const; ///< \c true, if the network includes \a addr
+        bool match(INet6Network 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. */
+        INet6Address host(boost::uint64_t id); ///< Return the host with the given id
+                                        /**< Returns the host with the given number within the
+                                             network. This call replaces the lower 64 bits of the
+                                             network address with the given id. */
+
+        INet6Network subnet(boost::uint64_t net, unsigned prefix_len);
+                                        ///< Return the given subnet of \c this
+                                        /**< The returned INet6Network will be a subnet of \c this
+                                             with the given network number. The network number is
+                                             comprised by the bits above \a prefix_len:
+                                             \code
+                                             INet6Network("2001:db8::/32").subnet(0x12u,40u) == INet6Network("2001:db8:1200::/40")
+                                             INet6Network("2001:db8:1200::/40").subnet(0x2345,64u) == INet6Network("2001:db8:1200:2345::/64")
+                                             \endcode 
+                                             \param[in] net network number
+                                             \param[in] prefix_len length of subnet prefix */
+
+    protected:
+
+    private:
+        unsigned prefix_len_;
+        INet6Address address_;
+    };
+
+    /** \brief Output INet6Network instance as it's string representation
+        \related INet6Network
+     */
+    std::ostream & operator<<(std::ostream & os, INet6Network const & addr);
 }
 
 ///////////////////////////////hh.e////////////////////////////////////////