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 
65 QT_BEGIN_NAMESPACE
66 
QHostAddressPrivate()67 QHostAddressPrivate::QHostAddressPrivate()
68     : a(0), protocol(QAbstractSocket::UnknownNetworkLayerProtocol)
69 {
70     memset(&a6, 0, sizeof(a6));
71 }
72 
setAddress(quint32 a_)73 void 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
convertToIpv4(quint32 & a,const Q_IPV6ADDR & a6,const QHostAddress::ConversionMode mode)90 static 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 
setAddress(const quint8 * a_)123 void 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 
setAddress(const Q_IPV6ADDR & a_)132 void QHostAddressPrivate::setAddress(const Q_IPV6ADDR &a_)
133 {
134     setAddress(a_.c);
135 }
136 
parseIp6(const QString & address,QIPAddressUtils::IPv6Address & addr,QString * scopeId)137 static bool parseIp6(const QString &address, QIPAddressUtils::IPv6Address &addr, QString *scopeId)
138 {
139     QStringRef 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.constBegin(), tmp.constEnd()) == nullptr;
148 }
149 
parse(const QString & ipString)150 bool 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 
clear()175 void QHostAddressPrivate::clear()
176 {
177     a = 0;
178     protocol = QAbstractSocket::UnknownNetworkLayerProtocol;
179     memset(&a6, 0, sizeof(a6));
180 }
181 
classify() const182 AddressClassification 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 
setAddress(const QHostAddress & address)252 bool 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 
clearBits(quint8 * where,int start,int end)320 static 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 
address(QAbstractSocket::NetworkLayerProtocol protocol) const334 QHostAddress 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 */
QHostAddress()411 QHostAddress::QHostAddress()
412     : d(new QHostAddressPrivate)
413 {
414 }
415 
416 /*!
417     Constructs a host address object with the IPv4 address \a ip4Addr.
418 */
QHostAddress(quint32 ip4Addr)419 QHostAddress::QHostAddress(quint32 ip4Addr)
420     : d(new QHostAddressPrivate)
421 {
422     setAddress(ip4Addr);
423 }
424 
425 /*!
426     Constructs a host address object with the IPv6 address \a ip6Addr.
427 
428     \a ip6Addr must be a 16-byte array in network byte order (big
429     endian).
430 */
QHostAddress(quint8 * ip6Addr)431 QHostAddress::QHostAddress(quint8 *ip6Addr)
432     : d(new QHostAddressPrivate)
433 {
434     setAddress(ip6Addr);
435 }
436 
437 /*!
438     \since 5.5
439     Constructs a host address object with the IPv6 address \a ip6Addr.
440 
441     \a ip6Addr must be a 16-byte array in network byte order (big
442     endian).
443 */
QHostAddress(const quint8 * ip6Addr)444 QHostAddress::QHostAddress(const quint8 *ip6Addr)
445     : d(new QHostAddressPrivate)
446 {
447     setAddress(ip6Addr);
448 }
449 
450 /*!
451     Constructs a host address object with the IPv6 address \a ip6Addr.
452 */
QHostAddress(const Q_IPV6ADDR & ip6Addr)453 QHostAddress::QHostAddress(const Q_IPV6ADDR &ip6Addr)
454     : d(new QHostAddressPrivate)
455 {
456     setAddress(ip6Addr);
457 }
458 
459 /*!
460     Constructs an IPv4 or IPv6 address based on the string \a address
461     (e.g., "127.0.0.1").
462 
463     \sa setAddress()
464 */
QHostAddress(const QString & address)465 QHostAddress::QHostAddress(const QString &address)
466     : d(new QHostAddressPrivate)
467 {
468     d->parse(address);
469 }
470 
471 /*!
472     \fn QHostAddress::QHostAddress(const sockaddr *sockaddr)
473 
474     Constructs an IPv4 or IPv6 address using the address specified by
475     the native structure \a sockaddr.
476 
477     \sa setAddress()
478 */
QHostAddress(const struct sockaddr * sockaddr)479 QHostAddress::QHostAddress(const struct sockaddr *sockaddr)
480     : d(new QHostAddressPrivate)
481 {
482 #ifndef Q_OS_WINRT
483     if (sockaddr->sa_family == AF_INET)
484         setAddress(htonl(((const sockaddr_in *)sockaddr)->sin_addr.s_addr));
485     else if (sockaddr->sa_family == AF_INET6)
486         setAddress(((const sockaddr_in6 *)sockaddr)->sin6_addr.s6_addr);
487 #else
488     Q_UNUSED(sockaddr)
489 #endif
490 }
491 
492 /*!
493     Constructs a copy of the given \a address.
494 */
QHostAddress(const QHostAddress & address)495 QHostAddress::QHostAddress(const QHostAddress &address)
496     : d(address.d)
497 {
498 }
499 
500 /*!
501     Constructs a QHostAddress object for \a address.
502 */
QHostAddress(SpecialAddress address)503 QHostAddress::QHostAddress(SpecialAddress address)
504     : d(new QHostAddressPrivate)
505 {
506     setAddress(address);
507 }
508 
509 /*!
510     Destroys the host address object.
511 */
~QHostAddress()512 QHostAddress::~QHostAddress()
513 {
514 }
515 
516 /*!
517     Assigns another host \a address to this object, and returns a reference
518     to this object.
519 */
operator =(const QHostAddress & address)520 QHostAddress &QHostAddress::operator=(const QHostAddress &address)
521 {
522     d = address.d;
523     return *this;
524 }
525 
526 #if QT_DEPRECATED_SINCE(5, 8)
527 /*!
528     Assigns the host address \a address to this object, and returns a
529     reference to this object.
530 
531     \sa setAddress()
532 */
operator =(const QString & address)533 QHostAddress &QHostAddress::operator=(const QString &address)
534 {
535     setAddress(address);
536     return *this;
537 }
538 #endif
539 
540 /*!
541     \since 5.8
542     Assigns the special address \a address to this object, and returns a
543     reference to this object.
544 
545     \sa setAddress()
546 */
operator =(SpecialAddress address)547 QHostAddress &QHostAddress::operator=(SpecialAddress address)
548 {
549     setAddress(address);
550     return *this;
551 }
552 
553 /*!
554     \fn void QHostAddress::swap(QHostAddress &other)
555     \since 5.6
556 
557     Swaps this host address with \a other. This operation is very fast
558     and never fails.
559 */
560 
561 /*!
562     \fn bool QHostAddress::operator!=(const QHostAddress &other) const
563     \since 4.2
564 
565     Returns \c true if this host address is not the same as the \a other
566     address given; otherwise returns \c false.
567 */
568 
569 /*!
570     \fn bool QHostAddress::operator!=(SpecialAddress other) const
571 
572     Returns \c true if this host address is not the same as the \a other
573     address given; otherwise returns \c false.
574 */
575 
576 /*!
577     Sets the host address to null and sets the protocol to
578     QAbstractSocket::UnknownNetworkLayerProtocol.
579 
580     \sa QHostAddress::Null
581 */
clear()582 void QHostAddress::clear()
583 {
584     d.detach();
585     d->clear();
586 }
587 
588 /*!
589     Set the IPv4 address specified by \a ip4Addr.
590 */
setAddress(quint32 ip4Addr)591 void QHostAddress::setAddress(quint32 ip4Addr)
592 {
593     d.detach();
594     d->setAddress(ip4Addr);
595 }
596 
597 /*!
598     \overload
599 
600     Set the IPv6 address specified by \a ip6Addr.
601 
602     \a ip6Addr must be an array of 16 bytes in network byte order
603     (high-order byte first).
604 */
setAddress(quint8 * ip6Addr)605 void QHostAddress::setAddress(quint8 *ip6Addr)
606 {
607     d.detach();
608     d->setAddress(ip6Addr);
609 }
610 
611 /*!
612     \overload
613     \since 5.5
614 
615     Set the IPv6 address specified by \a ip6Addr.
616 
617     \a ip6Addr must be an array of 16 bytes in network byte order
618     (high-order byte first).
619 */
setAddress(const quint8 * ip6Addr)620 void QHostAddress::setAddress(const quint8 *ip6Addr)
621 {
622     d.detach();
623     d->setAddress(ip6Addr);
624 }
625 
626 /*!
627     \overload
628 
629     Set the IPv6 address specified by \a ip6Addr.
630 */
setAddress(const Q_IPV6ADDR & ip6Addr)631 void QHostAddress::setAddress(const Q_IPV6ADDR &ip6Addr)
632 {
633     d.detach();
634     d->setAddress(ip6Addr);
635 }
636 
637 /*!
638     \overload
639 
640     Sets the IPv4 or IPv6 address specified by the string
641     representation specified by \a address (e.g. "127.0.0.1").
642     Returns \c true and sets the address if the address was successfully
643     parsed; otherwise returns \c false.
644 */
setAddress(const QString & address)645 bool QHostAddress::setAddress(const QString &address)
646 {
647     d.detach();
648     return d->parse(address);
649 }
650 
651 /*!
652     \fn void QHostAddress::setAddress(const sockaddr *sockaddr)
653     \overload
654 
655     Sets the IPv4 or IPv6 address specified by the native structure \a
656     sockaddr.  Returns \c true and sets the address if the address was
657     successfully parsed; otherwise returns \c false.
658 */
setAddress(const struct sockaddr * sockaddr)659 void QHostAddress::setAddress(const struct sockaddr *sockaddr)
660 {
661     d.detach();
662 #ifndef Q_OS_WINRT
663     clear();
664     if (sockaddr->sa_family == AF_INET)
665         setAddress(htonl(((const sockaddr_in *)sockaddr)->sin_addr.s_addr));
666     else if (sockaddr->sa_family == AF_INET6)
667         setAddress(((const sockaddr_in6 *)sockaddr)->sin6_addr.s6_addr);
668 #else
669     Q_UNUSED(sockaddr)
670 #endif
671 }
672 
673 /*!
674     \overload
675     \since 5.8
676 
677     Sets the special address specified by \a address.
678 */
setAddress(SpecialAddress address)679 void QHostAddress::setAddress(SpecialAddress address)
680 {
681     clear();
682 
683     Q_IPV6ADDR ip6;
684     memset(&ip6, 0, sizeof ip6);
685     quint32 ip4 = INADDR_ANY;
686 
687     switch (address) {
688     case Null:
689         return;
690 
691     case Broadcast:
692         ip4 = INADDR_BROADCAST;
693         break;
694     case LocalHost:
695         ip4 = INADDR_LOOPBACK;
696         break;
697     case AnyIPv4:
698         break;
699 
700     case LocalHostIPv6:
701         ip6[15] = 1;
702         Q_FALLTHROUGH();
703     case AnyIPv6:
704         d->setAddress(ip6);
705         return;
706 
707     case Any:
708         d->protocol = QAbstractSocket::AnyIPProtocol;
709         return;
710     }
711 
712     // common IPv4 part
713     d->setAddress(ip4);
714 }
715 
716 /*!
717     Returns the IPv4 address as a number.
718 
719     For example, if the address is 127.0.0.1, the returned value is
720     2130706433 (i.e. 0x7f000001).
721 
722     This value is valid if the protocol() is
723     \l{QAbstractSocket::}{IPv4Protocol},
724     or if the protocol is
725     \l{QAbstractSocket::}{IPv6Protocol},
726     and the IPv6 address is an IPv4 mapped address. (RFC4291)
727 
728     \sa toString()
729 */
toIPv4Address() const730 quint32 QHostAddress::toIPv4Address() const
731 {
732     return toIPv4Address(nullptr);
733 }
734 
735 /*!
736     Returns the IPv4 address as a number.
737 
738     For example, if the address is 127.0.0.1, the returned value is
739     2130706433 (i.e. 0x7f000001).
740 
741     This value is valid if the protocol() is
742     \l{QAbstractSocket::}{IPv4Protocol},
743     or if the protocol is
744     \l{QAbstractSocket::}{IPv6Protocol},
745     and the IPv6 address is an IPv4 mapped address. (RFC4291). In those
746     cases, \a ok will be set to true. Otherwise, it will be set to false.
747 
748     \sa toString()
749 */
toIPv4Address(bool * ok) const750 quint32 QHostAddress::toIPv4Address(bool *ok) const
751 {
752     quint32 dummy;
753     if (ok)
754         *ok = d->protocol == QAbstractSocket::IPv4Protocol || d->protocol == QAbstractSocket::AnyIPProtocol
755               || (d->protocol == QAbstractSocket::IPv6Protocol
756                   && convertToIpv4(dummy, d->a6, ConversionMode(QHostAddress::ConvertV4MappedToIPv4
757                                                                 | QHostAddress::ConvertUnspecifiedAddress)));
758     return d->a;
759 }
760 
761 /*!
762     Returns the network layer protocol of the host address.
763 */
protocol() const764 QAbstractSocket::NetworkLayerProtocol QHostAddress::protocol() const
765 {
766     return QAbstractSocket::NetworkLayerProtocol(d->protocol);
767 }
768 
769 /*!
770     Returns the IPv6 address as a Q_IPV6ADDR structure. The structure
771     consists of 16 unsigned characters.
772 
773     \snippet code/src_network_kernel_qhostaddress.cpp 0
774 
775     This value is valid if the protocol() is
776     \l{QAbstractSocket::}{IPv6Protocol}.
777     If the protocol is
778     \l{QAbstractSocket::}{IPv4Protocol},
779     then the address is returned an an IPv4 mapped IPv6 address. (RFC4291)
780 
781     \sa toString()
782 */
toIPv6Address() const783 Q_IPV6ADDR QHostAddress::toIPv6Address() const
784 {
785     return d->a6;
786 }
787 
788 /*!
789     Returns the address as a string.
790 
791     For example, if the address is the IPv4 address 127.0.0.1, the
792     returned string is "127.0.0.1". For IPv6 the string format will
793     follow the RFC5952 recommendation.
794     For QHostAddress::Any, its IPv4 address will be returned ("0.0.0.0")
795 
796     \sa toIPv4Address()
797 */
toString() const798 QString QHostAddress::toString() const
799 {
800     QString s;
801     if (d->protocol == QAbstractSocket::IPv4Protocol
802         || d->protocol == QAbstractSocket::AnyIPProtocol) {
803         quint32 i = toIPv4Address();
804         QIPAddressUtils::toString(s, i);
805     } else if (d->protocol == QAbstractSocket::IPv6Protocol) {
806         QIPAddressUtils::toString(s, d->a6.c);
807         if (!d->scopeId.isEmpty())
808             s.append(QLatin1Char('%') + d->scopeId);
809     }
810     return s;
811 }
812 
813 /*!
814     \since 4.1
815 
816     Returns the scope ID of an IPv6 address. For IPv4 addresses, or if the
817     address does not contain a scope ID, an empty QString is returned.
818 
819     The IPv6 scope ID specifies the scope of \e reachability for non-global
820     IPv6 addresses, limiting the area in which the address can be used. All
821     IPv6 addresses are associated with such a reachability scope. The scope ID
822     is used to disambiguate addresses that are not guaranteed to be globally
823     unique.
824 
825     IPv6 specifies the following four levels of reachability:
826 
827     \list
828 
829     \li Node-local: Addresses that are only used for communicating with
830     services on the same interface (e.g., the loopback interface "::1").
831 
832     \li Link-local: Addresses that are local to the network interface
833     (\e{link}). There is always one link-local address for each IPv6 interface
834     on your host. Link-local addresses ("fe80...") are generated from the MAC
835     address of the local network adaptor, and are not guaranteed to be unique.
836 
837     \li Global: For globally routable addresses, such as public servers on the
838     Internet.
839 
840     \endlist
841 
842     When using a link-local or site-local address for IPv6 connections, you
843     must specify the scope ID. The scope ID for a link-local address is
844     usually the same as the interface name (e.g., "eth0", "en1") or number
845     (e.g., "1", "2").
846 
847     \sa setScopeId(), QNetworkInterface, QNetworkInterface::interfaceFromName
848 */
scopeId() const849 QString QHostAddress::scopeId() const
850 {
851     return (d->protocol == QAbstractSocket::IPv6Protocol) ? d->scopeId : QString();
852 }
853 
854 /*!
855     \since 4.1
856 
857     Sets the IPv6 scope ID of the address to \a id. If the address protocol is
858     not IPv6, this function does nothing. The scope ID may be set as an
859     interface name (such as "eth0" or "en1") or as an integer representing the
860     interface index. If \a id is an interface name, QtNetwork will convert to
861     an interface index using QNetworkInterface::interfaceIndexFromName() before
862     calling the operating system networking functions.
863 
864     \sa scopeId(), QNetworkInterface, QNetworkInterface::interfaceFromName
865 */
setScopeId(const QString & id)866 void QHostAddress::setScopeId(const QString &id)
867 {
868     d.detach();
869     if (d->protocol == QAbstractSocket::IPv6Protocol)
870         d->scopeId = id;
871 }
872 
873 /*!
874     Returns \c true if this host address is the same as the \a other address
875     given; otherwise returns \c false. This operator just calls isEqual(other, StrictConversion).
876 
877     \sa isEqual()
878 */
operator ==(const QHostAddress & other) const879 bool QHostAddress::operator==(const QHostAddress &other) const
880 {
881     return d == other.d || isEqual(other, StrictConversion);
882 }
883 
884 /*!
885     \since 5.8
886 
887     Returns \c true if this host address is the same as the \a other address
888     given; otherwise returns \c false.
889 
890     The parameter \a mode controls which conversions are preformed between addresses
891     of differing protocols. If no \a mode is given, \c TolerantConversion is performed
892     by default.
893 
894     \sa ConversionMode, operator==()
895  */
isEqual(const QHostAddress & other,ConversionMode mode) const896 bool QHostAddress::isEqual(const QHostAddress &other, ConversionMode mode) const
897 {
898     if (d == other.d)
899         return true;
900 
901     if (d->protocol == QAbstractSocket::IPv4Protocol) {
902         switch (other.d->protocol) {
903         case QAbstractSocket::IPv4Protocol:
904             return d->a == other.d->a;
905         case QAbstractSocket::IPv6Protocol:
906             quint32 a4;
907             return convertToIpv4(a4, other.d->a6, mode) && (a4 == d->a);
908         case QAbstractSocket::AnyIPProtocol:
909             return (mode & QHostAddress::ConvertUnspecifiedAddress) && d->a == 0;
910         case QAbstractSocket::UnknownNetworkLayerProtocol:
911             return false;
912         }
913     }
914 
915     if (d->protocol == QAbstractSocket::IPv6Protocol) {
916         switch (other.d->protocol) {
917         case QAbstractSocket::IPv4Protocol:
918             quint32 a4;
919             return convertToIpv4(a4, d->a6, mode) && (a4 == other.d->a);
920         case QAbstractSocket::IPv6Protocol:
921             return memcmp(&d->a6, &other.d->a6, sizeof(Q_IPV6ADDR)) == 0;
922         case QAbstractSocket::AnyIPProtocol:
923             return (mode & QHostAddress::ConvertUnspecifiedAddress)
924                     && (other.d->a6_64.c[0] == 0) && (other.d->a6_64.c[1] == 0);
925         case QAbstractSocket::UnknownNetworkLayerProtocol:
926             return false;
927         }
928     }
929 
930     if ((d->protocol == QAbstractSocket::AnyIPProtocol)
931             && (mode & QHostAddress::ConvertUnspecifiedAddress)) {
932         switch (other.d->protocol) {
933         case QAbstractSocket::IPv4Protocol:
934             return other.d->a == 0;
935         case QAbstractSocket::IPv6Protocol:
936             return (other.d->a6_64.c[0] == 0) && (other.d->a6_64.c[1] == 0);
937         default:
938             break;
939         }
940     }
941 
942     return d->protocol == other.d->protocol;
943 }
944 
945 /*!
946     Returns \c true if this host address is the same as the \a other
947     address given; otherwise returns \c false.
948 */
operator ==(SpecialAddress other) const949 bool QHostAddress::operator ==(SpecialAddress other) const
950 {
951     quint32 ip4 = INADDR_ANY;
952     switch (other) {
953     case Null:
954         return d->protocol == QAbstractSocket::UnknownNetworkLayerProtocol;
955 
956     case Broadcast:
957         ip4 = INADDR_BROADCAST;
958         break;
959 
960     case LocalHost:
961         ip4 = INADDR_LOOPBACK;
962         break;
963 
964     case Any:
965         return d->protocol == QAbstractSocket::AnyIPProtocol;
966 
967     case AnyIPv4:
968         break;
969 
970     case LocalHostIPv6:
971     case AnyIPv6:
972         if (d->protocol == QAbstractSocket::IPv6Protocol) {
973             quint64 second = quint8(other == LocalHostIPv6);  // 1 for localhost, 0 for any
974             return d->a6_64.c[0] == 0 && d->a6_64.c[1] == qToBigEndian(second);
975         }
976         return false;
977     }
978 
979     // common IPv4 part
980     return d->protocol == QAbstractSocket::IPv4Protocol && d->a == ip4;
981 }
982 
983 /*!
984     Returns \c true if this host address is not valid for any host or interface.
985 
986     The default constructor creates a null address.
987 
988     \sa QHostAddress::Null
989 */
isNull() const990 bool QHostAddress::isNull() const
991 {
992     return d->protocol == QAbstractSocket::UnknownNetworkLayerProtocol;
993 }
994 
995 /*!
996     \since 4.5
997 
998     Returns \c true if this IP is in the subnet described by the network
999     prefix \a subnet and netmask \a netmask.
1000 
1001     An IP is considered to belong to a subnet if it is contained
1002     between the lowest and the highest address in that subnet. In the
1003     case of IP version 4, the lowest address is the network address,
1004     while the highest address is the broadcast address.
1005 
1006     The \a subnet argument does not have to be the actual network
1007     address (the lowest address in the subnet). It can be any valid IP
1008     belonging to that subnet. In particular, if it is equal to the IP
1009     address held by this object, this function will always return true
1010     (provided the netmask is a valid value).
1011 
1012     \sa parseSubnet()
1013 */
isInSubnet(const QHostAddress & subnet,int netmask) const1014 bool QHostAddress::isInSubnet(const QHostAddress &subnet, int netmask) const
1015 {
1016     if (subnet.protocol() != d->protocol || netmask < 0)
1017         return false;
1018 
1019     union {
1020         quint32 ip;
1021         quint8 data[4];
1022     } ip4, net4;
1023     const quint8 *ip;
1024     const quint8 *net;
1025     if (d->protocol == QAbstractSocket::IPv4Protocol) {
1026         if (netmask > 32)
1027             netmask = 32;
1028         ip4.ip = qToBigEndian(d->a);
1029         net4.ip = qToBigEndian(subnet.d->a);
1030         ip = ip4.data;
1031         net = net4.data;
1032     } else if (d->protocol == QAbstractSocket::IPv6Protocol) {
1033         if (netmask > 128)
1034             netmask = 128;
1035         ip = d->a6.c;
1036         net = subnet.d->a6.c;
1037     } else {
1038         return false;
1039     }
1040 
1041     if (netmask >= 8 && memcmp(ip, net, netmask / 8) != 0)
1042         return false;
1043     if ((netmask & 7) == 0)
1044         return true;
1045 
1046     // compare the last octet now
1047     quint8 bytemask = 256 - (1 << (8 - (netmask & 7)));
1048     quint8 ipbyte = ip[netmask / 8];
1049     quint8 netbyte = net[netmask / 8];
1050     return (ipbyte & bytemask) == (netbyte & bytemask);
1051 }
1052 
1053 /*!
1054     \since 4.5
1055     \overload
1056 
1057     Returns \c true if this IP is in the subnet described by \a
1058     subnet. The QHostAddress member of \a subnet contains the network
1059     prefix and the int (second) member contains the netmask (prefix
1060     length).
1061 */
isInSubnet(const QPair<QHostAddress,int> & subnet) const1062 bool QHostAddress::isInSubnet(const QPair<QHostAddress, int> &subnet) const
1063 {
1064     return isInSubnet(subnet.first, subnet.second);
1065 }
1066 
1067 
1068 /*!
1069     \since 4.5
1070 
1071     Parses the IP and subnet information contained in \a subnet and
1072     returns the network prefix for that network and its prefix length.
1073 
1074     The IP address and the netmask must be separated by a slash
1075     (/).
1076 
1077     This function supports arguments in the form:
1078     \list
1079       \li 123.123.123.123/n  where n is any value between 0 and 32
1080       \li 123.123.123.123/255.255.255.255
1081       \li <ipv6-address>/n  where n is any value between 0 and 128
1082     \endlist
1083 
1084     For IP version 4, this function accepts as well missing trailing
1085     components (i.e., less than 4 octets, like "192.168.1"), followed
1086     or not by a dot. If the netmask is also missing in that case, it
1087     is set to the number of octets actually passed (in the example
1088     above, it would be 24, for 3 octets).
1089 
1090     \sa isInSubnet()
1091 */
parseSubnet(const QString & subnet)1092 QPair<QHostAddress, int> QHostAddress::parseSubnet(const QString &subnet)
1093 {
1094     // We support subnets in the form:
1095     //   ddd.ddd.ddd.ddd/nn
1096     //   ddd.ddd.ddd/nn
1097     //   ddd.ddd/nn
1098     //   ddd/nn
1099     //   ddd.ddd.ddd.
1100     //   ddd.ddd.ddd
1101     //   ddd.ddd.
1102     //   ddd.ddd
1103     //   ddd.
1104     //   ddd
1105     //   <ipv6-address>/nn
1106     //
1107     //  where nn can be an IPv4-style netmask for the IPv4 forms
1108 
1109     const QPair<QHostAddress, int> invalid = qMakePair(QHostAddress(), -1);
1110     if (subnet.isEmpty())
1111         return invalid;
1112 
1113     int slash = subnet.indexOf(QLatin1Char('/'));
1114     QStringRef netStr(&subnet);
1115     if (slash != -1)
1116         netStr.truncate(slash);
1117 
1118     int netmask = -1;
1119     bool isIpv6 = netStr.contains(QLatin1Char(':'));
1120 
1121     if (slash != -1) {
1122         // is the netmask given in IP-form or in bit-count form?
1123         if (!isIpv6 && subnet.indexOf(QLatin1Char('.'), slash + 1) != -1) {
1124             // IP-style, convert it to bit-count form
1125             QHostAddress mask;
1126             QNetmask parser;
1127             if (!mask.setAddress(subnet.mid(slash + 1)))
1128                 return invalid;
1129             if (!parser.setAddress(mask))
1130                 return invalid;
1131             netmask = parser.prefixLength();
1132         } else {
1133             bool ok;
1134             netmask = subnet.midRef(slash + 1).toUInt(&ok);
1135             if (!ok)
1136                 return invalid;     // failed to parse the subnet
1137         }
1138     }
1139 
1140     if (isIpv6) {
1141         // looks like it's an IPv6 address
1142         if (netmask > 128)
1143             return invalid;     // invalid netmask
1144         if (netmask < 0)
1145             netmask = 128;
1146 
1147         QHostAddress net;
1148         if (!net.setAddress(netStr.toString()))
1149             return invalid;     // failed to parse the IP
1150 
1151         clearBits(net.d->a6.c, netmask, 128);
1152         return qMakePair(net, netmask);
1153     }
1154 
1155     if (netmask > 32)
1156         return invalid;         // invalid netmask
1157 
1158     // parse the address manually
1159     auto parts = netStr.split(QLatin1Char('.'));
1160     if (parts.isEmpty() || parts.count() > 4)
1161         return invalid;         // invalid IPv4 address
1162 
1163     if (parts.constLast().isEmpty())
1164         parts.removeLast();
1165 
1166     quint32 addr = 0;
1167     for (int i = 0; i < parts.count(); ++i) {
1168         bool ok;
1169         uint byteValue = parts.at(i).toUInt(&ok);
1170         if (!ok || byteValue > 255)
1171             return invalid;     // invalid IPv4 address
1172 
1173         addr <<= 8;
1174         addr += byteValue;
1175     }
1176     addr <<= 8 * (4 - parts.count());
1177     if (netmask == -1) {
1178         netmask = 8 * parts.count();
1179     } else if (netmask == 0) {
1180         // special case here
1181         // x86's instructions "shr" and "shl" do not operate when
1182         // their argument is 32, so the code below doesn't work as expected
1183         addr = 0;
1184     } else if (netmask != 32) {
1185         // clear remaining bits
1186         quint32 mask = quint32(0xffffffff) >> (32 - netmask) << (32 - netmask);
1187         addr &= mask;
1188     }
1189 
1190     return qMakePair(QHostAddress(addr), netmask);
1191 }
1192 
1193 /*!
1194     \since 5.0
1195 
1196     returns \c true if the address is the IPv6 loopback address, or any
1197     of the IPv4 loopback addresses.
1198 */
isLoopback() const1199 bool QHostAddress::isLoopback() const
1200 {
1201     return d->classify() == LoopbackAddress;
1202 }
1203 
1204 /*!
1205     \since 5.11
1206 
1207     Returns \c true if the address is an IPv4 or IPv6 global address, \c false
1208     otherwise. A global address is an address that is not reserved for
1209     special purposes (like loopback or multicast) or future purposes.
1210 
1211     Note that IPv6 unique local unicast addresses are considered global
1212     addresses (see isUniqueLocalUnicast()), as are IPv4 addresses reserved for
1213     local networks by \l {https://tools.ietf.org/html/rfc1918}{RFC 1918}.
1214 
1215     Also note that IPv6 site-local addresses are deprecated and should be
1216     considered as global in new applications. This function returns true for
1217     site-local addresses too.
1218 
1219     \sa isLoopback(), isSiteLocal(), isUniqueLocalUnicast()
1220 */
isGlobal() const1221 bool QHostAddress::isGlobal() const
1222 {
1223     return d->classify() & GlobalAddress;   // GlobalAddress is a bit
1224 }
1225 
1226 /*!
1227     \since 5.11
1228 
1229     Returns \c true if the address is an IPv4 or IPv6 link-local address, \c
1230     false otherwise.
1231 
1232     An IPv4 link-local address is an address in the network 169.254.0.0/16. An
1233     IPv6 link-local address is one in the network fe80::/10. See the
1234     \l{https://www.iana.org/assignments/ipv6-address-space/ipv6-address-space.xhtml}{IANA
1235     IPv6 Address Space} registry for more information.
1236 
1237     \sa isLoopback(), isGlobal(), isMulticast(), isSiteLocal(), isUniqueLocalUnicast()
1238 */
isLinkLocal() const1239 bool QHostAddress::isLinkLocal() const
1240 {
1241     return d->classify() == LinkLocalAddress;
1242 }
1243 
1244 /*!
1245     \since 5.11
1246 
1247     Returns \c true if the address is an IPv6 site-local address, \c
1248     false otherwise.
1249 
1250     An IPv6 site-local address is one in the network fec0::/10. See the
1251     \l{https://www.iana.org/assignments/ipv6-address-space/ipv6-address-space.xhtml}{IANA
1252     IPv6 Address Space} registry for more information.
1253 
1254     IPv6 site-local addresses are deprecated and should not be depended upon in
1255     new applications. New applications should not depend on this function and
1256     should consider site-local addresses the same as global (which is why
1257     isGlobal() also returns true). Site-local addresses were replaced by Unique
1258     Local Addresses (ULA).
1259 
1260     \sa isLoopback(), isGlobal(), isMulticast(), isLinkLocal(), isUniqueLocalUnicast()
1261 */
isSiteLocal() const1262 bool QHostAddress::isSiteLocal() const
1263 {
1264     return d->classify() == SiteLocalAddress;
1265 }
1266 
1267 /*!
1268     \since 5.11
1269 
1270     Returns \c true if the address is an IPv6 unique local unicast address, \c
1271     false otherwise.
1272 
1273     An IPv6 unique local unicast address is one in the network fc00::/7. See the
1274     \l{https://www.iana.org/assignments/ipv6-address-space/ipv6-address-space.xhtml}
1275     {IANA IPv6 Address Space} registry for more information.
1276 
1277     Note that Unique local unicast addresses count as global addresses too. RFC
1278     4193 says that, in practice, "applications may treat these addresses like
1279     global scoped addresses." Only routers need care about the distinction.
1280 
1281     \sa isLoopback(), isGlobal(), isMulticast(), isLinkLocal(), isUniqueLocalUnicast()
1282 */
isUniqueLocalUnicast() const1283 bool QHostAddress::isUniqueLocalUnicast() const
1284 {
1285     return d->classify() == UniqueLocalAddress;
1286 }
1287 
1288 /*!
1289     \since 5.6
1290 
1291     Returns \c true if the address is an IPv4 or IPv6 multicast address, \c
1292     false otherwise.
1293 
1294     \sa isLoopback(), isGlobal(), isLinkLocal(), isSiteLocal(), isUniqueLocalUnicast()
1295 */
isMulticast() const1296 bool QHostAddress::isMulticast() const
1297 {
1298     return d->classify() == MulticastAddress;
1299 }
1300 
1301 /*!
1302     \since 5.11
1303 
1304     Returns \c true if the address is the IPv4 broadcast address, \c false
1305     otherwise. The IPv4 broadcast address is 255.255.255.255.
1306 
1307     Note that this function does not return true for an IPv4 network's local
1308     broadcast address. For that, please use \l QNetworkInterface to obtain the
1309     broadcast addresses of the local machine.
1310 
1311     \sa isLoopback(), isGlobal(), isMulticast(), isLinkLocal(), isUniqueLocalUnicast()
1312 */
isBroadcast() const1313 bool QHostAddress::isBroadcast() const
1314 {
1315     return d->classify() == BroadcastAddress;
1316 }
1317 
1318 #ifndef QT_NO_DEBUG_STREAM
operator <<(QDebug d,const QHostAddress & address)1319 QDebug operator<<(QDebug d, const QHostAddress &address)
1320 {
1321     QDebugStateSaver saver(d);
1322     d.resetFormat().nospace();
1323     if (address == QHostAddress::Any)
1324         d << "QHostAddress(QHostAddress::Any)";
1325     else
1326         d << "QHostAddress(" << address.toString() << ')';
1327     return d;
1328 }
1329 #endif
1330 
1331 /*!
1332     \since 5.0
1333     \relates QHostAddress
1334     Returns a hash of the host address \a key, using \a seed to seed the calculation.
1335 */
qHash(const QHostAddress & key,uint seed)1336 uint qHash(const QHostAddress &key, uint seed) noexcept
1337 {
1338     return qHashBits(key.d->a6.c, 16, seed);
1339 }
1340 
1341 /*!
1342     \fn bool operator==(QHostAddress::SpecialAddress lhs, const QHostAddress &rhs)
1343     \relates QHostAddress
1344 
1345     Returns \c true if special address \a lhs is the same as host address \a rhs;
1346     otherwise returns \c false.
1347 
1348     \sa isEqual()
1349 */
1350 
1351 /*!
1352     \fn bool operator!=(QHostAddress::SpecialAddress lhs, const QHostAddress &rhs)
1353     \relates QHostAddress
1354     \since 5.9
1355 
1356     Returns \c false if special address \a lhs is the same as host address \a rhs;
1357     otherwise returns \c true.
1358 
1359     \sa isEqual()
1360 */
1361 
1362 #ifndef QT_NO_DATASTREAM
1363 
1364 /*! \relates QHostAddress
1365 
1366     Writes host address \a address to the stream \a out and returns a reference
1367     to the stream.
1368 
1369     \sa {Serializing Qt Data Types}
1370 */
operator <<(QDataStream & out,const QHostAddress & address)1371 QDataStream &operator<<(QDataStream &out, const QHostAddress &address)
1372 {
1373     qint8 prot;
1374     prot = qint8(address.protocol());
1375     out << prot;
1376     switch (address.protocol()) {
1377     case QAbstractSocket::UnknownNetworkLayerProtocol:
1378     case QAbstractSocket::AnyIPProtocol:
1379         break;
1380     case QAbstractSocket::IPv4Protocol:
1381         out << address.toIPv4Address();
1382         break;
1383     case QAbstractSocket::IPv6Protocol:
1384     {
1385         Q_IPV6ADDR ipv6 = address.toIPv6Address();
1386         for (int i = 0; i < 16; ++i)
1387             out << ipv6[i];
1388         out << address.scopeId();
1389     }
1390         break;
1391     }
1392     return out;
1393 }
1394 
1395 /*! \relates QHostAddress
1396 
1397     Reads a host address into \a address from the stream \a in and returns a
1398     reference to the stream.
1399 
1400     \sa {Serializing Qt Data Types}
1401 */
operator >>(QDataStream & in,QHostAddress & address)1402 QDataStream &operator>>(QDataStream &in, QHostAddress &address)
1403 {
1404     qint8 prot;
1405     in >> prot;
1406     switch (QAbstractSocket::NetworkLayerProtocol(prot)) {
1407     case QAbstractSocket::UnknownNetworkLayerProtocol:
1408         address.clear();
1409         break;
1410     case QAbstractSocket::IPv4Protocol:
1411     {
1412         quint32 ipv4;
1413         in >> ipv4;
1414         address.setAddress(ipv4);
1415     }
1416         break;
1417     case QAbstractSocket::IPv6Protocol:
1418     {
1419         Q_IPV6ADDR ipv6;
1420         for (int i = 0; i < 16; ++i)
1421             in >> ipv6[i];
1422         address.setAddress(ipv6);
1423 
1424         QString scope;
1425         in >> scope;
1426         address.setScopeId(scope);
1427     }
1428         break;
1429     case QAbstractSocket::AnyIPProtocol:
1430         address = QHostAddress::Any;
1431         break;
1432     default:
1433         address.clear();
1434         in.setStatus(QDataStream::ReadCorruptData);
1435     }
1436     return in;
1437 }
1438 
1439 #endif //QT_NO_DATASTREAM
1440 
1441 QT_END_NAMESPACE
1442