#include "netlinkmonitor.h" #include #include #include #include #include #include #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(&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; } } }