OpenDDS  Snapshot(2023/04/28-20:55)
NetworkAddress.cpp
Go to the documentation of this file.
1 /*
2  * Distributed under the OpenDDS License.
3  * See: http://www.opendds.org/license.html
4  */
5 
6 #include "DCPS/DdsDcps_pch.h"
7 
8 #include "NetworkAddress.h"
9 
10 #include "Hash.h"
11 #include "LogAddr.h"
12 
13 #include <cstring>
14 
16 
17 namespace OpenDDS {
18 namespace DCPS {
19 
21 {
22  // We want to take care here to make sure that our NetworkAddress can be used with std::memcmp
23  std::memset(&inet_addr_, 0, sizeof (inet_addr_));
24 
25  // The following is required to achieve equivalence between default-constructed NetworkAddress and ACE_INET_Addr
26 #if defined (ACE_HAS_IPV6)
27 # if defined (ACE_USES_IPV4_IPV6_MIGRATION)
28  if (ACE::ipv6_enabled()) {
29  inet_addr_.in6_.sin6_family = AF_INET6;
30 # ifdef ACE_HAS_SOCKADDR_IN_SIN_LEN
31  inet_addr_.in6_.sin6_len = sizeof (inet_addr_);
32 # endif /* ACE_HAS_SOCKADDR_IN_SIN_LEN */
33  } else {
34  inet_addr_.in4_.sin_family = AF_INET;
35 # ifdef ACE_HAS_SOCKADDR_IN_SIN_LEN
36  inet_addr_.in4_.sin_len = sizeof (inet_addr_);
37 # endif /* ACE_HAS_SOCKADDR_IN_SIN_LEN */
38  }
39 
40 # else /* ACE_USES_IPV4_IPV6_MIGRATION */
41  inet_addr_.in6_.sin6_family = AF_INET6;
42 # ifdef ACE_HAS_SOCKADDR_IN_SIN_LEN
43  inet_addr_.in6_.sin6_len = sizeof (inet_addr_);
44 # endif /* ACE_HAS_SOCKADDR_IN_SIN_LEN */
45 # endif /* ACE_USES_IPV4_IPV6_MIGRATION */
46 
47 #else /* ACE_HAS_IPV6 */
48  inet_addr_.in4_.sin_family = AF_INET;
49 # ifdef ACE_HAS_SOCKADDR_IN_SIN_LEN
50  inet_addr_.in4_.sin_len = sizeof (inet_addr_);
51 # endif /* ACE_HAS_SOCKADDR_IN_SIN_LEN */
52 #endif /* ACE_HAS_IPV6 */
53 }
54 
56 {
57  *this = val;
58 }
59 
61 {
62  *this = ACE_INET_Addr(str);
63 }
64 
65 NetworkAddress::NetworkAddress(ACE_UINT16 port, const char* str)
66 {
67  *this = ACE_INET_Addr(port, str);
68 }
69 
70 #if defined (ACE_HAS_WCHAR)
71 
72 NetworkAddress::NetworkAddress(const wchar_t* str)
73 {
74  *this = ACE_INET_Addr(str);
75 }
76 
77 NetworkAddress::NetworkAddress(ACE_UINT16 port, const wchar_t* str)
78 {
79  *this = ACE_INET_Addr(port, str);
80 }
81 
82 #endif
83 
85 {
86  // We want to take care here to make sure that our NetworkAddress can be used with std::memcmp
87  std::memset(&inet_addr_, 0, sizeof (inet_addr_));
88 
89  const ip46& in = *reinterpret_cast<ip46*>(addr.get_addr());
90  if (in.in4_.sin_family == AF_INET) {
91  inet_addr_.in4_.sin_family = in.in4_.sin_family;
92  inet_addr_.in4_.sin_port = in.in4_.sin_port;
93 #ifdef ACE_HAS_SOCKADDR_IN_SIN_LEN
94  inet_addr_.in4_.sin_len = in.in4_.sin_len;
95 #endif
96  inet_addr_.in4_.sin_addr = in.in4_.sin_addr;
97 #if defined (ACE_HAS_IPV6)
98  } else if (in.in6_.sin6_family == AF_INET6) {
99  inet_addr_.in6_.sin6_family = in.in6_.sin6_family;
100  inet_addr_.in6_.sin6_port = in.in6_.sin6_port;
101  inet_addr_.in6_.sin6_flowinfo = in.in6_.sin6_flowinfo;
102 #ifdef ACE_HAS_SOCKADDR_IN_SIN_LEN
103  inet_addr_.in6_.sin6_len = in.in6_.sin6_len;
104 #endif
105  inet_addr_.in6_.sin6_addr = in.in6_.sin6_addr;
106  inet_addr_.in6_.sin6_scope_id = in.in6_.sin6_scope_id;
107 #endif
108  }
109 }
110 
112 {
113  if (&rhs != this) {
114  std::memcpy(&inet_addr_, &rhs.inet_addr_, sizeof (inet_addr_));
115  }
116  return *this;
117 }
118 
120 {
121  return *this = NetworkAddress(rhs);
122 }
123 
124 NetworkAddress::operator bool() const
125 {
126  static const NetworkAddress empty = NetworkAddress();
127  return *this != empty;
128 }
129 
131 {
132  static const NetworkAddress empty = NetworkAddress();
133  return *this == empty;
134 }
135 
137 {
138  return std::memcmp(&inet_addr_, &rhs.inet_addr_, sizeof (inet_addr_)) == 0;
139 }
140 
142 {
143  return std::memcmp(&inet_addr_, &rhs.inet_addr_, sizeof (inet_addr_)) != 0;
144 }
145 
147 {
148  return std::memcmp(&inet_addr_, &rhs.inet_addr_, sizeof (inet_addr_)) < 0;
149 }
150 
151 #if defined ACE_HAS_CPP11
152 size_t NetworkAddress::hash(size_t start_hash) const {
153  return static_cast<size_t>(OpenDDS::DCPS::one_at_a_time_hash(reinterpret_cast<const uint8_t*>(&inet_addr_), sizeof(inet_addr_), static_cast<uint32_t>(start_hash)));
154 }
155 #endif
156 
158 {
159  if (inet_addr_.in4_.sin_family == AF_INET && rhs.inet_addr_.in4_.sin_family == AF_INET) {
160  return std::memcmp(&inet_addr_.in4_.sin_addr, &rhs.inet_addr_.in4_.sin_addr, sizeof (inet_addr_.in4_.sin_addr)) == 0;
161 #if defined (ACE_HAS_IPV6)
162  } else if (inet_addr_.in6_.sin6_family == AF_INET6 && rhs.inet_addr_.in6_.sin6_family == AF_INET6) {
163  return std::memcmp(&inet_addr_.in6_.sin6_addr, &rhs.inet_addr_.in6_.sin6_addr, sizeof (inet_addr_.in6_.sin6_addr)) == 0;
164 #endif
165  }
166  // Don't worry about ipv4 mapped / compatible ipv6 addresses for now
167  return false;
168 }
169 
171 {
172  ACE_INET_Addr result;
173  result.set_addr(const_cast<ip46*>(&inet_addr_), sizeof (inet_addr_));
174  return result;
175 }
176 
178 {
179  addr.set_addr(const_cast<ip46*>(&inet_addr_), sizeof (inet_addr_));
180 }
181 
182 ACE_INT16 NetworkAddress::get_type() const
183 {
184  return static_cast<ACE_INT16>(inet_addr_.in4_.sin_family);
185 }
186 
187 void NetworkAddress::set_type(ACE_INT16 type)
188 {
189  inet_addr_.in4_.sin_family = type;
190 }
191 
193 {
194  if (inet_addr_.in4_.sin_family == AF_INET) {
195  return ACE_NTOHS(inet_addr_.in4_.sin_port);
196 #if defined (ACE_HAS_IPV6)
197  } else if (inet_addr_.in6_.sin6_family == AF_INET6) {
198  return ACE_NTOHS(inet_addr_.in6_.sin6_port);
199 #endif
200  }
201  return 0;
202 }
203 
204 void NetworkAddress::set_port_number(ACE_UINT16 port)
205 {
206  if (inet_addr_.in4_.sin_family == AF_INET) {
207  inet_addr_.in4_.sin_port = ACE_HTONS(port);
208 #if defined (ACE_HAS_IPV6)
209  } else if (inet_addr_.in6_.sin6_family == AF_INET6) {
210  inet_addr_.in6_.sin6_port = ACE_HTONS(port);
211 #endif
212  }
213 }
214 
216 {
217  if (inet_addr_.in4_.sin_family == AF_INET) {
218  return inet_addr_.in4_.sin_addr.s_addr == INADDR_ANY;
219 #if defined (ACE_HAS_IPV6)
220  } else if (inet_addr_.in6_.sin6_family == AF_INET6) {
221  if (IN6_IS_ADDR_UNSPECIFIED(&inet_addr_.in6_.sin6_addr)) {
222  return true;
223  }
224  static const unsigned char buff[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 };
225  return memcmp(buff, &inet_addr_.in6_.sin6_addr, sizeof (buff)) == 0;
226 #endif
227  }
228  return false;
229 }
230 
232 {
233  if (inet_addr_.in4_.sin_family == AF_INET) {
234  // RFC 3330 defines loopback as any address with 127.x.x.x
235  return (ACE_HTONL(inet_addr_.in4_.sin_addr.s_addr) & 0xFF000000) == 0x7F000000;
236 #if defined (ACE_HAS_IPV6)
237  } else if (inet_addr_.in6_.sin6_family == AF_INET6) {
238  return IN6_IS_ADDR_LOOPBACK(&inet_addr_.in6_.sin6_addr);
239 #endif
240  }
241  return false;
242 }
243 
245 {
246  if (inet_addr_.in4_.sin_family == AF_INET) {
247  return (ACE_HTONL(inet_addr_.in4_.sin_addr.s_addr) & 0xF0000000) == 0xE0000000;
248 #if defined (ACE_HAS_IPV6)
249  } else if (inet_addr_.in6_.sin6_family == AF_INET6) {
250  return this->inet_addr_.in6_.sin6_addr.s6_addr[0] == 0xFF;
251 #endif
252  }
253  return false;
254 }
255 
257 {
258  if (inet_addr_.in4_.sin_family == AF_INET) {
259  // private address classes are 10.x.x.x/8, 172.16.x.x/16, 192.168.x.x/24
260  return ((ACE_HTONL(inet_addr_.in4_.sin_addr.s_addr) & 0xFF000000) == 0x0A000000 ||
261  (ACE_HTONL(inet_addr_.in4_.sin_addr.s_addr) & 0xFFF00000) == 0xAC100000 ||
262  (ACE_HTONL(inet_addr_.in4_.sin_addr.s_addr) & 0xFFFF0000) == 0xC0A80000);
263  }
264  return false;
265 }
266 
268 {
269 #if defined (ACE_HAS_IPV6)
270  if (inet_addr_.in6_.sin6_family == AF_INET6) {
271  return (inet_addr_.in6_.sin6_addr.s6_addr[0] & 0xFE) == 0xFC;
272  }
273 #endif
274  return false;
275 }
276 
278 {
279 #if defined (ACE_HAS_IPV6)
280  if (inet_addr_.in6_.sin6_family == AF_INET6) {
281  return IN6_IS_ADDR_LINKLOCAL(&inet_addr_.in6_.sin6_addr);
282  }
283 #endif
284  return false;
285 }
286 
288 {
289 #if defined (ACE_HAS_IPV6)
290  if (inet_addr_.in6_.sin6_family == AF_INET6) {
291  return IN6_IS_ADDR_SITELOCAL(&inet_addr_.in6_.sin6_addr);
292  }
293 #endif
294  return false;
295 }
296 
297 bool is_more_local(const NetworkAddress& current, const NetworkAddress& incoming)
298 {
299  // The question to answer here: "Is the incoming address 'more local' than the current address?"
300 
301  if (!current) {
302  return true;
303  }
304 
305 #ifdef ACE_HAS_IPV6
306  if (current.get_type() == AF_INET) {
307  if (incoming.get_type() == AF_INET6) {
308  return true;
309  }
310 #endif /* ACE_HAS_IPV6 */
311  if (current.is_loopback()) {
312  return false;
313  } else if (incoming.is_loopback()) {
314  return true;
315  }
316 
317  if (current.is_private()) {
318  return false;
319  } else if (incoming.is_private()) {
320  return true;
321  }
322 #ifdef ACE_HAS_IPV6
323  } else if (current.get_type() == AF_INET6) {
324  if (incoming.get_type() == AF_INET) {
325  return false;
326  }
327 
328  if (current.is_loopback()) {
329  return false;
330  } else if (incoming.is_loopback()) {
331  return true;
332  }
333 
334  if (current.is_linklocal()) {
335  return false;
336  } else if (incoming.is_linklocal()) {
337  return true;
338  }
339 
340  if (current.is_uniquelocal()) {
341  return false;
342  } else if (incoming.is_uniquelocal()) {
343  return true;
344  }
345 
346  if (current.is_sitelocal()) {
347  return false;
348  } else if (incoming.is_sitelocal()) {
349  return true;
350  }
351  }
352 #endif /* ACE_HAS_IPV6 */
353  return false;
354 }
355 
356 #if defined ACE_HAS_CPP11
357 size_t calculate_hash(const AddrSet& addrs, size_t start_hash)
358 {
359  size_t result = start_hash;
360  for (AddrSet::const_iterator it = addrs.begin(), limit = addrs.end(); it != limit; ++it) {
361  result = it->hash(result);
362  }
363  return result;
364 }
365 #endif
366 
367 } // namespace DCPS
368 } // namespace OpenDDS
369 
#define ACE_HTONL(X)
ACE_INET_Addr to_addr() const
int hash(const std::vector< const DDS::OctetSeq *> &src, DDS::OctetSeq &dst)
bool addr_bytes_equal(const NetworkAddress &rhs) const
int ipv6_enabled(void)
bool operator==(const NetworkAddress &rhs) const
bool operator!=(const NetworkAddress &rhs) const
#define ACE_HTONS(x)
bool is_more_local(const NetworkAddress &current, const NetworkAddress &incoming)
NetworkAddress & operator=(const NetworkAddress &rhs)
bool operator<(const NetworkAddress &rhs) const
void set_type(ACE_INT16 type)
ACE_UINT16 get_port_number() const
virtual void * get_addr(void) const
#define AF_INET
int memcmp(const void *t, const void *s, size_t len)
virtual void set_addr(const void *, int len)
void set_port_number(ACE_UINT16 port)
#define OPENDDS_END_VERSIONED_NAMESPACE_DECL
#define ACE_NTOHS(x)
The Internal API and Implementation of OpenDDS.
Definition: AddressCache.h:28
#define INADDR_ANY
union OpenDDS::DCPS::NetworkAddress::ip46 inet_addr_