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