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