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/IPAddressImpl.h"
16#include "Poco/Net/NetException.h"
17#include "Poco/RefCountedObject.h"
18#include "Poco/NumberFormatter.h"
19#include "Poco/ByteOrder.h"
20#include "Poco/String.h"
21#include "Poco/Types.h"
22
23
24using Poco::RefCountedObject;
25using Poco::NumberFormatter;
26using Poco::toLower;
27using Poco::UInt8;
28using Poco::UInt16;
29using Poco::UInt32;
30
31
32namespace {
33
34
35template <typename T>
36unsigned maskBits(T val, unsigned size)
37 /// Returns the length of the mask (number of bits set in val).
38 /// The val should be either all zeros or two contiguos areas of 1s and 0s.
39 /// The algorithm ignores invalid non-contiguous series of 1s and treats val
40 /// as if all bits between MSb and last non-zero bit are set to 1.
41{
42 unsigned count = 0;
43 if (val)
44 {
45 val = (val ^ (val - 1)) >> 1;
46 for (count = 0; val; ++count) val >>= 1;
47 }
48 else count = size;
49 return size - count;
50}
51
52
53} // namespace
54
55
56namespace Poco {
57namespace Net {
58namespace Impl {
59
60
61//
62// IPAddressImpl
63//
64
65
66IPAddressImpl::IPAddressImpl()
67{
68}
69
70
71IPAddressImpl::~IPAddressImpl()
72{
73}
74
75
76//
77// IPv4AddressImpl
78//
79
80
81IPv4AddressImpl::IPv4AddressImpl()
82{
83 std::memset(&_addr, 0, sizeof(_addr));
84}
85
86
87IPv4AddressImpl::IPv4AddressImpl(const void* addr)
88{
89 std::memcpy(&_addr, addr, sizeof(_addr));
90}
91
92
93IPv4AddressImpl::IPv4AddressImpl(unsigned prefix)
94{
95 UInt32 addr = (prefix == 32) ? 0xffffffff : ~(0xffffffff >> prefix);
96 _addr.s_addr = ByteOrder::toNetwork(addr);
97}
98
99
100IPv4AddressImpl::IPv4AddressImpl(const IPv4AddressImpl& addr)
101{
102 std::memcpy(&_addr, &addr._addr, sizeof(_addr));
103}
104
105
106IPv4AddressImpl& IPv4AddressImpl::operator = (const IPv4AddressImpl& addr)
107{
108 if (this == &addr)
109 return *this;
110
111 std::memcpy(&_addr, &addr._addr, sizeof(_addr));
112 return *this;
113}
114
115
116std::string IPv4AddressImpl::toString() const
117{
118 const UInt8* bytes = reinterpret_cast<const UInt8*>(&_addr);
119 std::string result;
120 result.reserve(16);
121 NumberFormatter::append(result, bytes[0]);
122 result.append(".");
123 NumberFormatter::append(result, bytes[1]);
124 result.append(".");
125 NumberFormatter::append(result, bytes[2]);
126 result.append(".");
127 NumberFormatter::append(result, bytes[3]);
128 return result;
129}
130
131
132poco_socklen_t IPv4AddressImpl::length() const
133{
134 return sizeof(_addr);
135}
136
137
138const void* IPv4AddressImpl::addr() const
139{
140 return &_addr;
141}
142
143
144IPAddressImpl::Family IPv4AddressImpl::family() const
145{
146 return AddressFamily::IPv4;
147}
148
149
150int IPv4AddressImpl::af() const
151{
152 return AF_INET;
153}
154
155
156unsigned IPv4AddressImpl::prefixLength() const
157{
158 return maskBits(ntohl(_addr.s_addr), 32);
159}
160
161
162Poco::UInt32 IPv4AddressImpl::scope() const
163{
164 return 0;
165}
166
167
168bool IPv4AddressImpl::isWildcard() const
169{
170 return _addr.s_addr == INADDR_ANY;
171}
172
173
174bool IPv4AddressImpl::isBroadcast() const
175{
176 return _addr.s_addr == INADDR_NONE;
177}
178
179
180bool IPv4AddressImpl::isLoopback() const
181{
182 return (ntohl(_addr.s_addr) & 0xFF000000) == 0x7F000000; // 127.0.0.1 to 127.255.255.255
183}
184
185
186bool IPv4AddressImpl::isMulticast() const
187{
188 return (ntohl(_addr.s_addr) & 0xF0000000) == 0xE0000000; // 224.0.0.0/24 to 239.0.0.0/24
189}
190
191
192bool IPv4AddressImpl::isLinkLocal() const
193{
194 return (ntohl(_addr.s_addr) & 0xFFFF0000) == 0xA9FE0000; // 169.254.0.0/16
195}
196
197
198bool IPv4AddressImpl::isSiteLocal() const
199{
200 UInt32 addr = ntohl(_addr.s_addr);
201 return (addr & 0xFF000000) == 0x0A000000 || // 10.0.0.0/24
202 (addr & 0xFFFF0000) == 0xC0A80000 || // 192.68.0.0/16
203 (addr >= 0xAC100000 && addr <= 0xAC1FFFFF); // 172.16.0.0 to 172.31.255.255
204}
205
206
207bool IPv4AddressImpl::isIPv4Compatible() const
208{
209 return true;
210}
211
212
213bool IPv4AddressImpl::isIPv4Mapped() const
214{
215 return true;
216}
217
218
219bool IPv4AddressImpl::isWellKnownMC() const
220{
221 return (ntohl(_addr.s_addr) & 0xFFFFFF00) == 0xE0000000; // 224.0.0.0/8
222}
223
224
225bool IPv4AddressImpl::isNodeLocalMC() const
226{
227 return false;
228}
229
230
231bool IPv4AddressImpl::isLinkLocalMC() const
232{
233 return (ntohl(_addr.s_addr) & 0xFF000000) == 0xE0000000; // 244.0.0.0/24
234}
235
236
237bool IPv4AddressImpl::isSiteLocalMC() const
238{
239 return (ntohl(_addr.s_addr) & 0xFFFF0000) == 0xEFFF0000; // 239.255.0.0/16
240}
241
242
243bool IPv4AddressImpl::isOrgLocalMC() const
244{
245 return (ntohl(_addr.s_addr) & 0xFFFF0000) == 0xEFC00000; // 239.192.0.0/16
246}
247
248
249bool IPv4AddressImpl::isGlobalMC() const
250{
251 UInt32 addr = ntohl(_addr.s_addr);
252 return addr >= 0xE0000100 && addr <= 0xEE000000; // 224.0.1.0 to 238.255.255.255
253}
254
255
256IPv4AddressImpl IPv4AddressImpl::parse(const std::string& addr)
257{
258 if (addr.empty()) return IPv4AddressImpl();
259#if defined(_WIN32)
260 struct in_addr ia;
261 ia.s_addr = inet_addr(addr.c_str());
262 if (ia.s_addr == INADDR_NONE && addr != "255.255.255.255")
263 return IPv4AddressImpl();
264 else
265 return IPv4AddressImpl(&ia);
266#else
267#if __GNUC__ < 3 || defined(POCO_VXWORKS)
268 struct in_addr ia;
269 ia.s_addr = inet_addr(const_cast<char*>(addr.c_str()));
270 if (ia.s_addr == INADDR_NONE && addr != "255.255.255.255")
271 return IPv4AddressImpl();
272 else
273 return IPv4AddressImpl(&ia);
274#else
275 struct in_addr ia;
276 if (inet_aton(addr.c_str(), &ia))
277 return IPv4AddressImpl(&ia);
278 else
279 return IPv4AddressImpl();
280#endif
281#endif
282}
283
284
285void IPv4AddressImpl::mask(const IPAddressImpl* pMask, const IPAddressImpl* pSet)
286{
287 poco_assert (pMask->af() == AF_INET && pSet->af() == AF_INET);
288
289 _addr.s_addr &= static_cast<const IPv4AddressImpl*>(pMask)->_addr.s_addr;
290 _addr.s_addr |= static_cast<const IPv4AddressImpl*>(pSet)->_addr.s_addr & ~static_cast<const IPv4AddressImpl*>(pMask)->_addr.s_addr;
291}
292
293
294IPAddressImpl* IPv4AddressImpl::clone() const
295{
296 return new IPv4AddressImpl(&_addr);
297}
298
299
300IPv4AddressImpl IPv4AddressImpl::operator & (const IPv4AddressImpl& addr) const
301{
302 IPv4AddressImpl result(&_addr);
303 result._addr.s_addr &= addr._addr.s_addr;
304 return result;
305}
306
307
308IPv4AddressImpl IPv4AddressImpl::operator | (const IPv4AddressImpl& addr) const
309{
310 IPv4AddressImpl result(&_addr);
311 result._addr.s_addr |= addr._addr.s_addr;
312 return result;
313}
314
315
316IPv4AddressImpl IPv4AddressImpl::operator ^ (const IPv4AddressImpl& addr) const
317{
318 IPv4AddressImpl result(&_addr);
319 result._addr.s_addr ^= addr._addr.s_addr;
320 return result;
321}
322
323
324IPv4AddressImpl IPv4AddressImpl::operator ~ () const
325{
326IPv4AddressImpl result(&_addr);
327 result._addr.s_addr ^= 0xffffffff;
328 return result;
329}
330
331
332bool IPv4AddressImpl::operator == (const IPv4AddressImpl& addr) const
333{
334 return 0 == std::memcmp(&addr._addr, &_addr, sizeof(_addr));
335}
336
337
338bool IPv4AddressImpl::operator != (const IPv4AddressImpl& addr) const
339{
340 return !(*this == addr);
341}
342
343
344#if defined(POCO_HAVE_IPv6)
345
346
347//
348// IPv6AddressImpl
349//
350
351
352IPv6AddressImpl::IPv6AddressImpl(): _scope(0)
353{
354 std::memset(&_addr, 0, sizeof(_addr));
355}
356
357
358IPv6AddressImpl::IPv6AddressImpl(const void* addr): _scope(0)
359{
360 std::memcpy(&_addr, addr, sizeof(_addr));
361}
362
363
364IPv6AddressImpl::IPv6AddressImpl(const void* addr, Poco::UInt32 scope): _scope(scope)
365{
366 std::memcpy(&_addr, addr, sizeof(_addr));
367}
368
369
370IPv6AddressImpl::IPv6AddressImpl(const IPv6AddressImpl& addr): _scope(addr._scope)
371{
372 std::memcpy((void*) &_addr, (void*) &addr._addr, sizeof(_addr));
373}
374
375
376IPv6AddressImpl& IPv6AddressImpl::operator = (const IPv6AddressImpl& addr)
377{
378 if (this == &addr)
379 return *this;
380
381 _scope = addr._scope;
382 std::memcpy(&_addr, &addr._addr, sizeof(_addr));
383 return *this;
384}
385
386
387IPv6AddressImpl::IPv6AddressImpl(unsigned prefix):
388 _scope(0)
389{
390 unsigned i = 0;
391#ifdef POCO_OS_FAMILY_WINDOWS
392 for (; prefix >= 16; ++i, prefix -= 16)
393 {
394 _addr.s6_addr16[i] = 0xffff;
395 }
396 if (prefix > 0)
397 {
398 _addr.s6_addr16[i++] = ByteOrder::toNetwork(static_cast<Poco::UInt16>(~(0xffff >> prefix)));
399 }
400 while (i < 8)
401 {
402 _addr.s6_addr16[i++] = 0;
403 }
404#else
405 for (; prefix >= 32; ++i, prefix -= 32)
406 {
407 _addr.s6_addr32[i] = 0xffffffff;
408 }
409 if (prefix > 0)
410 {
411 _addr.s6_addr32[i++] = ByteOrder::toNetwork(~(0xffffffffU >> prefix));
412 }
413 while (i < 4)
414 {
415 _addr.s6_addr32[i++] = 0;
416 }
417#endif
418}
419
420
421std::string IPv6AddressImpl::toString() const
422{
423 const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
424 if ((isIPv4Compatible() && !isLoopback()) || isIPv4Mapped())
425 {
426 std::string result;
427 result.reserve(24);
428 if (words[5] == 0)
429 result.append("::");
430 else
431 result.append("::ffff:");
432 const UInt8* bytes = reinterpret_cast<const UInt8*>(&_addr);
433 if (bytes[12] != 0) // only 0.0.0.0 can start with zero
434 {
435 NumberFormatter::append(result, bytes[12]);
436 result.append(".");
437 NumberFormatter::append(result, bytes[13]);
438 result.append(".");
439 NumberFormatter::append(result, bytes[14]);
440 result.append(".");
441 NumberFormatter::append(result, bytes[15]);
442 }
443 return result;
444 }
445 else
446 {
447 std::string result;
448 result.reserve(64);
449 bool zeroSequence = false;
450 int i = 0;
451 while (i < 8)
452 {
453 if (!zeroSequence && words[i] == 0)
454 {
455 int zi = i;
456 while (zi < 8 && words[zi] == 0) ++zi;
457 if (zi > i + 1)
458 {
459 i = zi;
460 result.append(":");
461 zeroSequence = true;
462 }
463 }
464 if (i > 0) result.append(":");
465 if (i < 8) NumberFormatter::appendHex(result, ByteOrder::fromNetwork(words[i++]));
466 }
467 if (_scope > 0)
468 {
469 result.append("%");
470#if defined(_WIN32)
471 NumberFormatter::append(result, _scope);
472#else
473 char buffer[IFNAMSIZ];
474 if (if_indextoname(_scope, buffer))
475 {
476 result.append(buffer);
477 }
478 else
479 {
480 NumberFormatter::append(result, _scope);
481 }
482#endif
483 }
484 return toLower(result);
485 }
486}
487
488
489poco_socklen_t IPv6AddressImpl::length() const
490{
491 return sizeof(_addr);
492}
493
494
495const void* IPv6AddressImpl::addr() const
496{
497 return &_addr;
498}
499
500
501IPAddressImpl::Family IPv6AddressImpl::family() const
502{
503 return AddressFamily::IPv6;
504}
505
506
507int IPv6AddressImpl::af() const
508{
509 return AF_INET6;
510}
511
512
513unsigned IPv6AddressImpl::prefixLength() const
514{
515 unsigned bits = 0;
516 unsigned bitPos = 128;
517#if defined(POCO_OS_FAMILY_UNIX)
518 for (int i = 3; i >= 0; --i)
519 {
520 unsigned addr = ntohl(_addr.s6_addr32[i]);
521 if ((bits = maskBits(addr, 32))) return (bitPos - (32 - bits));
522 bitPos -= 32;
523 }
524 return 0;
525#elif defined(POCO_OS_FAMILY_WINDOWS)
526 for (int i = 7; i >= 0; --i)
527 {
528 unsigned short addr = ByteOrder::fromNetwork(_addr.s6_addr16[i]);
529 bits = maskBits(addr, 16);
530 if (bits)
531 return (bitPos - (16 - bits));
532 bitPos -= 16;
533 }
534 return 0;
535#else
536#warning prefixLength() not implemented
537 throw NotImplementedException("prefixLength() not implemented");
538#endif
539}
540
541
542Poco::UInt32 IPv6AddressImpl::scope() const
543{
544 return _scope;
545}
546
547
548bool IPv6AddressImpl::isWildcard() const
549{
550 const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
551 return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 &&
552 words[4] == 0 && words[5] == 0 && words[6] == 0 && words[7] == 0;
553}
554
555
556bool IPv6AddressImpl::isBroadcast() const
557{
558 return false;
559}
560
561
562bool IPv6AddressImpl::isLoopback() const
563{
564 const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
565 return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 &&
566 words[4] == 0 && words[5] == 0 && words[6] == 0 && ByteOrder::fromNetwork(words[7]) == 0x0001;
567}
568
569
570bool IPv6AddressImpl::isMulticast() const
571{
572 const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
573 return (ByteOrder::fromNetwork(words[0]) & 0xFFE0) == 0xFF00;
574}
575
576
577bool IPv6AddressImpl::isLinkLocal() const
578{
579 const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
580 return (ByteOrder::fromNetwork(words[0]) & 0xFFE0) == 0xFE80;
581}
582
583
584bool IPv6AddressImpl::isSiteLocal() const
585{
586 const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
587 return ((ByteOrder::fromNetwork(words[0]) & 0xFFE0) == 0xFEC0) || ((ByteOrder::fromNetwork(words[0]) & 0xFF00) == 0xFC00);
588}
589
590
591bool IPv6AddressImpl::isIPv4Compatible() const
592{
593 const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
594 return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 && words[4] == 0 && words[5] == 0;
595}
596
597
598bool IPv6AddressImpl::isIPv4Mapped() const
599{
600 const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
601 return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 && words[4] == 0 && ByteOrder::fromNetwork(words[5]) == 0xFFFF;
602}
603
604
605bool IPv6AddressImpl::isWellKnownMC() const
606{
607 const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
608 return (ByteOrder::fromNetwork(words[0]) & 0xFFF0) == 0xFF00;
609}
610
611
612bool IPv6AddressImpl::isNodeLocalMC() const
613{
614 const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
615 return (ByteOrder::fromNetwork(words[0]) & 0xFFEF) == 0xFF01;
616}
617
618
619bool IPv6AddressImpl::isLinkLocalMC() const
620{
621 const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
622 return (ByteOrder::fromNetwork(words[0]) & 0xFFEF) == 0xFF02;
623}
624
625
626bool IPv6AddressImpl::isSiteLocalMC() const
627{
628 const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
629 return (ByteOrder::fromNetwork(words[0]) & 0xFFEF) == 0xFF05;
630}
631
632
633bool IPv6AddressImpl::isOrgLocalMC() const
634{
635 const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
636 return (ByteOrder::fromNetwork(words[0]) & 0xFFEF) == 0xFF08;
637}
638
639
640bool IPv6AddressImpl::isGlobalMC() const
641{
642 const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
643 return (ByteOrder::fromNetwork(words[0]) & 0xFFEF) == 0xFF0F;
644}
645
646
647IPv6AddressImpl IPv6AddressImpl::parse(const std::string& addr)
648{
649 if (addr.empty()) return IPv6AddressImpl();
650#if defined(_WIN32)
651 struct addrinfo* pAI;
652 struct addrinfo hints;
653 std::memset(&hints, 0, sizeof(hints));
654 hints.ai_flags = AI_NUMERICHOST;
655 int rc = getaddrinfo(addr.c_str(), NULL, &hints, &pAI);
656 if (rc == 0)
657 {
658 IPv6AddressImpl result = IPv6AddressImpl(&reinterpret_cast<struct sockaddr_in6*>(pAI->ai_addr)->sin6_addr, static_cast<int>(reinterpret_cast<struct sockaddr_in6*>(pAI->ai_addr)->sin6_scope_id));
659 freeaddrinfo(pAI);
660 return result;
661 }
662 else return IPv6AddressImpl();
663#else
664 struct in6_addr ia;
665 std::string::size_type pos = addr.find('%');
666 if (std::string::npos != pos)
667 {
668 std::string::size_type start = ('[' == addr[0]) ? 1 : 0;
669 std::string unscopedAddr(addr, start, pos - start);
670 std::string scope(addr, pos + 1, addr.size() - start - pos);
671 Poco::UInt32 scopeId(0);
672 if (!(scopeId = if_nametoindex(scope.c_str())))
673 return IPv6AddressImpl();
674 if (inet_pton(AF_INET6, unscopedAddr.c_str(), &ia) == 1)
675 return IPv6AddressImpl(&ia, scopeId);
676 else
677 return IPv6AddressImpl();
678 }
679 else
680 {
681 if (inet_pton(AF_INET6, addr.c_str(), &ia) == 1)
682 return IPv6AddressImpl(&ia);
683 else
684 return IPv6AddressImpl();
685 }
686#endif
687}
688
689
690void IPv6AddressImpl::mask(const IPAddressImpl* /*pMask*/, const IPAddressImpl* /*pSet*/)
691{
692 throw Poco::NotImplementedException("mask() is only supported for IPv4 addresses");
693}
694
695
696IPAddressImpl* IPv6AddressImpl::clone() const
697{
698 return new IPv6AddressImpl(*this);
699}
700
701
702IPv6AddressImpl IPv6AddressImpl::operator & (const IPv6AddressImpl& addr) const
703{
704 if (_scope != addr._scope)
705 throw Poco::InvalidArgumentException("Scope ID of passed IPv6 address does not match with the source one.");
706
707 IPv6AddressImpl result(*this);
708#ifdef POCO_OS_FAMILY_WINDOWS
709 result._addr.s6_addr16[0] &= addr._addr.s6_addr16[0];
710 result._addr.s6_addr16[1] &= addr._addr.s6_addr16[1];
711 result._addr.s6_addr16[2] &= addr._addr.s6_addr16[2];
712 result._addr.s6_addr16[3] &= addr._addr.s6_addr16[3];
713 result._addr.s6_addr16[4] &= addr._addr.s6_addr16[4];
714 result._addr.s6_addr16[5] &= addr._addr.s6_addr16[5];
715 result._addr.s6_addr16[6] &= addr._addr.s6_addr16[6];
716 result._addr.s6_addr16[7] &= addr._addr.s6_addr16[7];
717#else
718 result._addr.s6_addr32[0] &= addr._addr.s6_addr32[0];
719 result._addr.s6_addr32[1] &= addr._addr.s6_addr32[1];
720 result._addr.s6_addr32[2] &= addr._addr.s6_addr32[2];
721 result._addr.s6_addr32[3] &= addr._addr.s6_addr32[3];
722#endif
723 return result;
724}
725
726
727IPv6AddressImpl IPv6AddressImpl::operator | (const IPv6AddressImpl& addr) const
728{
729 if (_scope != addr._scope)
730 throw Poco::InvalidArgumentException("Scope ID of passed IPv6 address does not match with the source one.");
731
732 IPv6AddressImpl result(*this);
733#ifdef POCO_OS_FAMILY_WINDOWS
734 result._addr.s6_addr16[0] |= addr._addr.s6_addr16[0];
735 result._addr.s6_addr16[1] |= addr._addr.s6_addr16[1];
736 result._addr.s6_addr16[2] |= addr._addr.s6_addr16[2];
737 result._addr.s6_addr16[3] |= addr._addr.s6_addr16[3];
738 result._addr.s6_addr16[4] |= addr._addr.s6_addr16[4];
739 result._addr.s6_addr16[5] |= addr._addr.s6_addr16[5];
740 result._addr.s6_addr16[6] |= addr._addr.s6_addr16[6];
741 result._addr.s6_addr16[7] |= addr._addr.s6_addr16[7];
742#else
743 result._addr.s6_addr32[0] |= addr._addr.s6_addr32[0];
744 result._addr.s6_addr32[1] |= addr._addr.s6_addr32[1];
745 result._addr.s6_addr32[2] |= addr._addr.s6_addr32[2];
746 result._addr.s6_addr32[3] |= addr._addr.s6_addr32[3];
747#endif
748 return result;
749}
750
751
752IPv6AddressImpl IPv6AddressImpl::operator ^ (const IPv6AddressImpl& addr) const
753{
754 if (_scope != addr._scope)
755 throw Poco::InvalidArgumentException("Scope ID of passed IPv6 address does not match with the source one.");
756
757 IPv6AddressImpl result(*this);
758
759#ifdef POCO_OS_FAMILY_WINDOWS
760 result._addr.s6_addr16[0] ^= addr._addr.s6_addr16[0];
761 result._addr.s6_addr16[1] ^= addr._addr.s6_addr16[1];
762 result._addr.s6_addr16[2] ^= addr._addr.s6_addr16[2];
763 result._addr.s6_addr16[3] ^= addr._addr.s6_addr16[3];
764 result._addr.s6_addr16[4] ^= addr._addr.s6_addr16[4];
765 result._addr.s6_addr16[5] ^= addr._addr.s6_addr16[5];
766 result._addr.s6_addr16[6] ^= addr._addr.s6_addr16[6];
767 result._addr.s6_addr16[7] ^= addr._addr.s6_addr16[7];
768#else
769 result._addr.s6_addr32[0] ^= addr._addr.s6_addr32[0];
770 result._addr.s6_addr32[1] ^= addr._addr.s6_addr32[1];
771 result._addr.s6_addr32[2] ^= addr._addr.s6_addr32[2];
772 result._addr.s6_addr32[3] ^= addr._addr.s6_addr32[3];
773#endif
774 return result;
775}
776
777
778IPv6AddressImpl IPv6AddressImpl::operator ~ () const
779{
780 IPv6AddressImpl result(*this);
781#ifdef POCO_OS_FAMILY_WINDOWS
782 result._addr.s6_addr16[0] ^= 0xffff;
783 result._addr.s6_addr16[1] ^= 0xffff;
784 result._addr.s6_addr16[2] ^= 0xffff;
785 result._addr.s6_addr16[3] ^= 0xffff;
786 result._addr.s6_addr16[4] ^= 0xffff;
787 result._addr.s6_addr16[5] ^= 0xffff;
788 result._addr.s6_addr16[6] ^= 0xffff;
789 result._addr.s6_addr16[7] ^= 0xffff;
790#else
791 result._addr.s6_addr32[0] ^= 0xffffffff;
792 result._addr.s6_addr32[1] ^= 0xffffffff;
793 result._addr.s6_addr32[2] ^= 0xffffffff;
794 result._addr.s6_addr32[3] ^= 0xffffffff;
795#endif
796 return result;
797}
798
799
800bool IPv6AddressImpl::operator == (const IPv6AddressImpl& addr) const
801{
802 return _scope == addr._scope && 0 == std::memcmp(&addr._addr, &_addr, sizeof(_addr));
803}
804
805
806bool IPv6AddressImpl::operator != (const IPv6AddressImpl& addr) const
807{
808 return !(*this == addr);
809}
810
811
812#endif // POCO_HAVE_IPv6
813
814
815} } } // namespace Poco::Net::Impl
816