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 FirstArgumentPointer =
typename FunctionTraits::Arguments::Car;
115 using FirstArgument = std::remove_pointer_t<FirstArgumentPointer>;
116 static_assert(std::is_pointer_v<FirstArgumentPointer>);
117 static_assert(std::is_aggregate_v<FirstArgument>);
119 static int expectedTypeForRequest(
int rtype)
121 static_assert(RTM_NEWADDR == RTM_GETADDR - 2);
122 static_assert(RTM_NEWLINK == RTM_GETLINK - 2);
123 Q_ASSERT(rtype == RTM_GETADDR || rtype == RTM_GETLINK);
130 if (send(
sock, hdr, hdr->nlmsg_len, 0) != ssize_t(hdr->nlmsg_len))
134 int expectedType = expectedTypeForRequest(hdr->nlmsg_type);
135 const bool isDump = hdr->nlmsg_flags & NLM_F_DUMP;
138 hdr =
reinterpret_cast<struct nlmsghdr *
>(
buf);
142 auto arg =
static_cast<FirstArgument *
>(NLMSG_DATA(hdr));
143 size_t payloadLen = NLMSG_PAYLOAD(hdr, 0);
146 Q_ASSERT(isDump == !!(hdr->nlmsg_flags & NLM_F_MULTI));
149 if (hdr->nlmsg_type == expectedType && payloadLen >=
sizeof(FirstArgument))
154 if (hdr->nlmsg_type == NLMSG_DONE)
156 if (hdr->nlmsg_type != expectedType || payloadLen <
sizeof(FirstArgument))
161 hdr = NLMSG_NEXT(hdr,
len);
162 arg =
static_cast<FirstArgument *
>(NLMSG_DATA(hdr));
163 payloadLen = NLMSG_PAYLOAD(hdr, 0);
172 qWarning(
"QNetworkInterface/AF_NETLINK: received unknown packet type (%d) or too short (%u)",
173 hdr->nlmsg_type, hdr->nlmsg_len);
175 qWarning(
"QNetworkInterface/AF_NETLINK: received invalid packet with size %d",
int(
len));
182template <
typename Lambda>
183void processNetlinkRequest(
int sock,
struct nlmsghdr *hdr,
char *
buf,
size_t bufsize, Lambda &&l)
185 ProcessNetlinkRequest<Lambda>()(
sock, hdr,
buf,
bufsize, std::forward<Lambda>(l));
192 if (
name.size() >= IFNAMSIZ)
199 strcpy(req.ifr_name,
name.toLatin1().constData());
202 index = req.ifr_ifindex;
213 req.ifr_ifindex =
index;
226 QList<QNetworkInterfacePrivate *>
result;
232 struct ifinfomsg ifi;
234 memset(&ifi_req, 0,
sizeof(ifi_req));
236 ifi_req.req.nlmsg_len =
sizeof(ifi_req);
237 ifi_req.req.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
238 ifi_req.req.nlmsg_type = RTM_GETLINK;
242 auto iface = new QNetworkInterfacePrivate;
243 iface->index = ifi->ifi_index;
244 iface->flags = convertFlags(ifi->ifi_flags);
247 auto rta = reinterpret_cast<struct rtattr *>(ifi + 1);
249 for ( ; RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) {
250 int payloadLen = RTA_PAYLOAD(rta);
251 auto payloadPtr = reinterpret_cast<char *>(RTA_DATA(rta));
253 switch (rta->rta_type) {
255 iface->hardwareAddress =
256 iface->makeHwAddress(payloadLen, reinterpret_cast<uchar *>(payloadPtr));
260 Q_ASSERT(payloadLen <= int(sizeof(req.ifr_name)));
261 memcpy(req.ifr_name, payloadPtr, payloadLen);
262 iface->name = QString::fromLatin1(payloadPtr, payloadLen - 1);
266 Q_ASSERT(payloadLen == sizeof(int));
267 iface->mtu = *reinterpret_cast<int *>(payloadPtr);
271 if (*payloadPtr != IF_OPER_UNKNOWN) {
273 iface->flags &= ~QNetworkInterface::IsRunning;
274 if (*payloadPtr == IF_OPER_UP)
275 iface->flags |= QNetworkInterface::IsRunning;
282 qWarning(
"QNetworkInterface: found interface %d with no name", iface->index);
285 iface->type = probeIfType(sock, &req, ifi->ifi_type);
286 result.append(iface);
297 struct ifaddrmsg ifa;
299 memset(&ifa_req, 0,
sizeof(ifa_req));
301 ifa_req.req.nlmsg_len =
sizeof(ifa_req);
302 ifa_req.req.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
303 ifa_req.req.nlmsg_type = RTM_GETADDR;
304 ifa_req.req.nlmsg_seq = 1;
308 if (Q_UNLIKELY(ifa->ifa_family != AF_INET && ifa->ifa_family != AF_INET6)) {
315 for (
auto candidate : std::as_const(
result)) {
316 if (candidate->index !=
int(ifa->ifa_index))
323 qWarning(
"QNetworkInterface/AF_NETLINK: found unknown interface with index %d", ifa->ifa_index);
332 if (ifa->ifa_family == AF_INET) {
334 addr.setAddress(qFromBigEndian<quint32>(
ptr));
340 if (
addr.isLinkLocal())
341 addr.setScopeId(iface->name);
347 auto rta =
reinterpret_cast<struct rtattr *
>(ifa + 1);
349 for ( ; RTA_OK(rta,
len); rta = RTA_NEXT(rta,
len)) {
350 int payloadLen = RTA_PAYLOAD(rta);
351 auto payloadPtr =
reinterpret_cast<uchar *
>(RTA_DATA(rta));
353 switch (rta->rta_type) {
356 if (
entry.ip().isNull())
357 entry.setIp(makeAddress(payloadPtr, payloadLen));
362 entry.setIp(makeAddress(payloadPtr, payloadLen));
366 Q_ASSERT(ifa->ifa_family == AF_INET);
367 entry.setBroadcast(makeAddress(payloadPtr, payloadLen));
371 if (
size_t(payloadLen) >=
sizeof(ifa_cacheinfo)) {
372 auto cacheinfo =
reinterpret_cast<ifa_cacheinfo *
>(payloadPtr);
378 entry.setAddressLifetime(toDeadline(cacheinfo->ifa_prefered), toDeadline(cacheinfo->ifa_valid));
384 flags = qFromUnaligned<quint32>(payloadPtr);
389 if (ifa->ifa_family ==
AF_INET6 && (ifa->ifa_flags & IFA_F_DADFAILED))
394 flags & IFA_F_TEMPORARY,
395 flags & IFA_F_DEPRECATED);
398 if (!
entry.ip().isNull()) {
399 entry.setPrefixLength(ifa->ifa_prefixlen);
400 iface->addressEntries.append(
entry);
405QList<QNetworkInterfacePrivate *> QNetworkInterfaceManager::scan()
408 QList<QNetworkInterfacePrivate *>
result;
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]