switch to new MPL based Fraunhofer FOKUS Public License
[senf.git] / senf / Socket / Protocols / INet / INet6Address.cci
1 // $Id$
2 //
3 // Copyright (C) 2007
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 //
6 // The contents of this file are subject to the Fraunhofer FOKUS Public License
7 // Version 1.0 (the "License"); you may not use this file except in compliance
8 // with the License. You may obtain a copy of the License at 
9 // http://senf.berlios.de/license.html
10 //
11 // The Fraunhofer FOKUS Public License Version 1.0 is based on, 
12 // but modifies the Mozilla Public License Version 1.1.
13 // See the full license text for the amendments.
14 //
15 // Software distributed under the License is distributed on an "AS IS" basis, 
16 // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 
17 // for the specific language governing rights and limitations under the License.
18 //
19 // The Original Code is Fraunhofer FOKUS code.
20 //
21 // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V. 
22 // (registered association), Hansastraße 27 c, 80686 Munich, Germany.
23 // All Rights Reserved.
24 //
25 // Contributor(s):
26 //   Stefan Bund <g0dil@berlios.de>
27
28 /** \file
29     \brief INet6Address inline non-template implementation */
30
31 #include "INet6Address.ih"
32
33 // Custom includes
34 #include <algorithm>
35 #include <boost/lambda/lambda.hpp>
36
37 #define prefix_ inline
38 //-/////////////////////////////////////////////////////////////////////////////////////////////////
39
40 prefix_ senf::INet6Address::INet6Address(senf::NoInit_t)
41 {}
42
43 prefix_ senf::INet6Address::INet6Address(boost::uint16_t a0, boost::uint16_t a1,
44                                          boost::uint16_t a2, boost::uint16_t a3,
45                                          boost::uint16_t a4, boost::uint16_t a5,
46                                          boost::uint16_t a6, boost::uint16_t a7)
47 {
48     (*this)[ 0] = boost::uint8_t(a0>>8);
49     (*this)[ 1] = boost::uint8_t(a0);
50     (*this)[ 2] = boost::uint8_t(a1>>8);
51     (*this)[ 3] = boost::uint8_t(a1);
52     (*this)[ 4] = boost::uint8_t(a2>>8);
53     (*this)[ 5] = boost::uint8_t(a2);
54     (*this)[ 6] = boost::uint8_t(a3>>8);
55     (*this)[ 7] = boost::uint8_t(a3);
56     (*this)[ 8] = boost::uint8_t(a4>>8);
57     (*this)[ 9] = boost::uint8_t(a4);
58     (*this)[10] = boost::uint8_t(a5>>8);
59     (*this)[11] = boost::uint8_t(a5);
60     (*this)[12] = boost::uint8_t(a6>>8);
61     (*this)[13] = boost::uint8_t(a6);
62     (*this)[14] = boost::uint8_t(a7>>8);
63     (*this)[15] = boost::uint8_t(a7);
64 }
65
66 prefix_ senf::INet6Address senf::INet6Address::from_in6addr(in6_addr const & in6addr)
67 {
68     return senf::INet6Address::from_data(&in6addr.s6_addr[0]);
69 }
70
71 prefix_ senf::INet6Address senf::INet6Address::from_inet4address(INet4Address const & addr4)
72 {
73     INet6Address addr;
74     addr[10] = 0xffu;
75     addr[11] = 0xffu;
76     std::copy(addr4.begin(), addr4.end(), addr.begin()+12);
77     return addr;
78 }
79
80 prefix_ senf::INet6Network senf::INet6Address::network()
81     const
82 {
83     return senf::INet6Network(*this, 64);
84 }
85
86 prefix_ bool senf::INet6Address::universalId()
87     const
88 {
89     return (*this)[8] & 2u;
90 }
91
92 prefix_ bool senf::INet6Address::groupId()
93     const
94 {
95     return (*this)[8] & 1u;
96 }
97
98 prefix_ senf::INet4Address senf::INet6Address::inet4address()
99     const
100 {
101     return INet4Address::from_data(&(*this)[12]);
102 }
103
104 prefix_ bool senf::INet6Address::inet4Mapped()
105     const
106 {
107     return CheckINet6Network<0u,0u,0u,0u,0u,0xFFFFu,96>::match(*this);
108 }
109
110 prefix_ bool senf::INet6Address::multicast()
111     const
112 {
113     return (*this)[0] == 0xFFu || (inet4Mapped() && inet4address().multicast());
114 }
115
116 prefix_ senf::INet6Address::ScopeId senf::INet6Address::scope()
117     const
118 {
119     static ScopeId const scopeMap[]
120         = { ReservedScope, InterfaceScope, LinkScope, ReservedScope,
121             AdminScope, SiteScope, UnassignedScope, UnassignedScope,
122             OrganizationScope, UnassignedScope, UnassignedScope, UnassignedScope,
123             UnassignedScope, UnassignedScope, GlobalScope, ReservedScope };
124     return multicast() ? scopeMap[(*this)[1] & 0x0Fu] :
125         (*this)[0] == 0xFEu ? (((*this)[1]&0xC0) == 0x80 ? LinkScope :
126                                ((*this)[1]&0xC0) == 0xC0 ? SiteScope : GlobalScope )
127         : GlobalScope;
128 }
129
130 prefix_ bool senf::INet6Address::unicast()
131     const
132 {
133     return ! multicast();
134 }
135
136 prefix_ bool senf::INet6Address::hasEUI64()
137     const
138 {
139     return unicast() && ((*this)[0]&0xE0u) != 0u;
140 }
141
142 prefix_ bool senf::INet6Address::globalScope()
143     const
144 {
145     return scope() == GlobalScope;
146 }
147
148 prefix_ bool senf::INet6Address::linkScope()
149     const
150 {
151     return scope() == LinkScope;
152 }
153
154 prefix_ bool senf::INet6Address::inet4Compatible()
155     const
156 {
157     return CheckINet6Network<0u,96>::match(*this);
158 }
159
160 prefix_ bool senf::INet6Address::globalMulticastAddr()
161     const
162 {
163     return multicast() && ! ((*this)[1] & 0x10u);
164 }
165
166 prefix_ bool senf::INet6Address::prefixMulticastAddr()
167     const
168 {
169     return multicast() && ((*this)[1] & 0x20u);
170 }
171
172 prefix_ bool senf::INet6Address::embeddedRpAddr()
173     const
174 {
175     return multicast() && ((*this)[1] & 0x40u);
176 }
177
178 prefix_ bool senf::INet6Address::boolean_test()
179     const
180 {
181     using boost::lambda::_1;
182     return std::find_if(begin(),end(), _1 != 0x00) != end();
183 }
184
185 prefix_ void senf::INet6Address::network(boost::uint64_t net)
186 {
187     (*this)[ 0] = net >> 56;
188     (*this)[ 1] = net >> 48;
189     (*this)[ 2] = net >> 40;
190     (*this)[ 3] = net >> 32;
191     (*this)[ 4] = net >> 24;
192     (*this)[ 5] = net >> 16;
193     (*this)[ 6] = net >>  8;
194     (*this)[ 7] = net      ;
195 }
196
197 prefix_ void senf::INet6Address::id(boost::uint64_t id)
198 {
199     (*this)[ 8] = id >> 56;
200     (*this)[ 9] = id >> 48;
201     (*this)[10] = id >> 40;
202     (*this)[11] = id >> 32;
203     (*this)[12] = id >> 24;
204     (*this)[13] = id >> 16;
205     (*this)[14] = id >>  8;
206     (*this)[15] = id      ;
207 }
208
209 //-/////////////////////////////////////////////////////////////////////////////////////////////////
210 // senf::INet6Network
211
212 prefix_ senf::INet6Network::INet6Network()
213     : prefix_len_(), address_()
214 {}
215
216 prefix_ senf::INet6Network::INet6Network(INet6Address const & address, unsigned prefix_len)
217     : prefix_len_(prefix_len), address_(address)
218 {
219     using boost::lambda::_1;
220     using boost::lambda::_2;
221     detail::apply_mask(prefix_len_, address_.begin(), address_.end(), _1 &= _2);
222 }
223
224 prefix_ senf::INet6Address const & senf::INet6Network::address()
225     const
226 {
227     return address_;
228 }
229
230 prefix_ unsigned senf::INet6Network::prefix_len()
231     const
232 {
233     return prefix_len_;
234 }
235
236 prefix_ bool senf::INet6Network::boolean_test()
237     const
238 {
239     return prefix_len() && address();
240 }
241
242 prefix_ bool senf::INet6Network::operator==(INet6Network const & other)
243     const
244 {
245     return prefix_len() == other.prefix_len() && address() == other.address();
246 }
247
248 prefix_ bool senf::INet6Network::match(INet6Address const & addr)
249     const
250 {
251     using boost::lambda::_1;
252     using boost::lambda::_2;
253     using boost::lambda::_3;
254     return detail::find_if_mask(prefix_len_, address_.begin(), address_.end(), addr.begin(),
255                                 _1 != (_2 & _3)) == address_.end();
256 }
257
258 prefix_ bool senf::INet6Network::match(INet6Network const & net)
259     const
260 {
261     return net.prefix_len() >= prefix_len() && match(net.address());
262 }
263
264 prefix_ senf::INet6Address senf::INet6Network::host(boost::uint64_t id)
265 {
266     INet6Address addr (address());
267     addr.id(id);
268     return addr;
269 }
270
271 prefix_ senf::INet6Network senf::INet6Network::subnet(boost::uint64_t net, unsigned prefix_len)
272 {
273     using boost::lambda::_1;
274     using boost::lambda::_2;
275     using boost::lambda::var;
276     using boost::lambda::ret;
277     INet6Address addr (address());
278     net <<= (64-prefix_len);
279     detail::apply_mask(prefix_len, addr.begin(), addr.end(),
280                        ( ( _1 |= ret<boost::uint8_t>((var(net) >> 56) & _2) ),
281                          ( var(net) <<= 8 ) ));
282     return INet6Network(addr, prefix_len);
283 }
284
285 prefix_ std::ostream & senf::operator<<(std::ostream & os, INet6Network const & addr)
286 {
287     os << addr.address() << '/' << addr.prefix_len();
288     return os;
289 }
290
291 //-/////////////////////////////////////////////////////////////////////////////////////////////////
292 // namespace senf::detail members
293
294 prefix_ boost::uint8_t senf::detail::low_bits_mask(unsigned bits)
295 {
296     return ((1<<bits)-1);
297 }
298
299 //-/////////////////////////////////////////////////////////////////////////////////////////////////
300 #undef prefix_
301
302 \f
303 // Local Variables:
304 // mode: c++
305 // fill-column: 100
306 // comment-column: 40
307 // c-file-style: "senf"
308 // indent-tabs-mode: nil
309 // ispell-local-dictionary: "american"
310 // compile-command: "scons -u test"
311 // End: