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