INet6Address.cc
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 
17 #include "INet6Address.hh"
18 #include "INet6Address.ih"
19 
20 // Custom includes
21 #include <sys/types.h>
22 #include <sys/socket.h>
23 #include <netinet/in.h>
24 #include <arpa/inet.h>
25 #include <netdb.h>
26 #include <boost/lexical_cast.hpp>
30 
31 //#include "INet6Address.mpp"
32 #define prefix_
33 //-/////////////////////////////////////////////////////////////////////////////////////////////////
34 
35 //-/////////////////////////////////////////////////////////////////////////////////////////////////
36 // senf::INet6Address
37 
39  Resolve_t resolve)
40 {
41  struct in6_addr ina;
42  if (::inet_pton(AF_INET6,s.c_str(),&ina) > 0)
43  return INet6Address::from_data(&ina.s6_addr[0]);
44 
45  if (s.empty())
46  throw AddressSyntaxException() << ": empty string";
47 
48 
49  // If available, we use the reentrant GNU variant. This has the additional advantage, that we
50  // can explicitly ask for IPv4 addresses
51 
52 # ifdef __GLIBC__
53 
54  struct hostent entbuf;
55  char buffer[4096];
56  struct hostent * ent (0);
57  int herr (0);
58  ::gethostbyname2_r(s.c_str(), AF_INET6, &entbuf, buffer, sizeof(buffer), &ent, &herr);
59 
60 # else // ! __GLIBC__
61 
62 # ifdef _REENTRANT
63  static boost::mutex mutex;
64  boost::mutex::scoped_lock lock(mutex);
65 # endif
66  struct hostent * ent (::gethostbyname(s.c_str()));
67 
68 # endif // __GLIBC__
69 
70  if (ent && ent->h_addrtype == AF_INET6)
71  // We are only interested in the first address ...
73  &reinterpret_cast<in6_addr*>(*(ent->h_addr_list))->s6_addr[0]);
74 
75  if (resolve == ResolveINet4)
77  else
78  throw UnknownHostnameException(s);
79 }
80 
82  ::in6_addr ina;
83  std::copy((*this).begin(), (*this).end(), &ina.s6_addr[0]);
84  return ina;
85 }
86 
88 {
89  INet6Address addr;
90  addr[0] = 0xfe;
91  addr[1] = 0x80;
92  addr[8] = mac[0] ^ 0x2; // invert the "u" (universal/local) bit; see RFC 4291 Appx. A
93  addr[9] = mac[1];
94  addr[10] = mac[2];
95  addr[11] = 0xff;
96  addr[12] = 0xfe;
97  addr[13] = mac[3];
98  addr[14] = mac[4];
99  addr[15] = mac[5];
100  return addr;
101 }
102 
104 {
105  INet6Address addr;
106  addr[0] = 0xfe;
107  addr[1] = 0x80;
108  addr[8] = eui[0] ^ 0x2; // invert the "u" (universal/local) bit; see RFC 4291 Appx. A
109  std::copy(eui.begin()+1, eui.end(), addr.begin()+9);
110  return addr;
111 }
112 
114  const
115 {
116  return EUI64::from_data(begin()+8);
117 }
118 
119 prefix_ std::ostream & senf::operator<<(std::ostream & os, INet6Address const & addr)
120 {
121  ::in6_addr ina;
122  char buffer[5*8];
123  std::copy(addr.begin(),addr.end(),&ina.s6_addr[0]);
124  ::inet_ntop(AF_INET6,&ina,buffer,sizeof(buffer));
125  buffer[sizeof(buffer)-1] = 0;
126  os << buffer;
127  return os;
128 }
129 
130 prefix_ std::istream & senf::operator>>(std::istream & is, INet6Address & addr)
131 {
132  std::string s;
133  if (!(is >> s))
134  return is;
135  try {
136  addr = INet6Address::from_string(s);
137  }
138  catch (AddressException &) {
139  is.setstate(std::ios::failbit);
140  }
141  return is;
142 }
143 
145 senf::INet6Address const senf::INet6Address::Loopback (0u,0u,0u,0u,0u,0u,0u,1u);
146 senf::INet6Address const senf::INet6Address::AllNodes (0xFF02u,0u,0u,0u,0u,0u,0u,1u);
147 senf::INet6Address const senf::INet6Address::AllRouters (0xFF02u,0u,0u,0u,0u,0u,0u,2u);
148 
149 //-/////////////////////////////////////////////////////////////////////////////////////////////////
150 // senf::INet6Network
151 
153 {
154  using boost::lambda::_1;
155  using boost::lambda::_2;
156  std::string::size_type i (s.find('/'));
157  if (i == std::string::npos)
158  throw AddressSyntaxException(s);
159  try {
160  prefix_len_ = prefix_len_checked( boost::lexical_cast<unsigned>(std::string(s,i+1)));
161  } catch (boost::bad_lexical_cast const &) {
162  throw AddressSyntaxException(s);
163  }
164  address_ = INet6Address::from_string(std::string(s, 0, i));
165  detail::apply_mask(prefix_len_, address_.begin(), address_.end(), _1 &= _2);
166 }
167 
168 prefix_ std::istream & senf::operator>>(std::istream & is, INet6Network & addr)
169 {
170  std::string s;
171  if (!(is >> s))
172  return is;
173  try {
174  addr = INet6Network(s);
175  }
176  catch (AddressException &) {
177  is.setstate(std::ios::failbit);
178  }
179  return is;
180 }
181 
182 //-/////////////////////////////////////////////////////////////////////////////////////////////////
183 #undef prefix_
184 //#include "INet6Address.mpp"
185 
186 
187 // Local Variables:
188 // mode: c++
189 // fill-column: 100
190 // comment-column: 40
191 // c-file-style: "senf"
192 // indent-tabs-mode: nil
193 // ispell-local-dictionary: "american"
194 // compile-command: "scons -u test"
195 // End:
MACAddress public header.
static INet6Address from_string(std::string const &s, Resolve_t resolve=ResolveINet6)
Convert string to address.
Definition: INet6Address.cc:38
EUI-64 data type.
Definition: EUI64.hh:66
INet6 network prefix.
Ethernet MAC address.
Definition: MACAddress.hh:72
static EUI64 from_data(InputIterator i)
Construct EUI-64 from 8 data octets.
std::ostream & operator<<(std::ostream &os, Packet const &packet)
INet6Address public header.
static INet6Address const Loopback
The loopback (::1) address.
in6_addr toin6_addr() const
get the linux in6_addr struct (convenience only)
Definition: INet6Address.cc:81
std::istream & operator>>(std::istream &is, INet4SocketAddress &addr)
EUI64 public header.
static INet6Address const AllNodes
The &#39;all nodes&#39; link-local multicast address.
static INet6Address from_inet4address(INet4Address const &addr)
Construct an INet6-mapped INet4 address.
INet6Network()
Construct empty (::/0) network.
AddressExceptions public header.
static INet6Address const AllRouters
The &#39;all routers&#39; link-local multicast address.
#define prefix_
Definition: INet6Address.cc:32
static INet4Address from_string(std::string const &s)
Convert string to address.
Definition: INet4Address.cc:41
INet6 network address.
EUI64 id() const
Return interface id (EUID-64)
static INet6Address from_data(InputIterator i)
Construct address from 16 bytes of raw data.
Base-class for Address exceptions.
Invalid address syntax.
static INet6Address from_eui64(EUI64 const &eui)
Construct link-local INet6 address.
static INet6Address const None
The empty (::0) address.
static INet6Address from_mac(MACAddress const &mac)
Construct a link-local INet6 address.
Definition: INet6Address.cc:87