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