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

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