Line data Source code
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 :
15 : OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL
16 :
17 : namespace OpenDDS {
18 : namespace DCPS {
19 :
20 7 : NetworkAddress::NetworkAddress()
21 : {
22 : // We want to take care here to make sure that our NetworkAddress can be used with std::memcmp
23 7 : 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 7 : 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 7 : }
54 :
55 290 : NetworkAddress::NetworkAddress(const NetworkAddress& val)
56 : {
57 290 : *this = val;
58 290 : }
59 :
60 15 : NetworkAddress::NetworkAddress(const char* str)
61 : {
62 15 : *this = ACE_INET_Addr(str);
63 15 : }
64 :
65 42 : NetworkAddress::NetworkAddress(ACE_UINT16 port, const char* str)
66 : {
67 42 : *this = ACE_INET_Addr(port, str);
68 42 : }
69 :
70 : #if defined (ACE_HAS_WCHAR)
71 :
72 0 : NetworkAddress::NetworkAddress(const wchar_t* str)
73 : {
74 0 : *this = ACE_INET_Addr(str);
75 0 : }
76 :
77 0 : NetworkAddress::NetworkAddress(ACE_UINT16 port, const wchar_t* str)
78 : {
79 0 : *this = ACE_INET_Addr(port, str);
80 0 : }
81 :
82 : #endif
83 :
84 114 : NetworkAddress::NetworkAddress(const ACE_INET_Addr& addr)
85 : {
86 : // We want to take care here to make sure that our NetworkAddress can be used with std::memcmp
87 114 : std::memset(&inet_addr_, 0, sizeof (inet_addr_));
88 :
89 114 : const ip46& in = *reinterpret_cast<ip46*>(addr.get_addr());
90 114 : if (in.in4_.sin_family == AF_INET) {
91 114 : inet_addr_.in4_.sin_family = in.in4_.sin_family;
92 114 : 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 114 : 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 114 : }
110 :
111 347 : NetworkAddress& NetworkAddress::operator=(const NetworkAddress& rhs)
112 : {
113 347 : if (&rhs != this) {
114 347 : std::memcpy(&inet_addr_, &rhs.inet_addr_, sizeof (inet_addr_));
115 : }
116 347 : return *this;
117 : }
118 :
119 57 : NetworkAddress& NetworkAddress::operator=(const ACE_INET_Addr& rhs)
120 : {
121 57 : return *this = NetworkAddress(rhs);
122 : }
123 :
124 4 : NetworkAddress::operator bool() const
125 : {
126 4 : static const NetworkAddress empty = NetworkAddress();
127 4 : return *this != empty;
128 : }
129 :
130 44 : bool NetworkAddress::operator!() const
131 : {
132 44 : static const NetworkAddress empty = NetworkAddress();
133 44 : return *this == empty;
134 : }
135 :
136 70 : bool NetworkAddress::operator==(const NetworkAddress& rhs) const
137 : {
138 70 : return std::memcmp(&inet_addr_, &rhs.inet_addr_, sizeof (inet_addr_)) == 0;
139 : }
140 :
141 16 : bool NetworkAddress::operator!=(const NetworkAddress& rhs) const
142 : {
143 16 : return std::memcmp(&inet_addr_, &rhs.inet_addr_, sizeof (inet_addr_)) != 0;
144 : }
145 :
146 43 : bool NetworkAddress::operator<(const NetworkAddress& rhs) const
147 : {
148 43 : return std::memcmp(&inet_addr_, &rhs.inet_addr_, sizeof (inet_addr_)) < 0;
149 : }
150 :
151 : #if defined ACE_HAS_CPP11
152 9 : size_t NetworkAddress::hash(size_t start_hash) const {
153 9 : 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 :
157 4 : bool NetworkAddress::addr_bytes_equal(const NetworkAddress& rhs) const
158 : {
159 4 : if (inet_addr_.in4_.sin_family == AF_INET && rhs.inet_addr_.in4_.sin_family == AF_INET) {
160 4 : 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 0 : return false;
168 : }
169 :
170 6 : ACE_INET_Addr NetworkAddress::to_addr() const
171 : {
172 6 : ACE_INET_Addr result;
173 6 : result.set_addr(const_cast<ip46*>(&inet_addr_), sizeof (inet_addr_));
174 6 : return result;
175 0 : }
176 :
177 0 : void NetworkAddress::to_addr(ACE_INET_Addr& addr) const
178 : {
179 0 : addr.set_addr(const_cast<ip46*>(&inet_addr_), sizeof (inet_addr_));
180 0 : }
181 :
182 6 : ACE_INT16 NetworkAddress::get_type() const
183 : {
184 6 : return static_cast<ACE_INT16>(inet_addr_.in4_.sin_family);
185 : }
186 :
187 0 : void NetworkAddress::set_type(ACE_INT16 type)
188 : {
189 0 : inet_addr_.in4_.sin_family = type;
190 0 : }
191 :
192 7 : ACE_UINT16 NetworkAddress::get_port_number() const
193 : {
194 7 : if (inet_addr_.in4_.sin_family == AF_INET) {
195 7 : 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 0 : return 0;
202 : }
203 :
204 1 : void NetworkAddress::set_port_number(ACE_UINT16 port)
205 : {
206 1 : if (inet_addr_.in4_.sin_family == AF_INET) {
207 1 : 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 1 : }
214 :
215 3 : bool NetworkAddress::is_any() const
216 : {
217 3 : if (inet_addr_.in4_.sin_family == AF_INET) {
218 3 : 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 0 : return false;
229 : }
230 :
231 64 : bool NetworkAddress::is_loopback() const
232 : {
233 64 : if (inet_addr_.in4_.sin_family == AF_INET) {
234 : // RFC 3330 defines loopback as any address with 127.x.x.x
235 64 : 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 0 : return false;
242 : }
243 :
244 5 : bool NetworkAddress::is_multicast() const
245 : {
246 5 : if (inet_addr_.in4_.sin_family == AF_INET) {
247 5 : 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 0 : return false;
254 : }
255 :
256 40 : bool NetworkAddress::is_private() const
257 : {
258 40 : 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 72 : return ((ACE_HTONL(inet_addr_.in4_.sin_addr.s_addr) & 0xFF000000) == 0x0A000000 ||
261 70 : (ACE_HTONL(inet_addr_.in4_.sin_addr.s_addr) & 0xFFF00000) == 0xAC100000 ||
262 70 : (ACE_HTONL(inet_addr_.in4_.sin_addr.s_addr) & 0xFFFF0000) == 0xC0A80000);
263 : }
264 0 : return false;
265 : }
266 :
267 0 : bool NetworkAddress::is_uniquelocal() const
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 0 : return false;
275 : }
276 :
277 0 : bool NetworkAddress::is_linklocal() const
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 0 : return false;
285 : }
286 :
287 0 : bool NetworkAddress::is_sitelocal() const
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 0 : return false;
295 : }
296 :
297 36 : 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 36 : if (!current) {
302 0 : 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 36 : if (current.is_loopback()) {
312 12 : return false;
313 24 : } else if (incoming.is_loopback()) {
314 8 : return true;
315 : }
316 :
317 16 : if (current.is_private()) {
318 8 : return false;
319 8 : } else if (incoming.is_private()) {
320 4 : 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 4 : return false;
354 : }
355 :
356 : #if defined ACE_HAS_CPP11
357 9 : size_t calculate_hash(const AddrSet& addrs, size_t start_hash)
358 : {
359 9 : size_t result = start_hash;
360 18 : for (AddrSet::const_iterator it = addrs.begin(), limit = addrs.end(); it != limit; ++it) {
361 9 : result = it->hash(result);
362 : }
363 9 : return result;
364 : }
365 : #endif
366 :
367 : } // namespace DCPS
368 : } // namespace OpenDDS
369 :
370 : OPENDDS_END_VERSIONED_NAMESPACE_DECL
|