1 | // |
2 | // IPAddress.cpp |
3 | // |
4 | // Library: Net |
5 | // Package: NetCore |
6 | // Module: IPAddress |
7 | // |
8 | // Copyright (c) 2005-2011, Applied Informatics Software Engineering GmbH. |
9 | // and Contributors. |
10 | // |
11 | // SPDX-License-Identifier: BSL-1.0 |
12 | // |
13 | |
14 | |
15 | #include "Poco/Net/IPAddress.h" |
16 | #include "Poco/Net/NetException.h" |
17 | #include "Poco/RefCountedObject.h" |
18 | #include "Poco/NumberFormatter.h" |
19 | #include "Poco/BinaryReader.h" |
20 | #include "Poco/BinaryWriter.h" |
21 | #include "Poco/String.h" |
22 | #include "Poco/Types.h" |
23 | |
24 | |
25 | using Poco::RefCountedObject; |
26 | using Poco::NumberFormatter; |
27 | using Poco::BinaryReader; |
28 | using Poco::BinaryWriter; |
29 | using Poco::toLower; |
30 | using Poco::trim; |
31 | using Poco::UInt8; |
32 | using Poco::UInt16; |
33 | using Poco::UInt32; |
34 | using Poco::Net::Impl::IPAddressImpl; |
35 | using Poco::Net::Impl::IPv4AddressImpl; |
36 | #if defined(POCO_HAVE_IPv6) |
37 | using Poco::Net::Impl::IPv6AddressImpl; |
38 | #endif |
39 | |
40 | |
41 | namespace Poco { |
42 | namespace Net { |
43 | |
44 | |
45 | #if !defined(_MSC_VER) || defined(__STDC__) |
46 | // Go home MSVC, you're drunk... |
47 | // See http://stackoverflow.com/questions/5899857/multiple-definition-error-for-static-const-class-members |
48 | const IPAddress::Family IPAddress::IPv4; |
49 | #if defined(POCO_HAVE_IPv6) |
50 | const IPAddress::Family IPAddress::IPv6; |
51 | #endif |
52 | #endif |
53 | |
54 | |
55 | IPAddress::IPAddress() |
56 | { |
57 | newIPv4(); |
58 | } |
59 | |
60 | |
61 | IPAddress::IPAddress(const IPAddress& addr) |
62 | { |
63 | if (addr.family() == IPv4) |
64 | newIPv4(addr.addr()); |
65 | #if defined(POCO_HAVE_IPv6) |
66 | else |
67 | newIPv6(addr.addr(), addr.scope()); |
68 | #endif |
69 | } |
70 | |
71 | |
72 | IPAddress::IPAddress(Family family) |
73 | { |
74 | if (family == IPv4) |
75 | newIPv4(); |
76 | #if defined(POCO_HAVE_IPv6) |
77 | else if (family == IPv6) |
78 | newIPv6(); |
79 | #endif |
80 | else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()" ); |
81 | } |
82 | |
83 | |
84 | IPAddress::IPAddress(const std::string& addr) |
85 | { |
86 | IPv4AddressImpl empty4 = IPv4AddressImpl(); |
87 | if (addr.empty() || trim(addr) == "0.0.0.0" ) |
88 | { |
89 | newIPv4(empty4.addr()); |
90 | return; |
91 | } |
92 | |
93 | IPv4AddressImpl addr4(IPv4AddressImpl::parse(addr)); |
94 | if (addr4 != empty4) |
95 | { |
96 | newIPv4(addr4.addr()); |
97 | return; |
98 | } |
99 | |
100 | #if defined(POCO_HAVE_IPv6) |
101 | IPv6AddressImpl empty6 = IPv6AddressImpl(); |
102 | if (addr.empty() || trim(addr) == "::" ) |
103 | { |
104 | newIPv6(empty6.addr()); |
105 | return; |
106 | } |
107 | |
108 | IPv6AddressImpl addr6(IPv6AddressImpl::parse(addr)); |
109 | if (addr6 != IPv6AddressImpl()) |
110 | { |
111 | newIPv6(addr6.addr(), addr6.scope()); |
112 | return; |
113 | } |
114 | #endif |
115 | |
116 | throw InvalidAddressException(addr); |
117 | } |
118 | |
119 | |
120 | IPAddress::IPAddress(const std::string& addr, Family family) |
121 | { |
122 | if (family == IPv4) |
123 | { |
124 | IPv4AddressImpl addr4(IPv4AddressImpl::parse(addr)); |
125 | newIPv4(addr4.addr()); |
126 | return; |
127 | } |
128 | #if defined(POCO_HAVE_IPv6) |
129 | else if (family == IPv6) |
130 | { |
131 | IPv6AddressImpl addr6(IPv6AddressImpl::parse(addr)); |
132 | newIPv6(addr6.addr(), addr6.scope()); |
133 | return; |
134 | } |
135 | #endif |
136 | else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()" ); |
137 | } |
138 | |
139 | |
140 | IPAddress::IPAddress(const void* addr, poco_socklen_t length) |
141 | { |
142 | if (length == sizeof(struct in_addr)) |
143 | newIPv4(addr); |
144 | #if defined(POCO_HAVE_IPv6) |
145 | else if (length == sizeof(struct in6_addr)) |
146 | newIPv6(addr); |
147 | #endif |
148 | else throw Poco::InvalidArgumentException("Invalid address length passed to IPAddress()" ); |
149 | } |
150 | |
151 | |
152 | IPAddress::IPAddress(const void* addr, poco_socklen_t length, Poco::UInt32 scope) |
153 | { |
154 | if (length == sizeof(struct in_addr)) |
155 | newIPv4(addr); |
156 | #if defined(POCO_HAVE_IPv6) |
157 | else if (length == sizeof(struct in6_addr)) |
158 | newIPv6(addr, scope); |
159 | #endif |
160 | else throw Poco::InvalidArgumentException("Invalid address length passed to IPAddress()" ); |
161 | } |
162 | |
163 | |
164 | IPAddress::IPAddress(unsigned prefix, Family family) |
165 | { |
166 | if (family == IPv4) |
167 | { |
168 | if (prefix <= 32) |
169 | newIPv4(prefix); |
170 | else |
171 | throw Poco::InvalidArgumentException("Invalid prefix length passed to IPAddress()" ); |
172 | } |
173 | #if defined(POCO_HAVE_IPv6) |
174 | else if (family == IPv6) |
175 | { |
176 | if (prefix <= 128) |
177 | newIPv6(prefix); |
178 | else |
179 | throw Poco::InvalidArgumentException("Invalid prefix length passed to IPAddress()" ); |
180 | } |
181 | #endif |
182 | else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()" ); |
183 | } |
184 | |
185 | |
186 | #if defined(_WIN32) |
187 | IPAddress::IPAddress(const SOCKET_ADDRESS& socket_address) |
188 | { |
189 | ADDRESS_FAMILY family = socket_address.lpSockaddr->sa_family; |
190 | if (family == AF_INET) |
191 | newIPv4(&reinterpret_cast<const struct sockaddr_in*>(socket_address.lpSockaddr)->sin_addr); |
192 | #if defined(POCO_HAVE_IPv6) |
193 | else if (family == AF_INET6) |
194 | newIPv6(&reinterpret_cast<const struct sockaddr_in6*>(socket_address.lpSockaddr)->sin6_addr, |
195 | reinterpret_cast<const struct sockaddr_in6*>(socket_address.lpSockaddr)->sin6_scope_id); |
196 | #endif |
197 | else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()" ); |
198 | } |
199 | #endif |
200 | |
201 | |
202 | IPAddress::IPAddress(const struct sockaddr& sockaddr) |
203 | { |
204 | unsigned short family = sockaddr.sa_family; |
205 | if (family == AF_INET) |
206 | newIPv4(&reinterpret_cast<const struct sockaddr_in*>(&sockaddr)->sin_addr); |
207 | #if defined(POCO_HAVE_IPv6) |
208 | else if (family == AF_INET6) |
209 | newIPv6(&reinterpret_cast<const struct sockaddr_in6*>(&sockaddr)->sin6_addr, |
210 | reinterpret_cast<const struct sockaddr_in6*>(&sockaddr)->sin6_scope_id); |
211 | #endif |
212 | else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()" ); |
213 | } |
214 | |
215 | |
216 | IPAddress::~IPAddress() |
217 | { |
218 | destruct(); |
219 | } |
220 | |
221 | |
222 | void IPAddress::destruct() |
223 | { |
224 | pImpl()->~IPAddressImpl(); |
225 | } |
226 | |
227 | |
228 | void IPAddress::newIPv4() |
229 | { |
230 | new (storage()) Poco::Net::Impl::IPv4AddressImpl; |
231 | } |
232 | |
233 | |
234 | void IPAddress::newIPv4(const void* hostAddr) |
235 | { |
236 | new (storage()) Poco::Net::Impl::IPv4AddressImpl(hostAddr); |
237 | } |
238 | |
239 | |
240 | void IPAddress::newIPv4(unsigned prefix) |
241 | { |
242 | new (storage()) Poco::Net::Impl::IPv4AddressImpl(prefix); |
243 | } |
244 | |
245 | |
246 | #if defined(POCO_HAVE_IPv6) |
247 | |
248 | |
249 | void IPAddress::newIPv6() |
250 | { |
251 | new (storage()) Poco::Net::Impl::IPv6AddressImpl; |
252 | } |
253 | |
254 | |
255 | void IPAddress::newIPv6(const void* hostAddr) |
256 | { |
257 | new (storage()) Poco::Net::Impl::IPv6AddressImpl(hostAddr); |
258 | } |
259 | |
260 | |
261 | void IPAddress::newIPv6(const void* hostAddr, Poco::UInt32 scope) |
262 | { |
263 | new (storage()) Poco::Net::Impl::IPv6AddressImpl(hostAddr, scope); |
264 | } |
265 | |
266 | |
267 | void IPAddress::newIPv6(unsigned prefix) |
268 | { |
269 | new (storage()) Poco::Net::Impl::IPv6AddressImpl(prefix); |
270 | } |
271 | |
272 | |
273 | #endif // POCO_HAVE_IPv6 |
274 | |
275 | |
276 | IPAddress& IPAddress::operator = (const IPAddress& addr) |
277 | { |
278 | if (&addr != this) |
279 | { |
280 | destruct(); |
281 | if (addr.family() == IPAddress::IPv4) |
282 | newIPv4(addr.addr()); |
283 | #if defined(POCO_HAVE_IPv6) |
284 | else if (addr.family() == IPAddress::IPv6) |
285 | newIPv6(addr.addr(), addr.scope()); |
286 | #endif |
287 | else |
288 | throw Poco::InvalidArgumentException("Invalid or unsupported address family" ); |
289 | } |
290 | return *this; |
291 | } |
292 | |
293 | |
294 | IPAddress::Family IPAddress::family() const |
295 | { |
296 | return pImpl()->family(); |
297 | } |
298 | |
299 | |
300 | Poco::UInt32 IPAddress::scope() const |
301 | { |
302 | return pImpl()->scope(); |
303 | } |
304 | |
305 | |
306 | std::string IPAddress::toString() const |
307 | { |
308 | return pImpl()->toString(); |
309 | } |
310 | |
311 | |
312 | bool IPAddress::isWildcard() const |
313 | { |
314 | return pImpl()->isWildcard(); |
315 | } |
316 | |
317 | |
318 | bool IPAddress::isBroadcast() const |
319 | { |
320 | return pImpl()->isBroadcast(); |
321 | } |
322 | |
323 | |
324 | bool IPAddress::isLoopback() const |
325 | { |
326 | return pImpl()->isLoopback(); |
327 | } |
328 | |
329 | |
330 | bool IPAddress::isMulticast() const |
331 | { |
332 | return pImpl()->isMulticast(); |
333 | } |
334 | |
335 | |
336 | bool IPAddress::isUnicast() const |
337 | { |
338 | return !isWildcard() && !isBroadcast() && !isMulticast(); |
339 | } |
340 | |
341 | |
342 | bool IPAddress::isLinkLocal() const |
343 | { |
344 | return pImpl()->isLinkLocal(); |
345 | } |
346 | |
347 | |
348 | bool IPAddress::isSiteLocal() const |
349 | { |
350 | return pImpl()->isSiteLocal(); |
351 | } |
352 | |
353 | |
354 | bool IPAddress::isIPv4Compatible() const |
355 | { |
356 | return pImpl()->isIPv4Compatible(); |
357 | } |
358 | |
359 | |
360 | bool IPAddress::isIPv4Mapped() const |
361 | { |
362 | return pImpl()->isIPv4Mapped(); |
363 | } |
364 | |
365 | |
366 | bool IPAddress::isWellKnownMC() const |
367 | { |
368 | return pImpl()->isWellKnownMC(); |
369 | } |
370 | |
371 | |
372 | bool IPAddress::isNodeLocalMC() const |
373 | { |
374 | return pImpl()->isNodeLocalMC(); |
375 | } |
376 | |
377 | |
378 | bool IPAddress::isLinkLocalMC() const |
379 | { |
380 | return pImpl()->isLinkLocalMC(); |
381 | } |
382 | |
383 | |
384 | bool IPAddress::isSiteLocalMC() const |
385 | { |
386 | return pImpl()->isSiteLocalMC(); |
387 | } |
388 | |
389 | |
390 | bool IPAddress::isOrgLocalMC() const |
391 | { |
392 | return pImpl()->isOrgLocalMC(); |
393 | } |
394 | |
395 | |
396 | bool IPAddress::isGlobalMC() const |
397 | { |
398 | return pImpl()->isGlobalMC(); |
399 | } |
400 | |
401 | |
402 | bool IPAddress::operator == (const IPAddress& a) const |
403 | { |
404 | poco_socklen_t l1 = length(); |
405 | poco_socklen_t l2 = a.length(); |
406 | if (l1 == l2) |
407 | { |
408 | #if defined(POCO_HAVE_IPv6) |
409 | if (scope() != a.scope()) return false; |
410 | #endif |
411 | return std::memcmp(addr(), a.addr(), l1) == 0; |
412 | } |
413 | else return false; |
414 | } |
415 | |
416 | |
417 | bool IPAddress::operator != (const IPAddress& a) const |
418 | { |
419 | return !(*this == a); |
420 | } |
421 | |
422 | |
423 | bool IPAddress::operator < (const IPAddress& a) const |
424 | { |
425 | poco_socklen_t l1 = length(); |
426 | poco_socklen_t l2 = a.length(); |
427 | if (l1 == l2) |
428 | { |
429 | #if defined(POCO_HAVE_IPv6) |
430 | if (scope() != a.scope()) |
431 | return scope() < a.scope(); |
432 | #endif |
433 | return std::memcmp(addr(), a.addr(), l1) < 0; |
434 | } |
435 | else return l1 < l2; |
436 | } |
437 | |
438 | |
439 | bool IPAddress::operator <= (const IPAddress& a) const |
440 | { |
441 | return !(a < *this); |
442 | } |
443 | |
444 | |
445 | bool IPAddress::operator > (const IPAddress& a) const |
446 | { |
447 | return a < *this; |
448 | } |
449 | |
450 | |
451 | bool IPAddress::operator >= (const IPAddress& a) const |
452 | { |
453 | return !(*this < a); |
454 | } |
455 | |
456 | |
457 | IPAddress IPAddress::operator & (const IPAddress& other) const |
458 | { |
459 | if (family() == other.family()) |
460 | { |
461 | if (family() == IPv4) |
462 | { |
463 | IPv4AddressImpl t(pImpl()->addr()); |
464 | IPv4AddressImpl o(other.pImpl()->addr()); |
465 | return IPAddress((t & o).addr(), sizeof(struct in_addr)); |
466 | } |
467 | #if defined(POCO_HAVE_IPv6) |
468 | else if (family() == IPv6) |
469 | { |
470 | const IPv6AddressImpl t(pImpl()->addr(), pImpl()->scope()); |
471 | const IPv6AddressImpl o(other.pImpl()->addr(), other.pImpl()->scope()); |
472 | const IPv6AddressImpl r = t & o; |
473 | return IPAddress(r.addr(), sizeof(struct in6_addr), r.scope()); |
474 | } |
475 | #endif |
476 | else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()" ); |
477 | } |
478 | else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()" ); |
479 | } |
480 | |
481 | |
482 | IPAddress IPAddress::operator | (const IPAddress& other) const |
483 | { |
484 | if (family() == other.family()) |
485 | { |
486 | if (family() == IPv4) |
487 | { |
488 | IPv4AddressImpl t(pImpl()->addr()); |
489 | IPv4AddressImpl o(other.pImpl()->addr()); |
490 | return IPAddress((t | o).addr(), sizeof(struct in_addr)); |
491 | } |
492 | #if defined(POCO_HAVE_IPv6) |
493 | else if (family() == IPv6) |
494 | { |
495 | const IPv6AddressImpl t(pImpl()->addr(), pImpl()->scope()); |
496 | const IPv6AddressImpl o(other.pImpl()->addr(), other.pImpl()->scope()); |
497 | const IPv6AddressImpl r = t | o; |
498 | return IPAddress(r.addr(), sizeof(struct in6_addr), r.scope()); |
499 | } |
500 | #endif |
501 | else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()" ); |
502 | } |
503 | else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()" ); |
504 | } |
505 | |
506 | |
507 | IPAddress IPAddress::operator ^ (const IPAddress& other) const |
508 | { |
509 | if (family() == other.family()) |
510 | { |
511 | if (family() == IPv4) |
512 | { |
513 | IPv4AddressImpl t(pImpl()->addr()); |
514 | IPv4AddressImpl o(other.pImpl()->addr()); |
515 | return IPAddress((t ^ o).addr(), sizeof(struct in_addr)); |
516 | } |
517 | #if defined(POCO_HAVE_IPv6) |
518 | else if (family() == IPv6) |
519 | { |
520 | const IPv6AddressImpl t(pImpl()->addr(), pImpl()->scope()); |
521 | const IPv6AddressImpl o(other.pImpl()->addr(), other.pImpl()->scope()); |
522 | const IPv6AddressImpl r = t ^ o; |
523 | return IPAddress(r.addr(), sizeof(struct in6_addr), r.scope()); |
524 | } |
525 | #endif |
526 | else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()" ); |
527 | } |
528 | else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()" ); |
529 | } |
530 | |
531 | |
532 | IPAddress IPAddress::operator ~ () const |
533 | { |
534 | if (family() == IPv4) |
535 | { |
536 | IPv4AddressImpl self(this->pImpl()->addr()); |
537 | return IPAddress((~self).addr(), sizeof(struct in_addr)); |
538 | } |
539 | #if defined(POCO_HAVE_IPv6) |
540 | else if (family() == IPv6) |
541 | { |
542 | const IPv6AddressImpl self(pImpl()->addr(), pImpl()->scope()); |
543 | const IPv6AddressImpl r = ~self; |
544 | return IPAddress(r.addr(), sizeof(struct in6_addr), r.scope()); |
545 | } |
546 | #endif |
547 | else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()" ); |
548 | } |
549 | |
550 | |
551 | poco_socklen_t IPAddress::length() const |
552 | { |
553 | return pImpl()->length(); |
554 | } |
555 | |
556 | |
557 | const void* IPAddress::addr() const |
558 | { |
559 | return pImpl()->addr(); |
560 | } |
561 | |
562 | |
563 | int IPAddress::af() const |
564 | { |
565 | return pImpl()->af(); |
566 | } |
567 | |
568 | |
569 | unsigned IPAddress::prefixLength() const |
570 | { |
571 | return pImpl()->prefixLength(); |
572 | } |
573 | |
574 | |
575 | IPAddress IPAddress::parse(const std::string& addr) |
576 | { |
577 | return IPAddress(addr); |
578 | } |
579 | |
580 | |
581 | bool IPAddress::tryParse(const std::string& addr, IPAddress& result) |
582 | { |
583 | IPv4AddressImpl impl4(IPv4AddressImpl::parse(addr)); |
584 | if (impl4 != IPv4AddressImpl() || trim(addr) == "0.0.0.0" ) |
585 | { |
586 | result.newIPv4(impl4.addr()); |
587 | return true; |
588 | } |
589 | #if defined(POCO_HAVE_IPv6) |
590 | IPv6AddressImpl impl6(IPv6AddressImpl::parse(addr)); |
591 | if (impl6 != IPv6AddressImpl()) |
592 | { |
593 | result.newIPv6(impl6.addr(), impl6.scope()); |
594 | return true; |
595 | } |
596 | #endif |
597 | return false; |
598 | } |
599 | |
600 | |
601 | void IPAddress::mask(const IPAddress& mask) |
602 | { |
603 | IPAddress null; |
604 | pImpl()->mask(mask.pImpl(), null.pImpl()); |
605 | } |
606 | |
607 | |
608 | void IPAddress::mask(const IPAddress& mask, const IPAddress& set) |
609 | { |
610 | pImpl()->mask(mask.pImpl(), set.pImpl()); |
611 | } |
612 | |
613 | |
614 | IPAddress IPAddress::wildcard(Family family) |
615 | { |
616 | return IPAddress(family); |
617 | } |
618 | |
619 | |
620 | IPAddress IPAddress::broadcast() |
621 | { |
622 | struct in_addr ia; |
623 | ia.s_addr = INADDR_NONE; |
624 | return IPAddress(&ia, sizeof(ia)); |
625 | } |
626 | |
627 | |
628 | } } // namespace Poco::Net |
629 | |
630 | |
631 | Poco::BinaryWriter& operator << (Poco::BinaryWriter& writer, const Poco::Net::IPAddress& value) |
632 | { |
633 | writer << static_cast<Poco::UInt8>(value.length()); |
634 | writer.writeRaw(reinterpret_cast<const char*>(value.addr()), value.length()); |
635 | return writer; |
636 | } |
637 | |
638 | |
639 | Poco::BinaryReader& operator >> (Poco::BinaryReader& reader, Poco::Net::IPAddress& value) |
640 | { |
641 | char buf[Poco::Net::IPAddress::MAX_ADDRESS_LENGTH]; |
642 | Poco::UInt8 length; |
643 | reader >> length; |
644 | reader.readRaw(buf, length); |
645 | value = Poco::Net::IPAddress(buf, length); |
646 | return reader; |
647 | } |
648 | |
649 | |
650 | std::ostream& operator << (std::ostream& ostr, const Poco::Net::IPAddress& addr) |
651 | { |
652 | ostr << addr.toString(); |
653 | return ostr; |
654 | } |
655 | |
656 | |