96e87f5e1d8c225f0fada4008958a79115b31204
[senf.git] / Socket / Protocols / INet / INet6Address.cci
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 inline non-template implementation */
25
26 #include "INet6Address.ih"
27
28 // Custom includes
29 #include <algorithm>
30 #include <boost/lambda/lambda.hpp>
31
32 #define prefix_ inline
33 ///////////////////////////////cci.p///////////////////////////////////////
34
35 prefix_ senf::INet6Address::INet6Address(senf::NoInit_t)
36 {}
37
38 prefix_ senf::INet6Address::INet6Address(boost::uint16_t a0, boost::uint16_t a1,
39                                          boost::uint16_t a2, boost::uint16_t a3,
40                                          boost::uint16_t a4, boost::uint16_t a5,
41                                          boost::uint16_t a6, boost::uint16_t a7)
42 {
43     (*this)[ 0] = boost::uint8_t(a0>>8);
44     (*this)[ 1] = boost::uint8_t(a0);
45     (*this)[ 2] = boost::uint8_t(a1>>8);
46     (*this)[ 3] = boost::uint8_t(a1);
47     (*this)[ 4] = boost::uint8_t(a2>>8);
48     (*this)[ 5] = boost::uint8_t(a2);
49     (*this)[ 6] = boost::uint8_t(a3>>8);
50     (*this)[ 7] = boost::uint8_t(a3);
51     (*this)[ 8] = boost::uint8_t(a4>>8);
52     (*this)[ 9] = boost::uint8_t(a4);
53     (*this)[10] = boost::uint8_t(a5>>8);
54     (*this)[11] = boost::uint8_t(a5);
55     (*this)[12] = boost::uint8_t(a6>>8);
56     (*this)[13] = boost::uint8_t(a6);
57     (*this)[14] = boost::uint8_t(a7>>8);
58     (*this)[15] = boost::uint8_t(a7);
59 }
60
61 prefix_ senf::INet6Address::INet6Address(in6_addr in6addr){
62         senf::INet6Address::from_data(&in6addr.s6_addr[0]);
63 }
64
65
66
67 prefix_ senf::INet6Address senf::INet6Address::from_inet4address(INet4Address addr4)
68 {
69     INet6Address addr;
70     addr[10] = 0xffu;
71     addr[11] = 0xffu;
72     std::copy(addr4.begin(), addr4.end(), addr.begin()+12);
73     return addr;
74 }
75
76 prefix_ boost::uint64_t senf::INet6Address::network()
77     const
78 {
79     return 
80         ((boost::uint64_t((*this)[0]) & 0xff) << 56 ) |
81         ((boost::uint64_t((*this)[1]) & 0xff) << 48 ) |
82         ((boost::uint64_t((*this)[2]) & 0xff) << 40 ) |
83         ((boost::uint64_t((*this)[3]) & 0xff) << 32 ) |
84         ((boost::uint64_t((*this)[4]) & 0xff) << 24 ) |
85         ((boost::uint64_t((*this)[5]) & 0xff) << 16 ) |
86         ((boost::uint64_t((*this)[6]) & 0xff) <<  8 ) |
87         ((boost::uint64_t((*this)[7]) & 0xff)       );
88 }
89
90 prefix_ bool senf::INet6Address::hasEuid64()
91     const
92 {
93     return unicast() && ((*this)[0]&0xE0u) != 0u;
94 }
95
96 prefix_ boost::uint64_t senf::INet6Address::id()
97     const
98 {
99     return 
100         ((boost::uint64_t((*this)[ 8]) & 0xff) << 56 ) |
101         ((boost::uint64_t((*this)[ 9]) & 0xff) << 48 ) |
102         ((boost::uint64_t((*this)[10]) & 0xff) << 40 ) |
103         ((boost::uint64_t((*this)[11]) & 0xff) << 32 ) |
104         ((boost::uint64_t((*this)[12]) & 0xff) << 24 ) |
105         ((boost::uint64_t((*this)[13]) & 0xff) << 16 ) |
106         ((boost::uint64_t((*this)[14]) & 0xff) <<  8 ) |
107         ((boost::uint64_t((*this)[15]) & 0xff)       );
108 }
109
110 prefix_ bool senf::INet6Address::universalId()
111     const
112 {
113     return (*this)[8] & 2u;
114 }
115
116 prefix_ bool senf::INet6Address::groupId()
117     const
118 {
119     return (*this)[8] & 1u;
120 }
121
122 prefix_ bool senf::INet6Address::unicast()
123     const
124 {
125     return ! multicast();
126 }
127
128 prefix_ bool senf::INet6Address::multicast()
129     const
130 {
131     return (*this)[0] == 0xFFu;
132 }
133
134 prefix_ senf::INet6Address::ScopeId senf::INet6Address::scope()
135     const
136 {
137     static ScopeId const scopeMap[]
138         = { ReservedScope, InterfaceScope, LinkScope, ReservedScope,
139             AdminScope, SiteScope, UnassignedScope, UnassignedScope,
140             OrganizationScope, UnassignedScope, UnassignedScope, UnassignedScope,
141             UnassignedScope, UnassignedScope, GlobalScope, ReservedScope };
142     return multicast() ? scopeMap[(*this)[1] & 0x0Fu] : 
143         (*this)[0] == 0xFEu ? (((*this)[1]&0xC0) == 0x80 ? LinkScope : 
144                                ((*this)[1]&0xC0) == 0xC0 ? SiteScope : GlobalScope ) 
145         : GlobalScope;
146 }
147
148 prefix_ bool senf::INet6Address::globalScope()
149     const
150 {
151     return scope() == GlobalScope;
152 }
153  
154 prefix_ bool senf::INet6Address::linkScope()
155     const
156 {
157     return scope() == LinkScope;
158 }
159
160 prefix_ senf::INet4Address senf::INet6Address::inet4address()
161     const
162 {
163     return INet4Address::from_data(&(*this)[12]);
164 }
165
166 prefix_ bool senf::INet6Address::inet4Compatible()
167     const
168 {
169     return CheckINet6Network<0u,96>::match(*this);
170 }
171
172 prefix_ bool senf::INet6Address::inet4Mapped()
173     const
174 {
175     return CheckINet6Network<0u,0u,0u,0u,0u,0xFFFFu,96>::match(*this);
176 }
177
178 prefix_ bool senf::INet6Address::globalMulticastAddr()
179     const
180 {
181     return multicast() && ! ((*this)[1] & 0x10u);
182 }
183
184 prefix_ bool senf::INet6Address::prefixMulticastAddr()
185     const
186 {
187     return multicast() && ((*this)[1] & 0x20u);
188 }
189
190 prefix_ bool senf::INet6Address::embeddedRpAddr()
191     const
192 {
193     return multicast() && ((*this)[1] & 0x40u);
194 }
195
196 prefix_ bool senf::INet6Address::boolean_test()
197     const
198 {
199     using boost::lambda::_1;
200     return std::find_if(begin(),end(), _1 != 0x00) != end();
201 }
202
203 prefix_ void senf::INet6Address::network(boost::uint64_t net)
204 {
205     (*this)[ 0] = net >> 56;
206     (*this)[ 1] = net >> 48;
207     (*this)[ 2] = net >> 40;
208     (*this)[ 3] = net >> 32;
209     (*this)[ 4] = net >> 24;
210     (*this)[ 5] = net >> 16;
211     (*this)[ 6] = net >>  8;
212     (*this)[ 7] = net      ;
213 }
214
215 prefix_ void senf::INet6Address::id(boost::uint64_t id)
216 {
217     (*this)[ 8] = id >> 56;
218     (*this)[ 9] = id >> 48;
219     (*this)[10] = id >> 40;
220     (*this)[11] = id >> 32;
221     (*this)[12] = id >> 24;
222     (*this)[13] = id >> 16;
223     (*this)[14] = id >>  8;
224     (*this)[15] = id      ;
225 }
226
227 ///////////////////////////////////////////////////////////////////////////
228 // senf::INet6Network
229
230 prefix_ senf::INet6Network::INet6Network()
231     : prefix_len_(), address_()
232 {}
233
234 prefix_ senf::INet6Network::INet6Network(INet6Address address, unsigned prefix_len)
235     : prefix_len_(prefix_len), address_(address)
236 {
237     using boost::lambda::_1;
238     using boost::lambda::_2;
239     detail::apply_mask(prefix_len_, address_.begin(), address_.end(), _1 &= _2);
240 }
241
242 prefix_ senf::INet6Address const & senf::INet6Network::address()
243     const
244 {
245     return address_;
246 }
247
248 prefix_ unsigned senf::INet6Network::prefix_len()
249     const
250 {
251     return prefix_len_;
252 }
253
254 prefix_ bool senf::INet6Network::boolean_test()
255     const
256 {
257     return prefix_len() && address();
258 }
259
260 prefix_ bool senf::INet6Network::operator==(INet6Network const & other)
261     const
262 {
263     return prefix_len() == other.prefix_len() && address() == other.address();
264 }
265
266 prefix_ bool senf::INet6Network::match(INet6Address addr)
267     const
268 {
269     using boost::lambda::_1;
270     using boost::lambda::_2;
271     using boost::lambda::_3;
272     return detail::find_if_mask(prefix_len_, address_.begin(), address_.end(), addr.begin(),
273                                 _1 != (_2 & _3)) == address_.end();
274 }
275
276 prefix_ bool senf::INet6Network::match(INet6Network net)
277     const
278 {
279     return net.prefix_len() >= prefix_len() && match(net.address());
280 }
281
282 prefix_ senf::INet6Address senf::INet6Network::host(boost::uint64_t id)
283 {
284     INet6Address addr (address());
285     addr.id(id);
286     return addr;
287 }
288
289 prefix_ senf::INet6Network senf::INet6Network::subnet(boost::uint64_t net, unsigned prefix_len)
290 {
291     using boost::lambda::_1;
292     using boost::lambda::_2;
293     using boost::lambda::var;
294     using boost::lambda::ret;
295     INet6Address addr (address());
296     net <<= (64-prefix_len);
297     detail::apply_mask(prefix_len, addr.begin(), addr.end(),
298                        ( ( _1 |= ret<boost::uint8_t>((var(net) >> 56) & _2) ),
299                          ( var(net) <<= 8 ) ));
300     return INet6Network(addr, prefix_len);
301 }
302
303 prefix_ std::ostream & senf::operator<<(std::ostream & os, INet6Network const & addr)
304 {
305     os << addr.address() << '/' << addr.prefix_len();
306     return os;
307 }
308
309 ///////////////////////////////////////////////////////////////////////////
310 // namespace senf::detail members
311
312 prefix_ boost::uint8_t senf::detail::low_bits_mask(unsigned bits)
313 {
314     return ((1<<bits)-1);
315 }
316
317 ///////////////////////////////cci.e///////////////////////////////////////
318 #undef prefix_
319
320 \f
321 // Local Variables:
322 // mode: c++
323 // fill-column: 100
324 // comment-column: 40
325 // c-file-style: "senf"
326 // indent-tabs-mode: nil
327 // ispell-local-dictionary: "american"
328 // compile-command: "scons -u test"
329 // End: