8#ifndef QT_NO_NETWORKINTERFACE
17#include <linux/if_arp.h>
18#include <linux/netlink.h>
19#include <linux/rtnetlink.h>
20#include <linux/wireless.h>
21#include <sys/socket.h>
24#define ARPHRD_PHONET 820
25#define ARPHRD_PHONET_PIPE 821
26#define ARPHRD_IEEE802154 804
27#define ARPHRD_6LOWPAN 825
62 case ARPHRD_IEEE80211:
63 case ARPHRD_IEEE80211_PRISM:
64 case ARPHRD_IEEE80211_RADIOTAP:
91 NetlinkSocket(
int bufferSize)
98 socklen_t
len =
sizeof(bufferSize);
99 setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &bufferSize,
len);
108 operator int()
const {
return sock; }
111template <
typename Lambda>
struct ProcessNetlinkRequest
114 using FirstArgument =
typename FunctionTraits::Arguments::Car;
116 static int expectedTypeForRequest(
int rtype)
118 static_assert(RTM_NEWADDR == RTM_GETADDR - 2);
119 static_assert(RTM_NEWLINK == RTM_GETLINK - 2);
120 Q_ASSERT(rtype == RTM_GETADDR || rtype == RTM_GETLINK);
127 if (send(
sock, hdr, hdr->nlmsg_len, 0) != ssize_t(hdr->nlmsg_len))
131 int expectedType = expectedTypeForRequest(hdr->nlmsg_type);
132 const bool isDump = hdr->nlmsg_flags & NLM_F_DUMP;
135 hdr =
reinterpret_cast<struct nlmsghdr *
>(
buf);
139 auto arg =
reinterpret_cast<FirstArgument
>(NLMSG_DATA(hdr));
140 size_t payloadLen = NLMSG_PAYLOAD(hdr, 0);
143 Q_ASSERT(isDump == !!(hdr->nlmsg_flags & NLM_F_MULTI));
146 if (hdr->nlmsg_type == expectedType && payloadLen >=
sizeof(FirstArgument))
151 if (hdr->nlmsg_type == NLMSG_DONE)
153 if (hdr->nlmsg_type != expectedType || payloadLen <
sizeof(FirstArgument))
158 hdr = NLMSG_NEXT(hdr,
len);
159 arg =
reinterpret_cast<FirstArgument
>(NLMSG_DATA(hdr));
160 payloadLen = NLMSG_PAYLOAD(hdr, 0);
169 qWarning(
"QNetworkInterface/AF_NETLINK: received unknown packet type (%d) or too short (%u)",
170 hdr->nlmsg_type, hdr->nlmsg_len);
172 qWarning(
"QNetworkInterface/AF_NETLINK: received invalid packet with size %d",
int(
len));
179template <
typename Lambda>
180void processNetlinkRequest(
int sock,
struct nlmsghdr *hdr,
char *
buf,
size_t bufsize, Lambda &&l)
182 ProcessNetlinkRequest<Lambda>()(
sock, hdr,
buf,
bufsize, std::forward<Lambda>(l));
189 if (
name.size() >= IFNAMSIZ)
196 strcpy(req.ifr_name,
name.toLatin1().constData());
199 index = req.ifr_ifindex;
210 req.ifr_ifindex =
index;
229 struct ifinfomsg ifi;
231 memset(&ifi_req, 0,
sizeof(ifi_req));
233 ifi_req.req.nlmsg_len =
sizeof(ifi_req);
234 ifi_req.req.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
235 ifi_req.req.nlmsg_type = RTM_GETLINK;
239 auto iface = new QNetworkInterfacePrivate;
240 iface->index = ifi->ifi_index;
241 iface->flags = convertFlags(ifi->ifi_flags);
244 auto rta = reinterpret_cast<struct rtattr *>(ifi + 1);
246 for ( ; RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) {
247 int payloadLen = RTA_PAYLOAD(rta);
248 auto payloadPtr = reinterpret_cast<char *>(RTA_DATA(rta));
250 switch (rta->rta_type) {
252 iface->hardwareAddress =
253 iface->makeHwAddress(payloadLen, reinterpret_cast<uchar *>(payloadPtr));
257 Q_ASSERT(payloadLen <= int(sizeof(req.ifr_name)));
258 memcpy(req.ifr_name, payloadPtr, payloadLen);
259 iface->name = QString::fromLatin1(payloadPtr, payloadLen - 1);
263 Q_ASSERT(payloadLen == sizeof(int));
264 iface->mtu = *reinterpret_cast<int *>(payloadPtr);
268 if (*payloadPtr != IF_OPER_UNKNOWN) {
270 iface->flags &= ~QNetworkInterface::IsRunning;
271 if (*payloadPtr == IF_OPER_UP)
272 iface->flags |= QNetworkInterface::IsRunning;
279 qWarning(
"QNetworkInterface: found interface %d with no name", iface->index);
282 iface->type = probeIfType(sock, &req, ifi->ifi_type);
283 result.append(iface);
294 struct ifaddrmsg ifa;
296 memset(&ifa_req, 0,
sizeof(ifa_req));
298 ifa_req.req.nlmsg_len =
sizeof(ifa_req);
299 ifa_req.req.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
300 ifa_req.req.nlmsg_type = RTM_GETADDR;
301 ifa_req.req.nlmsg_seq = 1;
305 if (Q_UNLIKELY(ifa->ifa_family != AF_INET && ifa->ifa_family != AF_INET6)) {
312 for (
auto candidate : std::as_const(
result)) {
313 if (candidate->index !=
int(ifa->ifa_index))
320 qWarning(
"QNetworkInterface/AF_NETLINK: found unknown interface with index %d", ifa->ifa_index);
329 if (ifa->ifa_family == AF_INET) {
331 addr.setAddress(qFromBigEndian<quint32>(
ptr));
337 if (
addr.isLinkLocal())
338 addr.setScopeId(iface->name);
344 auto rta =
reinterpret_cast<struct rtattr *
>(ifa + 1);
346 for ( ; RTA_OK(rta,
len); rta = RTA_NEXT(rta,
len)) {
347 int payloadLen = RTA_PAYLOAD(rta);
348 auto payloadPtr =
reinterpret_cast<uchar *
>(RTA_DATA(rta));
350 switch (rta->rta_type) {
353 if (
entry.ip().isNull())
354 entry.setIp(makeAddress(payloadPtr, payloadLen));
359 entry.setIp(makeAddress(payloadPtr, payloadLen));
363 Q_ASSERT(ifa->ifa_family == AF_INET);
364 entry.setBroadcast(makeAddress(payloadPtr, payloadLen));
368 if (
size_t(payloadLen) >=
sizeof(ifa_cacheinfo)) {
369 auto cacheinfo =
reinterpret_cast<ifa_cacheinfo *
>(payloadPtr);
375 entry.setAddressLifetime(toDeadline(cacheinfo->ifa_prefered), toDeadline(cacheinfo->ifa_valid));
381 flags = qFromUnaligned<quint32>(payloadPtr);
386 if (ifa->ifa_family ==
AF_INET6 && (ifa->ifa_flags & IFA_F_DADFAILED))
391 flags & IFA_F_TEMPORARY,
392 flags & IFA_F_DEPRECATED);
395 if (!
entry.ip().isNull()) {
396 entry.setPrefixLength(ifa->ifa_prefixlen);
397 iface->addressEntries.append(
entry);
static constexpr ForeverConstant Forever
The QHostAddress class provides an IP address.
The QNetworkAddressEntry class stores one IP address supported by a network interface,...
static uint interfaceIndexFromName(const QString &name)
static QString interfaceNameFromIndex(uint index)
static void calculateDnsEligibility(QNetworkAddressEntry *entry, bool isTemporary, bool isDeprecated)
InterfaceType
Specifies the type of hardware (PHY layer, OSI level 1) this interface is, if it could be determined.
\macro QT_RESTRICTED_CAST_FROM_ASCII
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
void qErrnoWarning(const char *msg,...)
Combined button and popup list for selecting options.
constexpr Initialization Uninitialized
static int qt_safe_close(int fd)
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
static constexpr int BufferSize
static ControlElement< T > * ptr(QWidget *widget)
static int qt_safe_ioctl(int sockfd, unsigned long request, T arg)
static int qt_safe_socket(int domain, int type, int protocol, int flags=0)
#define ARPHRD_PHONET_PIPE
static void getAddresses(int sock, char *buf, QList< QNetworkInterfacePrivate * > &result)
static QNetworkInterface::InterfaceType probeIfType(int socket, struct ifreq *req, short arptype)
#define ARPHRD_IEEE802154
static QList< QNetworkInterfacePrivate * > getInterfaces(int sock, char *buf)
GLenum GLuint GLenum GLsizei const GLchar * buf
if(qFloatDistance(a, b)<(1<< 7))
[0]