source: trunk/src/network/kernel/qnetworkinterface.cpp@ 397

Last change on this file since 397 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 19.2 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtNetwork module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** 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 are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
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 io
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))
174{
175}
176
177/*!
178 Makes a copy of the QNetworkAddressEntry object \a other.
179*/
180QNetworkAddressEntry &QNetworkAddressEntry::operator=(const QNetworkAddressEntry &other)
181{
182 *d = *other.d;
183 return *this;
184}
185
186/*!
187 Destroys this QNetworkAddressEntry object.
188*/
189QNetworkAddressEntry::~QNetworkAddressEntry()
190{
191 delete d;
192}
193
194/*!
195 Returns true if this network address entry is the same as \a
196 other.
197*/
198bool QNetworkAddressEntry::operator==(const QNetworkAddressEntry &other) const
199{
200 if (d == other.d) return true;
201 if (!d || !other.d) return false;
202 return d->address == other.d->address &&
203 d->netmask == other.d->netmask &&
204 d->broadcast == other.d->broadcast;
205}
206
207/*!
208 \fn bool QNetworkAddressEntry::operator!=(const QNetworkAddressEntry &other) const
209
210 Returns true if this network address entry is different from \a
211 other.
212*/
213
214/*!
215 This function returns one IPv4 or IPv6 address found, that was
216 found in a network interface.
217*/
218QHostAddress QNetworkAddressEntry::ip() const
219{
220 return d->address;
221}
222
223/*!
224 Sets the IP address the QNetworkAddressEntry object contains to \a
225 newIp.
226*/
227void QNetworkAddressEntry::setIp(const QHostAddress &newIp)
228{
229 d->address = newIp;
230}
231
232/*!
233 Returns the netmask associated with the IP address. The
234 netmask is expressed in the form of an IP address, such as
235 255.255.0.0.
236
237 For IPv6 addresses, the prefix length is converted to an address
238 where the number of bits set to 1 is equal to the prefix
239 length. For a prefix length of 64 bits (the most common value),
240 the netmask will be expressed as a QHostAddress holding the
241 address FFFF:FFFF:FFFF:FFFF::
242
243 \sa prefixLength()
244*/
245QHostAddress QNetworkAddressEntry::netmask() const
246{
247 return d->netmask;
248}
249
250/*!
251 Sets the netmask that this QNetworkAddressEntry object contains to
252 \a newNetmask. Setting the netmask also sets the prefix length to
253 match the new netmask.
254
255 \sa setPrefixLength()
256*/
257void QNetworkAddressEntry::setNetmask(const QHostAddress &newNetmask)
258{
259 if (newNetmask.protocol() != ip().protocol()) {
260 d->netmask = QNetmaskAddress();
261 return;
262 }
263
264 d->netmask.setAddress(newNetmask);
265}
266
267/*!
268 \since 4.5
269 Returns the prefix length of this IP address. The prefix length
270 matches the number of bits set to 1 in the netmask (see
271 netmask()). For IPv4 addresses, the value is between 0 and 32. For
272 IPv6 addresses, it's contained between 0 and 128 and is the
273 preferred form of representing addresses.
274
275 This function returns -1 if the prefix length could not be
276 determined (i.e., netmask() returns a null QHostAddress()).
277
278 \sa netmask()
279*/
280int QNetworkAddressEntry::prefixLength() const
281{
282 return d->netmask.prefixLength();
283}
284
285/*!
286 \since 4.5
287 Sets the prefix length of this IP address to \a length. The value
288 of \a length must be valid for this type of IP address: between 0
289 and 32 for IPv4 addresses, between 0 and 128 for IPv6
290 addresses. Setting to any invalid value is equivalent to setting
291 to -1, which means "no prefix length".
292
293 Setting the prefix length also sets the netmask (see netmask()).
294
295 \sa setNetmask()
296*/
297void QNetworkAddressEntry::setPrefixLength(int length)
298{
299 d->netmask.setPrefixLength(d->address.protocol(), length);
300}
301
302/*!
303 Returns the broadcast address associated with the IPv4
304 address and netmask. It can usually be derived from those two by
305 setting to 1 the bits of the IP address where the netmask contains
306 a 0. (In other words, by bitwise-OR'ing the IP address with the
307 inverse of the netmask)
308
309 This member is always empty for IPv6 addresses, since the concept
310 of broadcast has been abandoned in that system in favor of
311 multicast. In particular, the group of hosts corresponding to all
312 the nodes in the local network can be reached by the "all-nodes"
313 special multicast group (address FF02::1).
314*/
315QHostAddress QNetworkAddressEntry::broadcast() const
316{
317 return d->broadcast;
318}
319
320/*!
321 Sets the broadcast IP address of this QNetworkAddressEntry object
322 to \a newBroadcast.
323*/
324void QNetworkAddressEntry::setBroadcast(const QHostAddress &newBroadcast)
325{
326 d->broadcast = newBroadcast;
327}
328
329/*!
330 \class QNetworkInterface
331 \brief The QNetworkInterface class provides a listing of the host's IP
332 addresses and network interfaces.
333
334 \since 4.2
335 \reentrant
336 \ingroup io
337
338 QNetworkInterface represents one network interface attached to the
339 host where the program is being run. Each network interface may
340 contain zero or more IP addresses, each of which is optionally
341 associated with a netmask and/or a broadcast address. The list of
342 such trios can be obtained with addressEntries(). Alternatively,
343 when the netmask or the broadcast addresses aren't necessary, use
344 the allAddresses() convenience function to obtain just the IP
345 addresses.
346
347 QNetworkInterface also reports the interface's hardware address with
348 hardwareAddress().
349
350 Not all operating systems support reporting all features. Only the
351 IPv4 addresses are guaranteed to be listed by this class in all
352 platforms. In particular, IPv6 address listing is only supported
353 on Windows XP and more recent versions, Linux, MacOS X and the
354 BSDs.
355
356 \sa QNetworkAddressEntry
357*/
358
359/*!
360 \enum QNetworkInterface::InterfaceFlag
361 Specifies the flags associated with this network interface. The
362 possible values are:
363
364 \value IsUp the network interface is active
365 \value IsRunning the network interface has resources
366 allocated
367 \value CanBroadcast the network interface works in
368 broadcast mode
369 \value IsLoopBack the network interface is a loopback
370 interface: that is, it's a virtual
371 interface whose destination is the
372 host computer itself
373 \value IsPointToPoint the network interface is a
374 point-to-point interface: that is,
375 there is one, single other address
376 that can be directly reached by it.
377 \value CanMulticast the network interface supports
378 multicasting
379
380 Note that one network interface cannot be both broadcast-based and
381 point-to-point.
382*/
383
384/*!
385 Constructs an empty network interface object.
386*/
387QNetworkInterface::QNetworkInterface()
388 : d(0)
389{
390}
391
392/*!
393 Frees the resources associated with the QNetworkInterface object.
394*/
395QNetworkInterface::~QNetworkInterface()
396{
397}
398
399/*!
400 Creates a copy of the the QNetworkInterface object contained in \a
401 other.
402*/
403QNetworkInterface::QNetworkInterface(const QNetworkInterface &other)
404 : d(other.d)
405{
406}
407
408/*!
409 Copies the contents of the QNetworkInterface object contained in \a
410 other into this one.
411*/
412QNetworkInterface &QNetworkInterface::operator=(const QNetworkInterface &other)
413{
414 d = other.d;
415 return *this;
416}
417
418/*!
419 Returns true if this QNetworkInterface object contains valid
420 information about a network interface.
421*/
422bool QNetworkInterface::isValid() const
423{
424 return !name().isEmpty();
425}
426
427/*!
428 \since 4.5
429 Returns the interface system index, if known. This is an integer
430 assigned by the operating system to identify this interface and it
431 generally doesn't change. It matches the scope ID field in IPv6
432 addresses.
433
434 If the index isn't known, this function returns 0.
435*/
436int QNetworkInterface::index() const
437{
438 return d ? d->index : 0;
439}
440
441/*!
442 Returns the name of this network interface. On Unix systems, this
443 is a string containing the type of the interface and optionally a
444 sequence number, such as "eth0", "lo" or "pcn0". On Windows, it's
445 an internal ID that cannot be changed by the user.
446*/
447QString QNetworkInterface::name() const
448{
449 return d ? d->name : QString();
450}
451
452/*!
453 \since 4.5
454
455 Returns the human-readable name of this network interface on
456 Windows, such as "Local Area Connection", if the name could be
457 determined. If it couldn't, this function returns the same as
458 name(). The human-readable name is a name that the user can modify
459 in the Windows Control Panel, so it may change during the
460 execution of the program.
461
462 On Unix, this function currently always returns the same as
463 name(), since Unix systems don't store a configuration for
464 human-readable names.
465*/
466QString QNetworkInterface::humanReadableName() const
467{
468 return d ? !d->friendlyName.isEmpty() ? d->friendlyName : name() : QString();
469}
470
471/*!
472 Returns the flags associated with this network interface.
473*/
474QNetworkInterface::InterfaceFlags QNetworkInterface::flags() const
475{
476 return d ? d->flags : InterfaceFlags(0);
477}
478
479/*!
480 Returns the low-level hardware address for this interface. On
481 Ethernet interfaces, this will be a MAC address in string
482 representation, separated by colons.
483
484 Other interface types may have other types of hardware
485 addresses. Implementations should not depend on this function
486 returning a valid MAC address.
487*/
488QString QNetworkInterface::hardwareAddress() const
489{
490 return d ? d->hardwareAddress : QString();
491}
492
493/*!
494 Returns the list of IP addresses that this interface possesses
495 along with their associated netmasks and broadcast addresses.
496
497 If the netmask or broadcast address information is not necessary,
498 you can call the allAddresses() function to obtain just the IP
499 addresses.
500*/
501QList<QNetworkAddressEntry> QNetworkInterface::addressEntries() const
502{
503 return d ? d->addressEntries : QList<QNetworkAddressEntry>();
504}
505
506/*!
507 Returns a QNetworkInterface object for the interface named \a
508 name. If no such interface exists, this function returns an
509 invalid QNetworkInterface object.
510
511 \sa name(), isValid()
512*/
513QNetworkInterface QNetworkInterface::interfaceFromName(const QString &name)
514{
515 QNetworkInterface result;
516 result.d = manager()->interfaceFromName(name);
517 return result;
518}
519
520/*!
521 Returns a QNetworkInterface object for the interface whose internal
522 ID is \a index. Network interfaces have a unique identifier called
523 the "interface index" to distinguish it from other interfaces on
524 the system. Often, this value is assigned progressively and
525 interfaces being removed and then added again get a different
526 value every time.
527
528 This index is also found in the IPv6 address' scope ID field.
529*/
530QNetworkInterface QNetworkInterface::interfaceFromIndex(int index)
531{
532 QNetworkInterface result;
533 result.d = manager()->interfaceFromIndex(index);
534 return result;
535}
536
537/*!
538 Returns a listing of all the network interfaces found on the host
539 machine.
540*/
541QList<QNetworkInterface> QNetworkInterface::allInterfaces()
542{
543 QList<QSharedDataPointer<QNetworkInterfacePrivate> > privs = manager()->allInterfaces();
544 QList<QNetworkInterface> result;
545 foreach (QSharedDataPointer<QNetworkInterfacePrivate> p, privs) {
546 QNetworkInterface item;
547 item.d = p;
548 result << item;
549 }
550
551 return result;
552}
553
554/*!
555 This convenience function returns all IP addresses found on the
556 host machine. It is equivalent to calling addressEntries() on all the
557 objects returned by allInterfaces() to obtain lists of QHostAddress
558 objects then calling QHostAddress::ip() on each of these.
559*/
560QList<QHostAddress> QNetworkInterface::allAddresses()
561{
562 QList<QSharedDataPointer<QNetworkInterfacePrivate> > privs = manager()->allInterfaces();
563 QList<QHostAddress> result;
564 foreach (const QSharedDataPointer<QNetworkInterfacePrivate> p, privs) {
565 foreach (const QNetworkAddressEntry &entry, p->addressEntries)
566 result += entry.ip();
567 }
568
569 return result;
570}
571
572#ifndef QT_NO_DEBUG_STREAM
573static inline QDebug flagsDebug(QDebug debug, QNetworkInterface::InterfaceFlags flags)
574{
575 if (flags & QNetworkInterface::IsUp)
576 debug.nospace() << "IsUp ";
577 if (flags & QNetworkInterface::IsRunning)
578 debug.nospace() << "IsRunning ";
579 if (flags & QNetworkInterface::CanBroadcast)
580 debug.nospace() << "CanBroadcast ";
581 if (flags & QNetworkInterface::IsLoopBack)
582 debug.nospace() << "IsLoopBack ";
583 if (flags & QNetworkInterface::IsPointToPoint)
584 debug.nospace() << "IsPointToPoint ";
585 if (flags & QNetworkInterface::CanMulticast)
586 debug.nospace() << "CanMulticast ";
587 return debug.nospace();
588}
589
590static inline QDebug operator<<(QDebug debug, const QNetworkAddressEntry &entry)
591{
592 debug.nospace() << "(address = " << entry.ip();
593 if (!entry.netmask().isNull())
594 debug.nospace() << ", netmask = " << entry.netmask();
595 if (!entry.broadcast().isNull())
596 debug.nospace() << ", broadcast = " << entry.broadcast();
597 debug.nospace() << ")";
598 return debug.space();
599}
600
601QDebug operator<<(QDebug debug, const QNetworkInterface &networkInterface)
602{
603 debug.nospace() << "QNetworkInterface(name = " << networkInterface.name()
604 << ", hardware address = " << networkInterface.hardwareAddress()
605 << ", flags = ";
606 flagsDebug(debug, networkInterface.flags());
607 debug.nospace() << ", entries = " << networkInterface.addressEntries()
608 << ")\n";
609 return debug.space();
610}
611#endif
612
613QT_END_NAMESPACE
614
615#endif // QT_NO_NETWORKINTERFACE
Note: See TracBrowser for help on using the repository browser.