source: trunk/src/network/kernel/qnetworkinterface_os2.cpp@ 807

Last change on this file since 807 was 801, checked in by Dmitry A. Kuminov, 15 years ago

network: QNetworkInterface: Fixed: hardwareAddress() returned null instead of a real MAC; netmask() returned null; allInterfaces() could sometimes return non-existent interfaces. Closes #63.

File size: 6.9 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** Copyright (C) 2010 netlabs.org. OS/2 parts.
8**
9** This file is part of the QtNetwork module of the Qt Toolkit.
10**
11** $QT_BEGIN_LICENSE:LGPL$
12** Commercial Usage
13** Licensees holding valid Qt Commercial licenses may use this file in
14** accordance with the Qt Commercial License Agreement provided with the
15** Software or, alternatively, in accordance with the terms contained in
16** a written agreement between you and Nokia.
17**
18** GNU Lesser General Public License Usage
19** Alternatively, this file may be used under the terms of the GNU Lesser
20** General Public License version 2.1 as published by the Free Software
21** Foundation and appearing in the file LICENSE.LGPL included in the
22** packaging of this file. Please review the following information to
23** ensure the GNU Lesser General Public License version 2.1 requirements
24** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25**
26** In addition, as a special exception, Nokia gives you certain additional
27** rights. These rights are described in the Nokia Qt LGPL Exception
28** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29**
30** GNU General Public License Usage
31** Alternatively, this file may be used under the terms of the GNU
32** General Public License version 3.0 as published by the Free Software
33** Foundation and appearing in the file LICENSE.GPL included in the
34** packaging of this file. Please review the following information to
35** ensure the GNU General Public License version 3.0 requirements will be
36** met: http://www.gnu.org/copyleft/gpl.html.
37**
38** If you have questions regarding the use of this file, please contact
39** Nokia at [email protected].
40** $QT_END_LICENSE$
41**
42****************************************************************************/
43
44#include "qset.h"
45#include "qnetworkinterface.h"
46#include "qnetworkinterface_p.h"
47#include "qalgorithms.h"
48
49#ifndef QT_NO_NETWORKINTERFACE
50
51#include <sys/types.h>
52#include <sys/socket.h>
53
54#include <sys/sockio.h>
55#include <net/if.h>
56#include <net/route.h>
57
58#include <qplatformdefs.h>
59
60QT_BEGIN_NAMESPACE
61
62static QNetworkInterface::InterfaceFlags convertFlags(uint rawFlags)
63{
64 QNetworkInterface::InterfaceFlags flags = 0;
65 flags |= (rawFlags & IFF_UP) ? QNetworkInterface::IsUp : QNetworkInterface::InterfaceFlag(0);
66 flags |= (rawFlags & IFF_RUNNING) ? QNetworkInterface::IsRunning : QNetworkInterface::InterfaceFlag(0);
67 flags |= (rawFlags & IFF_BROADCAST) ? QNetworkInterface::CanBroadcast : QNetworkInterface::InterfaceFlag(0);
68 flags |= (rawFlags & IFF_LOOPBACK) ? QNetworkInterface::IsLoopBack : QNetworkInterface::InterfaceFlag(0);
69 flags |= (rawFlags & IFF_POINTOPOINT) ? QNetworkInterface::IsPointToPoint : QNetworkInterface::InterfaceFlag(0);
70 flags |= (rawFlags & IFF_MULTICAST) ? QNetworkInterface::CanMulticast : QNetworkInterface::InterfaceFlag(0);
71 return flags;
72}
73
74static QList<QNetworkInterfacePrivate *> interfaceListing()
75{
76 // in this function, we use OS/2 specific socket IOCTLs to get more precise
77 // interface information than provided by the standard socket IOCTLs. Note
78 // that os2_ioctl() does not support high-mem so all buffers should be
79 // either on stack or in low-mem
80
81 QList<QNetworkInterfacePrivate *> interfaces;
82
83 int socket;
84 if ((socket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) == -1)
85 return interfaces; // error
86
87 // rumors say that the address buffer should be at least 65536 bytes long
88 char addrBuf[65536];
89 short naddrs;
90 statatreq *addrs;
91
92 ifmib ifmibget;
93 // zero the interface table because garbage will be returned in interface
94 // names otherwise
95 memset(&ifmibget,0, sizeof(ifmib));
96
97 int rc;
98
99 // get available interfaces
100 rc = ::os2_ioctl(socket, SIOSTATIF, (char*)&ifmibget, sizeof(ifmib));
101 if (rc == -1) {
102 ::close(socket);
103 return interfaces;
104 }
105
106 // get IP addresses
107 rc = ::os2_ioctl(socket, SIOSTATAT, addrBuf, sizeof(addrBuf));
108 if (rc == -1) {
109 ::close(socket);
110 return interfaces;
111 }
112 naddrs = *(short *)addrBuf;
113 addrs = (statatreq *)(addrBuf + sizeof(unsigned short));
114
115 // loop over interfaces
116 int idx = 0;
117 for (int i = 0; i < IFMIB_ENTRIES && idx < ifmibget.ifNumber; ++i) {
118 // skip empty interface entries
119 if (ifmibget.iftable[i].iftType == 0)
120 continue;
121
122 QNetworkInterfacePrivate *iface = new QNetworkInterfacePrivate;
123 iface->index = ifmibget.iftable[i].iftIndex;
124
125 // Derive the interface name. Not perfect, but there seems to be no
126 // other documented way (taken from Odin sources)
127 if (iface->index >= 0 && iface->index < 9) {// lanX
128 iface->name = QString(QLatin1String("lan%1")).arg(iface->index);
129 } else if (strstr(ifmibget.iftable[i].iftDescr, "back")) { // loopback
130 iface->name = QLatin1String("lo");
131 }
132 else if (strstr(ifmibget.iftable[i].iftDescr, "ace ppp")) {// pppX
133 iface->name = QLatin1String(strstr(ifmibget.iftable[i].iftDescr, "ppp"));
134 } else if (strstr(ifmibget.iftable[i].iftDescr,"ace sl")) { // slX
135 iface->name = QLatin1String(strstr(ifmibget.iftable[i].iftDescr, "sl"));
136 } else if (strstr(ifmibget.iftable[i].iftDescr,"ace dod")) { // dodX
137 iface->name = QLatin1String(strstr(ifmibget.iftable[i].iftDescr, "dod"));
138 } else { // something else...
139 iface->name = QString(QLatin1String("unk%1")).arg(iface->index);
140 }
141
142 iface->friendlyName = QString::fromLocal8Bit(ifmibget.iftable[i].iftDescr);
143 iface->hardwareAddress =
144 iface->makeHwAddress(sizeof(ifmibget.iftable[i].iftPhysAddr),
145 (uchar *)&ifmibget.iftable[i].iftPhysAddr[0]);
146
147 // get interface flags
148 ifreq req;
149 memset(&req, 0, sizeof(ifreq));
150 strncpy(req.ifr_name, iface->name.toLatin1(), sizeof(req.ifr_name));
151 if (::ioctl(socket, SIOCGIFFLAGS, &req) != -1) {
152 iface->flags = convertFlags(req.ifr_flags);
153 }
154
155 // get interface addresses
156 for (int j = 0; j < naddrs; ++j) {
157 if (addrs[j].interface == iface->index) {
158 QNetworkAddressEntry entry;
159 entry.setIp(QHostAddress(htonl(addrs[j].addr)));
160 // mask is the only one in network byte order for some reason
161 entry.setNetmask(QHostAddress(addrs[j].mask));
162 entry.setBroadcast(QHostAddress(htonl(addrs[j].broadcast)));
163 iface->addressEntries << entry;
164 }
165 }
166
167 // store the interface
168 interfaces << iface;
169 }
170
171 ::close(socket);
172 return interfaces;
173}
174
175QList<QNetworkInterfacePrivate *> QNetworkInterfaceManager::scan()
176{
177 return interfaceListing();
178}
179
180QT_END_NAMESPACE
181
182#endif // QT_NO_NETWORKINTERFACE
Note: See TracBrowser for help on using the repository browser.