Coverage Report

Created: 2026-01-25 07:18

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