aa29b29052988ee737cda5d3e0d4a3384a4a05b6
[senf.git] / Socket / Protocols / INet / INet6Address.hh
1 // $Id$
2 //
3 // Copyright (C) 2007
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
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 <netinet/in.h>
33 #include <boost/cstdint.hpp>
34 #include <boost/array.hpp>
35 #include <boost/operators.hpp>
36 #include "../../../Utils/safe_bool.hh"
37 #include "../../../Utils/Tags.hh"
38 #include "INet4Address.hh"
39 #include "../AddressExceptions.hh"
40
41 //#include "INet6Address.mpp"
42 #include "INet6Address.ih"
43 ///////////////////////////////hh.p////////////////////////////////////////
44
45 namespace senf {
46
47     /** \brief INet6 network address
48
49         This implementation of an INet6 address is based strictly on 
50         <a href="http://tools.ietf.org/html/rfc4291">RFC 4291</a>: Internet Protocol
51         Version 6 (INet6) Addressing Architecture. This class provides accessors to all the
52         information fields defined in this document.
53
54         The INet6 addressing architecture however has several other components defined in other
55         RFC's. These RFC's should be implemented in additional modules:
56
57         \li <a href="http://tools.ietf.org/html/rfc4193">RFC 4193</a>:
58             Unique Local Addresses (ULA). Defines the fc00::/7 prefix
59         \li <a href="http://tools.ietf.org/html/rfc3306">RFC 3306</a>:
60             Unicast-Prefix-based INet6 Multicast Addresses. Defines the ff30::/12 prefix
61         \li <a href="http://tools.ietf.org/html/rfc3956">RFC 3956</a>:
62             Embedding the Rendezvous Point (RP) Address in an INet6 Multicast
63             Address. Defines the ff70::/12 prefix
64         \li <a href="http://tools.ietf.org/html/rfc3056">RFC 3056</a>:
65             Connection of INet6 Domains via INet4 Clouds. Defines 6to4 tunneling and the
66             2002::/16 prefix
67         \li <a href="http://tools.ietf.org/html/rfc3849">RFC 3849</a>:
68             INet6 Address Prefix Reserved for Documentation. Defines the 2001:db8::/32 prefix
69         
70         Here an overview of well-known prefixes:
71
72         \htmlonly
73         <table class="senf">
74         <tr><th>Prefix</th>                  <th>Description</th>                         <th>Definition</th>  <th>Note</th></tr>
75         <tr><td><tt>::/96</tt></td>          <td>INet4 compatible INet6 address</td>      <td>RFC4291</td>     <td>deprecated</td></tr>
76         <tr><td><tt>::ffff:0:0/96</tt></td>  <td>INet6 mapped INet4 address</td>          <td>RFC4291</td>     <td></td></tr>
77         <tr><td><tt>2000::/3</tt></td>       <td>Global unicast addresses</td>            <td>RFC3587</td>     <td>only noted, not defined</td></tr>
78         <tr><td><tt>2001:db8::/32</tt></td>  <td>Documentation-only prefix</td>           <td>RFC3849</td>     <td></td></tr>
79         <tr><td><tt>2002::/16</tt></td>      <td>6to4 addressing</td>                     <td>RFC3056</td>     <td></td></tr>
80         <tr><td><tt>fc00::/7</tt></td>       <td>ULA</td>                                 <td>RFC4193</td>     <td></td></tr>
81         <tr><td><tt>fe80::/64</tt></td>      <td>Link-local addresses</td>                <td>RFC4291</td>     <td></td></tr>
82         <tr><td><tt>fec0::/10</tt></td>      <td>Site-local addresses </td>               <td>RFC4291</td>     <td>deprecated</td></tr>
83         <tr><td><tt>ff00::/8</tt></td>       <td>Multicast</td>                           <td>RFC4291</td>     <td></td></tr>
84         <tr><td><tt>ff00::/12</tt></td>      <td>Globally allocated multicast</td>        <td>RFC4291</td>     <td></td></tr>
85         <tr><td><tt>ff10::/12</tt></td>      <td>Locally allocated multicast</td>         <td>RFC4291</td>     <td></td></tr>
86         <tr><td><tt>ff30::/12</tt></td>      <td>Unicast prefic based multicast</td>      <td>RFC3306</td>     <td></td></tr>
87         <tr><td><tt>ff70::/12</tt></td>      <td>Multicast address with embedded RP</td>  <td>RFC3956</td>     <td></td></tr>
88         </table>
89         \endhtmlonly
90
91         The following statements all create the same INet6 address
92         <code>2001:db8::a0b1:1a2b:3dff:fe4e:5f00</code>:
93         \code
94         // Used to construct constant INet6 addresses
95         INet6Address(0x2001u,0xDB8u,0x0u,0xA0B1u 0x1A2Bu,0x3DFFu,0xFE4Eu,0x5F00u)
96
97         // Construct INet6 address from it's string representation
98         INet6Address::from_string("2001:db8::a0b1:1a2b:3dff:fe4e:5f00")
99
100         // Construct an INet6 address from raw data. 'from_data' takes an arbitrary iterator (e.g. a
101         // pointer) as argument. Here we use a fixed array but normally you will need this to build
102         // an INet6 address in a packet parser
103         char rawBytes[] = { 0x20, 0x01, 0x0D, 0xB8, 0x00, 0x00, 0xA0, 0xB1,
104                             0x1a, 0x2b, 0x3d, 0xff, 0xfe, 0x4e, 0xff, 0x00 };
105         INet6Address::from_data(rawBytes)
106         \endcode
107
108         Since INet6Address class is based on \c boost::array and is built as a fixed-size sequence
109         of 16 bytes, you can access the raw data bytes of the address (in network byte order) using
110         \c begin(), \c end() or \c operator[]
111         \code
112         INet6Address ina = ...;
113         Packet::iterator i = ...;
114         std::copy(ina.begin(), ina.end(), i); // Copies 16 bytes
115         \endcode
116
117         \see CheckINet6Network \n INet6Network
118         \ingroup addr_group
119
120         \implementation We awkwardly need to use static named constructors (<tt>from_</tt> members)
121             instead of ordinarily overloaded constructors for one simple reason: <tt>char *</tt>
122             doubles as string literal and as arbitrary data iterator. The iterator constructor can
123             therefore not be distinguished from initialization with a string literal. Therefore we
124             need to disambiguate using the named constructors.
125      */
126     class INet6Address
127         : public boost::array<boost::uint8_t,16>,
128           public comparable_safe_bool<INet6Address>
129     {
130     public:
131         ///////////////////////////////////////////////////////////////////////////
132         // Types
133
134         static INet6Address const None;        ///< The empty (::0) address
135         static INet6Address const Loopback;    ///< The loopback (::1) address
136         static INet6Address const AllNodes;    ///< The 'all nodes' link-local multicast address
137         static INet6Address const AllRouters;  ///< The 'all routers' link-local multicast address
138
139         enum Resolve_t { ResolveINet6, ResolveINet4 };
140
141         /** \brief Possible scope values
142
143             List of all possible scope values. This list includes all scope values defined for
144             multicast addresses in <a href="http://tools.ietf.org/html/rfc4291">RFC 4291</a>. 
145             The values \ref LinkScope, \ref SiteScope and \ref GlobalScope are also used with 
146             unicast addresses.
147          */
148         enum ScopeId {
149               InterfaceScope    =  1    /**< Interface only scope */
150             , LinkScope         =  2    /**< Link-local scope */
151             , AdminScope        =  4    /**< Administration defined local scope */
152             , SiteScope         =  5    /**< Site-local scope */
153             , OrganizationScope =  8    /**< Scope covering multiple sites of an organization */
154             , GlobalScope       = 14    /**< Global Internet scope */
155
156             , ReservedScope     =  0    /**< Reserved scope value */
157             , UnassignedScope   =  6    /**< Unassigned scope, may be defined locally */
158         }; 
159
160         ///////////////////////////////////////////////////////////////////////////
161         ///\name Structors and default members
162         ///@{
163
164         explicit INet6Address(senf::NoInit_t); ///< Construct uninitialized (!) address
165         explicit INet6Address(boost::uint16_t a0=0u, boost::uint16_t a1=0u, boost::uint16_t a2=0u,
166                               boost::uint16_t a3=0u, boost::uint16_t a4=0u, boost::uint16_t a5=0u,
167                               boost::uint16_t a6=0u, boost::uint16_t a7=0u);
168                                         ///< Construct an address constant
169         
170         static INet6Address from_in6addr(in6_addr const & in6addr); ///< Construct from std C struct
171
172         static INet6Address from_string(std::string const & s, Resolve_t resolve = ResolveINet6);
173                                         ///< Convert string to address
174                                         /**< This member will try to convert the given string into
175                                              an IP address. from_string() supports all standard IP
176                                              literal representations as well es hostnames.
177                                              \attention This call may block if \a s represents a
178                                                  hostname which must be looked up via some network
179                                                  protocol like DNS or NIS
180                                              \throws AddressSyntaxException if the address cannot be
181                                                  converted for some reason
182                                              \param[in] s Address literal or hostname 
183                                              \param[in] resolve If this is set to \c ResolveINet4,
184                                                  the call will additionally try to interpret \a s as
185                                                  an INet4 address if no valid INet6 address is
186                                                  found. The address will be returned as mapped INet6
187                                                  address. */
188
189         template <class InputIterator> 
190         static INet6Address from_data(InputIterator i);
191                                         ///< Construct address from 16 bytes of raw data
192                                         /**< from_data will build an address from 16 bytes of raw
193                                              data as accessed by the iterator. The data must be in
194                                              network byte order. */
195
196         static INet6Address from_inet4address(INet4Address addr);
197                                         ///< Construct an INet6-mapped INet4 address
198                                         /**< This will construct an address of the form
199                                              <tt>::FFFF::w.x.y.z</tt> where <tt>w.x.y.z</tt> is
200                                              the INet4Address value. This kind of address is called
201                                              an INet6-mapped INet4 address (see 
202                                              <a href="http://tools.ietf.org/html/rfc4291">RFC 4291</a>).
203                                              \par 
204                                              INet4 compatible INet6 addresses are not directly
205                                              supported, they are deprecated in the RFC. */
206         std::string toString() const;
207                                         ///< get the string representation of this INet6Address
208         in6_addr  toin6_addr() const;
209                                         ///< get the linux in6_addr struct (convinience only) 
210         
211         
212         ///@}
213         ///////////////////////////////////////////////////////////////////////////
214         ///\name Accessors
215         ///@{
216
217         boost::uint64_t network() const; ///< Return 64bit network part
218         bool hasEuid64() const;         ///< \c true, if address is based on an EUID-64
219         boost::uint64_t id() const;     ///< Return interface id (EUID-64)
220         bool universalId() const;       ///< \c true, if the id() is universally assigned
221         bool groupId() const;           ///< \c true, if the id()'s \a group bit is set
222
223         bool unicast() const;           ///< \c true, if address is unicast
224         bool multicast() const;         ///< \c true, if address is multicast
225                                         /**< To support a linux specific extension, INet4 multicast
226                                              addressed mapped to INet6 are also interpreted as
227                                              multicast addresses. This is NOT part of the standard,
228                                              however the standard officially only allows unicast v4
229                                              addresses to be mapped to v6 so this does not collide
230                                              with any standard conforming use. */
231
232         ScopeId scope() const;          ///< Get address's scope
233                                         /**< The scope of an address is one of the \ref ScopeId
234                                              values. We need to differentiate between unicast and
235                                              multicast addresses: unicast addresses only have local,
236                                              site or global scope (where site scope is deprecated),
237                                              multicast address can have a number of scope values of
238                                              which local, site and global are a few. See the \ref
239                                              ScopeId enumerators. */ 
240         bool globalScope() const;       ///< \c true, if address is global unicast or multicast
241         bool linkScope() const;         ///< \c true, if address is link-local unicast or multicast
242
243         INet4Address inet4address() const; ///< Return embedded INet4 address
244                                         /**< Returns the INet4 address embedded within an INet4
245                                              compatible or INet4 mapped unicast address. This address
246                                              is given by the last 32 bits of the INet6 address. \par
247                                              The value returned is only a valid INet4 address if
248                                              either inet4Compatible() or inet4Mapped() return \c
249                                              true. */ 
250         bool inet4Compatible() const;   ///< \c true, if address is INet4 compatible
251                                         /**< INet4 compatible INet6 addresses are deprecated. */
252         bool inet4Mapped() const;       ///< \c true, if address is INet4 mapped
253
254         bool globalMulticastAddr() const; ///< \c true, if T bit is \e not set
255                                         /**< Any multicast address with a cleared T bit must be
256                                              globally assigned. See 
257                                              <a href="http://tools.ietf.org/html/rfc4291">RFC 4291</a>. */
258         bool prefixMulticastAddr() const; ///< \c true, if P bit is set
259                                         /**< In <a href="http://tools.ietf.org/html/rfc4291">RFC 4291</a>,
260                                              the P bit is specified as defining a
261                                              unicast prefix based multicast address. See 
262                                              <a href="http://tools.ietf.org/html/rfc3306">RFC 3306</a>. */ 
263         bool embeddedRpAddr() const;    ///< \c true, if R bit is set
264                                         /**< In <a href="http://tools.ietf.org/html/rfc4291">RFC 4291</a>,
265                                              the R bit is specified as defining a multicast address 
266                                              with embedded rendezvous point. See
267                                              <a href="http://tools.ietf.org/html/rfc3956">RFC 3956</a>. */
268
269         bool boolean_test() const;      ///< \c true, if address != '::' (None)
270
271         ///@}
272         ///\name Mutators
273         ///@{
274         
275         void network(boost::uint64_t net); ///< Set network part of address
276         void id(boost::uint64_t id);    ///< Set interface id part of address
277
278         ///@}
279
280     };
281
282     /** \brief Output INet6Address instance as it's string representation
283         \related INet6Address
284      */
285     std::ostream & operator<<(std::ostream & os, INet6Address const & addr);
286
287     /** \brief Check INet6Address against a fixed network prefix
288         
289         This helper allows to easily and efficiently check an INet6Address against an arbitrary but
290         constant network prefix. It takes from 1 to 8 arguments for the network address and an
291         additional last argument providing the prefix length. So
292
293         \par ""
294             <tt>senf::CheckINet6Network<</tt> <i>addr_1</i> <tt>,</tt> <i>addr_2</i> <tt>,</tt>
295             ... <tt>,</tt> <i>prefix_len</i> <tt>></tt>
296
297         represents the network
298         
299         \par ""
300             <i>addr_1</i> <tt>:</tt> <i>addr_2</i> <tt>:</tt> ... <tt>::/</tt> <i>prefix_len</i> .
301
302         The class exposes a single static member <tt>match(</tt> <i>addr</i> <tt>)</tt> which
303         matches the INet6Address \a addr against the prefix:
304         
305         \code
306         if (senf::CheckINet6Network<0x2000u,0xDB8u,32u>::match(addr)) {
307             // 'addr' is within in the 2001:db8::/32 documentation-only network
308             ...
309         }
310         \endcode
311
312         The code generated by this call is highly optimized and probably as efficient as it can get.
313      */
314     template <unsigned a0, unsigned a1, unsigned a2=0u, unsigned a3=0u, unsigned a4=0u,
315               unsigned a5=0u, unsigned a6=0u, unsigned a7=0u, unsigned a8=0u>
316     struct CheckINet6Network
317         : public detail::CheckINet6Network_impl<a0,a1,a2,a3,a4,a5,a6,a7,a8>
318     {};
319
320     /** \brief INet6 network prefix
321
322         This class represents an INet6 network prefix in CIDR notation. 
323       */
324     class INet6Network
325         : public boost::equality_comparable<INet6Network>, 
326           public comparable_safe_bool<INet6Network>
327     {
328     public:
329         ///////////////////////////////////////////////////////////////////////////
330         ///\name Structors and default members
331         ///@{
332
333         INet6Network();                 ///< Construct empty (::/0) network
334         INet6Network(INet6Address address, unsigned prefix_len);
335                                         ///< Construct network from given address and prefix length
336         explicit INet6Network(std::string s); ///< Construct network from CIDR notation
337
338         ///@}
339         ///////////////////////////////////////////////////////////////////////////
340
341         INet6Address const & address() const; ///< Get the network address
342         unsigned prefix_len() const;    ///< Get the network prefix length
343
344         bool boolean_test() const;      ///< \c true, if INet6Network is non-empty
345         bool operator==(INet6Network const & other) const;
346                                         ///< Compare two networks for equality
347         
348         bool match(INet6Address addr) const; ///< \c true, if the network includes \a addr
349         bool match(INet6Network net) const; ///< \c true, if the network includes \a net
350                                         /**< The is true, if \a net is sub-network (or the same as)
351                                              \c this. */
352         INet6Address host(boost::uint64_t id); ///< Return the host with the given id
353                                         /**< Returns the host with the given number within the
354                                              network. This call replaces the lower 64 bits of the
355                                              network address with the given id. */
356
357         INet6Network subnet(boost::uint64_t net, unsigned prefix_len);
358                                         ///< Return the given subnet of \c this
359                                         /**< The returned INet6Network will be a subnet of \c this
360                                              with the given network number. The network number is
361                                              comprised by the bits above \a prefix_len:
362                                              \code
363                                              INet6Network("2001:db8::/32").subnet(0x12u,40u) == INet6Network("2001:db8:1200::/40")
364                                              INet6Network("2001:db8:1200::/40").subnet(0x2345,64u) == INet6Network("2001:db8:1200:2345::/64")
365                                              \endcode 
366                                              \param[in] net network number
367                                              \param[in] prefix_len length of subnet prefix */
368
369     protected:
370
371     private:
372         unsigned prefix_len_;
373         INet6Address address_;
374     };
375
376     /** \brief Output INet6Network instance as it's string representation
377         \related INet6Network
378      */
379     std::ostream & operator<<(std::ostream & os, INet6Network const & addr);
380 }
381
382 ///////////////////////////////hh.e////////////////////////////////////////
383 #include "INet6Address.cci"
384 #include "INet6Address.ct"
385 #include "INet6Address.cti"
386 #endif
387
388 \f
389 // Local Variables:
390 // mode: c++
391 // fill-column: 100
392 // comment-column: 40
393 // c-file-style: "senf"
394 // indent-tabs-mode: nil
395 // ispell-local-dictionary: "american"
396 // compile-command: "scons -u test"
397 // End: