Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qnetworkinterface_unix.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// Copyright (C) 2016 Intel Corporation.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4// Qt-Security score:significant reason:trusted-data
5
6#include "qbytearray.h"
7#include "qset.h"
11#include "qalgorithms.h"
12
13#include <QtCore/private/qduplicatetracker_p.h>
14
15#ifndef QT_NO_NETWORKINTERFACE
16
17#if QT_CONFIG(getifaddrs)
18# include <ifaddrs.h>
19#endif
20
21#ifdef QT_LINUXBASE
22# include <arpa/inet.h>
23# ifndef SIOCGIFBRDADDR
24# define SIOCGIFBRDADDR 0x8919
25# endif
26#endif // QT_LINUXBASE
27
28#include <qplatformdefs.h>
29
31
32static QHostAddress addressFromSockaddr(sockaddr *sa, int ifindex = 0, const QString &ifname = QString())
33{
34 QHostAddress address;
35 if (!sa)
36 return address;
37
38 if (sa->sa_family == AF_INET)
39 address.setAddress(htonl(((sockaddr_in *)sa)->sin_addr.s_addr));
40 else if (sa->sa_family == AF_INET6) {
41 address.setAddress(((sockaddr_in6 *)sa)->sin6_addr.s6_addr);
42 int scope = ((sockaddr_in6 *)sa)->sin6_scope_id;
43 if (scope && scope == ifindex) {
44 // this is the most likely scenario:
45 // a scope ID in a socket is that of the interface this address came from
46 address.setScopeId(ifname);
47 } else if (scope) {
48 address.setScopeId(QNetworkInterfaceManager::interfaceNameFromIndex(scope));
49 }
50 }
51 return address;
52}
53
54template <typename Req> [[maybe_unused]]
55static auto &ifreq_index(Req &req, std::enable_if_t<sizeof(std::declval<Req>().ifr_index) != 0, int> = 0)
56{
57 return req.ifr_index;
58}
59
60template <typename Req> [[maybe_unused]]
61static auto &ifreq_index(Req &req, std::enable_if_t<sizeof(std::declval<Req>().ifr_ifindex) != 0, int> = 0)
62{
63 return req.ifr_ifindex;
64}
65
66uint QNetworkInterfaceManager::interfaceIndexFromName(const QString &name)
67{
68#if QT_CONFIG(ipv6ifname)
69 return ::if_nametoindex(name.toLatin1().constData());
70#elif defined(SIOCGIFINDEX)
71 struct ifreq req;
72 int socket = qt_safe_socket(AF_INET, SOCK_STREAM, 0);
73 if (socket < 0)
74 return 0;
75
76 const QByteArray name8bit = name.toLatin1();
77 memset(&req, 0, sizeof(ifreq));
78 if (!name8bit.isNull())
79 memcpy(req.ifr_name, name8bit.data(), qMin(size_t(name8bit.length()) + 1, sizeof(req.ifr_name) - 1));
80
81 uint id = 0;
82 if (qt_safe_ioctl(socket, SIOCGIFINDEX, &req) >= 0)
83 id = ifreq_index(req);
84 qt_safe_close(socket);
85 return id;
86#else
87 Q_UNUSED(name);
88 return 0;
89#endif
90}
91
92QString QNetworkInterfaceManager::interfaceNameFromIndex(uint index)
93{
94#if QT_CONFIG(ipv6ifname)
95 char buf[IF_NAMESIZE];
96 if (::if_indextoname(index, buf))
97 return QString::fromLatin1(buf);
98#elif defined(SIOCGIFNAME)
99 struct ifreq req;
100 int socket = qt_safe_socket(AF_INET, SOCK_STREAM, 0);
101 if (socket >= 0) {
102 memset(&req, 0, sizeof(ifreq));
103 ifreq_index(req) = index;
104 if (qt_safe_ioctl(socket, SIOCGIFNAME, &req) >= 0) {
105 qt_safe_close(socket);
106 return QString::fromLatin1(req.ifr_name);
107 }
108 qt_safe_close(socket);
109 }
110#endif
111 return QString::number(uint(index));
112}
113
114static int getMtu(int socket, struct ifreq *req)
115{
116#ifdef SIOCGIFMTU
117 if (qt_safe_ioctl(socket, SIOCGIFMTU, req) == 0)
118 return req->ifr_mtu;
119#endif
120 return 0;
121}
122
123#if !QT_CONFIG(getifaddrs)
124// getifaddrs not available
125
126static QSet<QByteArray> interfaceNames(int socket)
127{
128 QSet<QByteArray> result;
129#if !QT_CONFIG(ipv6ifname)
130 QByteArray storageBuffer;
131 struct ifconf interfaceList;
132 static const int STORAGEBUFFER_GROWTH = 256;
133
134 forever {
135 // grow the storage buffer
136 storageBuffer.resize(storageBuffer.size() + STORAGEBUFFER_GROWTH);
137 interfaceList.ifc_buf = storageBuffer.data();
138 interfaceList.ifc_len = storageBuffer.size();
139
140 // get the interface list
141 if (qt_safe_ioctl(socket, SIOCGIFCONF, &interfaceList) >= 0) {
142 if (int(interfaceList.ifc_len + sizeof(ifreq) + 64) < storageBuffer.size()) {
143 // if the buffer was big enough, break
144 storageBuffer.resize(interfaceList.ifc_len);
145 break;
146 }
147 } else {
148 // internal error
149 return result;
150 }
151 if (storageBuffer.size() > 100000) {
152 // out of space
153 return result;
154 }
155 }
156
157 int interfaceCount = interfaceList.ifc_len / sizeof(ifreq);
158 for (int i = 0; i < interfaceCount; ++i) {
159 QByteArray name = QByteArray(interfaceList.ifc_req[i].ifr_name);
160 if (!name.isEmpty())
161 result << name;
162 }
163
164 return result;
165#else
166 Q_UNUSED(socket);
167
168 // use if_nameindex
169 struct if_nameindex *interfaceList = ::if_nameindex();
170 for (struct if_nameindex *ptr = interfaceList; ptr && ptr->if_name; ++ptr)
171 result << ptr->if_name;
172
173 if_freenameindex(interfaceList);
174 return result;
175#endif
176}
177
178static QNetworkInterfacePrivate *findInterface(int socket, QList<QNetworkInterfacePrivate *> &interfaces,
179 struct ifreq &req)
180{
181 QNetworkInterfacePrivate *iface = nullptr;
182 int ifindex = 0;
183
184#if QT_CONFIG(ipv6ifname) || defined(SIOCGIFINDEX)
185 // Get the interface index
186# ifdef SIOCGIFINDEX
187 if (qt_safe_ioctl(socket, SIOCGIFINDEX, &req) >= 0)
188 ifindex = ifreq_index(req);
189# else
190 ifindex = if_nametoindex(req.ifr_name);
191# endif
192
193 // find the interface data
194 QList<QNetworkInterfacePrivate *>::Iterator if_it = interfaces.begin();
195 for ( ; if_it != interfaces.end(); ++if_it)
196 if ((*if_it)->index == ifindex) {
197 // existing interface
198 iface = *if_it;
199 break;
200 }
201#else
202 Q_UNUSED(socket);
203 // Search by name
204 QList<QNetworkInterfacePrivate *>::Iterator if_it = interfaces.begin();
205 for ( ; if_it != interfaces.end(); ++if_it)
206 if ((*if_it)->name == QLatin1StringView(req.ifr_name)) {
207 // existing interface
208 iface = *if_it;
209 break;
210 }
211#endif
212
213 if (!iface) {
214 // new interface, create data:
215 iface = new QNetworkInterfacePrivate;
216 iface->index = ifindex;
217 interfaces << iface;
218 }
219
220 return iface;
221}
222
223static QList<QNetworkInterfacePrivate *> interfaceListing()
224{
225 QList<QNetworkInterfacePrivate *> interfaces;
226
227 int socket;
228 if ((socket = qt_safe_socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) == -1)
229 return interfaces; // error
230
231 QSet<QByteArray> names = interfaceNames(socket);
232 QSet<QByteArray>::ConstIterator it = names.constBegin();
233 for ( ; it != names.constEnd(); ++it) {
234 ifreq req;
235 memset(&req, 0, sizeof(ifreq));
236 if (!it->isNull())
237 memcpy(req.ifr_name, it->constData(), qMin(size_t(it->length()) + 1, sizeof(req.ifr_name) - 1));
238
239 QNetworkInterfacePrivate *iface = findInterface(socket, interfaces, req);
240
241#ifdef SIOCGIFNAME
242 // Get the canonical name
243 QByteArray oldName = req.ifr_name;
244 if (qt_safe_ioctl(socket, SIOCGIFNAME, &req) >= 0) {
245 iface->name = QString::fromLatin1(req.ifr_name);
246
247 // reset the name:
248 if (!oldName.isNull())
249 memcpy(req.ifr_name, oldName.constData(), qMin(size_t(oldName.length()) + 1, sizeof(req.ifr_name) - 1));
250 } else
251#endif
252 {
253 // use this name anyways
254 iface->name = QString::fromLatin1(req.ifr_name);
255 }
256
257 // Get interface flags
258 if (qt_safe_ioctl(socket, SIOCGIFFLAGS, &req) >= 0) {
259 iface->flags = convertFlags(req.ifr_flags);
260 }
261 iface->mtu = getMtu(socket, &req);
262
263#ifdef SIOCGIFHWADDR
264 // Get the HW address
265 if (qt_safe_ioctl(socket, SIOCGIFHWADDR, &req) >= 0) {
266 uchar *addr = (uchar *)req.ifr_addr.sa_data;
267 iface->hardwareAddress = iface->makeHwAddress(6, addr);
268 }
269#endif
270
271 // Get the address of the interface
272 QNetworkAddressEntry entry;
273 if (qt_safe_ioctl(socket, SIOCGIFADDR, &req) >= 0) {
274 sockaddr *sa = &req.ifr_addr;
275 entry.setIp(addressFromSockaddr(sa));
276
277 // Get the interface broadcast address
278 if (iface->flags & QNetworkInterface::CanBroadcast) {
279 if (qt_safe_ioctl(socket, SIOCGIFBRDADDR, &req) >= 0) {
280 sockaddr *sa = &req.ifr_addr;
281 if (sa->sa_family == AF_INET)
282 entry.setBroadcast(addressFromSockaddr(sa));
283 }
284 }
285
286 // Get the interface netmask
287 if (qt_safe_ioctl(socket, SIOCGIFNETMASK, &req) >= 0) {
288 sockaddr *sa = &req.ifr_addr;
289 entry.setNetmask(addressFromSockaddr(sa));
290 }
291
292 iface->addressEntries << entry;
293 }
294 }
295
296 ::close(socket);
297 return interfaces;
298}
299
300#else
301// use getifaddrs
302
303// platform-specific defs:
304# ifdef Q_OS_LINUX
305QT_BEGIN_INCLUDE_NAMESPACE
306# include <features.h>
307QT_END_INCLUDE_NAMESPACE
308# endif
309
310static int openSocket(int &socket)
311{
312 if (socket == -1)
313 socket = qt_safe_socket(AF_INET, SOCK_DGRAM, 0);
314 return socket;
315}
316
317# if defined(Q_OS_LINUX) && __GLIBC__ - 0 >= 2 && __GLIBC_MINOR__ - 0 >= 1 && !defined(QT_LINUXBASE)
318# include <netpacket/packet.h>
319
320static QList<QNetworkInterfacePrivate *> createInterfaces(ifaddrs *rawList)
321{
322 Q_UNUSED(getMtu);
323 Q_UNUSED(openSocket);
324 QList<QNetworkInterfacePrivate *> interfaces;
325 QDuplicateTracker<QString> seenInterfaces;
326 QDuplicateTracker<int> seenIndexes;
327
328 // On Linux, glibc, uClibc and MUSL obtain the address listing via two
329 // netlink calls: first an RTM_GETLINK to obtain the interface listing,
330 // then one RTM_GETADDR to get all the addresses (uClibc implementation is
331 // copied from glibc; Bionic currently doesn't support getifaddrs). They
332 // synthesize AF_PACKET addresses from the RTM_GETLINK responses, which
333 // means by construction they currently show up first in the interface
334 // listing.
335 for (ifaddrs *ptr = rawList; ptr; ptr = ptr->ifa_next) {
336 if (ptr->ifa_addr && ptr->ifa_addr->sa_family == AF_PACKET) {
337 sockaddr_ll *sll = (sockaddr_ll *)ptr->ifa_addr;
338 QNetworkInterfacePrivate *iface = new QNetworkInterfacePrivate;
339 interfaces << iface;
340 iface->index = sll->sll_ifindex;
341 iface->name = QString::fromLatin1(ptr->ifa_name);
342 iface->flags = convertFlags(ptr->ifa_flags);
343 iface->hardwareAddress = iface->makeHwAddress(sll->sll_halen, (uchar*)sll->sll_addr);
344
345 const bool sawIfaceIndex = seenIndexes.hasSeen(iface->index);
346 Q_ASSERT(!sawIfaceIndex);
347 (void)seenInterfaces.hasSeen(iface->name);
348 }
349 }
350
351 // see if we missed anything:
352 // - virtual interfaces with no HW address have no AF_PACKET
353 // - interface labels have no AF_PACKET, but shouldn't be shown as a new interface
354 for (ifaddrs *ptr = rawList; ptr; ptr = ptr->ifa_next) {
355 if (!ptr->ifa_addr || ptr->ifa_addr->sa_family != AF_PACKET) {
356 QString name = QString::fromLatin1(ptr->ifa_name);
357 if (seenInterfaces.hasSeen(name))
358 continue;
359
360 int ifindex = if_nametoindex(ptr->ifa_name);
361 if (seenIndexes.hasSeen(ifindex))
362 continue;
363
364 QNetworkInterfacePrivate *iface = new QNetworkInterfacePrivate;
365 interfaces << iface;
366 iface->name = name;
367 iface->flags = convertFlags(ptr->ifa_flags);
368 iface->index = ifindex;
369 }
370 }
371
372 return interfaces;
373}
374
375static void getAddressExtraInfo(QNetworkAddressEntry *entry, struct sockaddr *sa, const char *ifname)
376{
377 Q_UNUSED(entry);
378 Q_UNUSED(sa);
379 Q_UNUSED(ifname);
380}
381
382# elif defined(Q_OS_BSD4)
383QT_BEGIN_INCLUDE_NAMESPACE
384# include <net/if_dl.h>
385#if defined(QT_PLATFORM_UIKIT)
386# include "qnetworkinterface_uikit_p.h"
387# include <net/if_types.h>
388#else
389# include <net/if_media.h>
390# include <net/if_types.h>
391# include <netinet/in_var.h>
392#endif // QT_PLATFORM_UIKIT
393QT_END_INCLUDE_NAMESPACE
394
395#if defined(Q_OS_MACOS)
396QT_BEGIN_INCLUDE_NAMESPACE
397# include <CoreFoundation/CoreFoundation.h>
398# include <SystemConfiguration/SystemConfiguration.h>
399# include <QtCore/private/qcore_mac_p.h>
400QT_END_INCLUDE_NAMESPACE
401
402// Maps BSD interface names (e.g. "en1") to the localized display names shown
403// in System Settings.
404static QHash<QString, QString> interfaceFriendlyNames()
405{
406 QHash<QString, QString> result;
407 QCFType<CFArrayRef> interfaces = SCNetworkInterfaceCopyAll();
408 if (!interfaces)
409 return result;
410
411 CFIndex count = CFArrayGetCount(interfaces);
412 result.reserve(count);
413 for (CFIndex i = 0; i < count; ++i) {
414 auto iface = static_cast<SCNetworkInterfaceRef>(CFArrayGetValueAtIndex(interfaces, i));
415 CFStringRef bsdName = SCNetworkInterfaceGetBSDName(iface);
416 CFStringRef displayName = SCNetworkInterfaceGetLocalizedDisplayName(iface);
417 if (bsdName && displayName)
418 result.insert(QString::fromCFString(bsdName), QString::fromCFString(displayName));
419 }
420 return result;
421}
422#else
423static QHash<QString, QString> interfaceFriendlyNames()
424{
425 return {};
426}
427#endif // Q_OS_MACOS
428
429static QNetworkInterface::InterfaceType probeIfType(int socket, int iftype, struct ifmediareq *req)
430{
431 // Determine the interface type.
432
433 // On Darwin, these are #defines, but on FreeBSD they're just an
434 // enum, so we can't #ifdef them. Use the authoritative list from
435 // https://www.iana.org/assignments/smi-numbers/smi-numbers.xhtml#smi-numbers-5
436 switch (iftype) {
437 case IFT_PPP:
438 return QNetworkInterface::Ppp;
439
440 case IFT_LOOP:
441 return QNetworkInterface::Loopback;
442
443 case IFT_SLIP:
444 return QNetworkInterface::Slip;
445
446 case 0x47: // IFT_IEEE80211
447 return QNetworkInterface::Ieee80211;
448
449 case IFT_IEEE1394:
450 return QNetworkInterface::Ieee1394;
451
452 case IFT_GIF:
453 case IFT_STF:
454 return QNetworkInterface::Virtual;
455 }
456
457 // For the remainder (including Ethernet), let's try SIOGIFMEDIA
458 req->ifm_count = 0;
459 if (qt_safe_ioctl(socket, SIOCGIFMEDIA, req) == 0) {
460 // see https://man.openbsd.org/ifmedia.4
461
462 switch (IFM_TYPE(req->ifm_current)) {
463 case IFM_ETHER:
464 return QNetworkInterface::Ethernet;
465
466#ifdef IFM_FDDI
467 case IFM_FDDI:
468 return QNetworkInterface::Fddi;
469#endif
470
471 case IFM_IEEE80211:
472 return QNetworkInterface::Ieee80211;
473 }
474 }
475
476 return QNetworkInterface::Unknown;
477}
478
479static QList<QNetworkInterfacePrivate *> createInterfaces(ifaddrs *rawList)
480{
481 QList<QNetworkInterfacePrivate *> interfaces;
482 union {
483 struct ifmediareq mediareq;
484 struct ifreq req;
485 };
486 int socket = -1;
487 memset(&mediareq, 0, sizeof(mediareq));
488
489 // ensure both structs start with the name field, of size IFNAMESIZ
490 static_assert(sizeof(mediareq.ifm_name) == sizeof(req.ifr_name));
491 static_assert(offsetof(struct ifmediareq, ifm_name) == 0);
492 static_assert(offsetof(struct ifreq, ifr_name) == 0);
493
494 const QHash<QString, QString> friendlyNames = interfaceFriendlyNames();
495
496 // on NetBSD we use AF_LINK and sockaddr_dl
497 // scan the list for that family
498 for (ifaddrs *ptr = rawList; ptr; ptr = ptr->ifa_next)
499 if (ptr->ifa_addr && ptr->ifa_addr->sa_family == AF_LINK) {
500 QNetworkInterfacePrivate *iface = new QNetworkInterfacePrivate;
501 interfaces << iface;
502
503 sockaddr_dl *sdl = (sockaddr_dl *)ptr->ifa_addr;
504 iface->index = sdl->sdl_index;
505 iface->name = QString::fromLatin1(ptr->ifa_name);
506 iface->flags = convertFlags(ptr->ifa_flags);
507 iface->hardwareAddress = iface->makeHwAddress(sdl->sdl_alen, (uchar*)LLADDR(sdl));
508 iface->friendlyName = friendlyNames.value(iface->name);
509
510 qstrncpy(mediareq.ifm_name, ptr->ifa_name, sizeof(mediareq.ifm_name));
511 iface->type = probeIfType(openSocket(socket), sdl->sdl_type, &mediareq);
512 iface->mtu = getMtu(socket, &req);
513 }
514
515 if (socket != -1)
516 qt_safe_close(socket);
517 return interfaces;
518}
519
520static void getAddressExtraInfo(QNetworkAddressEntry *entry, struct sockaddr *sa, const char *ifname)
521{
522 // get IPv6 address lifetimes
523 if (sa->sa_family != AF_INET6)
524 return;
525
526 struct in6_ifreq ifr;
527
528 int s6 = qt_safe_socket(AF_INET6, SOCK_DGRAM, 0);
529 if (Q_UNLIKELY(s6 < 0)) {
530 qErrnoWarning("QNetworkInterface: could not create IPv6 socket");
531 return;
532 }
533
534 qstrncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
535
536 // get flags
537 ifr.ifr_addr = *reinterpret_cast<struct sockaddr_in6 *>(sa);
538 if (qt_safe_ioctl(s6, SIOCGIFAFLAG_IN6, &ifr) < 0) {
539 qt_safe_close(s6);
540 return;
541 }
542 int flags = ifr.ifr_ifru.ifru_flags6;
543 QNetworkInterfacePrivate::calculateDnsEligibility(entry,
544 flags & IN6_IFF_TEMPORARY,
545 flags & IN6_IFF_DEPRECATED);
546
547 // get lifetimes
548 ifr.ifr_addr = *reinterpret_cast<struct sockaddr_in6 *>(sa);
549 if (qt_safe_ioctl(s6, SIOCGIFALIFETIME_IN6, &ifr) < 0) {
550 qt_safe_close(s6);
551 return;
552 }
553 qt_safe_close(s6);
554
555# if defined(Q_OS_DARWIN)
556 constexpr clockid_t LifetimeClock = CLOCK_REALTIME;
557# else
558 constexpr clockid_t LifetimeClock = CLOCK_UPTIME;
559# endif
560 timespec now;
561 clock_gettime(LifetimeClock, &now);
562 auto toDeadline = [now](time_t when) {
563 QDeadlineTimer deadline = QDeadlineTimer::Forever;
564 if (when) {
565 deadline.setPreciseRemainingTime(when - now.tv_sec);
566 }
567 return deadline;
568 };
569 entry->setAddressLifetime(toDeadline(ifr.ifr_ifru.ifru_lifetime.ia6t_preferred),
570 toDeadline(ifr.ifr_ifru.ifru_lifetime.ia6t_expire));
571}
572
573# else // Generic version
574
575static QList<QNetworkInterfacePrivate *> createInterfaces(ifaddrs *rawList)
576{
577 QList<QNetworkInterfacePrivate *> interfaces;
578 int socket = -1;
579
580 // make sure there's one entry for each interface
581 for (ifaddrs *ptr = rawList; ptr; ptr = ptr->ifa_next) {
582 // Get the interface index
583 int ifindex = if_nametoindex(ptr->ifa_name);
584
585 QList<QNetworkInterfacePrivate *>::Iterator if_it = interfaces.begin();
586 for ( ; if_it != interfaces.end(); ++if_it)
587 if ((*if_it)->index == ifindex)
588 // this one has been added already
589 break;
590
591 if (if_it == interfaces.end()) {
592 // none found, create
594 interfaces << iface;
595
596 iface->index = ifindex;
597 iface->name = QString::fromLatin1(ptr->ifa_name);
598 iface->flags = convertFlags(ptr->ifa_flags);
599
600 if ((socket = openSocket(socket)) >= 0) {
601 struct ifreq ifr;
602 qstrncpy(ifr.ifr_name, ptr->ifa_name, sizeof(ifr.ifr_name));
603 iface->mtu = getMtu(socket, &ifr);
604 }
605 }
606 }
607
608 if (socket != -1)
609 qt_safe_close(socket);
610
611 return interfaces;
612}
613
614static void getAddressExtraInfo(QNetworkAddressEntry *entry, struct sockaddr *sa, const char *ifname)
615{
616 Q_UNUSED(entry);
617 Q_UNUSED(sa);
618 Q_UNUSED(ifname);
619}
620# endif
621
622static QList<QNetworkInterfacePrivate *> interfaceListing()
623{
624 QList<QNetworkInterfacePrivate *> interfaces;
625
626 ifaddrs *interfaceListing;
627 if (getifaddrs(&interfaceListing) == -1) {
628 // error
629 return interfaces;
630 }
631
632 interfaces = createInterfaces(interfaceListing);
633 for (ifaddrs *ptr = interfaceListing; ptr; ptr = ptr->ifa_next) {
634 // Find the interface
635 QLatin1StringView name(ptr->ifa_name);
636 QNetworkInterfacePrivate *iface = nullptr;
637 QList<QNetworkInterfacePrivate *>::Iterator if_it = interfaces.begin();
638 for ( ; if_it != interfaces.end(); ++if_it)
639 if ((*if_it)->name == name) {
640 // found this interface already
641 iface = *if_it;
642 break;
643 }
644
645 if (!iface) {
646 // it may be an interface label, search by interface index
647 int ifindex = if_nametoindex(ptr->ifa_name);
648 for (if_it = interfaces.begin(); if_it != interfaces.end(); ++if_it)
649 if ((*if_it)->index == ifindex) {
650 // found this interface already
651 iface = *if_it;
652 break;
653 }
654 }
655
656 if (!iface) {
657 // skip all non-IP interfaces
658 continue;
659 }
660
662 entry.setIp(addressFromSockaddr(ptr->ifa_addr, iface->index, iface->name));
663 if (entry.ip().isNull())
664 // could not parse the address
665 continue;
666
667 entry.setNetmask(addressFromSockaddr(ptr->ifa_netmask, iface->index, iface->name));
668 if (iface->flags & QNetworkInterface::CanBroadcast)
669 entry.setBroadcast(addressFromSockaddr(ptr->ifa_broadaddr, iface->index, iface->name));
670 getAddressExtraInfo(&entry, ptr->ifa_addr, name.latin1());
671
672 iface->addressEntries << entry;
673 }
674
675 freeifaddrs(interfaceListing);
676 return interfaces;
677}
678#endif
679
680QList<QNetworkInterfacePrivate *> QNetworkInterfaceManager::scan()
681{
682 return interfaceListing();
683}
684
685QT_END_NAMESPACE
686
687#endif // QT_NO_NETWORKINTERFACE
The QNetworkAddressEntry class stores one IP address supported by a network interface,...
Combined button and popup list for selecting options.
#define AF_INET6
static QT_BEGIN_NAMESPACE QHostAddress addressFromSockaddr(sockaddr *sa, int ifindex=0, const QString &ifname=QString())
static int getMtu(int socket, struct ifreq *req)
static auto & ifreq_index(Req &req, std::enable_if_t< sizeof(std::declval< Req >().ifr_index) !=0, int >=0)