This repository has been archived on 2025-07-17. You can view files and clone it, but cannot push or open issues or pull requests.
upper_netlink/netlinkhandler.cpp
2025-06-07 23:36:39 +08:00

100 lines
2.3 KiB
C++

#include "netlinkhandler.h"
#include <sys/socket.h>
#include <linux/netlink.h>
#include <unistd.h>
#include <cstring>
#include <QDebug>
NetlinkHandler::NetlinkHandler(QObject *parent) : QObject(parent) {}
NetlinkHandler::~NetlinkHandler()
{
closeSocket();
}
bool NetlinkHandler::init(int protocol)
{
LOG_DEBUG("protoal is %d",protocol);
if (!createSocket(protocol)) {
emit errorOccurred("Failed to create netlink socket");
return false;
}
m_notifier = new QSocketNotifier(m_sock, QSocketNotifier::Read, this);
connect(m_notifier, &QSocketNotifier::activated, this, &NetlinkHandler::onSocketReadyRead);
return true;
}
bool NetlinkHandler::createSocket(int protocol)
{
m_sock = socket(AF_NETLINK, SOCK_RAW, protocol);
if (m_sock < 0) return false;
sockaddr_nl local = {};
local.nl_family = AF_NETLINK;
local.nl_pid = getpid(); // 用户态PID
local.nl_groups = 0;
if (bind(m_sock, reinterpret_cast<sockaddr*>(&local), sizeof(local)) < 0) {
close(m_sock);
return false;
}
return true;
}
void NetlinkHandler::closeSocket()
{
if (m_sock >= 0) {
::close(m_sock);
m_sock = -1;
}
}
bool NetlinkHandler::sendMessage(const QByteArray &msg)
{
if (m_sock < 0) return false;
struct nlmsghdr *nlh;
struct sockaddr_nl kernel = {};
struct iovec iov;
struct msghdr message = {};
char buffer[4096] = {};
nlh = reinterpret_cast<struct nlmsghdr*>(buffer);
nlh->nlmsg_len = NLMSG_LENGTH(msg.size());
nlh->nlmsg_pid = getpid();
nlh->nlmsg_flags = 0;
memcpy(NLMSG_DATA(nlh), msg.data(), msg.size());
kernel.nl_family = AF_NETLINK;
iov.iov_base = nlh;
iov.iov_len = nlh->nlmsg_len;
message.msg_name = &kernel;
message.msg_namelen = sizeof(kernel);
message.msg_iov = &iov;
message.msg_iovlen = 1;
return sendmsg(m_sock, &message, 0) >= 0;
}
void NetlinkHandler::onSocketReadyRead()
{
char buffer[4096] = {};
int len = recv(m_sock, buffer, sizeof(buffer), 0);
if (len < 0) {
emit errorOccurred("recv failed");
return;
}
struct nlmsghdr *nlh = reinterpret_cast<struct nlmsghdr*>(buffer);
if (NLMSG_OK(nlh, len)) {
QByteArray data(reinterpret_cast<char*>(NLMSG_DATA(nlh)), nlh->nlmsg_len - NLMSG_HDRLEN);
emit messageReceived(data);
}
}