jbl610-linux/kde-app/JBLQunatumStatus/netlinkmonitor.cpp
2025-01-29 12:53:47 +04:00

111 lines
No EOL
3.3 KiB
C++

#include "netlinkmonitor.h"
#include <QDebug>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#define NETLINK_MYPROTO NETLINK_USERSOCK // Matches your kernel module, or use NETLINK_USERSOCK
#define MY_NETLINK_GROUP 27 // Multicast group your kernel module broadcasts on
#define MAX_PAYLOAD 1024
NetlinkMonitor::NetlinkMonitor(QObject *parent)
: QObject(parent)
, m_sockFd(-1)
, m_socketNotifier(nullptr)
{
}
NetlinkMonitor::~NetlinkMonitor()
{
if (m_socketNotifier) {
delete m_socketNotifier;
m_socketNotifier = nullptr;
}
if (m_sockFd != -1) {
close(m_sockFd);
m_sockFd = -1;
}
}
bool NetlinkMonitor::setupNetlink()
{
// 1. Create netlink socket
m_sockFd = socket(AF_NETLINK, SOCK_RAW, NETLINK_MYPROTO);
if (m_sockFd < 0) {
qWarning() << "Failed to create netlink socket:" << strerror(errno);
return false;
}
// 2. Bind to a local address with the desired groups
struct sockaddr_nl addr;
memset(&addr, 0, sizeof(addr));
addr.nl_family = AF_NETLINK;
addr.nl_pid = getpid(); // our user-space PID
// Subscribe to the group (bitmask). For group #1, you set bit (1-1).
addr.nl_groups = 1 << (MY_NETLINK_GROUP - 1);
if (bind(m_sockFd, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr)) < 0) {
qWarning() << "Failed to bind netlink socket:" << strerror(errno);
close(m_sockFd);
m_sockFd = -1;
return false;
}
// 3. Create a QSocketNotifier to watch for incoming data
m_socketNotifier = new QSocketNotifier(m_sockFd, QSocketNotifier::Read, this);
connect(m_socketNotifier, &QSocketNotifier::activated,
this, &NetlinkMonitor::handleReadyRead);
qDebug() << "NetlinkMonitor: socket setup complete, fd =" << m_sockFd;
return true;
}
void NetlinkMonitor::handleReadyRead()
{
// This slot is triggered whenever the netlink socket has data to read.
char buffer[MAX_PAYLOAD];
struct iovec iov = {
.iov_base = buffer,
.iov_len = sizeof(buffer)
};
struct sockaddr_nl srcAddr;
struct msghdr msg;
struct nlmsghdr *nlh;
memset(&srcAddr, 0, sizeof(srcAddr));
memset(&msg, 0, sizeof(msg));
msg.msg_name = &srcAddr;
msg.msg_namelen = sizeof(srcAddr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
ssize_t ret = recvmsg(m_sockFd, &msg, 0);
if (ret < 0) {
qWarning() << "recvmsg() failed:" << strerror(errno);
return;
}
// The netlink message is in the buffer as one or more nlmsghdr blocks.
for (nlh = (struct nlmsghdr *)buffer; NLMSG_OK(nlh, ret);
nlh = NLMSG_NEXT(nlh, ret)) {
if (nlh->nlmsg_type == NLMSG_DONE) {
// The actual payload is after the nlmsghdr
char *payload = (char *)NLMSG_DATA(nlh);
// Convert to QString, then emit a signal
QString msgStr = QString::fromLatin1(payload);
messageReceived(msgStr);
printf("%s\n", msgStr.toStdString().c_str());
}
else if (nlh->nlmsg_type == NLMSG_ERROR) {
qWarning() << "Received netlink error message";
}
else {
// In a real app, handle other message types as needed
qDebug() << "Received netlink type:" << nlh->nlmsg_type;
}
}
}