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
25using Poco::RefCountedObject;
26using Poco::NumberFormatter;
27using Poco::BinaryReader;
28using Poco::BinaryWriter;
29using Poco::toLower;
30using Poco::trim;
31using Poco::UInt8;
32using Poco::UInt16;
33using Poco::UInt32;
34using Poco::Net::Impl::IPAddressImpl;
35using Poco::Net::Impl::IPv4AddressImpl;
36#if defined(POCO_HAVE_IPv6)
37using Poco::Net::Impl::IPv6AddressImpl;
38#endif
39
40
41namespace Poco {
42namespace 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
48const IPAddress::Family IPAddress::IPv4;
49#if defined(POCO_HAVE_IPv6)
50const IPAddress::Family IPAddress::IPv6;
51#endif
52#endif
53
54
55IPAddress::IPAddress()
56{
57 newIPv4();
58}
59
60
61IPAddress::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
72IPAddress::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
84IPAddress::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
120IPAddress::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
140IPAddress::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
152IPAddress::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
164IPAddress::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)
187IPAddress::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
202IPAddress::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
216IPAddress::~IPAddress()
217{
218 destruct();
219}
220
221
222void IPAddress::destruct()
223{
224 pImpl()->~IPAddressImpl();
225}
226
227
228void IPAddress::newIPv4()
229{
230 new (storage()) Poco::Net::Impl::IPv4AddressImpl;
231}
232
233
234void IPAddress::newIPv4(const void* hostAddr)
235{
236 new (storage()) Poco::Net::Impl::IPv4AddressImpl(hostAddr);
237}
238
239
240void IPAddress::newIPv4(unsigned prefix)
241{
242 new (storage()) Poco::Net::Impl::IPv4AddressImpl(prefix);
243}
244
245
246#if defined(POCO_HAVE_IPv6)
247
248
249void IPAddress::newIPv6()
250{
251 new (storage()) Poco::Net::Impl::IPv6AddressImpl;
252}
253
254
255void IPAddress::newIPv6(const void* hostAddr)
256{
257 new (storage()) Poco::Net::Impl::IPv6AddressImpl(hostAddr);
258}
259
260
261void IPAddress::newIPv6(const void* hostAddr, Poco::UInt32 scope)
262{
263 new (storage()) Poco::Net::Impl::IPv6AddressImpl(hostAddr, scope);
264}
265
266
267void IPAddress::newIPv6(unsigned prefix)
268{
269 new (storage()) Poco::Net::Impl::IPv6AddressImpl(prefix);
270}
271
272
273#endif // POCO_HAVE_IPv6
274
275
276IPAddress& 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
294IPAddress::Family IPAddress::family() const
295{
296 return pImpl()->family();
297}
298
299
300Poco::UInt32 IPAddress::scope() const
301{
302 return pImpl()->scope();
303}
304
305
306std::string IPAddress::toString() const
307{
308 return pImpl()->toString();
309}
310
311
312bool IPAddress::isWildcard() const
313{
314 return pImpl()->isWildcard();
315}
316
317
318bool IPAddress::isBroadcast() const
319{
320 return pImpl()->isBroadcast();
321}
322
323
324bool IPAddress::isLoopback() const
325{
326 return pImpl()->isLoopback();
327}
328
329
330bool IPAddress::isMulticast() const
331{
332 return pImpl()->isMulticast();
333}
334
335
336bool IPAddress::isUnicast() const
337{
338 return !isWildcard() && !isBroadcast() && !isMulticast();
339}
340
341
342bool IPAddress::isLinkLocal() const
343{
344 return pImpl()->isLinkLocal();
345}
346
347
348bool IPAddress::isSiteLocal() const
349{
350 return pImpl()->isSiteLocal();
351}
352
353
354bool IPAddress::isIPv4Compatible() const
355{
356 return pImpl()->isIPv4Compatible();
357}
358
359
360bool IPAddress::isIPv4Mapped() const
361{
362 return pImpl()->isIPv4Mapped();
363}
364
365
366bool IPAddress::isWellKnownMC() const
367{
368 return pImpl()->isWellKnownMC();
369}
370
371
372bool IPAddress::isNodeLocalMC() const
373{
374 return pImpl()->isNodeLocalMC();
375}
376
377
378bool IPAddress::isLinkLocalMC() const
379{
380 return pImpl()->isLinkLocalMC();
381}
382
383
384bool IPAddress::isSiteLocalMC() const
385{
386 return pImpl()->isSiteLocalMC();
387}
388
389
390bool IPAddress::isOrgLocalMC() const
391{
392 return pImpl()->isOrgLocalMC();
393}
394
395
396bool IPAddress::isGlobalMC() const
397{
398 return pImpl()->isGlobalMC();
399}
400
401
402bool 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
417bool IPAddress::operator != (const IPAddress& a) const
418{
419 return !(*this == a);
420}
421
422
423bool 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
439bool IPAddress::operator <= (const IPAddress& a) const
440{
441 return !(a < *this);
442}
443
444
445bool IPAddress::operator > (const IPAddress& a) const
446{
447 return a < *this;
448}
449
450
451bool IPAddress::operator >= (const IPAddress& a) const
452{
453 return !(*this < a);
454}
455
456
457IPAddress 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
482IPAddress 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
507IPAddress 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
532IPAddress 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
551poco_socklen_t IPAddress::length() const
552{
553 return pImpl()->length();
554}
555
556
557const void* IPAddress::addr() const
558{
559 return pImpl()->addr();
560}
561
562
563int IPAddress::af() const
564{
565 return pImpl()->af();
566}
567
568
569unsigned IPAddress::prefixLength() const
570{
571 return pImpl()->prefixLength();
572}
573
574
575IPAddress IPAddress::parse(const std::string& addr)
576{
577 return IPAddress(addr);
578}
579
580
581bool 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
601void IPAddress::mask(const IPAddress& mask)
602{
603 IPAddress null;
604 pImpl()->mask(mask.pImpl(), null.pImpl());
605}
606
607
608void IPAddress::mask(const IPAddress& mask, const IPAddress& set)
609{
610 pImpl()->mask(mask.pImpl(), set.pImpl());
611}
612
613
614IPAddress IPAddress::wildcard(Family family)
615{
616 return IPAddress(family);
617}
618
619
620IPAddress 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
631Poco::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
639Poco::BinaryReader& operator >> (Poco::BinaryReader& reader, Poco::Net::IPAddress& value)
640{
641 char buf[sizeof(struct in6_addr)];
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
650std::ostream& operator << (std::ostream& ostr, const Poco::Net::IPAddress& addr)
651{
652 ostr << addr.toString();
653 return ostr;
654}
655
656