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 | |
24 | using Poco::RefCountedObject; |
25 | using Poco::NumberFormatter; |
26 | using Poco::toLower; |
27 | using Poco::UInt8; |
28 | using Poco::UInt16; |
29 | using Poco::UInt32; |
30 | |
31 | |
32 | namespace { |
33 | |
34 | |
35 | template <typename T> |
36 | unsigned 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 | |
56 | namespace Poco { |
57 | namespace Net { |
58 | namespace Impl { |
59 | |
60 | |
61 | // |
62 | // IPAddressImpl |
63 | // |
64 | |
65 | |
66 | IPAddressImpl::IPAddressImpl() |
67 | { |
68 | } |
69 | |
70 | |
71 | IPAddressImpl::~IPAddressImpl() |
72 | { |
73 | } |
74 | |
75 | |
76 | // |
77 | // IPv4AddressImpl |
78 | // |
79 | |
80 | |
81 | IPv4AddressImpl::IPv4AddressImpl() |
82 | { |
83 | std::memset(&_addr, 0, sizeof(_addr)); |
84 | } |
85 | |
86 | |
87 | IPv4AddressImpl::IPv4AddressImpl(const void* addr) |
88 | { |
89 | std::memcpy(&_addr, addr, sizeof(_addr)); |
90 | } |
91 | |
92 | |
93 | IPv4AddressImpl::IPv4AddressImpl(unsigned prefix) |
94 | { |
95 | UInt32 addr = (prefix == 32) ? 0xffffffff : ~(0xffffffff >> prefix); |
96 | _addr.s_addr = ByteOrder::toNetwork(addr); |
97 | } |
98 | |
99 | |
100 | IPv4AddressImpl::IPv4AddressImpl(const IPv4AddressImpl& addr) |
101 | { |
102 | std::memcpy(&_addr, &addr._addr, sizeof(_addr)); |
103 | } |
104 | |
105 | |
106 | IPv4AddressImpl& 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 | |
116 | std::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 | |
132 | poco_socklen_t IPv4AddressImpl::length() const |
133 | { |
134 | return sizeof(_addr); |
135 | } |
136 | |
137 | |
138 | const void* IPv4AddressImpl::addr() const |
139 | { |
140 | return &_addr; |
141 | } |
142 | |
143 | |
144 | IPAddressImpl::Family IPv4AddressImpl::family() const |
145 | { |
146 | return AddressFamily::IPv4; |
147 | } |
148 | |
149 | |
150 | int IPv4AddressImpl::af() const |
151 | { |
152 | return AF_INET; |
153 | } |
154 | |
155 | |
156 | unsigned IPv4AddressImpl::prefixLength() const |
157 | { |
158 | return maskBits(ntohl(_addr.s_addr), 32); |
159 | } |
160 | |
161 | |
162 | Poco::UInt32 IPv4AddressImpl::scope() const |
163 | { |
164 | return 0; |
165 | } |
166 | |
167 | |
168 | bool IPv4AddressImpl::isWildcard() const |
169 | { |
170 | return _addr.s_addr == INADDR_ANY; |
171 | } |
172 | |
173 | |
174 | bool IPv4AddressImpl::isBroadcast() const |
175 | { |
176 | return _addr.s_addr == INADDR_NONE; |
177 | } |
178 | |
179 | |
180 | bool IPv4AddressImpl::isLoopback() const |
181 | { |
182 | return (ntohl(_addr.s_addr) & 0xFF000000) == 0x7F000000; // 127.0.0.1 to 127.255.255.255 |
183 | } |
184 | |
185 | |
186 | bool 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 | |
192 | bool IPv4AddressImpl::isLinkLocal() const |
193 | { |
194 | return (ntohl(_addr.s_addr) & 0xFFFF0000) == 0xA9FE0000; // 169.254.0.0/16 |
195 | } |
196 | |
197 | |
198 | bool 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 | |
207 | bool IPv4AddressImpl::isIPv4Compatible() const |
208 | { |
209 | return true; |
210 | } |
211 | |
212 | |
213 | bool IPv4AddressImpl::isIPv4Mapped() const |
214 | { |
215 | return true; |
216 | } |
217 | |
218 | |
219 | bool IPv4AddressImpl::isWellKnownMC() const |
220 | { |
221 | return (ntohl(_addr.s_addr) & 0xFFFFFF00) == 0xE0000000; // 224.0.0.0/8 |
222 | } |
223 | |
224 | |
225 | bool IPv4AddressImpl::isNodeLocalMC() const |
226 | { |
227 | return false; |
228 | } |
229 | |
230 | |
231 | bool IPv4AddressImpl::isLinkLocalMC() const |
232 | { |
233 | return (ntohl(_addr.s_addr) & 0xFF000000) == 0xE0000000; // 244.0.0.0/24 |
234 | } |
235 | |
236 | |
237 | bool IPv4AddressImpl::isSiteLocalMC() const |
238 | { |
239 | return (ntohl(_addr.s_addr) & 0xFFFF0000) == 0xEFFF0000; // 239.255.0.0/16 |
240 | } |
241 | |
242 | |
243 | bool IPv4AddressImpl::isOrgLocalMC() const |
244 | { |
245 | return (ntohl(_addr.s_addr) & 0xFFFF0000) == 0xEFC00000; // 239.192.0.0/16 |
246 | } |
247 | |
248 | |
249 | bool 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 | |
256 | IPv4AddressImpl 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 | |
285 | void 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 | |
294 | IPAddressImpl* IPv4AddressImpl::clone() const |
295 | { |
296 | return new IPv4AddressImpl(&_addr); |
297 | } |
298 | |
299 | |
300 | IPv4AddressImpl 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 | |
308 | IPv4AddressImpl 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 | |
316 | IPv4AddressImpl 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 | |
324 | IPv4AddressImpl IPv4AddressImpl::operator ~ () const |
325 | { |
326 | IPv4AddressImpl result(&_addr); |
327 | result._addr.s_addr ^= 0xffffffff; |
328 | return result; |
329 | } |
330 | |
331 | |
332 | bool IPv4AddressImpl::operator == (const IPv4AddressImpl& addr) const |
333 | { |
334 | return 0 == std::memcmp(&addr._addr, &_addr, sizeof(_addr)); |
335 | } |
336 | |
337 | |
338 | bool 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 | |
352 | IPv6AddressImpl::IPv6AddressImpl(): _scope(0) |
353 | { |
354 | std::memset(&_addr, 0, sizeof(_addr)); |
355 | } |
356 | |
357 | |
358 | IPv6AddressImpl::IPv6AddressImpl(const void* addr): _scope(0) |
359 | { |
360 | std::memcpy(&_addr, addr, sizeof(_addr)); |
361 | } |
362 | |
363 | |
364 | IPv6AddressImpl::IPv6AddressImpl(const void* addr, Poco::UInt32 scope): _scope(scope) |
365 | { |
366 | std::memcpy(&_addr, addr, sizeof(_addr)); |
367 | } |
368 | |
369 | |
370 | IPv6AddressImpl::IPv6AddressImpl(const IPv6AddressImpl& addr): _scope(addr._scope) |
371 | { |
372 | std::memcpy((void*) &_addr, (void*) &addr._addr, sizeof(_addr)); |
373 | } |
374 | |
375 | |
376 | IPv6AddressImpl& 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 | |
387 | IPv6AddressImpl::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 | |
421 | std::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 | |
489 | poco_socklen_t IPv6AddressImpl::length() const |
490 | { |
491 | return sizeof(_addr); |
492 | } |
493 | |
494 | |
495 | const void* IPv6AddressImpl::addr() const |
496 | { |
497 | return &_addr; |
498 | } |
499 | |
500 | |
501 | IPAddressImpl::Family IPv6AddressImpl::family() const |
502 | { |
503 | return AddressFamily::IPv6; |
504 | } |
505 | |
506 | |
507 | int IPv6AddressImpl::af() const |
508 | { |
509 | return AF_INET6; |
510 | } |
511 | |
512 | |
513 | unsigned 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 | if ((bits = maskBits(addr, 16))) return (bitPos - (16 - bits)); |
530 | bitPos -= 16; |
531 | } |
532 | return 0; |
533 | #else |
534 | #warning prefixLength() not implemented |
535 | throw NotImplementedException("prefixLength() not implemented" ); |
536 | #endif |
537 | } |
538 | |
539 | |
540 | Poco::UInt32 IPv6AddressImpl::scope() const |
541 | { |
542 | return _scope; |
543 | } |
544 | |
545 | |
546 | bool IPv6AddressImpl::isWildcard() const |
547 | { |
548 | const UInt16* words = reinterpret_cast<const UInt16*>(&_addr); |
549 | return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 && |
550 | words[4] == 0 && words[5] == 0 && words[6] == 0 && words[7] == 0; |
551 | } |
552 | |
553 | |
554 | bool IPv6AddressImpl::isBroadcast() const |
555 | { |
556 | return false; |
557 | } |
558 | |
559 | |
560 | bool IPv6AddressImpl::isLoopback() const |
561 | { |
562 | const UInt16* words = reinterpret_cast<const UInt16*>(&_addr); |
563 | return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 && |
564 | words[4] == 0 && words[5] == 0 && words[6] == 0 && ByteOrder::fromNetwork(words[7]) == 0x0001; |
565 | } |
566 | |
567 | |
568 | bool IPv6AddressImpl::isMulticast() const |
569 | { |
570 | const UInt16* words = reinterpret_cast<const UInt16*>(&_addr); |
571 | return (ByteOrder::fromNetwork(words[0]) & 0xFFE0) == 0xFF00; |
572 | } |
573 | |
574 | |
575 | bool IPv6AddressImpl::isLinkLocal() const |
576 | { |
577 | const UInt16* words = reinterpret_cast<const UInt16*>(&_addr); |
578 | return (ByteOrder::fromNetwork(words[0]) & 0xFFE0) == 0xFE80; |
579 | } |
580 | |
581 | |
582 | bool IPv6AddressImpl::isSiteLocal() const |
583 | { |
584 | const UInt16* words = reinterpret_cast<const UInt16*>(&_addr); |
585 | return ((ByteOrder::fromNetwork(words[0]) & 0xFFE0) == 0xFEC0) || ((ByteOrder::fromNetwork(words[0]) & 0xFF00) == 0xFC00); |
586 | } |
587 | |
588 | |
589 | bool IPv6AddressImpl::isIPv4Compatible() const |
590 | { |
591 | const UInt16* words = reinterpret_cast<const UInt16*>(&_addr); |
592 | return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 && words[4] == 0 && words[5] == 0; |
593 | } |
594 | |
595 | |
596 | bool IPv6AddressImpl::isIPv4Mapped() const |
597 | { |
598 | const UInt16* words = reinterpret_cast<const UInt16*>(&_addr); |
599 | return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 && words[4] == 0 && ByteOrder::fromNetwork(words[5]) == 0xFFFF; |
600 | } |
601 | |
602 | |
603 | bool IPv6AddressImpl::isWellKnownMC() const |
604 | { |
605 | const UInt16* words = reinterpret_cast<const UInt16*>(&_addr); |
606 | return (ByteOrder::fromNetwork(words[0]) & 0xFFF0) == 0xFF00; |
607 | } |
608 | |
609 | |
610 | bool IPv6AddressImpl::isNodeLocalMC() const |
611 | { |
612 | const UInt16* words = reinterpret_cast<const UInt16*>(&_addr); |
613 | return (ByteOrder::fromNetwork(words[0]) & 0xFFEF) == 0xFF01; |
614 | } |
615 | |
616 | |
617 | bool IPv6AddressImpl::isLinkLocalMC() const |
618 | { |
619 | const UInt16* words = reinterpret_cast<const UInt16*>(&_addr); |
620 | return (ByteOrder::fromNetwork(words[0]) & 0xFFEF) == 0xFF02; |
621 | } |
622 | |
623 | |
624 | bool IPv6AddressImpl::isSiteLocalMC() const |
625 | { |
626 | const UInt16* words = reinterpret_cast<const UInt16*>(&_addr); |
627 | return (ByteOrder::fromNetwork(words[0]) & 0xFFEF) == 0xFF05; |
628 | } |
629 | |
630 | |
631 | bool IPv6AddressImpl::isOrgLocalMC() const |
632 | { |
633 | const UInt16* words = reinterpret_cast<const UInt16*>(&_addr); |
634 | return (ByteOrder::fromNetwork(words[0]) & 0xFFEF) == 0xFF08; |
635 | } |
636 | |
637 | |
638 | bool IPv6AddressImpl::isGlobalMC() const |
639 | { |
640 | const UInt16* words = reinterpret_cast<const UInt16*>(&_addr); |
641 | return (ByteOrder::fromNetwork(words[0]) & 0xFFEF) == 0xFF0F; |
642 | } |
643 | |
644 | |
645 | IPv6AddressImpl IPv6AddressImpl::parse(const std::string& addr) |
646 | { |
647 | if (addr.empty()) return IPv6AddressImpl(); |
648 | #if defined(_WIN32) |
649 | struct addrinfo* pAI; |
650 | struct addrinfo hints; |
651 | std::memset(&hints, 0, sizeof(hints)); |
652 | hints.ai_flags = AI_NUMERICHOST; |
653 | int rc = getaddrinfo(addr.c_str(), NULL, &hints, &pAI); |
654 | if (rc == 0) |
655 | { |
656 | 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)); |
657 | freeaddrinfo(pAI); |
658 | return result; |
659 | } |
660 | else return IPv6AddressImpl(); |
661 | #else |
662 | struct in6_addr ia; |
663 | std::string::size_type pos = addr.find('%'); |
664 | if (std::string::npos != pos) |
665 | { |
666 | std::string::size_type start = ('[' == addr[0]) ? 1 : 0; |
667 | std::string unscopedAddr(addr, start, pos - start); |
668 | std::string scope(addr, pos + 1, addr.size() - start - pos); |
669 | Poco::UInt32 scopeId(0); |
670 | if (!(scopeId = if_nametoindex(scope.c_str()))) |
671 | return IPv6AddressImpl(); |
672 | if (inet_pton(AF_INET6, unscopedAddr.c_str(), &ia) == 1) |
673 | return IPv6AddressImpl(&ia, scopeId); |
674 | else |
675 | return IPv6AddressImpl(); |
676 | } |
677 | else |
678 | { |
679 | if (inet_pton(AF_INET6, addr.c_str(), &ia) == 1) |
680 | return IPv6AddressImpl(&ia); |
681 | else |
682 | return IPv6AddressImpl(); |
683 | } |
684 | #endif |
685 | } |
686 | |
687 | |
688 | void IPv6AddressImpl::mask(const IPAddressImpl* pMask, const IPAddressImpl* pSet) |
689 | { |
690 | throw Poco::NotImplementedException("mask() is only supported for IPv4 addresses" ); |
691 | } |
692 | |
693 | |
694 | IPAddressImpl* IPv6AddressImpl::clone() const |
695 | { |
696 | return new IPv6AddressImpl(*this); |
697 | } |
698 | |
699 | |
700 | IPv6AddressImpl IPv6AddressImpl::operator & (const IPv6AddressImpl& addr) const |
701 | { |
702 | if (_scope != addr._scope) |
703 | throw Poco::InvalidArgumentException("Scope ID of passed IPv6 address does not match with the source one." ); |
704 | |
705 | IPv6AddressImpl result(*this); |
706 | #ifdef POCO_OS_FAMILY_WINDOWS |
707 | result._addr.s6_addr16[0] &= addr._addr.s6_addr16[0]; |
708 | result._addr.s6_addr16[1] &= addr._addr.s6_addr16[1]; |
709 | result._addr.s6_addr16[2] &= addr._addr.s6_addr16[2]; |
710 | result._addr.s6_addr16[3] &= addr._addr.s6_addr16[3]; |
711 | result._addr.s6_addr16[4] &= addr._addr.s6_addr16[4]; |
712 | result._addr.s6_addr16[5] &= addr._addr.s6_addr16[5]; |
713 | result._addr.s6_addr16[6] &= addr._addr.s6_addr16[6]; |
714 | result._addr.s6_addr16[7] &= addr._addr.s6_addr16[7]; |
715 | #else |
716 | result._addr.s6_addr32[0] &= addr._addr.s6_addr32[0]; |
717 | result._addr.s6_addr32[1] &= addr._addr.s6_addr32[1]; |
718 | result._addr.s6_addr32[2] &= addr._addr.s6_addr32[2]; |
719 | result._addr.s6_addr32[3] &= addr._addr.s6_addr32[3]; |
720 | #endif |
721 | return result; |
722 | } |
723 | |
724 | |
725 | IPv6AddressImpl IPv6AddressImpl::operator | (const IPv6AddressImpl& addr) const |
726 | { |
727 | if (_scope != addr._scope) |
728 | throw Poco::InvalidArgumentException("Scope ID of passed IPv6 address does not match with the source one." ); |
729 | |
730 | IPv6AddressImpl result(*this); |
731 | #ifdef POCO_OS_FAMILY_WINDOWS |
732 | result._addr.s6_addr16[0] |= addr._addr.s6_addr16[0]; |
733 | result._addr.s6_addr16[1] |= addr._addr.s6_addr16[1]; |
734 | result._addr.s6_addr16[2] |= addr._addr.s6_addr16[2]; |
735 | result._addr.s6_addr16[3] |= addr._addr.s6_addr16[3]; |
736 | result._addr.s6_addr16[4] |= addr._addr.s6_addr16[4]; |
737 | result._addr.s6_addr16[5] |= addr._addr.s6_addr16[5]; |
738 | result._addr.s6_addr16[6] |= addr._addr.s6_addr16[6]; |
739 | result._addr.s6_addr16[7] |= addr._addr.s6_addr16[7]; |
740 | #else |
741 | result._addr.s6_addr32[0] |= addr._addr.s6_addr32[0]; |
742 | result._addr.s6_addr32[1] |= addr._addr.s6_addr32[1]; |
743 | result._addr.s6_addr32[2] |= addr._addr.s6_addr32[2]; |
744 | result._addr.s6_addr32[3] |= addr._addr.s6_addr32[3]; |
745 | #endif |
746 | return result; |
747 | } |
748 | |
749 | |
750 | IPv6AddressImpl IPv6AddressImpl::operator ^ (const IPv6AddressImpl& addr) const |
751 | { |
752 | if (_scope != addr._scope) |
753 | throw Poco::InvalidArgumentException("Scope ID of passed IPv6 address does not match with the source one." ); |
754 | |
755 | IPv6AddressImpl result(*this); |
756 | |
757 | #ifdef POCO_OS_FAMILY_WINDOWS |
758 | result._addr.s6_addr16[0] ^= addr._addr.s6_addr16[0]; |
759 | result._addr.s6_addr16[1] ^= addr._addr.s6_addr16[1]; |
760 | result._addr.s6_addr16[2] ^= addr._addr.s6_addr16[2]; |
761 | result._addr.s6_addr16[3] ^= addr._addr.s6_addr16[3]; |
762 | result._addr.s6_addr16[4] ^= addr._addr.s6_addr16[4]; |
763 | result._addr.s6_addr16[5] ^= addr._addr.s6_addr16[5]; |
764 | result._addr.s6_addr16[6] ^= addr._addr.s6_addr16[6]; |
765 | result._addr.s6_addr16[7] ^= addr._addr.s6_addr16[7]; |
766 | #else |
767 | result._addr.s6_addr32[0] ^= addr._addr.s6_addr32[0]; |
768 | result._addr.s6_addr32[1] ^= addr._addr.s6_addr32[1]; |
769 | result._addr.s6_addr32[2] ^= addr._addr.s6_addr32[2]; |
770 | result._addr.s6_addr32[3] ^= addr._addr.s6_addr32[3]; |
771 | #endif |
772 | return result; |
773 | } |
774 | |
775 | |
776 | IPv6AddressImpl IPv6AddressImpl::operator ~ () const |
777 | { |
778 | IPv6AddressImpl result(*this); |
779 | #ifdef POCO_OS_FAMILY_WINDOWS |
780 | result._addr.s6_addr16[0] ^= 0xffff; |
781 | result._addr.s6_addr16[1] ^= 0xffff; |
782 | result._addr.s6_addr16[2] ^= 0xffff; |
783 | result._addr.s6_addr16[3] ^= 0xffff; |
784 | result._addr.s6_addr16[4] ^= 0xffff; |
785 | result._addr.s6_addr16[5] ^= 0xffff; |
786 | result._addr.s6_addr16[6] ^= 0xffff; |
787 | result._addr.s6_addr16[7] ^= 0xffff; |
788 | #else |
789 | result._addr.s6_addr32[0] ^= 0xffffffff; |
790 | result._addr.s6_addr32[1] ^= 0xffffffff; |
791 | result._addr.s6_addr32[2] ^= 0xffffffff; |
792 | result._addr.s6_addr32[3] ^= 0xffffffff; |
793 | #endif |
794 | return result; |
795 | } |
796 | |
797 | |
798 | bool IPv6AddressImpl::operator == (const IPv6AddressImpl& addr) const |
799 | { |
800 | return _scope == addr._scope && 0 == std::memcmp(&addr._addr, &_addr, sizeof(_addr)); |
801 | } |
802 | |
803 | |
804 | bool IPv6AddressImpl::operator != (const IPv6AddressImpl& addr) const |
805 | { |
806 | return !(*this == addr); |
807 | } |
808 | |
809 | |
810 | #endif // POCO_HAVE_IPv6 |
811 | |
812 | |
813 | } } } // namespace Poco::Net::Impl |
814 | |