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

Last change on this file since 376 was 2, checked in by Dmitry A. Kuminov, 17 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