source: trunk/src/network/kernel/qnetworkinterface.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: 19.3 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 "qnetworkinterface.h"
43#include "qnetworkinterface_p.h"
44
45#include "qdebug.h"
46#include "qendian.h"
47
48#ifndef QT_NO_NETWORKINTERFACE
49
50QT_BEGIN_NAMESPACE
51
52static QList<QNetworkInterfacePrivate *> postProcess(QList<QNetworkInterfacePrivate *> list)
53{
54 // Some platforms report a netmask but don't report a broadcast address
55 // Go through all available addresses and calculate the broadcast address
56 // from the IP and the netmask
57 //
58 // This is an IPv4-only thing -- IPv6 has no concept of broadcasts
59 // The math is:
60 // broadcast = IP | ~netmask
61
62 QList<QNetworkInterfacePrivate *>::Iterator it = list.begin();
63 const QList<QNetworkInterfacePrivate *>::Iterator end = list.end();
64 for ( ; it != end; ++it) {
65 QList<QNetworkAddressEntry>::Iterator addr_it = (*it)->addressEntries.begin();
66 const QList<QNetworkAddressEntry>::Iterator addr_end = (*it)->addressEntries.end();
67 for ( ; addr_it != addr_end; ++addr_it) {
68 if (addr_it->ip().protocol() != QAbstractSocket::IPv4Protocol)
69 continue;
70
71 if (!addr_it->netmask().isNull() && addr_it->broadcast().isNull()) {
72 QHostAddress bcast = addr_it->ip();
73 bcast = QHostAddress(bcast.toIPv4Address() | ~addr_it->netmask().toIPv4Address());
74 addr_it->setBroadcast(bcast);
75 }
76 }
77 }
78
79 return list;
80}
81
82Q_GLOBAL_STATIC(QNetworkInterfaceManager, manager)
83
84QNetworkInterfaceManager::QNetworkInterfaceManager()
85{
86}
87
88QNetworkInterfaceManager::~QNetworkInterfaceManager()
89{
90}
91
92QSharedDataPointer<QNetworkInterfacePrivate> QNetworkInterfaceManager::interfaceFromName(const QString &name)
93{
94 QList<QSharedDataPointer<QNetworkInterfacePrivate> > interfaceList = allInterfaces();
95 QList<QSharedDataPointer<QNetworkInterfacePrivate> >::ConstIterator it = interfaceList.constBegin();
96 for ( ; it != interfaceList.constEnd(); ++it)
97 if ((*it)->name == name)
98 return *it;
99
100 return empty;
101}
102
103QSharedDataPointer<QNetworkInterfacePrivate> QNetworkInterfaceManager::interfaceFromIndex(int index)
104{
105 QList<QSharedDataPointer<QNetworkInterfacePrivate> > interfaceList = allInterfaces();
106 QList<QSharedDataPointer<QNetworkInterfacePrivate> >::ConstIterator it = interfaceList.constBegin();
107 for ( ; it != interfaceList.constEnd(); ++it)
108 if ((*it)->index == index)
109 return *it;
110
111 return empty;
112}
113
114QList<QSharedDataPointer<QNetworkInterfacePrivate> > QNetworkInterfaceManager::allInterfaces()
115{
116 QList<QNetworkInterfacePrivate *> list = postProcess(scan());
117 QList<QSharedDataPointer<QNetworkInterfacePrivate> > result;
118
119 foreach (QNetworkInterfacePrivate *ptr, list)
120 result << QSharedDataPointer<QNetworkInterfacePrivate>(ptr);
121
122 return result;
123}
124
125QString QNetworkInterfacePrivate::makeHwAddress(int len, uchar *data)
126{
127 QString result;
128 for (int i = 0; i < len; ++i) {
129 if (i)
130 result += QLatin1Char(':');
131
132 char buf[3];
133#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && defined(_MSC_VER) && _MSC_VER >= 1400
134 sprintf_s(buf, 3, "%02hX", ushort(data[i]));
135#else
136 sprintf(buf, "%02hX", ushort(data[i]));
137#endif
138 result += QLatin1String(buf);
139 }
140 return result;
141}
142
143/*!
144 \class QNetworkAddressEntry
145 \brief The QNetworkAddressEntry class stores one IP address
146 supported by a network interface, along with its associated
147 netmask and broadcast address.
148
149 \since 4.2
150 \reentrant
151 \ingroup network
152
153 Each network interface can contain zero or more IP addresses, which
154 in turn can be associated with a netmask and/or a broadcast
155 address (depending on support from the operating system).
156
157 This class represents one such group.
158*/
159
160/*!
161 Constructs an empty QNetworkAddressEntry object.
162*/
163QNetworkAddressEntry::QNetworkAddressEntry()
164 : d(new QNetworkAddressEntryPrivate)
165{
166}
167
168/*!
169 Constructs a QNetworkAddressEntry object that is a copy of the
170 object \a other.
171*/
172QNetworkAddressEntry::QNetworkAddressEntry(const QNetworkAddressEntry &other)
173 : d(new QNetworkAddressEntryPrivate(*other.d.data()))
174{
175}
176
177/*!
178 Makes a copy of the QNetworkAddressEntry object \a other.
179*/
180QNetworkAddressEntry &QNetworkAddressEntry::operator=(const QNetworkAddressEntry &other)
181{
182 *d.data() = *other.d.data();
183 return *this;
184}
185
186/*!
187 Destroys this QNetworkAddressEntry object.
188*/
189QNetworkAddressEntry::~QNetworkAddressEntry()
190{
191}
192
193/*!
194 Returns true if this network address entry is the same as \a
195 other.
196*/
197bool QNetworkAddressEntry::operator==(const QNetworkAddressEntry &other) const
198{
199 if (d == other.d) return true;
200 if (!d || !other.d) return false;
201 return d->address == other.d->address &&
202 d->netmask == other.d->netmask &&
203 d->broadcast == other.d->broadcast;
204}
205
206/*!
207 \fn bool QNetworkAddressEntry::operator!=(const QNetworkAddressEntry &other) const
208
209 Returns true if this network address entry is different from \a
210 other.
211*/
212
213/*!
214 This function returns one IPv4 or IPv6 address found, that was
215 found in a network interface.
216*/
217QHostAddress QNetworkAddressEntry::ip() const
218{
219 return d->address;
220}
221
222/*!
223 Sets the IP address the QNetworkAddressEntry object contains to \a
224 newIp.
225*/
226void QNetworkAddressEntry::setIp(const QHostAddress &newIp)
227{
228 d->address = newIp;
229}
230
231/*!
232 Returns the netmask associated with the IP address. The
233 netmask is expressed in the form of an IP address, such as
234 255.255.0.0.
235
236 For IPv6 addresses, the prefix length is converted to an address
237 where the number of bits set to 1 is equal to the prefix
238 length. For a prefix length of 64 bits (the most common value),
239 the netmask will be expressed as a QHostAddress holding the
240 address FFFF:FFFF:FFFF:FFFF::
241
242 \sa prefixLength()
243*/
244QHostAddress QNetworkAddressEntry::netmask() const
245{
246 return d->netmask;
247}
248
249/*!
250 Sets the netmask that this QNetworkAddressEntry object contains to
251 \a newNetmask. Setting the netmask also sets the prefix length to
252 match the new netmask.
253
254 \sa setPrefixLength()
255*/
256void QNetworkAddressEntry::setNetmask(const QHostAddress &newNetmask)
257{
258 if (newNetmask.protocol() != ip().protocol()) {
259 d->netmask = QNetmaskAddress();
260 return;
261 }
262
263 d->netmask.setAddress(newNetmask);
264}
265
266/*!
267 \since 4.5
268 Returns the prefix length of this IP address. The prefix length
269 matches the number of bits set to 1 in the netmask (see
270 netmask()). For IPv4 addresses, the value is between 0 and 32. For
271 IPv6 addresses, it's contained between 0 and 128 and is the
272 preferred form of representing addresses.
273
274 This function returns -1 if the prefix length could not be
275 determined (i.e., netmask() returns a null QHostAddress()).
276
277 \sa netmask()
278*/
279int QNetworkAddressEntry::prefixLength() const
280{
281 return d->netmask.prefixLength();
282}
283
284/*!
285 \since 4.5
286 Sets the prefix length of this IP address to \a length. The value
287 of \a length must be valid for this type of IP address: between 0
288 and 32 for IPv4 addresses, between 0 and 128 for IPv6
289 addresses. Setting to any invalid value is equivalent to setting
290 to -1, which means "no prefix length".
291
292 Setting the prefix length also sets the netmask (see netmask()).
293
294 \sa setNetmask()
295*/
296void QNetworkAddressEntry::setPrefixLength(int length)
297{
298 d->netmask.setPrefixLength(d->address.protocol(), length);
299}
300
301/*!
302 Returns the broadcast address associated with the IPv4
303 address and netmask. It can usually be derived from those two by
304 setting to 1 the bits of the IP address where the netmask contains
305 a 0. (In other words, by bitwise-OR'ing the IP address with the
306 inverse of the netmask)
307
308 This member is always empty for IPv6 addresses, since the concept
309 of broadcast has been abandoned in that system in favor of
310 multicast. In particular, the group of hosts corresponding to all
311 the nodes in the local network can be reached by the "all-nodes"
312 special multicast group (address FF02::1).
313*/
314QHostAddress QNetworkAddressEntry::broadcast() const
315{
316 return d->broadcast;
317}
318
319/*!
320 Sets the broadcast IP address of this QNetworkAddressEntry object
321 to \a newBroadcast.
322*/
323void QNetworkAddressEntry::setBroadcast(const QHostAddress &newBroadcast)
324{
325 d->broadcast = newBroadcast;
326}
327
328/*!
329 \class QNetworkInterface
330 \brief The QNetworkInterface class provides a listing of the host's IP
331 addresses and network interfaces.
332
333 \since 4.2
334 \reentrant
335 \ingroup network
336
337 QNetworkInterface represents one network interface attached to the
338 host where the program is being run. Each network interface may
339 contain zero or more IP addresses, each of which is optionally
340 associated with a netmask and/or a broadcast address. The list of
341 such trios can be obtained with addressEntries(). Alternatively,
342 when the netmask or the broadcast addresses aren't necessary, use
343 the allAddresses() convenience function to obtain just the IP
344 addresses.
345
346 QNetworkInterface also reports the interface's hardware address with
347 hardwareAddress().
348
349 Not all operating systems support reporting all features. Only the
350 IPv4 addresses are guaranteed to be listed by this class in all
351 platforms. In particular, IPv6 address listing is only supported
352 on Windows XP and more recent versions, Linux, MacOS X and the
353 BSDs.
354
355 \sa QNetworkAddressEntry
356*/
357
358/*!
359 \enum QNetworkInterface::InterfaceFlag
360 Specifies the flags associated with this network interface. The
361 possible values are:
362
363 \value IsUp the network interface is active
364 \value IsRunning the network interface has resources
365 allocated
366 \value CanBroadcast the network interface works in
367 broadcast mode
368 \value IsLoopBack the network interface is a loopback
369 interface: that is, it's a virtual
370 interface whose destination is the
371 host computer itself
372 \value IsPointToPoint the network interface is a
373 point-to-point interface: that is,
374 there is one, single other address
375 that can be directly reached by it.
376 \value CanMulticast the network interface supports
377 multicasting
378
379 Note that one network interface cannot be both broadcast-based and
380 point-to-point.
381*/
382
383/*!
384 Constructs an empty network interface object.
385*/
386QNetworkInterface::QNetworkInterface()
387 : d(0)
388{
389}
390
391/*!
392 Frees the resources associated with the QNetworkInterface object.
393*/
394QNetworkInterface::~QNetworkInterface()
395{
396}
397
398/*!
399 Creates a copy of the QNetworkInterface object contained in \a
400 other.
401*/
402QNetworkInterface::QNetworkInterface(const QNetworkInterface &other)
403 : d(other.d)
404{
405}
406
407/*!
408 Copies the contents of the QNetworkInterface object contained in \a
409 other into this one.
410*/
411QNetworkInterface &QNetworkInterface::operator=(const QNetworkInterface &other)
412{
413 d = other.d;
414 return *this;
415}
416
417/*!
418 Returns true if this QNetworkInterface object contains valid
419 information about a network interface.
420*/
421bool QNetworkInterface::isValid() const
422{
423 return !name().isEmpty();
424}
425
426/*!
427 \since 4.5
428 Returns the interface system index, if known. This is an integer
429 assigned by the operating system to identify this interface and it
430 generally doesn't change. It matches the scope ID field in IPv6
431 addresses.
432
433 If the index isn't known, this function returns 0.
434*/
435int QNetworkInterface::index() const
436{
437 return d ? d->index : 0;
438}
439
440/*!
441 Returns the name of this network interface. On Unix systems, this
442 is a string containing the type of the interface and optionally a
443 sequence number, such as "eth0", "lo" or "pcn0". On Windows, it's
444 an internal ID that cannot be changed by the user.
445*/
446QString QNetworkInterface::name() const
447{
448 return d ? d->name : QString();
449}
450
451/*!
452 \since 4.5
453
454 Returns the human-readable name of this network interface on
455 Windows, such as "Local Area Connection", if the name could be
456 determined. If it couldn't, this function returns the same as
457 name(). The human-readable name is a name that the user can modify
458 in the Windows Control Panel, so it may change during the
459 execution of the program.
460
461 On Unix, this function currently always returns the same as
462 name(), since Unix systems don't store a configuration for
463 human-readable names.
464*/
465QString QNetworkInterface::humanReadableName() const
466{
467 return d ? !d->friendlyName.isEmpty() ? d->friendlyName : name() : QString();
468}
469
470/*!
471 Returns the flags associated with this network interface.
472*/
473QNetworkInterface::InterfaceFlags QNetworkInterface::flags() const
474{
475 return d ? d->flags : InterfaceFlags(0);
476}
477
478/*!
479 Returns the low-level hardware address for this interface. On
480 Ethernet interfaces, this will be a MAC address in string
481 representation, separated by colons.
482
483 Other interface types may have other types of hardware
484 addresses. Implementations should not depend on this function
485 returning a valid MAC address.
486*/
487QString QNetworkInterface::hardwareAddress() const
488{
489 return d ? d->hardwareAddress : QString();
490}
491
492/*!
493 Returns the list of IP addresses that this interface possesses
494 along with their associated netmasks and broadcast addresses.
495
496 If the netmask or broadcast address information is not necessary,
497 you can call the allAddresses() function to obtain just the IP
498 addresses.
499*/
500QList<QNetworkAddressEntry> QNetworkInterface::addressEntries() const
501{
502 return d ? d->addressEntries : QList<QNetworkAddressEntry>();
503}
504
505/*!
506 Returns a QNetworkInterface object for the interface named \a
507 name. If no such interface exists, this function returns an
508 invalid QNetworkInterface object.
509
510 \sa name(), isValid()
511*/
512QNetworkInterface QNetworkInterface::interfaceFromName(const QString &name)
513{
514 QNetworkInterface result;
515 result.d = manager()->interfaceFromName(name);
516 return result;
517}
518
519/*!
520 Returns a QNetworkInterface object for the interface whose internal
521 ID is \a index. Network interfaces have a unique identifier called
522 the "interface index" to distinguish it from other interfaces on
523 the system. Often, this value is assigned progressively and
524 interfaces being removed and then added again get a different
525 value every time.
526
527 This index is also found in the IPv6 address' scope ID field.
528*/
529QNetworkInterface QNetworkInterface::interfaceFromIndex(int index)
530{
531 QNetworkInterface result;
532 result.d = manager()->interfaceFromIndex(index);
533 return result;
534}
535
536/*!
537 Returns a listing of all the network interfaces found on the host
538 machine.
539*/
540QList<QNetworkInterface> QNetworkInterface::allInterfaces()
541{
542 QList<QSharedDataPointer<QNetworkInterfacePrivate> > privs = manager()->allInterfaces();
543 QList<QNetworkInterface> result;
544 foreach (const QSharedDataPointer<QNetworkInterfacePrivate> &p, privs) {
545 QNetworkInterface item;
546 item.d = p;
547 result << item;
548 }
549
550 return result;
551}
552
553/*!
554 This convenience function returns all IP addresses found on the
555 host machine. It is equivalent to calling addressEntries() on all the
556 objects returned by allInterfaces() to obtain lists of QHostAddress
557 objects then calling QHostAddress::ip() on each of these.
558*/
559QList<QHostAddress> QNetworkInterface::allAddresses()
560{
561 QList<QSharedDataPointer<QNetworkInterfacePrivate> > privs = manager()->allInterfaces();
562 QList<QHostAddress> result;
563 foreach (const QSharedDataPointer<QNetworkInterfacePrivate> &p, privs) {
564 foreach (const QNetworkAddressEntry &entry, p->addressEntries)
565 result += entry.ip();
566 }
567
568 return result;
569}
570
571#ifndef QT_NO_DEBUG_STREAM
572static inline QDebug flagsDebug(QDebug debug, QNetworkInterface::InterfaceFlags flags)
573{
574 if (flags & QNetworkInterface::IsUp)
575 debug.nospace() << "IsUp ";
576 if (flags & QNetworkInterface::IsRunning)
577 debug.nospace() << "IsRunning ";
578 if (flags & QNetworkInterface::CanBroadcast)
579 debug.nospace() << "CanBroadcast ";
580 if (flags & QNetworkInterface::IsLoopBack)
581 debug.nospace() << "IsLoopBack ";
582 if (flags & QNetworkInterface::IsPointToPoint)
583 debug.nospace() << "IsPointToPoint ";
584 if (flags & QNetworkInterface::CanMulticast)
585 debug.nospace() << "CanMulticast ";
586 return debug.nospace();
587}
588
589static inline QDebug operator<<(QDebug debug, const QNetworkAddressEntry &entry)
590{
591 debug.nospace() << "(address = " << entry.ip();
592 if (!entry.netmask().isNull())
593 debug.nospace() << ", netmask = " << entry.netmask();
594 if (!entry.broadcast().isNull())
595 debug.nospace() << ", broadcast = " << entry.broadcast();
596 debug.nospace() << ')';
597 return debug.space();
598}
599
600QDebug operator<<(QDebug debug, const QNetworkInterface &networkInterface)
601{
602 debug.nospace() << "QNetworkInterface(name = " << networkInterface.name()
603 << ", hardware address = " << networkInterface.hardwareAddress()
604 << ", flags = ";
605 flagsDebug(debug, networkInterface.flags());
606#if defined(Q_CC_RVCT)
607 // RVCT gets confused with << networkInterface.addressEntries(), reason unknown.
608 debug.nospace() << ")\n";
609#else
610 debug.nospace() << ", entries = " << networkInterface.addressEntries()
611 << ")\n";
612#endif
613 return debug.space();
614}
615#endif
616
617QT_END_NAMESPACE
618
619#endif // QT_NO_NETWORKINTERFACE
Note: See TracBrowser for help on using the repository browser.