| 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 "qset.h"
|
|---|
| 43 | #include "qnetworkinterface.h"
|
|---|
| 44 | #include "qnetworkinterface_p.h"
|
|---|
| 45 | #include "qalgorithms.h"
|
|---|
| 46 |
|
|---|
| 47 | #ifndef QT_NO_NETWORKINTERFACE
|
|---|
| 48 |
|
|---|
| 49 | #define IP_MULTICAST // make AIX happy and define IFF_MULTICAST
|
|---|
| 50 |
|
|---|
| 51 | #include <sys/types.h>
|
|---|
| 52 | #include <sys/socket.h>
|
|---|
| 53 |
|
|---|
| 54 | #ifdef Q_OS_SOLARIS
|
|---|
| 55 | # include <sys/sockio.h>
|
|---|
| 56 | #endif
|
|---|
| 57 | #include <net/if.h>
|
|---|
| 58 |
|
|---|
| 59 | #ifndef QT_NO_GETIFADDRS
|
|---|
| 60 | # include <ifaddrs.h>
|
|---|
| 61 | #endif
|
|---|
| 62 |
|
|---|
| 63 | #ifdef QT_LINUXBASE
|
|---|
| 64 | # include <arpa/inet.h>
|
|---|
| 65 | # ifndef SIOCGIFBRDADDR
|
|---|
| 66 | # define SIOCGIFBRDADDR 0x8919
|
|---|
| 67 | # endif
|
|---|
| 68 | #endif // QT_LINUXBASE
|
|---|
| 69 |
|
|---|
| 70 | #include <qplatformdefs.h>
|
|---|
| 71 |
|
|---|
| 72 | QT_BEGIN_NAMESPACE
|
|---|
| 73 |
|
|---|
| 74 | static QHostAddress addressFromSockaddr(sockaddr *sa)
|
|---|
| 75 | {
|
|---|
| 76 | QHostAddress address;
|
|---|
| 77 | if (!sa)
|
|---|
| 78 | return address;
|
|---|
| 79 |
|
|---|
| 80 | if (sa->sa_family == AF_INET)
|
|---|
| 81 | address.setAddress(htonl(((sockaddr_in *)sa)->sin_addr.s_addr));
|
|---|
| 82 | #ifndef QT_NO_IPV6
|
|---|
| 83 | else if (sa->sa_family == AF_INET6)
|
|---|
| 84 | address.setAddress(((sockaddr_in6 *)sa)->sin6_addr.s6_addr);
|
|---|
| 85 | #endif
|
|---|
| 86 | return address;
|
|---|
| 87 |
|
|---|
| 88 | }
|
|---|
| 89 |
|
|---|
| 90 | static QNetworkInterface::InterfaceFlags convertFlags(uint rawFlags)
|
|---|
| 91 | {
|
|---|
| 92 | QNetworkInterface::InterfaceFlags flags = 0;
|
|---|
| 93 | flags |= (rawFlags & IFF_UP) ? QNetworkInterface::IsUp : QNetworkInterface::InterfaceFlag(0);
|
|---|
| 94 | flags |= (rawFlags & IFF_RUNNING) ? QNetworkInterface::IsRunning : QNetworkInterface::InterfaceFlag(0);
|
|---|
| 95 | flags |= (rawFlags & IFF_BROADCAST) ? QNetworkInterface::CanBroadcast : QNetworkInterface::InterfaceFlag(0);
|
|---|
| 96 | flags |= (rawFlags & IFF_LOOPBACK) ? QNetworkInterface::IsLoopBack : QNetworkInterface::InterfaceFlag(0);
|
|---|
| 97 | #ifdef IFF_POINTOPOINT //cygwin doesn't define IFF_POINTOPOINT
|
|---|
| 98 | flags |= (rawFlags & IFF_POINTOPOINT) ? QNetworkInterface::IsPointToPoint : QNetworkInterface::InterfaceFlag(0);
|
|---|
| 99 | #endif
|
|---|
| 100 |
|
|---|
| 101 | #ifdef IFF_MULTICAST
|
|---|
| 102 | flags |= (rawFlags & IFF_MULTICAST) ? QNetworkInterface::CanMulticast : QNetworkInterface::InterfaceFlag(0);
|
|---|
| 103 | #endif
|
|---|
| 104 | return flags;
|
|---|
| 105 | }
|
|---|
| 106 |
|
|---|
| 107 | #ifdef QT_NO_GETIFADDRS
|
|---|
| 108 | // getifaddrs not available
|
|---|
| 109 |
|
|---|
| 110 | static const int STORAGEBUFFER_GROWTH = 256;
|
|---|
| 111 |
|
|---|
| 112 | static QSet<QByteArray> interfaceNames(int socket)
|
|---|
| 113 | {
|
|---|
| 114 | QSet<QByteArray> result;
|
|---|
| 115 | #ifdef QT_NO_IPV6IFNAME
|
|---|
| 116 | QByteArray storageBuffer;
|
|---|
| 117 | struct ifconf interfaceList;
|
|---|
| 118 |
|
|---|
| 119 | forever {
|
|---|
| 120 | // grow the storage buffer
|
|---|
| 121 | storageBuffer.resize(storageBuffer.size() + STORAGEBUFFER_GROWTH);
|
|---|
| 122 | interfaceList.ifc_buf = storageBuffer.data();
|
|---|
| 123 | interfaceList.ifc_len = storageBuffer.size();
|
|---|
| 124 |
|
|---|
| 125 | // get the interface list
|
|---|
| 126 | if (::ioctl(socket, SIOCGIFCONF, &interfaceList) >= 0) {
|
|---|
| 127 | if (int(interfaceList.ifc_len + sizeof(ifreq) + 64) < storageBuffer.size()) {
|
|---|
| 128 | // if the buffer was big enough, break
|
|---|
| 129 | storageBuffer.resize(interfaceList.ifc_len);
|
|---|
| 130 | break;
|
|---|
| 131 | }
|
|---|
| 132 | } else {
|
|---|
| 133 | // internal error
|
|---|
| 134 | return result;
|
|---|
| 135 | }
|
|---|
| 136 | if (storageBuffer.size() > 100000) {
|
|---|
| 137 | // out of space
|
|---|
| 138 | return result;
|
|---|
| 139 | }
|
|---|
| 140 | }
|
|---|
| 141 |
|
|---|
| 142 | int interfaceCount = interfaceList.ifc_len / sizeof(ifreq);
|
|---|
| 143 | for (int i = 0; i < interfaceCount; ++i) {
|
|---|
| 144 | QByteArray name = QByteArray(interfaceList.ifc_req[i].ifr_name);
|
|---|
| 145 | if (!name.isEmpty())
|
|---|
| 146 | result << name;
|
|---|
| 147 | }
|
|---|
| 148 |
|
|---|
| 149 | return result;
|
|---|
| 150 | #else
|
|---|
| 151 | Q_UNUSED(socket);
|
|---|
| 152 |
|
|---|
| 153 | // use if_nameindex
|
|---|
| 154 | struct if_nameindex *interfaceList = ::if_nameindex();
|
|---|
| 155 | for (struct if_nameindex *ptr = interfaceList; ptr && ptr->if_name; ++ptr)
|
|---|
| 156 | result << ptr->if_name;
|
|---|
| 157 |
|
|---|
| 158 | if_freenameindex(interfaceList);
|
|---|
| 159 | return result;
|
|---|
| 160 | #endif
|
|---|
| 161 | }
|
|---|
| 162 |
|
|---|
| 163 | static QNetworkInterfacePrivate *findInterface(int socket, QList<QNetworkInterfacePrivate *> &interfaces,
|
|---|
| 164 | struct ifreq &req)
|
|---|
| 165 | {
|
|---|
| 166 | QNetworkInterfacePrivate *iface = 0;
|
|---|
| 167 | int ifindex = 0;
|
|---|
| 168 |
|
|---|
| 169 | #ifndef QT_NO_IPV6IFNAME
|
|---|
| 170 | // Get the interface index
|
|---|
| 171 | ifindex = if_nametoindex(req.ifr_name);
|
|---|
| 172 |
|
|---|
| 173 | // find the interface data
|
|---|
| 174 | QList<QNetworkInterfacePrivate *>::Iterator if_it = interfaces.begin();
|
|---|
| 175 | for ( ; if_it != interfaces.end(); ++if_it)
|
|---|
| 176 | if ((*if_it)->index == ifindex) {
|
|---|
| 177 | // existing interface
|
|---|
| 178 | iface = *if_it;
|
|---|
| 179 | break;
|
|---|
| 180 | }
|
|---|
| 181 | #else
|
|---|
| 182 | // Search by name
|
|---|
| 183 | QList<QNetworkInterfacePrivate *>::Iterator if_it = interfaces.begin();
|
|---|
| 184 | for ( ; if_it != interfaces.end(); ++if_it)
|
|---|
| 185 | if ((*if_it)->name == QLatin1String(req.ifr_name)) {
|
|---|
| 186 | // existing interface
|
|---|
| 187 | iface = *if_it;
|
|---|
| 188 | break;
|
|---|
| 189 | }
|
|---|
| 190 | #endif
|
|---|
| 191 |
|
|---|
| 192 | if (!iface) {
|
|---|
| 193 | // new interface, create data:
|
|---|
| 194 | iface = new QNetworkInterfacePrivate;
|
|---|
| 195 | iface->index = ifindex;
|
|---|
| 196 | interfaces << iface;
|
|---|
| 197 |
|
|---|
| 198 | #ifdef SIOCGIFNAME
|
|---|
| 199 | // Get the canonical name
|
|---|
| 200 | QByteArray oldName = req.ifr_name;
|
|---|
| 201 | if (::ioctl(socket, SIOCGIFNAME, &req) >= 0) {
|
|---|
| 202 | iface->name = QString::fromLatin1(req.ifr_name);
|
|---|
| 203 |
|
|---|
| 204 | // reset the name:
|
|---|
| 205 | memcpy(req.ifr_name, oldName, qMin<int>(oldName.length() + 1, sizeof(req.ifr_name) - 1));
|
|---|
| 206 | } else
|
|---|
| 207 | #endif
|
|---|
| 208 | {
|
|---|
| 209 | // use this name anyways
|
|---|
| 210 | iface->name = QString::fromLatin1(req.ifr_name);
|
|---|
| 211 | }
|
|---|
| 212 |
|
|---|
| 213 | // Get interface flags
|
|---|
| 214 | if (::ioctl(socket, SIOCGIFFLAGS, &req) >= 0) {
|
|---|
| 215 | iface->flags = convertFlags(req.ifr_flags);
|
|---|
| 216 | }
|
|---|
| 217 |
|
|---|
| 218 | #ifdef SIOCGIFHWADDR
|
|---|
| 219 | // Get the HW address
|
|---|
| 220 | if (::ioctl(socket, SIOCGIFHWADDR, &req) >= 0) {
|
|---|
| 221 | uchar *addr = (uchar *)&req.ifr_addr;
|
|---|
| 222 | iface->hardwareAddress = iface->makeHwAddress(6, addr);
|
|---|
| 223 | }
|
|---|
| 224 | #endif
|
|---|
| 225 | }
|
|---|
| 226 |
|
|---|
| 227 | return iface;
|
|---|
| 228 | }
|
|---|
| 229 |
|
|---|
| 230 | static QList<QNetworkInterfacePrivate *> interfaceListing()
|
|---|
| 231 | {
|
|---|
| 232 | QList<QNetworkInterfacePrivate *> interfaces;
|
|---|
| 233 |
|
|---|
| 234 | int socket;
|
|---|
| 235 | if ((socket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) == -1)
|
|---|
| 236 | return interfaces; // error
|
|---|
| 237 |
|
|---|
| 238 | QSet<QByteArray> names = interfaceNames(socket);
|
|---|
| 239 | QSet<QByteArray>::ConstIterator it = names.constBegin();
|
|---|
| 240 | for ( ; it != names.constEnd(); ++it) {
|
|---|
| 241 | ifreq req;
|
|---|
| 242 | memset(&req, 0, sizeof(ifreq));
|
|---|
| 243 | memcpy(req.ifr_name, *it, qMin<int>(it->length() + 1, sizeof(req.ifr_name) - 1));
|
|---|
| 244 |
|
|---|
| 245 | QNetworkInterfacePrivate *iface = findInterface(socket, interfaces, req);
|
|---|
| 246 |
|
|---|
| 247 | // Get the interface broadcast address
|
|---|
| 248 | QNetworkAddressEntry entry;
|
|---|
| 249 | if (iface->flags & QNetworkInterface::CanBroadcast) {
|
|---|
| 250 | if (::ioctl(socket, SIOCGIFBRDADDR, &req) >= 0) {
|
|---|
| 251 | sockaddr *sa = &req.ifr_addr;
|
|---|
| 252 | if (sa->sa_family == AF_INET)
|
|---|
| 253 | entry.setBroadcast(addressFromSockaddr(sa));
|
|---|
| 254 | }
|
|---|
| 255 | }
|
|---|
| 256 |
|
|---|
| 257 | // Get the interface netmask
|
|---|
| 258 | if (::ioctl(socket, SIOCGIFNETMASK, &req) >= 0) {
|
|---|
| 259 | sockaddr *sa = &req.ifr_addr;
|
|---|
| 260 | entry.setNetmask(addressFromSockaddr(sa));
|
|---|
| 261 | }
|
|---|
| 262 |
|
|---|
| 263 | // Get the address of the interface
|
|---|
| 264 | if (::ioctl(socket, SIOCGIFADDR, &req) >= 0) {
|
|---|
| 265 | sockaddr *sa = &req.ifr_addr;
|
|---|
| 266 | entry.setIp(addressFromSockaddr(sa));
|
|---|
| 267 | }
|
|---|
| 268 |
|
|---|
| 269 | iface->addressEntries << entry;
|
|---|
| 270 | }
|
|---|
| 271 |
|
|---|
| 272 | ::close(socket);
|
|---|
| 273 | return interfaces;
|
|---|
| 274 | }
|
|---|
| 275 |
|
|---|
| 276 | #else
|
|---|
| 277 | // use getifaddrs
|
|---|
| 278 |
|
|---|
| 279 | // platform-specific defs:
|
|---|
| 280 | # ifdef Q_OS_LINUX
|
|---|
| 281 | QT_BEGIN_INCLUDE_NAMESPACE
|
|---|
| 282 | # include <features.h>
|
|---|
| 283 | QT_END_INCLUDE_NAMESPACE
|
|---|
| 284 | # endif
|
|---|
| 285 |
|
|---|
| 286 | # if defined(Q_OS_LINUX) && __GLIBC__ - 0 >= 2 && __GLIBC_MINOR__ - 0 >= 1
|
|---|
| 287 | # include <netpacket/packet.h>
|
|---|
| 288 |
|
|---|
| 289 | static QList<QNetworkInterfacePrivate *> createInterfaces(ifaddrs *rawList)
|
|---|
| 290 | {
|
|---|
| 291 | QList<QNetworkInterfacePrivate *> interfaces;
|
|---|
| 292 |
|
|---|
| 293 | for (ifaddrs *ptr = rawList; ptr; ptr = ptr->ifa_next) {
|
|---|
| 294 | if ( !ptr->ifa_addr )
|
|---|
| 295 | continue;
|
|---|
| 296 |
|
|---|
| 297 | // Get the interface index
|
|---|
| 298 | int ifindex = if_nametoindex(ptr->ifa_name);
|
|---|
| 299 |
|
|---|
| 300 | // on Linux we use AF_PACKET and sockaddr_ll to obtain hHwAddress
|
|---|
| 301 | QList<QNetworkInterfacePrivate *>::Iterator if_it = interfaces.begin();
|
|---|
| 302 | for ( ; if_it != interfaces.end(); ++if_it)
|
|---|
| 303 | if ((*if_it)->index == ifindex) {
|
|---|
| 304 | // this one has been added already
|
|---|
| 305 | if ( ptr->ifa_addr->sa_family == AF_PACKET
|
|---|
| 306 | && (*if_it)->hardwareAddress.isEmpty()) {
|
|---|
| 307 | sockaddr_ll *sll = (sockaddr_ll *)ptr->ifa_addr;
|
|---|
| 308 | (*if_it)->hardwareAddress = (*if_it)->makeHwAddress(sll->sll_halen, (uchar*)sll->sll_addr);
|
|---|
| 309 | }
|
|---|
| 310 | break;
|
|---|
| 311 | }
|
|---|
| 312 | if ( if_it != interfaces.end() )
|
|---|
| 313 | continue;
|
|---|
| 314 |
|
|---|
| 315 | QNetworkInterfacePrivate *iface = new QNetworkInterfacePrivate;
|
|---|
| 316 | interfaces << iface;
|
|---|
| 317 | iface->index = ifindex;
|
|---|
| 318 | iface->name = QString::fromLatin1(ptr->ifa_name);
|
|---|
| 319 | iface->flags = convertFlags(ptr->ifa_flags);
|
|---|
| 320 |
|
|---|
| 321 | if ( ptr->ifa_addr->sa_family == AF_PACKET ) {
|
|---|
| 322 | sockaddr_ll *sll = (sockaddr_ll *)ptr->ifa_addr;
|
|---|
| 323 | iface->hardwareAddress = iface->makeHwAddress(sll->sll_halen, (uchar*)sll->sll_addr);
|
|---|
| 324 | }
|
|---|
| 325 | }
|
|---|
| 326 |
|
|---|
| 327 | return interfaces;
|
|---|
| 328 | }
|
|---|
| 329 |
|
|---|
| 330 | # elif defined(Q_OS_BSD4)
|
|---|
| 331 | QT_BEGIN_INCLUDE_NAMESPACE
|
|---|
| 332 | # include <net/if_dl.h>
|
|---|
| 333 | QT_END_INCLUDE_NAMESPACE
|
|---|
| 334 |
|
|---|
| 335 | static QList<QNetworkInterfacePrivate *> createInterfaces(ifaddrs *rawList)
|
|---|
| 336 | {
|
|---|
| 337 | QList<QNetworkInterfacePrivate *> interfaces;
|
|---|
| 338 |
|
|---|
| 339 | // on NetBSD we use AF_LINK and sockaddr_dl
|
|---|
| 340 | // scan the list for that family
|
|---|
| 341 | for (ifaddrs *ptr = rawList; ptr; ptr = ptr->ifa_next)
|
|---|
| 342 | if (ptr->ifa_addr && ptr->ifa_addr->sa_family == AF_LINK) {
|
|---|
| 343 | QNetworkInterfacePrivate *iface = new QNetworkInterfacePrivate;
|
|---|
| 344 | interfaces << iface;
|
|---|
| 345 |
|
|---|
| 346 | sockaddr_dl *sdl = (sockaddr_dl *)ptr->ifa_addr;
|
|---|
| 347 | iface->index = sdl->sdl_index;
|
|---|
| 348 | iface->name = QString::fromLatin1(ptr->ifa_name);
|
|---|
| 349 | iface->flags = convertFlags(ptr->ifa_flags);
|
|---|
| 350 | iface->hardwareAddress = iface->makeHwAddress(sdl->sdl_alen, (uchar*)LLADDR(sdl));
|
|---|
| 351 | }
|
|---|
| 352 |
|
|---|
| 353 | return interfaces;
|
|---|
| 354 | }
|
|---|
| 355 |
|
|---|
| 356 | # else // Generic version
|
|---|
| 357 |
|
|---|
| 358 | static QList<QNetworkInterfacePrivate *> createInterfaces(ifaddrs *rawList)
|
|---|
| 359 | {
|
|---|
| 360 | QList<QNetworkInterfacePrivate *> interfaces;
|
|---|
| 361 |
|
|---|
| 362 | // make sure there's one entry for each interface
|
|---|
| 363 | for (ifaddrs *ptr = rawList; ptr; ptr = ptr->ifa_next) {
|
|---|
| 364 | // Get the interface index
|
|---|
| 365 | int ifindex = if_nametoindex(ptr->ifa_name);
|
|---|
| 366 |
|
|---|
| 367 | QList<QNetworkInterfacePrivate *>::Iterator if_it = interfaces.begin();
|
|---|
| 368 | for ( ; if_it != interfaces.end(); ++if_it)
|
|---|
| 369 | if ((*if_it)->index == ifindex)
|
|---|
| 370 | // this one has been added already
|
|---|
| 371 | break;
|
|---|
| 372 |
|
|---|
| 373 | if (if_it == interfaces.end()) {
|
|---|
| 374 | // none found, create
|
|---|
| 375 | QNetworkInterfacePrivate *iface = new QNetworkInterfacePrivate;
|
|---|
| 376 | interfaces << iface;
|
|---|
| 377 |
|
|---|
| 378 | iface->index = ifindex;
|
|---|
| 379 | iface->name = QString::fromLatin1(ptr->ifa_name);
|
|---|
| 380 | iface->flags = convertFlags(ptr->ifa_flags);
|
|---|
| 381 | }
|
|---|
| 382 | }
|
|---|
| 383 |
|
|---|
| 384 | return interfaces;
|
|---|
| 385 | }
|
|---|
| 386 |
|
|---|
| 387 | # endif
|
|---|
| 388 |
|
|---|
| 389 |
|
|---|
| 390 | static QList<QNetworkInterfacePrivate *> interfaceListing()
|
|---|
| 391 | {
|
|---|
| 392 | QList<QNetworkInterfacePrivate *> interfaces;
|
|---|
| 393 |
|
|---|
| 394 | int socket;
|
|---|
| 395 | if ((socket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) == -1)
|
|---|
| 396 | return interfaces; // error
|
|---|
| 397 |
|
|---|
| 398 | ifaddrs *interfaceListing;
|
|---|
| 399 | if (getifaddrs(&interfaceListing) == -1) {
|
|---|
| 400 | // error
|
|---|
| 401 | ::close(socket);
|
|---|
| 402 | return interfaces;
|
|---|
| 403 | }
|
|---|
| 404 |
|
|---|
| 405 | interfaces = createInterfaces(interfaceListing);
|
|---|
| 406 | for (ifaddrs *ptr = interfaceListing; ptr; ptr = ptr->ifa_next) {
|
|---|
| 407 | // Get the interface index
|
|---|
| 408 | int ifindex = if_nametoindex(ptr->ifa_name);
|
|---|
| 409 | QNetworkInterfacePrivate *iface = 0;
|
|---|
| 410 | QList<QNetworkInterfacePrivate *>::Iterator if_it = interfaces.begin();
|
|---|
| 411 | for ( ; if_it != interfaces.end(); ++if_it)
|
|---|
| 412 | if ((*if_it)->index == ifindex) {
|
|---|
| 413 | // found this interface already
|
|---|
| 414 | iface = *if_it;
|
|---|
| 415 | break;
|
|---|
| 416 | }
|
|---|
| 417 | if (!iface) {
|
|---|
| 418 | // skip all non-IP interfaces
|
|---|
| 419 | continue;
|
|---|
| 420 | }
|
|---|
| 421 |
|
|---|
| 422 | QNetworkAddressEntry entry;
|
|---|
| 423 | entry.setIp(addressFromSockaddr(ptr->ifa_addr));
|
|---|
| 424 | if (entry.ip().isNull())
|
|---|
| 425 | // could not parse the address
|
|---|
| 426 | continue;
|
|---|
| 427 |
|
|---|
| 428 | entry.setNetmask(addressFromSockaddr(ptr->ifa_netmask));
|
|---|
| 429 | if (iface->flags & QNetworkInterface::CanBroadcast)
|
|---|
| 430 | entry.setBroadcast(addressFromSockaddr(ptr->ifa_broadaddr));
|
|---|
| 431 |
|
|---|
| 432 | iface->addressEntries << entry;
|
|---|
| 433 | }
|
|---|
| 434 |
|
|---|
| 435 | freeifaddrs(interfaceListing);
|
|---|
| 436 | ::close(socket);
|
|---|
| 437 | return interfaces;
|
|---|
| 438 | }
|
|---|
| 439 | #endif
|
|---|
| 440 |
|
|---|
| 441 | QList<QNetworkInterfacePrivate *> QNetworkInterfaceManager::scan()
|
|---|
| 442 | {
|
|---|
| 443 | return interfaceListing();
|
|---|
| 444 | }
|
|---|
| 445 |
|
|---|
| 446 | QT_END_NAMESPACE
|
|---|
| 447 |
|
|---|
| 448 | #endif // QT_NO_NETWORKINTERFACE
|
|---|