EMANE  1.2.1
inetaddr.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015-2016 - Adjacent Link LLC, Bridgewater, New Jersey
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * * Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in
13  * the documentation and/or other materials provided with the
14  * distribution.
15  * * Neither the name of Adjacent Link LLC nor the names of its
16  * contributors may be used to endorse or promote products derived
17  * from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #include "emane/inetaddr.h"
36 
37 #include <string>
38 #include <memory>
39 #include <algorithm>
40 
41 #include <netdb.h>
42 #include <net/if.h>
43 #include <arpa/inet.h>
44 
45 class EMANE::INETAddr::Implementation
46 {
47 public:
48  Implementation():
49  Implementation{"0.0.0.0",0}{}
50 
51  Implementation(const std::string & sEndPoint):
52  length_{},
53  iFamily_{AF_UNSPEC},
54  u16Port_{}
55  {
56  set(sEndPoint);
57  }
58 
59  Implementation(const std::string & sAddress,
60  std::uint16_t u16Port):
61  pSockAddr_{},
62  length_{},
63  iFamily_{AF_UNSPEC},
64  u16Port_{}
65  {
66  set(sAddress,u16Port);
67  }
68 
69  Implementation(const sockaddr_in & sockaddr):
70  pSockAddr_{reinterpret_cast<struct sockaddr*>(new sockaddr_in)},
71  length_{sizeof(sockaddr_in)},
72  iFamily_{AF_INET},
73  u16Port_{}
74  {
75  memcpy(pSockAddr_.get(),
76  &sockaddr,
77  sizeof(sockaddr));
78 
79  u16Port_ = reinterpret_cast<sockaddr_in*>(pSockAddr_.get())->sin_port;
80  }
81 
82  Implementation(const sockaddr_in6 & sockaddr):
83  pSockAddr_{reinterpret_cast<struct sockaddr*>(new sockaddr_in6)},
84  length_{sizeof(sockaddr_in6)},
85  iFamily_{AF_INET6},
86  u16Port_{}
87  {
88  memcpy(pSockAddr_.get(),
89  &sockaddr,
90  sizeof(sockaddr));
91 
92  u16Port_ = reinterpret_cast<sockaddr_in6*>(pSockAddr_.get())->sin6_port;
93  }
94 
95  void set(const std::string & sAddress,std::uint16_t u16Port)
96  {
97  addrinfo * pAddrInfo{};
98 
99  addrinfo hints;
100  memset(&hints,0,sizeof(hints));
101  hints.ai_family = AF_UNSPEC;
102  hints.ai_socktype = 0;
103 
104  int iRet{};
105 
106  // lookup the ipv4 or ipv6 address info
107  if((iRet = getaddrinfo(sAddress.c_str(),
108  std::to_string(u16Port).c_str(),
109  &hints,
110  &pAddrInfo)) != 0)
111  {
112  throw INETAddrException(gai_strerror(iRet));
113  }
114 
115  if(pAddrInfo->ai_family == AF_INET)
116  {
117  pSockAddr_.reset(reinterpret_cast<sockaddr*>(new sockaddr_in));
118  memcpy(pSockAddr_.get(),
119  reinterpret_cast<sockaddr_in*>(pAddrInfo->ai_addr),
120  sizeof(sockaddr_in));
121  }
122  else if(pAddrInfo->ai_family == AF_INET6)
123  {
124  pSockAddr_.reset(reinterpret_cast<sockaddr*>(new sockaddr_in6));
125  memcpy(pSockAddr_.get(),
126  reinterpret_cast<sockaddr_in6*>(pAddrInfo->ai_addr),
127  sizeof(sockaddr_in6));
128  }
129  else
130  {
131  freeaddrinfo(pAddrInfo);
132  throw INETAddrException("Unknown family");
133  }
134 
135  iFamily_ = pAddrInfo->ai_family;
136  length_ = pAddrInfo->ai_addrlen;
137  u16Port_ = u16Port;
138 
139  freeaddrinfo(pAddrInfo);
140  }
141 
142  void set(const std::string & sEndPoint)
143  {
144  if(sEndPoint.empty())
145  {
146  throw INETAddrException("Empty endpoint string");
147  }
148 
149  size_t pos = sEndPoint.rfind("/");
150 
151  if(pos == std::string::npos)
152  {
153  // only used ':' as a port seperator for
154  // hostname or IPv4 addresses
155  if(std::count(sEndPoint.begin(),
156  sEndPoint.end(),
157  ':') == 1 ||
158  sEndPoint.front() == '[')
159  {
160  pos = sEndPoint.rfind(":");
161  }
162  }
163 
164  std::string sAddress{sEndPoint};
165  std::uint16_t u16Port{};
166 
167  if(pos != std::string::npos)
168  {
169  sAddress = sEndPoint.substr(0,pos);
170  u16Port = Utils::ParameterConvert(sEndPoint.substr(pos+1)).toUINT16();
171  }
172 
173 
174  if(!sAddress.empty())
175  {
176  if(sAddress.front() == '[' &&
177  sAddress.back() == ']')
178  {
179  sAddress = sAddress.substr(1,sAddress.size() - 2);
180  }
181 
182  }
183 
184  set(sAddress,u16Port);
185  }
186 
187 
188  Implementation(const Implementation & address)
189  {
190  copy(address);
191  }
192 
193  Implementation & operator=(const Implementation & address)
194  {
195  copy(address);
196  return *this;
197  }
198 
199  bool isIPv6() const
200  {
201  return iFamily_ == AF_INET6;
202  }
203 
204  bool isIPv4() const
205  {
206  return iFamily_ == AF_INET;
207  }
208 
209  int getFamily() const
210  {
211  return iFamily_;
212  }
213 
214  bool isAny() const
215  {
216  if(isIPv4())
217  {
218  return reinterpret_cast<sockaddr_in*>(pSockAddr_.get())->sin_addr.s_addr == INADDR_ANY;
219  }
220  else
221  {
222  return IN6_IS_ADDR_UNSPECIFIED(&reinterpret_cast<sockaddr_in6 *>(pSockAddr_.get())->sin6_addr);
223  }
224  }
225 
226 
227  bool isMulticast() const
228  {
229  if(isIPv6())
230  {
231  return reinterpret_cast<sockaddr_in6 *>(pSockAddr_.get())->sin6_addr.s6_addr[0] == 0xFF;
232  }
233  else
234  {
235  return ntohl(reinterpret_cast<sockaddr_in*>(pSockAddr_.get())->sin_addr.s_addr) >= 0xE0000000 && // 224.0.0.0
236  ntohl(reinterpret_cast<sockaddr_in*>(pSockAddr_.get())->sin_addr.s_addr) <= 0xEFFFFFFF; // 239.255.255.255
237  }
238  }
239 
240  sockaddr * getSockAddr() const
241  {
242  return pSockAddr_.get();
243  }
244 
245  socklen_t getAddrLength() const
246  {
247  return length_;
248  }
249 
250  std::uint16_t getPort() const
251  {
252  return u16Port_;
253  }
254 
255  std::string str(bool bWithPort) const
256  {
257  std::string sCharacterString{};
258 
259  if(isIPv4())
260  {
261  char buf[INET_ADDRSTRLEN];
262 
263  inet_ntop(AF_INET,
264  &reinterpret_cast<sockaddr_in*>(pSockAddr_.get())->sin_addr,
265  buf,
266  sizeof(buf));
267 
268  if(bWithPort)
269  {
270  sCharacterString = std::string{buf} + ":" + std::to_string(u16Port_);
271  }
272  else
273  {
274  sCharacterString = std::string{buf};
275  }
276  }
277  else
278  {
279  char buf[INET6_ADDRSTRLEN];
280 
281  inet_ntop(AF_INET6,
282  &reinterpret_cast<sockaddr_in6 *>(pSockAddr_.get())->sin6_addr,
283  buf,
284  sizeof(buf));
285 
286  if(bWithPort)
287  {
288  sCharacterString = std::string{"["} + buf + "]:" + std::to_string(u16Port_);
289  }
290  else
291  {
292  sCharacterString = std::string{buf};
293  }
294  }
295 
296  return sCharacterString;
297  }
298 
299 private:
300  std::unique_ptr<sockaddr> pSockAddr_;
301  socklen_t length_;
302  int iFamily_;
303  std::uint16_t u16Port_;
304 
305  void copy(const Implementation & address)
306  {
307  iFamily_ = address.iFamily_;
308  length_ = address.length_;
309  u16Port_ = address.u16Port_;
310 
311  if(address.iFamily_ == AF_INET)
312  {
313  pSockAddr_.reset(reinterpret_cast<sockaddr*>(new sockaddr_in));
314  memcpy(pSockAddr_.get(),
315  reinterpret_cast<sockaddr_in*>(address.pSockAddr_.get()),
316  sizeof(sockaddr_in));
317  }
318  else
319  {
320  pSockAddr_.reset(reinterpret_cast<sockaddr*>(new sockaddr_in6));
321  memcpy(pSockAddr_.get(),
322  reinterpret_cast<sockaddr_in6*>(address.pSockAddr_.get()),
323  sizeof(sockaddr_in6));
324  }
325  }
326 };
327 
328 EMANE::INETAddr::INETAddr(const sockaddr_in & sockaddr):
329  pImpl_{new Implementation{sockaddr}}{}
330 
331 EMANE::INETAddr::INETAddr(const sockaddr_in6 & sockaddr):
332  pImpl_{new Implementation{sockaddr}}{}
333 
335  pImpl_{new Implementation{}}{}
336 
337 EMANE::INETAddr::INETAddr(const std::string & sEndPoint):
338  pImpl_{new Implementation{sEndPoint}}{}
339 
340 EMANE::INETAddr::INETAddr(const std::string & sAddress,
341  std::uint16_t u16Port):
342  pImpl_{new Implementation{sAddress,u16Port}}{}
343 
345 {
346  pImpl_.reset(new Implementation(*address.pImpl_.get()));
347 }
348 
350 {
351  pImpl_.reset(new Implementation(*address.pImpl_.get()));
352  return *this;
353 }
354 
356 {
357  pImpl_.swap(address.pImpl_);
358 }
359 
361 {
362  pImpl_.swap(address.pImpl_);
363  return *this;
364 }
365 
367 
368 void EMANE::INETAddr::set(const std::string & sAddress,
369  std::uint16_t u16Port)
370 {
371  pImpl_->set(sAddress,u16Port);
372 }
373 
374 void EMANE::INETAddr::set(const std::string & sEndPoint)
375 {
376  pImpl_->set(sEndPoint);
377 }
378 
380 {
381  return pImpl_->isIPv6();
382 }
383 
385 {
386  return pImpl_->isIPv4();
387 }
388 
390 {
391  return pImpl_->isAny();
392 }
393 
395 {
396  return pImpl_->getFamily();
397 }
398 
400 {
401  return pImpl_->getSockAddr();
402 }
403 
405 {
406  return pImpl_->getAddrLength();
407 }
408 
409 std::string EMANE::INETAddr::str(bool bWithPort) const
410 {
411  return pImpl_->str(bWithPort);
412 }
413 
414 std::uint16_t EMANE::INETAddr::getPort() const
415 {
416  return pImpl_->getPort();
417 }
bool isMulticast() const
socklen_t getAddrLength() const
Definition: inetaddr.cc:404
std::uint16_t getPort() const
Definition: inetaddr.cc:414
bool isIPv6() const
Definition: inetaddr.cc:379
sockaddr * getSockAddr() const
Definition: inetaddr.cc:399
bool isIPv4() const
Definition: inetaddr.cc:384
struct in_addr sin_addr
Definition: tuntap.h:544
bool isAny() const
Definition: inetaddr.cc:389
unsigned short sin_port
Definition: tuntap.h:543
std::string str(bool bWithPort=true) const
Definition: inetaddr.cc:409
int getFamily() const
Definition: inetaddr.cc:394
void set(const std::string &sAddress, std::uint16_t u16Port)
Definition: inetaddr.cc:368
INETAddr & operator=(const INETAddr &address)
Definition: inetaddr.cc:349