100 lines
2.3 KiB
C++
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);
|
|
}
|
|
}
|