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