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
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
15 \brief INet6Address inline non-template implementation */
17 #include "INet6Address.ih"
21 #include <boost/lambda/lambda.hpp>
23 #define prefix_ inline
24 //-/////////////////////////////////////////////////////////////////////////////////////////////////
26 prefix_ senf::INet6Address::INet6Address(senf::NoInit_t)
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)
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);
52 prefix_ senf::INet6Address senf::INet6Address::from_in6addr(in6_addr const & in6addr)
54 return senf::INet6Address::from_data(&in6addr.s6_addr[0]);
57 prefix_ senf::INet6Address senf::INet6Address::from_inet4address(INet4Address const & addr4)
62 std::copy(addr4.begin(), addr4.end(), addr.begin()+12);
66 prefix_ senf::INet6Network senf::INet6Address::network()
69 return senf::INet6Network(*this, 64);
72 prefix_ bool senf::INet6Address::universalId()
75 return (*this)[8] & 2u;
78 prefix_ bool senf::INet6Address::groupId()
81 return (*this)[8] & 1u;
84 prefix_ senf::INet4Address senf::INet6Address::inet4address()
87 return INet4Address::from_data(&(*this)[12]);
90 prefix_ bool senf::INet6Address::inet4Mapped()
93 return CheckINet6Network<0u,0u,0u,0u,0u,0xFFFFu,96>::match(*this);
96 prefix_ bool senf::INet6Address::multicast()
99 return (*this)[0] == 0xFFu || (inet4Mapped() && inet4address().multicast());
102 prefix_ senf::INet6Address::ScopeId senf::INet6Address::scope()
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 )
116 prefix_ bool senf::INet6Address::unicast()
119 return ! multicast();
122 prefix_ bool senf::INet6Address::hasEUI64()
125 return unicast() && ((*this)[0]&0xE0u) != 0u;
128 prefix_ bool senf::INet6Address::globalScope()
131 return scope() == GlobalScope;
134 prefix_ bool senf::INet6Address::linkScope()
137 return scope() == LinkScope;
140 prefix_ bool senf::INet6Address::inet4Compatible()
143 return CheckINet6Network<0u,96>::match(*this);
146 prefix_ bool senf::INet6Address::globalMulticastAddr()
149 return multicast() && ! ((*this)[1] & 0x10u);
152 prefix_ bool senf::INet6Address::prefixMulticastAddr()
155 return multicast() && ((*this)[1] & 0x20u);
158 prefix_ bool senf::INet6Address::embeddedRpAddr()
161 return multicast() && ((*this)[1] & 0x40u);
164 prefix_ bool senf::INet6Address::boolean_test()
167 using boost::lambda::_1;
168 return std::find_if(begin(),end(), _1 != 0x00) != end();
171 prefix_ void senf::INet6Address::network(boost::uint64_t net)
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;
183 prefix_ void senf::INet6Address::id(boost::uint64_t id)
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;
195 //-/////////////////////////////////////////////////////////////////////////////////////////////////
196 // senf::INet6Network
198 prefix_ senf::INet6Network::INet6Network()
199 : prefix_len_(), address_()
202 prefix_ senf::INet6Network::INet6Network(INet6Address const & address, unsigned prefix_len)
203 : prefix_len_( prefix_len_checked(prefix_len)),
206 using boost::lambda::_1;
207 using boost::lambda::_2;
208 detail::apply_mask(prefix_len_, address_.begin(), address_.end(), _1 &= _2);
211 prefix_ senf::INet6Address const & senf::INet6Network::address()
217 prefix_ unsigned senf::INet6Network::prefix_len()
223 prefix_ bool senf::INet6Network::boolean_test()
226 return prefix_len() && address();
229 prefix_ bool senf::INet6Network::operator==(INet6Network const & other)
232 return prefix_len() == other.prefix_len() && address() == other.address();
235 prefix_ bool senf::INet6Network::match(INet6Address const & addr)
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();
245 prefix_ bool senf::INet6Network::match(INet6Network const & net)
248 return net.prefix_len() >= prefix_len() && match(net.address());
251 prefix_ senf::INet6Address senf::INet6Network::host(boost::uint64_t id)
253 INet6Address addr (address());
258 prefix_ senf::INet6Network senf::INet6Network::subnet(boost::uint64_t net, unsigned prefix_len)
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);
272 prefix_ unsigned senf::INet6Network::prefix_len_checked(unsigned prefix_len)
275 if (prefix_len > 128)
276 throw AddressSyntaxException("invalid INet6 prefix length: " +
277 boost::lexical_cast<std::string>(prefix_len));
281 prefix_ std::ostream & senf::operator<<(std::ostream & os, INet6Network const & addr)
283 os << addr.address() << '/' << addr.prefix_len();
287 //-/////////////////////////////////////////////////////////////////////////////////////////////////
288 // namespace senf::detail members
290 prefix_ boost::uint8_t senf::detail::low_bits_mask(unsigned bits)
292 return ((1<<bits)-1);
295 //-/////////////////////////////////////////////////////////////////////////////////////////////////
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"