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