1// Copyright (C) 2017 The Qt Company Ltd.
2// Copyright (C) 2016 Intel Corporation.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4// Qt-Security score:critical reason:data-parser
5
6#include "qhostaddress.h"
7#include "qhostaddress_p.h"
8#include "private/qipaddress_p.h"
9#include "qdebug.h"
10#if defined(Q_OS_WIN)
11# include <winsock2.h>
12# include <ws2tcpip.h>
13#else
14# include <netinet/in.h>
15#endif
16#include "qplatformdefs.h"
17#include "qstringlist.h"
18#include "qendian.h"
19#ifndef QT_NO_DATASTREAM
20#include <qdatastream.h>
21#endif
22#ifdef __SSE2__
23# include <private/qsimd_p.h>
24#endif
25
26#ifdef QT_LINUXBASE
27# include <arpa/inet.h>
28#endif
29
30QT_BEGIN_NAMESPACE
31
32QHostAddressPrivate::QHostAddressPrivate()
33 : a(0), protocol(QHostAddress::UnknownNetworkLayerProtocol)
34{
35 memset(s: &a6, c: 0, n: sizeof(a6));
36}
37
38QT_DEFINE_QESDP_SPECIALIZATION_DTOR(QHostAddressPrivate)
39
40void QHostAddressPrivate::setAddress(quint32 a_)
41{
42 a = a_;
43 protocol = QHostAddress::IPv4Protocol;
44
45 //create mapped address, except for a_ == 0 (any)
46 a6_64.c[0] = 0;
47 if (a) {
48 a6_32.c[2] = qToBigEndian(source: 0xffff);
49 a6_32.c[3] = qToBigEndian(source: a);
50 } else {
51 a6_64.c[1] = 0;
52 }
53}
54
55/// parses v4-mapped addresses or the AnyIPv6 address and stores in \a a;
56/// returns true if the address was one of those
57static bool convertToIpv4(quint32& a, const Q_IPV6ADDR &a6, const QHostAddress::ConversionMode mode)
58{
59 if (mode == QHostAddress::StrictConversion)
60 return false;
61
62 const uchar *ptr = a6.c;
63 if (qFromUnaligned<quint64>(src: ptr) != 0)
64 return false;
65
66 const quint32 mid = qFromBigEndian<quint32>(src: ptr + 8);
67 if ((mid == 0xffff) && (mode & QHostAddress::ConvertV4MappedToIPv4)) {
68 a = qFromBigEndian<quint32>(src: ptr + 12);
69 return true;
70 }
71 if (mid != 0)
72 return false;
73
74 const quint32 low = qFromBigEndian<quint32>(src: ptr + 12);
75 if ((low == 0) && (mode & QHostAddress::ConvertUnspecifiedAddress)) {
76 a = 0;
77 return true;
78 }
79 if ((low == 1) && (mode & QHostAddress::ConvertLocalHost)) {
80 a = INADDR_LOOPBACK;
81 return true;
82 }
83 if ((low != 1) && (mode & QHostAddress::ConvertV4CompatToIPv4)) {
84 a = low;
85 return true;
86 }
87 return false;
88}
89
90void QHostAddressPrivate::setAddress(const quint8 *a_)
91{
92 protocol = QHostAddress::IPv6Protocol;
93 memcpy(dest: a6.c, src: a_, n: sizeof(a6));
94 a = 0;
95 convertToIpv4(a, a6: a6, mode: (QHostAddress::ConvertV4MappedToIPv4
96 | QHostAddress::ConvertUnspecifiedAddress));
97}
98
99void QHostAddressPrivate::setAddress(const Q_IPV6ADDR &a_)
100{
101 setAddress(a_.c);
102}
103
104static bool parseIp6(const QString &address, QIPAddressUtils::IPv6Address &addr, QString *scopeId)
105{
106 QStringView tmp(address);
107 qsizetype scopeIdPos = tmp.lastIndexOf(c: u'%');
108 if (scopeIdPos != -1) {
109 *scopeId = tmp.mid(pos: scopeIdPos + 1).toString();
110 tmp.chop(n: tmp.size() - scopeIdPos);
111 } else {
112 scopeId->clear();
113 }
114 return QIPAddressUtils::parseIp6(address&: addr, begin: tmp.begin(), end: tmp.end()) == nullptr;
115}
116
117bool QHostAddressPrivate::parse(const QString &ipString)
118{
119 protocol = QHostAddress::UnknownNetworkLayerProtocol;
120 QString a = ipString.simplified();
121 if (a.isEmpty())
122 return false;
123
124 // All IPv6 addresses contain a ':', and may contain a '.'.
125 if (a.contains(c: u':')) {
126 quint8 maybeIp6[16];
127 if (parseIp6(address: a, addr&: maybeIp6, scopeId: &scopeId)) {
128 setAddress(maybeIp6);
129 return true;
130 }
131 }
132
133 quint32 maybeIp4 = 0;
134 if (QIPAddressUtils::parseIp4(address&: maybeIp4, begin: a.constBegin(), end: a.constEnd())) {
135 setAddress(maybeIp4);
136 return true;
137 }
138
139 return false;
140}
141
142void QHostAddressPrivate::clear()
143{
144 a = 0;
145 protocol = QHostAddress::UnknownNetworkLayerProtocol;
146 memset(s: &a6, c: 0, n: sizeof(a6));
147}
148
149AddressClassification QHostAddressPrivate::classify() const
150{
151 if (a) {
152 // This is an IPv4 address or an IPv6 v4-mapped address includes all
153 // IPv6 v4-compat addresses, except for ::ffff:0.0.0.0 (because `a' is
154 // zero). See setAddress(quint8*) below, which calls convertToIpv4(),
155 // for details.
156 // Source: RFC 5735
157 if ((a & 0xff000000U) == 0x7f000000U) // 127.0.0.0/8
158 return LoopbackAddress;
159 if ((a & 0xf0000000U) == 0xe0000000U) // 224.0.0.0/4
160 return MulticastAddress;
161 if ((a & 0xffff0000U) == 0xa9fe0000U) // 169.254.0.0/16
162 return LinkLocalAddress;
163 if ((a & 0xff000000U) == 0) // 0.0.0.0/8 except 0.0.0.0 (handled below)
164 return LocalNetAddress;
165 if ((a & 0xf0000000U) == 0xf0000000U) { // 240.0.0.0/4
166 if (a == 0xffffffffU) // 255.255.255.255
167 return BroadcastAddress;
168 return UnknownAddress;
169 }
170 if (((a & 0xff000000U) == 0x0a000000U) // 10.0.0.0/8
171 || ((a & 0xfff00000U) == 0xac100000U) // 172.16.0.0/12
172 || ((a & 0xffff0000U) == 0xc0a80000U)) // 192.168.0.0/16
173 return PrivateNetworkAddress;
174
175 // Not testing for TestNetworkAddress
176 // since we don't need them yet.
177 return GlobalAddress;
178 }
179
180 // As `a' is zero, this address is either ::ffff:0.0.0.0 or a non-v4-mapped IPv6 address.
181 // Source: https://www.iana.org/assignments/ipv6-address-space/ipv6-address-space.xhtml
182 if (a6_64.c[0]) {
183 quint32 high16 = qFromBigEndian(source: a6_32.c[0]) >> 16;
184 switch (high16 >> 8) {
185 case 0xff: // ff00::/8
186 return MulticastAddress;
187 case 0xfe:
188 switch (high16 & 0xffc0) {
189 case 0xfec0: // fec0::/10
190 return SiteLocalAddress;
191
192 case 0xfe80: // fe80::/10
193 return LinkLocalAddress;
194
195 default: // fe00::/9
196 return UnknownAddress;
197 }
198 case 0xfd: // fc00::/7
199 case 0xfc:
200 return UniqueLocalAddress;
201 default:
202 return GlobalAddress;
203 }
204 }
205
206 quint64 low64 = qFromBigEndian(source: a6_64.c[1]);
207 if (low64 == 1) // ::1
208 return LoopbackAddress;
209 if (low64 >> 32 == 0xffff) { // ::ffff:0.0.0.0/96
210 Q_ASSERT(quint32(low64) == 0);
211 return LocalNetAddress;
212 }
213 if (low64) // not ::
214 return GlobalAddress;
215
216 if (protocol == QHostAddress::UnknownNetworkLayerProtocol)
217 return UnknownAddress;
218
219 // only :: and 0.0.0.0 remain now
220 return LocalNetAddress;
221}
222
223bool QNetmask::setAddress(const QHostAddress &address)
224{
225 static const quint8 zeroes[16] = { 0 };
226 union {
227 quint32 v4;
228 quint8 v6[16];
229 } ip;
230
231 int netmask = 0;
232 quint8 *ptr = ip.v6;
233 quint8 *end;
234 length = 255;
235
236 if (address.protocol() == QHostAddress::IPv4Protocol) {
237 ip.v4 = qToBigEndian(source: address.toIPv4Address());
238 end = ptr + 4;
239 } else if (address.protocol() == QHostAddress::IPv6Protocol) {
240 memcpy(dest: ip.v6, src: address.toIPv6Address().c, n: 16);
241 end = ptr + 16;
242 } else {
243 return false;
244 }
245
246 while (ptr < end) {
247 switch (*ptr) {
248 case 255:
249 netmask += 8;
250 ++ptr;
251 continue;
252
253 default:
254 return false; // invalid IP-style netmask
255
256 case 254:
257 ++netmask;
258 Q_FALLTHROUGH();
259 case 252:
260 ++netmask;
261 Q_FALLTHROUGH();
262 case 248:
263 ++netmask;
264 Q_FALLTHROUGH();
265 case 240:
266 ++netmask;
267 Q_FALLTHROUGH();
268 case 224:
269 ++netmask;
270 Q_FALLTHROUGH();
271 case 192:
272 ++netmask;
273 Q_FALLTHROUGH();
274 case 128:
275 ++netmask;
276 Q_FALLTHROUGH();
277 case 0:
278 break;
279 }
280 break;
281 }
282
283 // confirm that the rest is only zeroes
284 if (ptr < end && memcmp(s1: ptr + 1, s2: zeroes, n: end - ptr - 1) != 0)
285 return false;
286
287 length = netmask;
288 return true;
289}
290
291static void clearBits(quint8 *where, int start, int end)
292{
293 Q_ASSERT(end == 32 || end == 128);
294 if (start == end)
295 return;
296
297 // for the byte where 'start' is, clear the lower bits only
298 quint8 bytemask = 256 - (1 << (8 - (start & 7)));
299 where[start / 8] &= bytemask;
300
301 // for the tail part, clear everything
302 memset(s: where + (start + 7) / 8, c: 0, n: end / 8 - (start + 7) / 8);
303}
304
305QHostAddress QNetmask::address(QHostAddress::NetworkLayerProtocol protocol) const
306{
307 if (length == 255 || protocol == QHostAddress::AnyIPProtocol ||
308 protocol == QHostAddress::UnknownNetworkLayerProtocol) {
309 return QHostAddress();
310 } else if (protocol == QHostAddress::IPv4Protocol) {
311 quint32 a;
312 if (length == 0)
313 a = 0;
314 else if (length == 32)
315 a = quint32(0xffffffff);
316 else
317 a = quint32(0xffffffff) >> (32 - length) << (32 - length);
318 return QHostAddress(a);
319 } else {
320 Q_IPV6ADDR a6;
321 memset(s: a6.c, c: 0xFF, n: sizeof(a6));
322 clearBits(where: a6.c, start: length, end: 128);
323 return QHostAddress(a6);
324 }
325}
326
327/*!
328 \class QHostAddress
329 \brief The QHostAddress class provides an IP address.
330 \ingroup network
331 \ingroup shared
332 \inmodule QtNetwork
333
334 This class holds an IPv4 or IPv6 address in a platform- and
335 protocol-independent manner.
336
337 QHostAddress is normally used with the QTcpSocket, QTcpServer,
338 and QUdpSocket to connect to a host or to set up a server.
339
340 A host address is set with setAddress(), and retrieved with
341 toIPv4Address(), toIPv6Address(), or toString(). You can check the
342 type with protocol().
343
344 \note Please note that QHostAddress does not do DNS lookups.
345 QHostInfo is needed for that.
346
347 The class also supports common predefined addresses: \l Null, \l
348 LocalHost, \l LocalHostIPv6, \l Broadcast, and \l Any.
349
350 \sa QHostInfo, QTcpSocket, QTcpServer, QUdpSocket
351*/
352
353/*! \enum QHostAddress::SpecialAddress
354
355 \value Null The null address object. Equivalent to QHostAddress(). See also QHostAddress::isNull().
356 \value LocalHost The IPv4 localhost address. Equivalent to QHostAddress("127.0.0.1").
357 \value LocalHostIPv6 The IPv6 localhost address. Equivalent to QHostAddress("::1").
358 \value Broadcast The IPv4 broadcast address. Equivalent to QHostAddress("255.255.255.255").
359 \value AnyIPv4 The IPv4 any-address. Equivalent to QHostAddress("0.0.0.0"). A socket bound with this address will listen only on IPv4 interfaces.
360 \value AnyIPv6 The IPv6 any-address. Equivalent to QHostAddress("::"). A socket bound with this address will listen only on IPv6 interfaces.
361 \value Any The dual stack any-address. A socket bound with this address will listen on both IPv4 and IPv6 interfaces.
362*/
363
364/*! \enum QHostAddress::ConversionModeFlag
365
366 \since 5.8
367
368 \value StrictConversion Don't convert IPv6 addresses to IPv4 when comparing two QHostAddress objects of different protocols, so they will always be considered different.
369 \value ConvertV4MappedToIPv4 Convert IPv4-mapped IPv6 addresses (RFC 4291 sect. 2.5.5.2) when comparing. Therefore QHostAddress("::ffff:192.168.1.1") will compare equal to QHostAddress("192.168.1.1").
370 \value ConvertV4CompatToIPv4 Convert IPv4-compatible IPv6 addresses (RFC 4291 sect. 2.5.5.1) when comparing. Therefore QHostAddress("::192.168.1.1") will compare equal to QHostAddress("192.168.1.1").
371 \value ConvertLocalHost Convert the IPv6 loopback addresses to its IPv4 equivalent when comparing. Therefore e.g. QHostAddress("::1") will compare equal to QHostAddress("127.0.0.1").
372 \value ConvertUnspecifiedAddress All unspecified addresses will compare equal, namely AnyIPv4, AnyIPv6 and Any.
373 \value TolerantConversion Sets all three preceding flags.
374
375 \sa isEqual()
376 */
377
378/*! Constructs a null host address object, i.e. an address which is not valid for any host or interface.
379
380 \sa clear()
381*/
382QHostAddress::QHostAddress()
383 : d(new QHostAddressPrivate)
384{
385}
386
387/*!
388 Constructs a host address object with the IPv4 address \a ip4Addr.
389*/
390QHostAddress::QHostAddress(quint32 ip4Addr)
391 : d(new QHostAddressPrivate)
392{
393 setAddress(ip4Addr);
394}
395
396/*!
397 \since 5.5
398 Constructs a host address object with the IPv6 address \a ip6Addr.
399
400 \a ip6Addr must be a 16-byte array in network byte order (big
401 endian).
402*/
403QHostAddress::QHostAddress(const quint8 *ip6Addr)
404 : d(new QHostAddressPrivate)
405{
406 setAddress(ip6Addr);
407}
408
409/*!
410 Constructs a host address object with the IPv6 address \a ip6Addr.
411*/
412QHostAddress::QHostAddress(const Q_IPV6ADDR &ip6Addr)
413 : d(new QHostAddressPrivate)
414{
415 setAddress(ip6Addr);
416}
417
418/*!
419 Constructs an IPv4 or IPv6 address based on the string \a address
420 (e.g., "127.0.0.1").
421
422 \sa setAddress()
423*/
424QHostAddress::QHostAddress(const QString &address)
425 : d(new QHostAddressPrivate)
426{
427 d->parse(ipString: address);
428}
429
430/*!
431 \fn QHostAddress::QHostAddress(const sockaddr *sockaddr)
432
433 Constructs an IPv4 or IPv6 address using the address specified by
434 the native structure \a sockaddr.
435
436 \sa setAddress()
437*/
438QHostAddress::QHostAddress(const struct sockaddr *sockaddr)
439 : d(new QHostAddressPrivate)
440{
441 if (sockaddr->sa_family == AF_INET)
442 setAddress(htonl(hostlong: ((const sockaddr_in *)sockaddr)->sin_addr.s_addr));
443 else if (sockaddr->sa_family == AF_INET6)
444 setAddress(((const sockaddr_in6 *)sockaddr)->sin6_addr.s6_addr);
445}
446
447/*!
448 Constructs a copy of the given \a address.
449*/
450QHostAddress::QHostAddress(const QHostAddress &address)
451 : d(address.d)
452{
453}
454
455/*!
456 \fn QHostAddress::QHostAddress(QHostAddress &&other)
457
458 \since 6.8
459
460 Move-constructs a new QHostAddress from \a other.
461
462 \note The moved-from object \a other is placed in a partially-formed state,
463 in which the only valid operations are destruction and assignment of a new
464 value.
465*/
466
467/*!
468 Constructs a QHostAddress object for \a address.
469*/
470QHostAddress::QHostAddress(SpecialAddress address)
471 : d(new QHostAddressPrivate)
472{
473 setAddress(address);
474}
475
476/*!
477 Destroys the host address object.
478*/
479QHostAddress::~QHostAddress()
480{
481}
482
483/*!
484 Assigns another host \a address to this object, and returns a reference
485 to this object.
486*/
487QHostAddress &QHostAddress::operator=(const QHostAddress &address)
488{
489 d = address.d;
490 return *this;
491}
492
493/*!
494 \since 5.8
495 Assigns the special address \a address to this object, and returns a
496 reference to this object.
497
498 \sa setAddress()
499*/
500QHostAddress &QHostAddress::operator=(SpecialAddress address)
501{
502 setAddress(address);
503 return *this;
504}
505
506/*!
507 \fn void QHostAddress::swap(QHostAddress &other)
508 \since 5.6
509 \memberswap{host address}
510*/
511
512/*!
513 \fn bool QHostAddress::operator!=(const QHostAddress &other) const
514 \since 4.2
515
516 Returns \c true if this host address is not the same as the \a other
517 address given; otherwise returns \c false.
518*/
519
520/*!
521 \fn bool QHostAddress::operator!=(SpecialAddress other) const
522
523 Returns \c true if this host address is not the same as the \a other
524 address given; otherwise returns \c false.
525*/
526
527/*!
528 Sets the host address to null and sets the protocol to
529 QAbstractSocket::UnknownNetworkLayerProtocol.
530
531 \sa QHostAddress::Null
532*/
533void QHostAddress::clear()
534{
535 d.detach();
536 d->clear();
537}
538
539/*!
540 Set the IPv4 address specified by \a ip4Addr.
541*/
542void QHostAddress::setAddress(quint32 ip4Addr)
543{
544 d.detach();
545 d->setAddress(ip4Addr);
546}
547
548/*!
549 \overload
550 \since 5.5
551
552 Set the IPv6 address specified by \a ip6Addr.
553
554 \a ip6Addr must be an array of 16 bytes in network byte order
555 (high-order byte first).
556*/
557void QHostAddress::setAddress(const quint8 *ip6Addr)
558{
559 d.detach();
560 d->setAddress(ip6Addr);
561}
562
563/*!
564 \overload
565
566 Set the IPv6 address specified by \a ip6Addr.
567*/
568void QHostAddress::setAddress(const Q_IPV6ADDR &ip6Addr)
569{
570 d.detach();
571 d->setAddress(ip6Addr);
572}
573
574/*!
575 \overload
576
577 Sets the IPv4 or IPv6 address specified by the string
578 representation specified by \a address (e.g. "127.0.0.1").
579 Returns \c true and sets the address if the address was successfully
580 parsed; otherwise returns \c false.
581*/
582bool QHostAddress::setAddress(const QString &address)
583{
584 d.detach();
585 return d->parse(ipString: address);
586}
587
588/*!
589 \fn void QHostAddress::setAddress(const sockaddr *sockaddr)
590 \overload
591
592 Sets the IPv4 or IPv6 address specified by the native structure \a
593 sockaddr. Returns \c true and sets the address if the address was
594 successfully parsed; otherwise returns \c false.
595*/
596void QHostAddress::setAddress(const struct sockaddr *sockaddr)
597{
598 d.detach();
599 clear();
600 if (sockaddr->sa_family == AF_INET)
601 setAddress(htonl(hostlong: ((const sockaddr_in *)sockaddr)->sin_addr.s_addr));
602 else if (sockaddr->sa_family == AF_INET6)
603 setAddress(((const sockaddr_in6 *)sockaddr)->sin6_addr.s6_addr);
604}
605
606/*!
607 \overload
608 \since 5.8
609
610 Sets the special address specified by \a address.
611*/
612void QHostAddress::setAddress(SpecialAddress address)
613{
614 clear();
615
616 Q_IPV6ADDR ip6;
617 memset(s: &ip6, c: 0, n: sizeof ip6);
618 quint32 ip4 = INADDR_ANY;
619
620 switch (address) {
621 case Null:
622 return;
623
624 case Broadcast:
625 ip4 = INADDR_BROADCAST;
626 break;
627 case LocalHost:
628 ip4 = INADDR_LOOPBACK;
629 break;
630 case AnyIPv4:
631 break;
632
633 case LocalHostIPv6:
634 ip6[15] = 1;
635 Q_FALLTHROUGH();
636 case AnyIPv6:
637 d->setAddress(ip6);
638 return;
639
640 case Any:
641 d->protocol = QHostAddress::AnyIPProtocol;
642 return;
643 }
644
645 // common IPv4 part
646 d->setAddress(ip4);
647}
648
649/*!
650 Returns the IPv4 address as a number.
651
652 For example, if the address is 127.0.0.1, the returned value is
653 2130706433 (i.e. 0x7f000001).
654
655 This value is valid if the protocol() is
656 \l{QAbstractSocket::}{IPv4Protocol},
657 or if the protocol is
658 \l{QAbstractSocket::}{IPv6Protocol},
659 and the IPv6 address is an IPv4 mapped address (RFC4291). In those
660 cases, \a ok will be set to true. Otherwise, it will be set to false.
661
662 \sa toString()
663*/
664quint32 QHostAddress::toIPv4Address(bool *ok) const
665{
666 quint32 dummy;
667 if (ok)
668 *ok = d->protocol == QHostAddress::IPv4Protocol || d->protocol == QHostAddress::AnyIPProtocol
669 || (d->protocol == QHostAddress::IPv6Protocol
670 && convertToIpv4(a&: dummy, a6: d->a6, mode: ConversionMode(QHostAddress::ConvertV4MappedToIPv4
671 | QHostAddress::ConvertUnspecifiedAddress)));
672 return d->a;
673}
674
675/*!
676 Returns the network layer protocol of the host address.
677*/
678QHostAddress::NetworkLayerProtocol QHostAddress::protocol() const
679{
680 return QHostAddress::NetworkLayerProtocol(d->protocol);
681}
682
683/*!
684 Returns the IPv6 address as a Q_IPV6ADDR structure. The structure
685 consists of 16 unsigned characters.
686
687 \snippet code/src_network_kernel_qhostaddress.cpp 0
688
689 This value is valid if the protocol() is
690 \l{QAbstractSocket::}{IPv6Protocol}.
691 If the protocol is
692 \l{QAbstractSocket::}{IPv4Protocol},
693 then the address is returned as an IPv4 mapped IPv6 address. (RFC4291)
694
695 \sa toString()
696*/
697Q_IPV6ADDR QHostAddress::toIPv6Address() const
698{
699 return d->a6;
700}
701
702/*!
703 Returns the address as a string.
704
705 For example, if the address is the IPv4 address 127.0.0.1, the
706 returned string is "127.0.0.1". For IPv6 the string format will
707 follow the RFC5952 recommendation.
708 For QHostAddress::Any, its IPv4 address will be returned ("0.0.0.0")
709
710 \sa toIPv4Address()
711*/
712QString QHostAddress::toString() const
713{
714 QString s;
715 if (d->protocol == QHostAddress::IPv4Protocol
716 || d->protocol == QHostAddress::AnyIPProtocol) {
717 quint32 i = toIPv4Address();
718 QIPAddressUtils::toString(appendTo&: s, address: i);
719 } else if (d->protocol == QHostAddress::IPv6Protocol) {
720 QIPAddressUtils::toString(appendTo&: s, address: d->a6.c);
721 if (!d->scopeId.isEmpty())
722 s += u'%' + d->scopeId;
723 }
724 return s;
725}
726
727/*!
728 \since 4.1
729
730 Returns the scope ID of an IPv6 address. For IPv4 addresses, or if the
731 address does not contain a scope ID, an empty QString is returned.
732
733 The IPv6 scope ID specifies the scope of \e reachability for non-global
734 IPv6 addresses, limiting the area in which the address can be used. All
735 IPv6 addresses are associated with such a reachability scope. The scope ID
736 is used to disambiguate addresses that are not guaranteed to be globally
737 unique.
738
739 IPv6 specifies the following four levels of reachability:
740
741 \list
742
743 \li Node-local: Addresses that are only used for communicating with
744 services on the same interface (e.g., the loopback interface "::1").
745
746 \li Link-local: Addresses that are local to the network interface
747 (\e{link}). There is always one link-local address for each IPv6 interface
748 on your host. Link-local addresses ("fe80...") are generated from the MAC
749 address of the local network adaptor, and are not guaranteed to be unique.
750
751 \li Global: For globally routable addresses, such as public servers on the
752 Internet.
753
754 \endlist
755
756 When using a link-local or site-local address for IPv6 connections, you
757 must specify the scope ID. The scope ID for a link-local address is
758 usually the same as the interface name (e.g., "eth0", "en1") or number
759 (e.g., "1", "2").
760
761 \sa setScopeId(), QNetworkInterface, QNetworkInterface::interfaceFromName
762*/
763QString QHostAddress::scopeId() const
764{
765 return (d->protocol == QHostAddress::IPv6Protocol) ? d->scopeId : QString();
766}
767
768/*!
769 \since 4.1
770
771 Sets the IPv6 scope ID of the address to \a id. If the address protocol is
772 not IPv6, this function does nothing. The scope ID may be set as an
773 interface name (such as "eth0" or "en1") or as an integer representing the
774 interface index. If \a id is an interface name, QtNetwork will convert to
775 an interface index using QNetworkInterface::interfaceIndexFromName() before
776 calling the operating system networking functions.
777
778 \sa scopeId(), QNetworkInterface, QNetworkInterface::interfaceFromName
779*/
780void QHostAddress::setScopeId(const QString &id)
781{
782 d.detach();
783 if (d->protocol == QHostAddress::IPv6Protocol)
784 d->scopeId = id;
785}
786
787/*!
788 Returns \c true if this host address is the same as the \a other address
789 given; otherwise returns \c false. This operator just calls isEqual(other, StrictConversion).
790
791 \sa isEqual()
792*/
793bool QHostAddress::operator==(const QHostAddress &other) const
794{
795 return d == other.d || isEqual(address: other, mode: StrictConversion);
796}
797
798/*!
799 \since 5.8
800
801 Returns \c true if this host address is the same as the \a other address
802 given; otherwise returns \c false.
803
804 The parameter \a mode controls which conversions are performed between addresses
805 of differing protocols. If no \a mode is given, \c TolerantConversion is performed
806 by default.
807
808 \sa ConversionMode, operator==()
809 */
810bool QHostAddress::isEqual(const QHostAddress &other, ConversionMode mode) const
811{
812 if (d == other.d)
813 return true;
814
815 if (d->protocol == QHostAddress::IPv4Protocol) {
816 switch (other.d->protocol) {
817 case QHostAddress::IPv4Protocol:
818 return d->a == other.d->a;
819 case QHostAddress::IPv6Protocol:
820 quint32 a4;
821 return convertToIpv4(a&: a4, a6: other.d->a6, mode) && (a4 == d->a);
822 case QHostAddress::AnyIPProtocol:
823 return (mode & QHostAddress::ConvertUnspecifiedAddress) && d->a == 0;
824 case QHostAddress::UnknownNetworkLayerProtocol:
825 return false;
826 }
827 }
828
829 if (d->protocol == QHostAddress::IPv6Protocol) {
830 switch (other.d->protocol) {
831 case QHostAddress::IPv4Protocol:
832 quint32 a4;
833 return convertToIpv4(a&: a4, a6: d->a6, mode) && (a4 == other.d->a);
834 case QHostAddress::IPv6Protocol:
835 return memcmp(s1: &d->a6, s2: &other.d->a6, n: sizeof(Q_IPV6ADDR)) == 0;
836 case QHostAddress::AnyIPProtocol:
837 return (mode & QHostAddress::ConvertUnspecifiedAddress)
838 && (d->a6_64.c[0] == 0) && (d->a6_64.c[1] == 0);
839 case QHostAddress::UnknownNetworkLayerProtocol:
840 return false;
841 }
842 }
843
844 if ((d->protocol == QHostAddress::AnyIPProtocol)
845 && (mode & QHostAddress::ConvertUnspecifiedAddress)) {
846 switch (other.d->protocol) {
847 case QHostAddress::IPv4Protocol:
848 return other.d->a == 0;
849 case QHostAddress::IPv6Protocol:
850 return (other.d->a6_64.c[0] == 0) && (other.d->a6_64.c[1] == 0);
851 default:
852 break;
853 }
854 }
855
856 return d->protocol == other.d->protocol;
857}
858
859/*!
860 Returns \c true if this host address is the same as the \a other
861 address given; otherwise returns \c false.
862*/
863bool QHostAddress::operator ==(SpecialAddress other) const
864{
865 quint32 ip4 = INADDR_ANY;
866 switch (other) {
867 case Null:
868 return d->protocol == QHostAddress::UnknownNetworkLayerProtocol;
869
870 case Broadcast:
871 ip4 = INADDR_BROADCAST;
872 break;
873
874 case LocalHost:
875 ip4 = INADDR_LOOPBACK;
876 break;
877
878 case Any:
879 return d->protocol == QHostAddress::AnyIPProtocol;
880
881 case AnyIPv4:
882 break;
883
884 case LocalHostIPv6:
885 case AnyIPv6:
886 if (d->protocol == QHostAddress::IPv6Protocol) {
887 quint64 second = quint8(other == LocalHostIPv6); // 1 for localhost, 0 for any
888 return d->a6_64.c[0] == 0 && d->a6_64.c[1] == qToBigEndian(source: second);
889 }
890 return false;
891 }
892
893 // common IPv4 part
894 return d->protocol == QHostAddress::IPv4Protocol && d->a == ip4;
895}
896
897/*!
898 Returns \c true if this host address is not valid for any host or interface.
899
900 The default constructor creates a null address.
901
902 \sa QHostAddress::Null
903*/
904bool QHostAddress::isNull() const
905{
906 return d->protocol == QHostAddress::UnknownNetworkLayerProtocol;
907}
908
909/*!
910 \since 4.5
911
912 Returns \c true if this IP is in the subnet described by the network
913 prefix \a subnet and netmask \a netmask.
914
915 An IP is considered to belong to a subnet if it is contained
916 between the lowest and the highest address in that subnet. In the
917 case of IP version 4, the lowest address is the network address,
918 while the highest address is the broadcast address.
919
920 The \a subnet argument does not have to be the actual network
921 address (the lowest address in the subnet). It can be any valid IP
922 belonging to that subnet. In particular, if it is equal to the IP
923 address held by this object, this function will always return true
924 (provided the netmask is a valid value).
925
926 \sa parseSubnet()
927*/
928bool QHostAddress::isInSubnet(const QHostAddress &subnet, int netmask) const
929{
930 if (subnet.protocol() != d->protocol || netmask < 0)
931 return false;
932
933 union {
934 quint32 ip;
935 quint8 data[4];
936 } ip4, net4;
937 const quint8 *ip;
938 const quint8 *net;
939 if (d->protocol == QHostAddress::IPv4Protocol) {
940 if (netmask > 32)
941 netmask = 32;
942 ip4.ip = qToBigEndian(source: d->a);
943 net4.ip = qToBigEndian(source: subnet.d->a);
944 ip = ip4.data;
945 net = net4.data;
946 } else if (d->protocol == QHostAddress::IPv6Protocol) {
947 if (netmask > 128)
948 netmask = 128;
949 ip = d->a6.c;
950 net = subnet.d->a6.c;
951 } else {
952 return false;
953 }
954
955 if (netmask >= 8 && memcmp(s1: ip, s2: net, n: netmask / 8) != 0)
956 return false;
957 if ((netmask & 7) == 0)
958 return true;
959
960 // compare the last octet now
961 quint8 bytemask = 256 - (1 << (8 - (netmask & 7)));
962 quint8 ipbyte = ip[netmask / 8];
963 quint8 netbyte = net[netmask / 8];
964 return (ipbyte & bytemask) == (netbyte & bytemask);
965}
966
967/*!
968 \since 4.5
969 \overload
970
971 Returns \c true if this IP is in the subnet described by \a
972 subnet. The QHostAddress member of \a subnet contains the network
973 prefix and the int (second) member contains the netmask (prefix
974 length).
975*/
976bool QHostAddress::isInSubnet(const std::pair<QHostAddress, int> &subnet) const
977{
978 return isInSubnet(subnet: subnet.first, netmask: subnet.second);
979}
980
981
982/*!
983 \since 4.5
984
985 Parses the IP and subnet information contained in \a subnet and
986 returns the network prefix for that network and its prefix length.
987
988 The IP address and the netmask must be separated by a slash
989 (/).
990
991 This function supports arguments in the form:
992 \list
993 \li 123.123.123.123/n where n is any value between 0 and 32
994 \li 123.123.123.123/255.255.255.255
995 \li <ipv6-address>/n where n is any value between 0 and 128
996 \endlist
997
998 For IP version 4, this function accepts as well missing trailing
999 components (i.e., less than 4 octets, like "192.168.1"), followed
1000 or not by a dot. If the netmask is also missing in that case, it
1001 is set to the number of octets actually passed (in the example
1002 above, it would be 24, for 3 octets).
1003
1004 \sa isInSubnet()
1005*/
1006std::pair<QHostAddress, int> QHostAddress::parseSubnet(const QString &subnet)
1007{
1008 // We support subnets in the form:
1009 // ddd.ddd.ddd.ddd/nn
1010 // ddd.ddd.ddd/nn
1011 // ddd.ddd/nn
1012 // ddd/nn
1013 // ddd.ddd.ddd.
1014 // ddd.ddd.ddd
1015 // ddd.ddd.
1016 // ddd.ddd
1017 // ddd.
1018 // ddd
1019 // <ipv6-address>/nn
1020 //
1021 // where nn can be an IPv4-style netmask for the IPv4 forms
1022
1023 const std::pair<QHostAddress, int> invalid = std::pair(QHostAddress(), -1);
1024 if (subnet.isEmpty())
1025 return invalid;
1026
1027 qsizetype slash = subnet.indexOf(ch: u'/');
1028 QStringView netStr(subnet);
1029 if (slash != -1)
1030 netStr.truncate(n: slash);
1031
1032 int netmask = -1;
1033 bool isIpv6 = netStr.contains(c: u':');
1034
1035 if (slash != -1) {
1036 // is the netmask given in IP-form or in bit-count form?
1037 if (!isIpv6 && subnet.indexOf(ch: u'.', from: slash + 1) != -1) {
1038 // IP-style, convert it to bit-count form
1039 QHostAddress mask;
1040 QNetmask parser;
1041 if (!mask.setAddress(subnet.mid(position: slash + 1)))
1042 return invalid;
1043 if (!parser.setAddress(mask))
1044 return invalid;
1045 netmask = parser.prefixLength();
1046 } else {
1047 bool ok;
1048 netmask = QStringView{subnet}.mid(pos: slash + 1).toUInt(ok: &ok);
1049 if (!ok)
1050 return invalid; // failed to parse the subnet
1051 }
1052 }
1053
1054 if (isIpv6) {
1055 // looks like it's an IPv6 address
1056 if (netmask > 128)
1057 return invalid; // invalid netmask
1058 if (netmask < 0)
1059 netmask = 128;
1060
1061 QHostAddress net;
1062 if (!net.setAddress(netStr.toString()))
1063 return invalid; // failed to parse the IP
1064
1065 clearBits(where: net.d->a6.c, start: netmask, end: 128);
1066 return std::pair(net, netmask);
1067 }
1068
1069 if (netmask > 32)
1070 return invalid; // invalid netmask
1071
1072 // parse the address manually
1073 auto parts = netStr.split(sep: u'.');
1074 if (parts.isEmpty() || parts.size() > 4)
1075 return invalid; // invalid IPv4 address
1076
1077 if (parts.constLast().isEmpty())
1078 parts.removeLast();
1079
1080 quint32 addr = 0;
1081 for (int i = 0; i < parts.size(); ++i) {
1082 bool ok;
1083 uint byteValue = parts.at(i).toUInt(ok: &ok);
1084 if (!ok || byteValue > 255)
1085 return invalid; // invalid IPv4 address
1086
1087 addr <<= 8;
1088 addr += byteValue;
1089 }
1090 addr <<= 8 * (4 - parts.size());
1091 if (netmask == -1) {
1092 netmask = 8 * parts.size();
1093 } else if (netmask == 0) {
1094 // special case here
1095 // x86's instructions "shr" and "shl" do not operate when
1096 // their argument is 32, so the code below doesn't work as expected
1097 addr = 0;
1098 } else if (netmask != 32) {
1099 // clear remaining bits
1100 quint32 mask = quint32(0xffffffff) >> (32 - netmask) << (32 - netmask);
1101 addr &= mask;
1102 }
1103
1104 return std::pair(QHostAddress(addr), netmask);
1105}
1106
1107/*!
1108 \since 5.0
1109
1110 returns \c true if the address is the IPv6 loopback address, or any
1111 of the IPv4 loopback addresses.
1112*/
1113bool QHostAddress::isLoopback() const
1114{
1115 return d->classify() == LoopbackAddress;
1116}
1117
1118/*!
1119 \since 5.11
1120
1121 Returns \c true if the address is an IPv4 or IPv6 global address, \c false
1122 otherwise. A global address is an address that is not reserved for
1123 special purposes (like loopback or multicast) or future purposes.
1124
1125 Note that IPv6 unique local unicast addresses are considered global
1126 addresses (see isUniqueLocalUnicast()), as are IPv4 addresses reserved for
1127 local networks by \l {RFC 1918}.
1128
1129 Also note that IPv6 site-local addresses are deprecated and should be
1130 considered as global in new applications. This function returns true for
1131 site-local addresses too.
1132
1133 \sa isLoopback(), isSiteLocal(), isUniqueLocalUnicast(), isPrivateUse()
1134*/
1135bool QHostAddress::isGlobal() const
1136{
1137 return d->classify() & GlobalAddress; // GlobalAddress is a bit
1138}
1139
1140/*!
1141 \since 5.11
1142
1143 Returns \c true if the address is an IPv4 or IPv6 link-local address, \c
1144 false otherwise.
1145
1146 An IPv4 link-local address is an address in the network 169.254.0.0/16. An
1147 IPv6 link-local address is one in the network fe80::/10. See the
1148 \l{https://www.iana.org/assignments/ipv6-address-space/ipv6-address-space.xhtml}{IANA
1149 IPv6 Address Space} registry for more information.
1150
1151 \sa isLoopback(), isGlobal(), isMulticast(), isSiteLocal(), isUniqueLocalUnicast(), isPrivateUse()
1152*/
1153bool QHostAddress::isLinkLocal() const
1154{
1155 return d->classify() == LinkLocalAddress;
1156}
1157
1158/*!
1159 \since 5.11
1160
1161 Returns \c true if the address is an IPv6 site-local address, \c
1162 false otherwise.
1163
1164 An IPv6 site-local address is one in the network fec0::/10. See the
1165 \l{https://www.iana.org/assignments/ipv6-address-space/ipv6-address-space.xhtml}{IANA
1166 IPv6 Address Space} registry for more information.
1167
1168 IPv6 site-local addresses are deprecated and should not be depended upon in
1169 new applications. New applications should not depend on this function and
1170 should consider site-local addresses the same as global (which is why
1171 isGlobal() also returns true). Site-local addresses were replaced by Unique
1172 Local Addresses (ULA).
1173
1174 \sa isLoopback(), isGlobal(), isMulticast(), isLinkLocal(), isUniqueLocalUnicast(), isPrivateUse()
1175*/
1176bool QHostAddress::isSiteLocal() const
1177{
1178 return d->classify() == SiteLocalAddress;
1179}
1180
1181/*!
1182 \since 5.11
1183
1184 Returns \c true if the address is an IPv6 unique local unicast address, \c
1185 false otherwise.
1186
1187 An IPv6 unique local unicast address is one in the network fc00::/7. See the
1188 \l{https://www.iana.org/assignments/ipv6-address-space/ipv6-address-space.xhtml}
1189 {IANA IPv6 Address Space} registry for more information.
1190
1191 Note that Unique local unicast addresses count as global addresses too. RFC
1192 4193 says that, in practice, "applications may treat these addresses like
1193 global scoped addresses." Only routers need care about the distinction.
1194
1195 \sa isLoopback(), isGlobal(), isMulticast(), isLinkLocal(), isPrivateUse()
1196*/
1197bool QHostAddress::isUniqueLocalUnicast() const
1198{
1199 return d->classify() == UniqueLocalAddress;
1200}
1201
1202/*!
1203 \since 5.6
1204
1205 Returns \c true if the address is an IPv4 or IPv6 multicast address, \c
1206 false otherwise.
1207
1208 \sa isLoopback(), isGlobal(), isLinkLocal(), isSiteLocal(), isUniqueLocalUnicast(), isPrivateUse()
1209*/
1210bool QHostAddress::isMulticast() const
1211{
1212 return d->classify() == MulticastAddress;
1213}
1214
1215/*!
1216 \since 5.11
1217
1218 Returns \c true if the address is the IPv4 broadcast address, \c false
1219 otherwise. The IPv4 broadcast address is 255.255.255.255.
1220
1221 Note that this function does not return true for an IPv4 network's local
1222 broadcast address. For that, please use \l QNetworkInterface to obtain the
1223 broadcast addresses of the local machine.
1224
1225 \sa isLoopback(), isGlobal(), isMulticast(), isLinkLocal(), isUniqueLocalUnicast(), isPrivateUse()
1226*/
1227bool QHostAddress::isBroadcast() const
1228{
1229 return d->classify() == BroadcastAddress;
1230}
1231
1232/*!
1233 \since 6.6
1234
1235 Returns \c true if the address is an IPv6 unique local unicast address or
1236 IPv4 address reserved for local networks by \l {RFC 1918}, \c false otherwise.
1237
1238 \sa isLoopback(), isGlobal(), isMulticast(), isLinkLocal(), isUniqueLocalUnicast(), isBroadcast()
1239*/
1240bool QHostAddress::isPrivateUse() const
1241{
1242 const AddressClassification classification = d->classify();
1243 return (classification == PrivateNetworkAddress) || (classification == UniqueLocalAddress);
1244}
1245
1246#ifndef QT_NO_DEBUG_STREAM
1247QDebug operator<<(QDebug d, const QHostAddress &address)
1248{
1249 QDebugStateSaver saver(d);
1250 d.resetFormat().nospace();
1251 if (address == QHostAddress::Any)
1252 d << "QHostAddress(QHostAddress::Any)";
1253 else
1254 d << "QHostAddress(" << address.toString() << ')';
1255 return d;
1256}
1257#endif
1258
1259/*!
1260 \since 5.0
1261 \qhashold{QHostAddress}
1262*/
1263size_t qHash(const QHostAddress &key, size_t seed) noexcept
1264{
1265 return qHashBits(p: key.d->a6.c, size: 16, seed);
1266}
1267
1268/*!
1269 \fn bool QHostAddress::operator==(QHostAddress::SpecialAddress lhs, const QHostAddress &rhs)
1270
1271 Returns \c true if special address \a lhs is the same as host address \a rhs;
1272 otherwise returns \c false.
1273
1274 \sa isEqual()
1275*/
1276
1277/*!
1278 \fn bool QHostAddress::operator!=(QHostAddress::SpecialAddress lhs, const QHostAddress &rhs)
1279 \since 5.9
1280
1281 Returns \c false if special address \a lhs is the same as host address \a rhs;
1282 otherwise returns \c true.
1283
1284 \sa isEqual()
1285*/
1286
1287#ifndef QT_NO_DATASTREAM
1288
1289/*! \relates QHostAddress
1290
1291 Writes host address \a address to the stream \a out and returns a reference
1292 to the stream.
1293
1294 \sa {Serializing Qt Data Types}
1295*/
1296QDataStream &operator<<(QDataStream &out, const QHostAddress &address)
1297{
1298 qint8 prot;
1299 prot = qint8(address.protocol());
1300 out << prot;
1301 switch (address.protocol()) {
1302 case QHostAddress::UnknownNetworkLayerProtocol:
1303 case QHostAddress::AnyIPProtocol:
1304 break;
1305 case QHostAddress::IPv4Protocol:
1306 out << address.toIPv4Address();
1307 break;
1308 case QHostAddress::IPv6Protocol:
1309 {
1310 Q_IPV6ADDR ipv6 = address.toIPv6Address();
1311 for (int i = 0; i < 16; ++i)
1312 out << ipv6[i];
1313 out << address.scopeId();
1314 }
1315 break;
1316 }
1317 return out;
1318}
1319
1320/*! \relates QHostAddress
1321
1322 Reads a host address into \a address from the stream \a in and returns a
1323 reference to the stream.
1324
1325 \sa {Serializing Qt Data Types}
1326*/
1327QDataStream &operator>>(QDataStream &in, QHostAddress &address)
1328{
1329 qint8 prot;
1330 in >> prot;
1331 switch (QHostAddress::NetworkLayerProtocol(prot)) {
1332 case QHostAddress::UnknownNetworkLayerProtocol:
1333 address.clear();
1334 break;
1335 case QHostAddress::IPv4Protocol:
1336 {
1337 quint32 ipv4;
1338 in >> ipv4;
1339 address.setAddress(ipv4);
1340 }
1341 break;
1342 case QHostAddress::IPv6Protocol:
1343 {
1344 Q_IPV6ADDR ipv6;
1345 for (int i = 0; i < 16; ++i)
1346 in >> ipv6[i];
1347 address.setAddress(ipv6);
1348
1349 QString scope;
1350 in >> scope;
1351 address.setScopeId(scope);
1352 }
1353 break;
1354 case QHostAddress::AnyIPProtocol:
1355 address = QHostAddress::Any;
1356 break;
1357 default:
1358 address.clear();
1359 in.setStatus(QDataStream::ReadCorruptData);
1360 }
1361 return in;
1362}
1363
1364#endif //QT_NO_DATASTREAM
1365
1366QT_END_NAMESPACE
1367
1368#include "moc_qhostaddress.cpp"
1369

source code of qtbase/src/network/kernel/qhostaddress.cpp