1639ba3a2e8643741a79ee9f4199525e6c2b1d9e
[senf.git] / Socket / Protocols / INet / INet6Address.hh
1 // $Id$
2 //
3 // Copyright (C) 2007 
4 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
5 // Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
6 //     Stefan Bund <g0dil@berlios.de>
7 //
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22
23 /** \file
24     \brief INet6Address public header */
25
26 #ifndef HH_INet6Address_
27 #define HH_INet6Address_ 1
28
29 // Custom includes
30 #include <iostream>
31 #include <string>
32 #include <boost/cstdint.hpp>
33 #include <boost/array.hpp>
34 #include <boost/operators.hpp>
35 #include "../../../Utils/SafeBool.hh"
36 #include "INet4Address.hh"
37
38 //#include "INet6Address.mpp"
39 #include "INet6Address.ih"
40 ///////////////////////////////hh.p////////////////////////////////////////
41
42 namespace senf {
43
44     /** \brief IpV6 network address
45
46         This implementation of an IpV6 address is based strictly on 
47         <a href="http://tools.ietf.org/html/rfc4291">RFC 4291</a>: Internet Protocol
48         Version 6 (IPv6) Addressing Architecture. This class provides accessors to all the
49         information fields defined in this document.
50
51         The IpV6 addressing architecture however has several other components defined in other
52         RFC's. These RFC's should be implemented in additional modules:
53
54         \li <a href="http://tools.ietf.org/html/rfc4193">RFC 4193</a>:
55             Unique Local Addresses (ULA). Defines the fc00::/7 prefix
56         \li <a href="http://tools.ietf.org/html/rfc3306">RFC 3306</a>:
57             Unicast-Prefix-based IPv6 Multicast Addresses. Defines the ff30::/12 prefix
58         \li <a href="http://tools.ietf.org/html/rfc3956">RFC 3956</a>:
59             Embedding the Rendezvous Point (RP) Address in an IPv6 Multicast
60             Address. Defines the ff70::/12 prefix
61         \li <a href="http://tools.ietf.org/html/rfc3056">RFC 3056</a>:
62             Connection of IPv6 Domains via IPv4 Clouds. Defines 6to4 tunneling and the
63             2002::/16 prefix
64         \li <a href="http://tools.ietf.org/html/rfc3849">RFC 3849</a>:
65             IPv6 Address Prefix Reserved for Documentation. Defines the 2001:db8::/32 prefix
66         
67         Here an overview of well-known prefixes:
68
69         <table class="senf">
70         <tr><th>Prefix</th>                  <th>Description</th>                        <th>Definition</th> <th>Note</th></tr>
71         <tr><td><tt>::/96</tt></td>          <td>IpV4 compatible IpV6 address</td>       <td>RFC4291</td>    <td>deprecated</td></tr>
72         <tr><td><tt>::ffff:0:0/96</tt></td>  <td>IpV6 mapped IpV4 address</td>           <td>RFC4291</td>    <td></td></tr>
73         <tr><td><tt>2000::/3</tt></td>       <td>Global unicast addresses</td>           <td>RFC3587</td>    <td>only noted, not defined</td></tr>
74         <tr><td><tt>2001:db8::/32</tt></td>  <td>Documentation-only prefix</td>          <td>RFC3849</td>    <td></td></tr>
75         <tr><td><tt>2002::/16</tt></td>      <td>6to4 addressing</td>                    <td>RFC3056</td>    <td></td></tr>
76         <tr><td><tt>fc00::/7</tt></td>       <td>ULA</td>                                <td>RFC4193</td>    <td></td></tr>
77         <tr><td><tt>fe80::/64</tt></td>      <td>Link-local addresses</td>               <td>RFC4291</td>    <td></td></tr>
78         <tr><td><tt>fec0::/10</tt></td>      <td>Site-local addresses </td>              <td>RFC4291</td>    <td>deprecated</td></tr>
79         <tr><td><tt>ff00::/8</tt></td>       <td>Multicast</td>                          <td>RFC4291</td>    <td></td></tr>
80         <tr><td><tt>ff00::/12</tt></td>      <td>Globally allocated multicast</td>       <td>RFC4291</td>    <td></td></tr>
81         <tr><td><tt>ff10::/12</tt></td>      <td>Locally allocated multicast</td>        <td>RFC4291</td>    <td></td></tr>
82         <tr><td><tt>ff30::/12</tt></td>      <td>Unicast prefic based multicast</td>     <td>RFC3306</td>    <td></td></tr>
83         <tr><td><tt>ff70::/12</tt></td>      <td>Multicast address with embedded RP</td> <td>RFC3956</td>    <td></td></tr>
84         </table>
85
86         The INet6Address class is based on \c boost::array and is built as a fixed-size sequence of
87         16 bytes.
88
89         \see CheckINet6Network \n INet6Network
90         \ingroup addr_group
91
92         \implementation We awkwardly need to use static named constructors (<tt>from_</tt> members)
93             instead of ordinarily overloaded constructors for one simple reason: <tt>char *</tt>
94             doubles as string literal and as arbitrary data iterator. The iterator constructor can
95             therefore not be distinguished from initialization with a string literal. Therefore we
96             need to disambiguate using the named constructors.
97      */
98     class INet6Address
99         : public boost::array<boost::uint8_t,16>,
100           public ComparableSafeBool<INet6Address>
101     {
102     public:
103         ///////////////////////////////////////////////////////////////////////////
104         // Types
105
106         static INet6Address const None;        ///< The empty (::0) address
107         static INet6Address const Loopback;    ///< The loopback (::1) address
108         static INet6Address const AllNodes;    ///< The 'all nodes' link-local multicast address
109         static INet6Address const AllRouters;  ///< The 'all routers' link-local multicast address
110
111         enum NoInit_t { noinit };
112         enum Resolve_t { ResolveINet6, ResolveINet4 };
113
114         /** \brief Possible scope values
115
116             List of all possible scope values. This list includes all scope values defined for
117             multicast addresses in <a href="http://tools.ietf.org/html/rfc4291">RFC 4291</a>. 
118             The values \ref LinkScope, \ref SiteScope and \ref GlobalScope are also used with 
119             unicast addresses.
120          */
121         enum ScopeId {
122               InterfaceScope    =  1    /**< Interface only scope */
123             , LinkScope         =  2    /**< Link-local scope */
124             , AdminScope        =  4    /**< Administration defined local scope */
125             , SiteScope         =  5    /**< Site-local scope */
126             , OrganizationScope =  8    /**< Scope covering multiple sites of an organization */
127             , GlobalScope       = 14    /**< Global Internet scope */
128
129             , ReservedScope     =  0    /**< Reserved scope value */
130             , UnassignedScope   =  6    /**< Unassigned scope, may be defined locally */
131         }; 
132
133         ///////////////////////////////////////////////////////////////////////////
134         ///\name Structors and default members
135         ///@{
136
137         explicit INet6Address(NoInit_t); ///< Construct uninitialized (!) address
138         INet6Address(boost::uint16_t a0=0u, boost::uint16_t a1=0u, boost::uint16_t a2=0u,
139                      boost::uint16_t a3=0u, boost::uint16_t a4=0u, boost::uint16_t a5=0u,
140                      boost::uint16_t a6=0u, boost::uint16_t a7=0u);
141                                         ///< Construct an address constant
142
143         static INet6Address from_string(std::string const & s, Resolve_t resolve = ResolveINet6);
144                                         ///< Convert string to address
145                                         /**< This member will try to convert the given string into
146                                              an IP address. from_string() supports all standard IP
147                                              literal representations as well es hostnames.
148                                              \attention This call may block if \a s represents a
149                                                  hostname which must be looked up via some network
150                                                  protocol like DNS or NIS
151                                              \throws SyntaxException if the address cannot be
152                                                  converted for some reason
153                                              \param[in] s Address literal or hostname 
154                                              \param[in] resolve If this is set to \c ResolveINet4,
155                                                  the call will additionally try to interpret \a s as
156                                                  an IpV4 address if no valid IpV6 address is
157                                                  found. The address will be returned as mapped IpV6
158                                                  address. */
159
160         template <class InputIterator> 
161         static INet6Address from_data(InputIterator i);
162                                         ///< Construct address from 16 bytes of raw data
163                                         /**< from_data will build an address from 16 bytes of raw
164                                              data as accessed by the iterator. The data must be in
165                                              network byte order. */
166
167         static INet6Address from_inet4address(INet4Address addr);
168                                         ///< Construct an IpV6-mapped IpV4 address
169                                         /**< This will construct an address of the form
170                                              <tt>::FFFF::w.x.y.z</tt> where <tt>w.x.y.z</tt> is
171                                              the INet4Address value. This kind of address is called
172                                              an IpV6-mapped IpV4 address (see 
173                                              <a href="http://tools.ietf.org/html/rfc4291">RFC 4291</a>).
174                                              \par 
175                                              IpV4 compatible IpV6 addresses are not directly
176                                              supported, they are deprecated in the RFC. */
177         ///@}
178         ///////////////////////////////////////////////////////////////////////////
179         ///\name Accessors
180         ///@{
181
182         boost::uint64_t network() const; ///< Return 64bit network part
183         bool hasEuid64() const;         ///< \c true, if address is based on an EUID-64
184         boost::uint64_t id() const;     ///< Return interface id (EUID-64)
185         bool universalId() const;       ///< \c true, if the id() is universally assigned
186         bool groupId() const;           ///< \c true, if the id()'s \a group bit is set
187
188         bool unicast() const;           ///< \c true, if address is unicast
189         bool multicast() const;         ///< \c true, if address is multicast
190
191         ScopeId scope() const;          ///< Get address's scope
192                                         /**< The scope of an address is one of the \ref ScopeId
193                                              values. We need to differentiate between unicast and
194                                              multicast addresses: unicast addresses only have local,
195                                              site or global scope (where site scope is deprecated),
196                                              multicast address can have a number of scope values of
197                                              which local, site and global are a few. See the \ref
198                                              ScopeId enumerators. */ 
199         bool globalScope() const;       ///< \c true, if address is global unicast or multicast
200         bool linkScope() const;         ///< \c true, if address is link-local unicast or multicast
201
202         INet4Address inet4address() const; ///< Return embedded IpV4 address
203                                         /**< Returns the IpV4 address embedded within an IpV4
204                                              compatible or IpV4 mapped unicast address. This address
205                                              is given by the last 32 bits of the IpV6 address. \par
206                                              The value returned is only a valid IpV4 address if
207                                              either ipv4Compatible() or ipv4Mapped() return \c
208                                              true. */ 
209         bool ipv4Compatible() const;    ///< \c true, if address is IpV4 compatible
210                                         /**< IpV4 compatible IpV6 addresses are deprecated. */
211         bool ipv4Mapped() const;        ///< \c true, if address is IpV4 mapped
212
213         bool globalMulticastAddr() const; ///< \c true, if T bit is \e not set
214                                         /**< Any multicast address with a cleared T bit must be
215                                              globally assigned. See 
216                                              <a href="http://tools.ietf.org/html/rfc4291">RFC 4291</a>. */
217         bool prefixMulticastAddr() const; ///< \c true, if P bit is set
218                                         /**< In <a href="http://tools.ietf.org/html/rfc4291">RFC 4291</a>,
219                                              the P bit is specified as defining a
220                                              unicast prefix based multicast address. See 
221                                              <a href="http://tools.ietf.org/html/rfc3306">RFC 3306</a>. */ 
222         bool embeddedRpAddr() const;    ///< \c true, if R bit is set
223                                         /**< In <a href="http://tools.ietf.org/html/rfc4291">RFC 4291</a>,
224                                              the R bit is specified as defining a multicast address 
225                                              with embedded rendezvous point. See
226                                              <a href="http://tools.ietf.org/html/rfc3956">RFC 3956</a>. */
227
228         bool boolean_test() const;      ///< \c true, if address != '::' (None)
229
230         ///@}
231         ///\name Mutators
232         ///@{
233         
234         void network(boost::uint64_t net); ///< Set network part of address
235         void id(boost::uint64_t id);    ///< Set interface id part of address
236
237         ///@}
238
239         /** \brief Base-class for INet6Address exceptions */
240         struct AddressException : public std::exception {};
241
242         /** \brief Invalid INet4 address syntax */
243         struct SyntaxException : public AddressException
244         { virtual char const * what() const throw() 
245                 { return "invalid INet6 address syntax"; } };
246
247         /** \brief Resolver failure */
248         struct UnknownHostnameException : public AddressException
249         { virtual char const * what() const throw() 
250                 { return "failed to resolve INet6 hostname"; } };
251     };
252
253     /** \brief Output INet6Address instance as it's string representation
254         \related INet6Address
255      */
256     std::ostream & operator<<(std::ostream & os, INet6Address const & addr);
257
258     /** \brief Check INet6Address against a fixed network prefix
259         
260         This helper allows to easily and efficiently check an INet6Address against an arbitrary but
261         constant network prefix. It takes from 1 to 8 arguments for the network address and an
262         additional last argument providing the prefix length. So
263
264         \par ""
265             <tt>senf::CheckINet6Network<</tt> <i>addr_1</i> <tt>,</tt> <i>addr_2</i> <tt>,</tt>
266             ... <tt>,</tt> <i>prefix_len</i> <tt>></tt>
267
268         represents the network
269         
270         \par ""
271             <i>addr_1</i> <tt>:</tt> <i>addr_2</i> <tt>:</tt> ... <tt>::/</tt> <i>prefix_len</i> .
272
273         The class exposes a single static member <tt>match(</tt> <i>addr</i> <tt>)</tt> which
274         matches the INet6Address \a addr against the prefix:
275         
276         \code
277         if (senf::CheckINet6Network<0x2000u,0xDB8u,32u>::match(addr)) {
278             // 'addr' is within in the 2001:db8::/32 documentation-only network
279             ...
280         }
281         \endcode
282
283         The code generated by this call is highly optimized and probably as efficient as it can get.
284      */
285     template <unsigned a0, unsigned a1, unsigned a2=0u, unsigned a3=0u, unsigned a4=0u,
286               unsigned a5=0u, unsigned a6=0u, unsigned a7=0u, unsigned a8=0u>
287     struct CheckINet6Network
288         : public detail::CheckINet6Network_impl<a0,a1,a2,a3,a4,a5,a6,a7,a8>
289     {};
290
291     /** \brief IpV6 network prefix
292
293         This class represents an IpV6 network prefix in CIDR notation. 
294       */
295     class INet6Network
296         : public boost::equality_comparable<INet6Network>, 
297           public ComparableSafeBool<INet6Network>
298     {
299     public:
300         ///////////////////////////////////////////////////////////////////////////
301         ///\name Structors and default members
302         ///@{
303
304         INet6Network();                 ///< Construct empty (::/0) network
305         INet6Network(INet6Address address, unsigned prefix_len);
306                                         ///< Construct network from given address and prefix length
307         explicit INet6Network(std::string s); ///< Construct network from CIDR notation
308
309         ///@}
310         ///////////////////////////////////////////////////////////////////////////
311
312         INet6Address const & address() const; ///< Get the network address
313         unsigned prefix_len() const;    ///< Get the network prefix length
314
315         bool boolean_test() const;      ///< \c true, if INet6Network is non-empty
316         bool operator==(INet6Network const & other) const;
317                                         ///< Compare two networks for equality
318         
319         bool match(INet6Address addr) const; ///< \c true, if the network includes \a addr
320         bool match(INet6Network net) const; ///< \c true, if the network includes \a net
321                                         /**< The is true, if \a net is sub-network (or the same as)
322                                              \c this. */
323         INet6Address host(boost::uint64_t id); ///< Return the host with the given id
324                                         /**< Returns the host with the given number within the
325                                              network. This call replaces the lower 64 bits of the
326                                              network address with the given id. */
327
328         INet6Network subnet(boost::uint64_t net, unsigned prefix_len);
329                                         ///< Return the given subnet of \c this
330                                         /**< The returned INet6Network will be a subnet of \c this
331                                              with the given network number. The network number is
332                                              comprised by the bits above \a prefix_len:
333                                              \code
334                                              INet6Network("2001:db8::/32").subnet(0x12u,40u) == INet6Network("2001:db8:1200::/40")
335                                              INet6Network("2001:db8:1200::/40").subnet(0x2345,64u) == INet6Network("2001:db8:1200:2345::/64")
336                                              \endcode 
337                                              \param[in] net network number
338                                              \param[in] prefix_len length of subnet prefix */
339
340     protected:
341
342     private:
343         unsigned prefix_len_;
344         INet6Address address_;
345     };
346
347     /** \brief Output INet6Network instance as it's string representation
348         \related INet6Network
349      */
350     std::ostream & operator<<(std::ostream & os, INet6Network const & addr);
351 }
352
353 ///////////////////////////////hh.e////////////////////////////////////////
354 #include "INet6Address.cci"
355 #include "INet6Address.ct"
356 #include "INet6Address.cti"
357 #endif
358
359 \f
360 // Local Variables:
361 // mode: c++
362 // fill-column: 100
363 // comment-column: 40
364 // c-file-style: "senf"
365 // indent-tabs-mode: nil
366 // ispell-local-dictionary: "american"
367 // compile-command: "scons -u test"
368 // End: