source: trunk/src/network/kernel/qhostaddress.cpp

Last change on this file was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 31.1 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the QtNetwork module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qhostaddress.h"
43#include "qhostaddress_p.h"
44#include "qdebug.h"
45#include "qplatformdefs.h"
46#include "qstringlist.h"
47#include "qendian.h"
48#ifndef QT_NO_DATASTREAM
49#include <qdatastream.h>
50#endif
51#if defined(Q_OS_WINCE)
52#include <winsock.h>
53#endif
54
55#ifdef QT_LINUXBASE
56# include <arpa/inet.h>
57#endif
58
59QT_BEGIN_NAMESPACE
60
61#define QT_ENSURE_PARSED(a) \
62 do { \
63 if (!(a)->d->isParsed) \
64 (a)->d->parse(); \
65 } while (0)
66
67#ifdef Q_OS_WIN
68# if !defined (QT_NO_IPV6)
69// sockaddr_in6 size changed between old and new SDK
70// Only the new version is the correct one, so always
71// use this structure.
72#if defined(Q_OS_WINCE)
73# if !defined(u_char)
74# define u_char unsigned char
75# endif
76# if !defined(u_short)
77# define u_short unsigned short
78# endif
79# if !defined(u_long)
80# define u_long unsigned long
81# endif
82#endif
83struct qt_in6_addr {
84 u_char qt_s6_addr[16];
85};
86typedef struct {
87 short sin6_family; /* AF_INET6 */
88 u_short sin6_port; /* Transport level port number */
89 u_long sin6_flowinfo; /* IPv6 flow information */
90 struct qt_in6_addr sin6_addr; /* IPv6 address */
91 u_long sin6_scope_id; /* set of interfaces for a scope */
92} qt_sockaddr_in6;
93# else
94typedef void * qt_sockaddr_in6 ;
95# endif
96# ifndef AF_INET6
97# define AF_INET6 23 /* Internetwork Version 6 */
98# endif
99#else
100#define qt_sockaddr_in6 sockaddr_in6
101#define qt_s6_addr s6_addr
102#endif
103
104
105class QHostAddressPrivate
106{
107public:
108 QHostAddressPrivate();
109
110 void setAddress(quint32 a_ = 0);
111 void setAddress(const quint8 *a_);
112 void setAddress(const Q_IPV6ADDR &a_);
113
114 bool parse();
115 void clear();
116
117 quint32 a; // IPv4 address
118 Q_IPV6ADDR a6; // IPv6 address
119 QAbstractSocket::NetworkLayerProtocol protocol;
120
121 QString ipString;
122 bool isParsed;
123 QString scopeId;
124
125 friend class QHostAddress;
126};
127
128QHostAddressPrivate::QHostAddressPrivate()
129 : a(0), protocol(QAbstractSocket::UnknownNetworkLayerProtocol), isParsed(true)
130{
131 memset(&a6, 0, sizeof(a6));
132}
133
134void QHostAddressPrivate::setAddress(quint32 a_)
135{
136 a = a_;
137 protocol = QAbstractSocket::IPv4Protocol;
138 isParsed = true;
139}
140
141void QHostAddressPrivate::setAddress(const quint8 *a_)
142{
143 for (int i = 0; i < 16; i++)
144 a6[i] = a_[i];
145 protocol = QAbstractSocket::IPv6Protocol;
146 isParsed = true;
147}
148
149void QHostAddressPrivate::setAddress(const Q_IPV6ADDR &a_)
150{
151 a6 = a_;
152 a = 0;
153 protocol = QAbstractSocket::IPv6Protocol;
154 isParsed = true;
155}
156
157static bool parseIp4(const QString& address, quint32 *addr)
158{
159 QStringList ipv4 = address.split(QLatin1String("."));
160 if (ipv4.count() != 4)
161 return false;
162
163 quint32 ipv4Address = 0;
164 for (int i = 0; i < 4; ++i) {
165 bool ok = false;
166 uint byteValue = ipv4.at(i).toUInt(&ok);
167 if (!ok || byteValue > 255)
168 return false;
169
170 ipv4Address <<= 8;
171 ipv4Address += byteValue;
172 }
173
174 *addr = ipv4Address;
175 return true;
176}
177
178static bool parseIp6(const QString &address, quint8 *addr, QString *scopeId)
179{
180 QString tmp = address;
181 int scopeIdPos = tmp.lastIndexOf(QLatin1Char('%'));
182 if (scopeIdPos != -1) {
183 *scopeId = tmp.mid(scopeIdPos + 1);
184 tmp.chop(tmp.size() - scopeIdPos);
185 } else {
186 scopeId->clear();
187 }
188
189 QStringList ipv6 = tmp.split(QLatin1String(":"));
190 int count = ipv6.count();
191 if (count < 3 || count > 8)
192 return false;
193
194 int colonColon = tmp.count(QLatin1String("::"));
195 if(count == 8 && colonColon > 1)
196 return false;
197
198 // address can be compressed with a "::", but that
199 // may only appear once (see RFC 1884)
200 // the statement below means:
201 // if(shortened notation is not used AND
202 // ((pure IPv6 notation AND less than 8 parts) OR
203 // ((mixed IPv4/6 notation AND less than 7 parts)))
204 if(colonColon != 1 && count < (tmp.contains(QLatin1Char('.')) ? 7 : 8))
205 return false;
206
207 int mc = 16;
208 int fillCount = 9 - count; // number of 0 words to fill in the middle
209 for (int i = count - 1; i >= 0; --i) {
210 if (mc <= 0)
211 return false;
212
213 if (ipv6.at(i).isEmpty()) {
214 if (i == count - 1) {
215 // special case: ":" is last character
216 if (!ipv6.at(i - 1).isEmpty())
217 return false;
218 addr[--mc] = 0;
219 addr[--mc] = 0;
220 } else if (i == 0) {
221 // special case: ":" is first character
222 if (!ipv6.at(i + 1).isEmpty())
223 return false;
224 addr[--mc] = 0;
225 addr[--mc] = 0;
226 } else {
227 for (int j = 0; j < fillCount; ++j) {
228 if (mc <= 0)
229 return false;
230 addr[--mc] = 0;
231 addr[--mc] = 0;
232 }
233 }
234 } else {
235 bool ok = false;
236 uint byteValue = ipv6.at(i).toUInt(&ok, 16);
237 if (ok && byteValue <= 0xffff) {
238 addr[--mc] = byteValue & 0xff;
239 addr[--mc] = (byteValue >> 8) & 0xff;
240 } else {
241 if (i != count - 1)
242 return false;
243
244 // parse the ipv4 part of a mixed type
245 quint32 maybeIp4;
246 if (!parseIp4(ipv6.at(i), &maybeIp4))
247 return false;
248
249 addr[--mc] = maybeIp4 & 0xff;
250 addr[--mc] = (maybeIp4 >> 8) & 0xff;
251 addr[--mc] = (maybeIp4 >> 16) & 0xff;
252 addr[--mc] = (maybeIp4 >> 24) & 0xff;
253 --fillCount;
254 }
255 }
256 }
257
258 return true;
259}
260
261bool QHostAddressPrivate::parse()
262{
263 isParsed = true;
264 protocol = QAbstractSocket::UnknownNetworkLayerProtocol;
265 QString a = ipString.simplified();
266
267 // All IPv6 addresses contain a ':', and may contain a '.'.
268 if (a.contains(QLatin1Char(':'))) {
269 quint8 maybeIp6[16];
270 if (parseIp6(a, maybeIp6, &scopeId)) {
271 setAddress(maybeIp6);
272 protocol = QAbstractSocket::IPv6Protocol;
273 return true;
274 }
275 }
276
277 // All IPv4 addresses contain a '.'.
278 if (a.contains(QLatin1Char('.'))) {
279 quint32 maybeIp4 = 0;
280 if (parseIp4(a, &maybeIp4)) {
281 setAddress(maybeIp4);
282 protocol = QAbstractSocket::IPv4Protocol;
283 return true;
284 }
285 }
286
287 return false;
288}
289
290void QHostAddressPrivate::clear()
291{
292 a = 0;
293 protocol = QAbstractSocket::UnknownNetworkLayerProtocol;
294 isParsed = true;
295 memset(&a6, 0, sizeof(a6));
296}
297
298
299bool QNetmaskAddress::setAddress(const QString &address)
300{
301 length = -1;
302 QHostAddress other;
303 return other.setAddress(address) && setAddress(other);
304}
305
306bool QNetmaskAddress::setAddress(const QHostAddress &address)
307{
308 static const quint8 zeroes[16] = { 0 };
309 union {
310 quint32 v4;
311 quint8 v6[16];
312 } ip;
313
314 int netmask = 0;
315 quint8 *ptr = ip.v6;
316 quint8 *end;
317 length = -1;
318
319 QHostAddress::operator=(address);
320
321 if (d->protocol == QAbstractSocket::IPv4Protocol) {
322 ip.v4 = qToBigEndian(d->a);
323 end = ptr + 4;
324 } else if (d->protocol == QAbstractSocket::IPv6Protocol) {
325 memcpy(ip.v6, d->a6.c, 16);
326 end = ptr + 16;
327 } else {
328 d->clear();
329 return false;
330 }
331
332 while (ptr < end) {
333 switch (*ptr) {
334 case 255:
335 netmask += 8;
336 ++ptr;
337 continue;
338
339 default:
340 d->clear();
341 return false; // invalid IP-style netmask
342
343 // the rest always falls through
344 case 254:
345 ++netmask;
346 case 252:
347 ++netmask;
348 case 248:
349 ++netmask;
350 case 240:
351 ++netmask;
352 case 224:
353 ++netmask;
354 case 192:
355 ++netmask;
356 case 128:
357 ++netmask;
358 case 0:
359 break;
360 }
361 break;
362 }
363
364 // confirm that the rest is only zeroes
365 if (ptr < end && memcmp(ptr + 1, zeroes, end - ptr - 1) != 0) {
366 d->clear();
367 return false;
368 }
369
370 length = netmask;
371 return true;
372}
373
374static void clearBits(quint8 *where, int start, int end)
375{
376 Q_ASSERT(end == 32 || end == 128);
377 if (start == end)
378 return;
379
380 // for the byte where 'start' is, clear the lower bits only
381 quint8 bytemask = 256 - (1 << (8 - (start & 7)));
382 where[start / 8] &= bytemask;
383
384 // for the tail part, clear everything
385 memset(where + (start + 7) / 8, 0, end / 8 - (start + 7) / 8);
386}
387
388int QNetmaskAddress::prefixLength() const
389{
390 return length;
391}
392
393void QNetmaskAddress::setPrefixLength(QAbstractSocket::NetworkLayerProtocol proto, int newLength)
394{
395 length = newLength;
396 if (length < 0 || length > (proto == QAbstractSocket::IPv4Protocol ? 32 :
397 proto == QAbstractSocket::IPv6Protocol ? 128 : -1)) {
398 // invalid information, reject
399 d->protocol = QAbstractSocket::UnknownNetworkLayerProtocol;
400 length = -1;
401 return;
402 }
403
404 d->protocol = proto;
405 if (d->protocol == QAbstractSocket::IPv4Protocol) {
406 if (length == 0) {
407 d->a = 0;
408 } else if (length == 32) {
409 d->a = quint32(0xffffffff);
410 } else {
411 d->a = quint32(0xffffffff) >> (32 - length) << (32 - length);
412 }
413 } else {
414 memset(d->a6.c, 0xFF, sizeof(d->a6));
415 clearBits(d->a6.c, length, 128);
416 }
417}
418
419/*!
420 \class QHostAddress
421 \brief The QHostAddress class provides an IP address.
422 \ingroup network
423 \inmodule QtNetwork
424
425 This class holds an IPv4 or IPv6 address in a platform- and
426 protocol-independent manner.
427
428 QHostAddress is normally used with the QTcpSocket, QTcpServer,
429 and QUdpSocket to connect to a host or to set up a server.
430
431 A host address is set with setAddress(), and retrieved with
432 toIPv4Address(), toIPv6Address(), or toString(). You can check the
433 type with protocol().
434
435 \note Please note that QHostAddress does not do DNS lookups.
436 QHostInfo is needed for that.
437
438 The class also supports common predefined addresses: \l Null, \l
439 LocalHost, \l LocalHostIPv6, \l Broadcast, and \l Any.
440
441 \sa QHostInfo, QTcpSocket, QTcpServer, QUdpSocket
442*/
443
444/*! \enum QHostAddress::SpecialAddress
445
446 \value Null The null address object. Equivalent to QHostAddress().
447 \value LocalHost The IPv4 localhost address. Equivalent to QHostAddress("127.0.0.1").
448 \value LocalHostIPv6 The IPv6 localhost address. Equivalent to QHostAddress("::1").
449 \value Broadcast The IPv4 broadcast address. Equivalent to QHostAddress("255.255.255.255").
450 \value Any The IPv4 any-address. Equivalent to QHostAddress("0.0.0.0").
451 \value AnyIPv6 The IPv6 any-address. Equivalent to QHostAddress("::").
452*/
453
454/*! Constructs a host address object with the IP address 0.0.0.0.
455
456 \sa clear()
457*/
458QHostAddress::QHostAddress()
459 : d(new QHostAddressPrivate)
460{
461}
462
463/*!
464 Constructs a host address object with the IPv4 address \a ip4Addr.
465*/
466QHostAddress::QHostAddress(quint32 ip4Addr)
467 : d(new QHostAddressPrivate)
468{
469 setAddress(ip4Addr);
470}
471
472/*!
473 Constructs a host address object with the IPv6 address \a ip6Addr.
474
475 \a ip6Addr must be a 16-byte array in network byte order (big
476 endian).
477*/
478QHostAddress::QHostAddress(quint8 *ip6Addr)
479 : d(new QHostAddressPrivate)
480{
481 setAddress(ip6Addr);
482}
483
484/*!
485 Constructs a host address object with the IPv6 address \a ip6Addr.
486*/
487QHostAddress::QHostAddress(const Q_IPV6ADDR &ip6Addr)
488 : d(new QHostAddressPrivate)
489{
490 setAddress(ip6Addr);
491}
492
493/*!
494 Constructs an IPv4 or IPv6 address based on the string \a address
495 (e.g., "127.0.0.1").
496
497 \sa setAddress()
498*/
499QHostAddress::QHostAddress(const QString &address)
500 : d(new QHostAddressPrivate)
501{
502 d->ipString = address;
503 d->isParsed = false;
504}
505
506/*!
507 \fn QHostAddress::QHostAddress(const sockaddr *sockaddr)
508
509 Constructs an IPv4 or IPv6 address using the address specified by
510 the native structure \a sockaddr.
511
512 \sa setAddress()
513*/
514QHostAddress::QHostAddress(const struct sockaddr *sockaddr)
515 : d(new QHostAddressPrivate)
516{
517 if (sockaddr->sa_family == AF_INET)
518 setAddress(htonl(((sockaddr_in *)sockaddr)->sin_addr.s_addr));
519#ifndef QT_NO_IPV6
520 else if (sockaddr->sa_family == AF_INET6)
521 setAddress(((qt_sockaddr_in6 *)sockaddr)->sin6_addr.qt_s6_addr);
522#endif
523}
524
525/*!
526 Constructs a copy of the given \a address.
527*/
528QHostAddress::QHostAddress(const QHostAddress &address)
529 : d(new QHostAddressPrivate(*address.d.data()))
530{
531}
532
533/*!
534 Constructs a QHostAddress object for \a address.
535*/
536QHostAddress::QHostAddress(SpecialAddress address)
537 : d(new QHostAddressPrivate)
538{
539 switch (address) {
540 case Null:
541 break;
542 case Broadcast:
543 setAddress(QLatin1String("255.255.255.255"));
544 break;
545 case LocalHost:
546 setAddress(QLatin1String("127.0.0.1"));
547 break;
548 case LocalHostIPv6:
549 setAddress(QLatin1String("::1"));
550 break;
551 case Any:
552 setAddress(QLatin1String("0.0.0.0"));
553 break;
554 case AnyIPv6:
555 setAddress(QLatin1String("::"));
556 break;
557 }
558}
559
560/*!
561 Destroys the host address object.
562*/
563QHostAddress::~QHostAddress()
564{
565}
566
567/*!
568 Assigns another host \a address to this object, and returns a reference
569 to this object.
570*/
571QHostAddress &QHostAddress::operator=(const QHostAddress &address)
572{
573 *d.data() = *address.d.data();
574 return *this;
575}
576
577/*!
578 Assigns the host address \a address to this object, and returns a
579 reference to this object.
580
581 \sa setAddress()
582*/
583QHostAddress &QHostAddress::operator=(const QString &address)
584{
585 setAddress(address);
586 return *this;
587}
588
589/*!
590 \fn bool QHostAddress::operator!=(const QHostAddress &other) const
591 \since 4.2
592
593 Returns true if this host address is not the same as the \a other
594 address given; otherwise returns false.
595*/
596
597/*!
598 \fn bool QHostAddress::operator!=(SpecialAddress other) const
599
600 Returns true if this host address is not the same as the \a other
601 address given; otherwise returns false.
602*/
603
604/*!
605 Sets the host address to 0.0.0.0.
606*/
607void QHostAddress::clear()
608{
609 d->clear();
610}
611
612/*!
613 Set the IPv4 address specified by \a ip4Addr.
614*/
615void QHostAddress::setAddress(quint32 ip4Addr)
616{
617 d->setAddress(ip4Addr);
618}
619
620/*!
621 \overload
622
623 Set the IPv6 address specified by \a ip6Addr.
624
625 \a ip6Addr must be an array of 16 bytes in network byte order
626 (high-order byte first).
627*/
628void QHostAddress::setAddress(quint8 *ip6Addr)
629{
630 d->setAddress(ip6Addr);
631}
632
633/*!
634 \overload
635
636 Set the IPv6 address specified by \a ip6Addr.
637*/
638void QHostAddress::setAddress(const Q_IPV6ADDR &ip6Addr)
639{
640 d->setAddress(ip6Addr);
641}
642
643/*!
644 \overload
645
646 Sets the IPv4 or IPv6 address specified by the string
647 representation specified by \a address (e.g. "127.0.0.1").
648 Returns true and sets the address if the address was successfully
649 parsed; otherwise returns false.
650*/
651bool QHostAddress::setAddress(const QString &address)
652{
653 d->ipString = address;
654 return d->parse();
655}
656
657/*!
658 \fn void QHostAddress::setAddress(const sockaddr *sockaddr)
659 \overload
660
661 Sets the IPv4 or IPv6 address specified by the native structure \a
662 sockaddr. Returns true and sets the address if the address was
663 successfully parsed; otherwise returns false.
664*/
665void QHostAddress::setAddress(const struct sockaddr *sockaddr)
666{
667 clear();
668 if (sockaddr->sa_family == AF_INET)
669 setAddress(htonl(((sockaddr_in *)sockaddr)->sin_addr.s_addr));
670#ifndef QT_NO_IPV6
671 else if (sockaddr->sa_family == AF_INET6)
672 setAddress(((qt_sockaddr_in6 *)sockaddr)->sin6_addr.qt_s6_addr);
673#endif
674}
675
676/*!
677 Returns the IPv4 address as a number.
678
679 For example, if the address is 127.0.0.1, the returned value is
680 2130706433 (i.e. 0x7f000001).
681
682 This value is only valid if the Protocol() is
683 \l{QAbstractSocket::}{IPv4Protocol}.
684
685 \sa toString()
686*/
687quint32 QHostAddress::toIPv4Address() const
688{
689 QT_ENSURE_PARSED(this);
690 return d->a;
691}
692
693/*!
694 Returns the network layer protocol of the host address.
695*/
696QAbstractSocket::NetworkLayerProtocol QHostAddress::protocol() const
697{
698 QT_ENSURE_PARSED(this);
699 return d->protocol;
700}
701
702/*!
703 Returns the IPv6 address as a Q_IPV6ADDR structure. The structure
704 consists of 16 unsigned characters.
705
706 \snippet doc/src/snippets/code/src_network_kernel_qhostaddress.cpp 0
707
708 This value is only valid if the protocol() is
709 \l{QAbstractSocket::}{IPv6Protocol}.
710
711 \sa toString()
712*/
713Q_IPV6ADDR QHostAddress::toIPv6Address() const
714{
715 QT_ENSURE_PARSED(this);
716 return d->a6;
717}
718
719/*!
720 Returns the address as a string.
721
722 For example, if the address is the IPv4 address 127.0.0.1, the
723 returned string is "127.0.0.1".
724
725 \sa toIPv4Address()
726*/
727QString QHostAddress::toString() const
728{
729 QT_ENSURE_PARSED(this);
730 if (d->protocol == QAbstractSocket::IPv4Protocol) {
731 quint32 i = toIPv4Address();
732 QString s;
733 s.sprintf("%d.%d.%d.%d", (i>>24) & 0xff, (i>>16) & 0xff,
734 (i >> 8) & 0xff, i & 0xff);
735 return s;
736 }
737
738 if (d->protocol == QAbstractSocket::IPv6Protocol) {
739 quint16 ugle[8];
740 for (int i = 0; i < 8; i++) {
741 ugle[i] = (quint16(d->a6[2*i]) << 8) | quint16(d->a6[2*i+1]);
742 }
743 QString s;
744 s.sprintf("%X:%X:%X:%X:%X:%X:%X:%X",
745 ugle[0], ugle[1], ugle[2], ugle[3], ugle[4], ugle[5], ugle[6], ugle[7]);
746 if (!d->scopeId.isEmpty())
747 s.append(QLatin1Char('%') + d->scopeId);
748 return s;
749 }
750
751 return QString();
752}
753
754/*!
755 \since 4.1
756
757 Returns the scope ID of an IPv6 address. For IPv4 addresses, or if the
758 address does not contain a scope ID, an empty QString is returned.
759
760 The IPv6 scope ID specifies the scope of \e reachability for non-global
761 IPv6 addresses, limiting the area in which the address can be used. All
762 IPv6 addresses are associated with such a reachability scope. The scope ID
763 is used to disambiguate addresses that are not guaranteed to be globally
764 unique.
765
766 IPv6 specifies the following four levels of reachability:
767
768 \list
769
770 \o Node-local: Addresses that are only used for communicating with
771 services on the same interface (e.g., the loopback interface "::1").
772
773 \o Link-local: Addresses that are local to the network interface
774 (\e{link}). There is always one link-local address for each IPv6 interface
775 on your host. Link-local addresses ("fe80...") are generated from the MAC
776 address of the local network adaptor, and are not guaranteed to be unique.
777
778 \o Site-local: Addresses that are local to the site / private network
779 (e.g., the company intranet). Site-local addresses ("fec0...") are
780 usually distributed by the site router, and are not guaranteed to be
781 unique outside of the local site.
782
783 \o Global: For globally routable addresses, such as public servers on the
784 Internet.
785
786 \endlist
787
788 When using a link-local or site-local address for IPv6 connections, you
789 must specify the scope ID. The scope ID for a link-local address is
790 usually the same as the interface name (e.g., "eth0", "en1") or number
791 (e.g., "1", "2").
792
793 \sa setScopeId()
794*/
795QString QHostAddress::scopeId() const
796{
797 QT_ENSURE_PARSED(this);
798 return (d->protocol == QAbstractSocket::IPv6Protocol) ? d->scopeId : QString();
799}
800
801/*!
802 \since 4.1
803
804 Sets the IPv6 scope ID of the address to \a id. If the address
805 protocol is not IPv6, this function does nothing.
806*/
807void QHostAddress::setScopeId(const QString &id)
808{
809 QT_ENSURE_PARSED(this);
810 if (d->protocol == QAbstractSocket::IPv6Protocol)
811 d->scopeId = id;
812}
813
814/*!
815 Returns true if this host address is the same as the \a other address
816 given; otherwise returns false.
817*/
818bool QHostAddress::operator==(const QHostAddress &other) const
819{
820 QT_ENSURE_PARSED(this);
821 QT_ENSURE_PARSED(&other);
822
823 if (d->protocol == QAbstractSocket::IPv4Protocol)
824 return other.d->protocol == QAbstractSocket::IPv4Protocol && d->a == other.d->a;
825 if (d->protocol == QAbstractSocket::IPv6Protocol) {
826 return other.d->protocol == QAbstractSocket::IPv6Protocol
827 && memcmp(&d->a6, &other.d->a6, sizeof(Q_IPV6ADDR)) == 0;
828 }
829 return d->protocol == other.d->protocol;
830}
831
832/*!
833 Returns true if this host address is the same as the \a other
834 address given; otherwise returns false.
835*/
836bool QHostAddress::operator ==(SpecialAddress other) const
837{
838 QT_ENSURE_PARSED(this);
839 QHostAddress otherAddress(other);
840 QT_ENSURE_PARSED(&otherAddress);
841
842 if (d->protocol == QAbstractSocket::IPv4Protocol)
843 return otherAddress.d->protocol == QAbstractSocket::IPv4Protocol && d->a == otherAddress.d->a;
844 if (d->protocol == QAbstractSocket::IPv6Protocol) {
845 return otherAddress.d->protocol == QAbstractSocket::IPv6Protocol
846 && memcmp(&d->a6, &otherAddress.d->a6, sizeof(Q_IPV6ADDR)) == 0;
847 }
848 return int(other) == int(Null);
849}
850
851/*!
852 Returns true if this host address is null (INADDR_ANY or in6addr_any).
853 The default constructor creates a null address, and that address is
854 not valid for any host or interface.
855*/
856bool QHostAddress::isNull() const
857{
858 QT_ENSURE_PARSED(this);
859 return d->protocol == QAbstractSocket::UnknownNetworkLayerProtocol;
860}
861
862/*!
863 \fn quint32 QHostAddress::ip4Addr() const
864
865 Use toIPv4Address() instead.
866*/
867
868/*!
869 \fn bool QHostAddress::isIp4Addr() const
870
871 Use protocol() instead.
872*/
873
874/*!
875 \fn bool QHostAddress::isIPv4Address() const
876
877 Use protocol() instead.
878*/
879
880/*!
881 \fn bool QHostAddress::isIPv6Address() const
882
883 Use protocol() instead.
884*/
885
886/*!
887 \since 4.5
888
889 Returns true if this IP is in the subnet described by the network
890 prefix \a subnet and netmask \a netmask.
891
892 An IP is considered to belong to a subnet if it is contained
893 between the lowest and the highest address in that subnet. In the
894 case of IP version 4, the lowest address is the network address,
895 while the highest address is the broadcast address.
896
897 The \a subnet argument does not have to be the actual network
898 address (the lowest address in the subnet). It can be any valid IP
899 belonging to that subnet. In particular, if it is equal to the IP
900 address held by this object, this function will always return true
901 (provided the netmask is a valid value).
902
903 \sa parseSubnet()
904*/
905bool QHostAddress::isInSubnet(const QHostAddress &subnet, int netmask) const
906{
907 QT_ENSURE_PARSED(this);
908 if (subnet.protocol() != d->protocol || netmask < 0)
909 return false;
910
911 union {
912 quint32 ip;
913 quint8 data[4];
914 } ip4, net4;
915 const quint8 *ip;
916 const quint8 *net;
917 if (d->protocol == QAbstractSocket::IPv4Protocol) {
918 if (netmask > 32)
919 netmask = 32;
920 ip4.ip = qToBigEndian(d->a);
921 net4.ip = qToBigEndian(subnet.d->a);
922 ip = ip4.data;
923 net = net4.data;
924 } else if (d->protocol == QAbstractSocket::IPv6Protocol) {
925 if (netmask > 128)
926 netmask = 128;
927 ip = d->a6.c;
928 net = subnet.d->a6.c;
929 } else {
930 return false;
931 }
932
933 if (netmask >= 8 && memcmp(ip, net, netmask / 8) != 0)
934 return false;
935 if ((netmask & 7) == 0)
936 return true;
937
938 // compare the last octet now
939 quint8 bytemask = 256 - (1 << (8 - (netmask & 7)));
940 quint8 ipbyte = ip[netmask / 8];
941 quint8 netbyte = net[netmask / 8];
942 return (ipbyte & bytemask) == (netbyte & bytemask);
943}
944
945/*!
946 \since 4.5
947 \overload
948
949 Returns true if this IP is in the subnet described by \a
950 subnet. The QHostAddress member of \a subnet contains the network
951 prefix and the int (second) member contains the netmask (prefix
952 length).
953*/
954bool QHostAddress::isInSubnet(const QPair<QHostAddress, int> &subnet) const
955{
956 return isInSubnet(subnet.first, subnet.second);
957}
958
959
960/*!
961 \since 4.5
962
963 Parses the IP and subnet information contained in \a subnet and
964 returns the network prefix for that network and its prefix length.
965
966 The IP address and the netmask must be separated by a slash
967 (/).
968
969 This function supports arguments in the form:
970 \list
971 \o 123.123.123.123/n where n is any value between 0 and 32
972 \o 123.123.123.123/255.255.255.255
973 \o <ipv6-address>/n where n is any value between 0 and 128
974 \endlist
975
976 For IP version 4, this function accepts as well missing trailing
977 components (i.e., less than 4 octets, like "192.168.1"), followed
978 or not by a dot. If the netmask is also missing in that case, it
979 is set to the number of octets actually passed (in the example
980 above, it would be 24, for 3 octets).
981
982 \sa isInSubnet()
983*/
984QPair<QHostAddress, int> QHostAddress::parseSubnet(const QString &subnet)
985{
986 // We support subnets in the form:
987 // ddd.ddd.ddd.ddd/nn
988 // ddd.ddd.ddd/nn
989 // ddd.ddd/nn
990 // ddd/nn
991 // ddd.ddd.ddd.
992 // ddd.ddd.ddd
993 // ddd.ddd.
994 // ddd.ddd
995 // ddd.
996 // ddd
997 // <ipv6-address>/nn
998 //
999 // where nn can be an IPv4-style netmask for the IPv4 forms
1000
1001 const QPair<QHostAddress, int> invalid = qMakePair(QHostAddress(), -1);
1002 if (subnet.isEmpty())
1003 return invalid;
1004
1005 int slash = subnet.indexOf(QLatin1Char('/'));
1006 QString netStr = subnet;
1007 if (slash != -1)
1008 netStr.truncate(slash);
1009
1010 int netmask = -1;
1011 bool isIpv6 = netStr.contains(QLatin1Char(':'));
1012
1013 if (slash != -1) {
1014 // is the netmask given in IP-form or in bit-count form?
1015 if (!isIpv6 && subnet.indexOf(QLatin1Char('.'), slash + 1) != -1) {
1016 // IP-style, convert it to bit-count form
1017 QNetmaskAddress parser;
1018 if (!parser.setAddress(subnet.mid(slash + 1)))
1019 return invalid;
1020 netmask = parser.prefixLength();
1021 } else {
1022 bool ok;
1023 netmask = subnet.mid(slash + 1).toUInt(&ok);
1024 if (!ok)
1025 return invalid; // failed to parse the subnet
1026 }
1027 }
1028
1029 if (isIpv6) {
1030 // looks like it's an IPv6 address
1031 if (netmask > 128)
1032 return invalid; // invalid netmask
1033 if (netmask < 0)
1034 netmask = 128;
1035
1036 QHostAddress net;
1037 if (!net.setAddress(netStr))
1038 return invalid; // failed to parse the IP
1039
1040 clearBits(net.d->a6.c, netmask, 128);
1041 return qMakePair(net, netmask);
1042 }
1043
1044 if (netmask > 32)
1045 return invalid; // invalid netmask
1046
1047 // parse the address manually
1048 QStringList parts = netStr.split(QLatin1Char('.'));
1049 if (parts.isEmpty() || parts.count() > 4)
1050 return invalid; // invalid IPv4 address
1051
1052 if (parts.last().isEmpty())
1053 parts.removeLast();
1054
1055 quint32 addr = 0;
1056 for (int i = 0; i < parts.count(); ++i) {
1057 bool ok;
1058 uint byteValue = parts.at(i).toUInt(&ok);
1059 if (!ok || byteValue > 255)
1060 return invalid; // invalid IPv4 address
1061
1062 addr <<= 8;
1063 addr += byteValue;
1064 }
1065 addr <<= 8 * (4 - parts.count());
1066 if (netmask == -1) {
1067 netmask = 8 * parts.count();
1068 } else if (netmask == 0) {
1069 // special case here
1070 // x86's instructions "shr" and "shl" do not operate when
1071 // their argument is 32, so the code below doesn't work as expected
1072 addr = 0;
1073 } else if (netmask != 32) {
1074 // clear remaining bits
1075 quint32 mask = quint32(0xffffffff) >> (32 - netmask) << (32 - netmask);
1076 addr &= mask;
1077 }
1078
1079 return qMakePair(QHostAddress(addr), netmask);
1080}
1081
1082#ifndef QT_NO_DEBUG_STREAM
1083QDebug operator<<(QDebug d, const QHostAddress &address)
1084{
1085 d.maybeSpace() << "QHostAddress(" << address.toString() << ')';
1086 return d.space();
1087}
1088#endif
1089
1090uint qHash(const QHostAddress &key)
1091{
1092 return qHash(key.toString());
1093}
1094
1095#ifndef QT_NO_DATASTREAM
1096
1097/*! \relates QHostAddress
1098
1099 Writes host address \a address to the stream \a out and returns a reference
1100 to the stream.
1101
1102 \sa {Serializing Qt Data Types}
1103*/
1104QDataStream &operator<<(QDataStream &out, const QHostAddress &address)
1105{
1106 qint8 prot;
1107 prot = qint8(address.protocol());
1108 out << prot;
1109 switch (address.protocol()) {
1110 case QAbstractSocket::UnknownNetworkLayerProtocol:
1111 break;
1112 case QAbstractSocket::IPv4Protocol:
1113 out << address.toIPv4Address();
1114 break;
1115 case QAbstractSocket::IPv6Protocol:
1116 {
1117 Q_IPV6ADDR ipv6 = address.toIPv6Address();
1118 for (int i = 0; i < 16; ++i)
1119 out << ipv6[i];
1120 out << address.scopeId();
1121 }
1122 break;
1123 }
1124 return out;
1125}
1126
1127/*! \relates QHostAddress
1128
1129 Reads a host address into \a address from the stream \a in and returns a
1130 reference to the stream.
1131
1132 \sa {Serializing Qt Data Types}
1133*/
1134QDataStream &operator>>(QDataStream &in, QHostAddress &address)
1135{
1136 qint8 prot;
1137 in >> prot;
1138 switch (QAbstractSocket::NetworkLayerProtocol(prot)) {
1139 case QAbstractSocket::UnknownNetworkLayerProtocol:
1140 address.clear();
1141 break;
1142 case QAbstractSocket::IPv4Protocol:
1143 {
1144 quint32 ipv4;
1145 in >> ipv4;
1146 address.setAddress(ipv4);
1147 }
1148 break;
1149 case QAbstractSocket::IPv6Protocol:
1150 {
1151 Q_IPV6ADDR ipv6;
1152 for (int i = 0; i < 16; ++i)
1153 in >> ipv6[i];
1154 address.setAddress(ipv6);
1155
1156 QString scope;
1157 in >> scope;
1158 address.setScopeId(scope);
1159 }
1160 break;
1161 default:
1162 address.clear();
1163 in.setStatus(QDataStream::ReadCorruptData);
1164 }
1165 return in;
1166}
1167
1168#endif //QT_NO_DATASTREAM
1169
1170QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.