From fd0b3b08e4ad0910a570388edd1540ed16edf186 Mon Sep 17 00:00:00 2001 From: lumos Date: Sat, 7 Jun 2025 23:36:39 +0800 Subject: [PATCH] First. --- .gitignore | 1 + log.h | 80 ++++++++++++++ main.cpp | 12 +++ mainwindow.cpp | 57 ++++++++++ mainwindow.h | 35 ++++++ mainwindow.ui | 68 ++++++++++++ netlinkhandler.cpp | 99 +++++++++++++++++ netlinkhandler.h | 35 ++++++ upper_netlink.pro | 27 +++++ upper_netlink.pro.user | 240 +++++++++++++++++++++++++++++++++++++++++ 10 files changed, 654 insertions(+) create mode 100644 .gitignore create mode 100644 log.h create mode 100644 main.cpp create mode 100644 mainwindow.cpp create mode 100644 mainwindow.h create mode 100644 mainwindow.ui create mode 100644 netlinkhandler.cpp create mode 100644 netlinkhandler.h create mode 100644 upper_netlink.pro create mode 100644 upper_netlink.pro.user diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..567609b --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/log.h b/log.h new file mode 100644 index 0000000..04b8a90 --- /dev/null +++ b/log.h @@ -0,0 +1,80 @@ +#ifndef LOG_H +#define LOG_H + +#include // 使用 std::time 和 std::strftime +#include // 使用 printf +#include // 使用 va_list 和 va_start +#include // 使用 std::mutex + +// 定义打印等级 +#define LOG_LEVEL_DEBUG 0 +#define LOG_LEVEL_INFO 1 +#define LOG_LEVEL_WARN 2 +#define LOG_LEVEL_ERROR 3 + +// 默认日志等级为INFO +#ifndef LOG_LEVEL +#define LOG_LEVEL LOG_LEVEL_DEBUG +#endif + +// 颜色配置:用户空间启用颜色 +#define LOG_COLOR true + +// 颜色宏定义 +#if LOG_COLOR +#define RESET_COLOR "\033[0m" +#define COLOR_DEBUG "\033[34m" // 蓝色 +#define COLOR_INFO "\033[32m" // 绿色 +#define COLOR_WARN "\033[33m" // 黄色 +#define COLOR_ERROR "\033[31m" // 红色 +#else +#define RESET_COLOR "" +#define COLOR_DEBUG "" +#define COLOR_INFO "" +#define COLOR_WARN "" +#define COLOR_ERROR "" +#endif + +// 获取当前时间的字符串(用户空间实现) +inline const char* current_time() { + static char buffer[64]; + std::time_t now = std::time(nullptr); + std::tm* tm_now = std::localtime(&now); + + std::strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", tm_now); + return buffer; +} + +// 定义一个静态互斥锁,保证线程安全 +static std::mutex log_mutex; + +// 定义一个外部 FILE 变量,可以用来切换输出目标 +extern FILE* log_output; // 默认为 stdout + +// 用户空间打印日志 +#define LOG(level, format, ...) do {\ +if (level >= LOG_LEVEL) {\ + std::lock_guard lock(log_mutex); /* 自动锁住互斥锁 */\ + const char *level_str;\ + const char *color;\ + switch (level) {\ + case LOG_LEVEL_DEBUG: level_str = "[DEBUG]"; color = COLOR_DEBUG; break;\ + case LOG_LEVEL_INFO: level_str = "[INFO]"; color = COLOR_INFO; break;\ + case LOG_LEVEL_WARN: level_str = "[WARN]"; color = COLOR_WARN; break;\ + case LOG_LEVEL_ERROR: level_str = "[ERROR]"; color = COLOR_ERROR; break;\ + default: level_str = "[UNKNOWN]"; color = ""; break;\ + }\ + fprintf(log_output, "%s%s %s %s:%d - ", color, current_time(), level_str, __FILE__, __LINE__);\ + fprintf(log_output, format, ##__VA_ARGS__); /* 打印日志信息 */\ + fprintf(log_output, "%s\n", RESET_COLOR);\ + fflush(log_output); /* 强制刷新到指定输出目标 */\ +}\ +} while (0) + +// 简便宏,用于各个等级的日志 +#define LOG_DEBUG(format, ...) LOG(LOG_LEVEL_DEBUG, format, ##__VA_ARGS__) +#define LOG_INFO(format, ...) LOG(LOG_LEVEL_INFO, format, ##__VA_ARGS__) +#define LOG_WARN(format, ...) LOG(LOG_LEVEL_WARN, format, ##__VA_ARGS__) +#define LOG_ERROR(format, ...) LOG(LOG_LEVEL_ERROR, format, ##__VA_ARGS__) + +#endif // LOG_H diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..cbff9e6 --- /dev/null +++ b/main.cpp @@ -0,0 +1,12 @@ +#include "mainwindow.h" + +#include + +FILE* log_output = stdout; +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindow w; + w.show(); + return a.exec(); +} diff --git a/mainwindow.cpp b/mainwindow.cpp new file mode 100644 index 0000000..f4d60b5 --- /dev/null +++ b/mainwindow.cpp @@ -0,0 +1,57 @@ +#include "mainwindow.h" +#include "ui_mainwindow.h" + +MainWindow::MainWindow(QWidget *parent) + : QMainWindow(parent) + , ui(new Ui::MainWindow) +{ + ui->setupUi(this); + + +} + +MainWindow::~MainWindow() +{ + delete ui; +} + +void MainWindow::on_pushButton_clicked() +{ + nh = new NetlinkHandler(this); + + connect(nh,&NetlinkHandler::errorOccurred,this,&MainWindow::onLogPrint); + connect(nh,&NetlinkHandler::messageReceived,this,&MainWindow::onLogRev); + + int protocalID = ui->lineEdit->text().toInt(); + nh->init(protocalID); +} + +void MainWindow::onLogPrint(const QString &msg){ + QDateTime cur = QDateTime::currentDateTime(); + QString tmp =cur.toString("yyyy-MM-dd HH:mm:ss"); + ui->textBrowser->append(tmp+" [ERROR] --> "+msg); +} + +void MainWindow::onLogRev(const QByteArray &data){ + QDateTime cur = QDateTime::currentDateTime(); + QString tmp =cur.toString("yyyy-MM-dd HH:mm:ss"); + QString data_; + for(int i =0;i(data.at(i)), 2, 16, QChar('0')); + if (i < data.size() - 1) { + data_ += " "; + } + } + + ui->textBrowser->append(tmp+" [REV] --> "+data_.toUpper()); +} + +void MainWindow::on_pushButton_2_clicked() +{ + QString tmp=ui->textEdit->toPlainText(); + nh->sendMessage(tmp.toUtf8()); + for(int i=0;i +#include "netlinkhandler.h" +#include "QDateTime" + +QT_BEGIN_NAMESPACE +namespace Ui { +class MainWindow; +} +QT_END_NAMESPACE + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + MainWindow(QWidget *parent = nullptr); + ~MainWindow(); + +public slots: + void onLogPrint(const QString &msg); + void onLogRev(const QByteArray &data); + +private slots: + void on_pushButton_clicked(); + + void on_pushButton_2_clicked(); + +private: + Ui::MainWindow *ui; + NetlinkHandler *nh; +}; +#endif // MAINWINDOW_H diff --git a/mainwindow.ui b/mainwindow.ui new file mode 100644 index 0000000..dcdeb01 --- /dev/null +++ b/mainwindow.ui @@ -0,0 +1,68 @@ + + + MainWindow + + + + 0 + 0 + 800 + 600 + + + + MainWindow + + + + + + + + + + protocol ID: + + + + + + + Init + + + + + + + Send + + + + + + + 16 + + + + + + + + + + + + 0 + 0 + 800 + 22 + + + + + + + + diff --git a/netlinkhandler.cpp b/netlinkhandler.cpp new file mode 100644 index 0000000..0c6ffe8 --- /dev/null +++ b/netlinkhandler.cpp @@ -0,0 +1,99 @@ +#include "netlinkhandler.h" +#include +#include +#include +#include +#include + +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(&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(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(buffer); + if (NLMSG_OK(nlh, len)) { + QByteArray data(reinterpret_cast(NLMSG_DATA(nlh)), nlh->nlmsg_len - NLMSG_HDRLEN); + emit messageReceived(data); + } +} diff --git a/netlinkhandler.h b/netlinkhandler.h new file mode 100644 index 0000000..23b3c00 --- /dev/null +++ b/netlinkhandler.h @@ -0,0 +1,35 @@ +#ifndef NETLINKHANDLER_H +#define NETLINKHANDLER_H + +#include +#include +#include +#include "log.h" + +class NetlinkHandler : public QObject +{ + Q_OBJECT +public: + explicit NetlinkHandler(QObject *parent = nullptr); + ~NetlinkHandler(); + + bool init(int protocol = 16); // 默认为 NETLINK_USERSOCK + bool sendMessage(const QByteArray &msg); + int socketFd() const { return m_sock; } + +signals: + void messageReceived(const QByteArray &msg); + void errorOccurred(const QString &err); + +private slots: + void onSocketReadyRead(); + +private: + int m_sock = -1; + QSocketNotifier *m_notifier = nullptr; + + bool createSocket(int protocol); + void closeSocket(); +}; + +#endif // NETLINKHANDLER_H diff --git a/upper_netlink.pro b/upper_netlink.pro new file mode 100644 index 0000000..114731a --- /dev/null +++ b/upper_netlink.pro @@ -0,0 +1,27 @@ +QT += core gui + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++17 + +# You can make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +SOURCES += \ + main.cpp \ + mainwindow.cpp \ + netlinkhandler.cpp + +HEADERS += \ + log.h \ + mainwindow.h \ + netlinkhandler.h + +FORMS += \ + mainwindow.ui + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target diff --git a/upper_netlink.pro.user b/upper_netlink.pro.user new file mode 100644 index 0000000..660e10d --- /dev/null +++ b/upper_netlink.pro.user @@ -0,0 +1,240 @@ + + + + + + EnvironmentId + {1ef3ffc4-a5a8-4c60-8a81-af3ba8bbb143} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + true + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + UTF-8 + false + 4 + false + 0 + 80 + true + true + 1 + 0 + false + true + false + 2 + true + true + 0 + 8 + true + false + 1 + true + true + true + *.md, *.MD, Makefile + false + true + true + + + + ProjectExplorer.Project.Target.0 + + Desktop + Desktop Qt 5.15.2 GCC 64bit + Desktop Qt 5.15.2 GCC 64bit + qt.qt5.5152.gcc_64_kit + 0 + 0 + 0 + + 0 + /home/leo/devCode/outer/USBFilter_30/upper_netlink/build/Desktop_Qt_5_15_2_GCC_64bit-Debug + /home/leo/devCode/outer/USBFilter_30/upper_netlink/build/Desktop_Qt_5_15_2_GCC_64bit-Debug + + + true + QtProjectManager.QMakeBuildStep + false + + + + true + Qt4ProjectManager.MakeStep + + 2 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + clean + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Debug + Qt4ProjectManager.Qt4BuildConfiguration + 2 + + + /home/leo/devCode/outer/USBFilter_30/upper_netlink/build/Desktop_Qt_5_15_2_GCC_64bit-Release + /home/leo/devCode/outer/USBFilter_30/upper_netlink/build/Desktop_Qt_5_15_2_GCC_64bit-Release + + + true + QtProjectManager.QMakeBuildStep + false + + + + true + Qt4ProjectManager.MakeStep + + 2 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + clean + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Release + Qt4ProjectManager.Qt4BuildConfiguration + 0 + 0 + + + 0 + /home/leo/devCode/outer/USBFilter_30/upper_netlink/build/Desktop_Qt_5_15_2_GCC_64bit-Profile + /home/leo/devCode/outer/USBFilter_30/upper_netlink/build/Desktop_Qt_5_15_2_GCC_64bit-Profile + + + true + QtProjectManager.QMakeBuildStep + false + + + + true + Qt4ProjectManager.MakeStep + + 2 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + clean + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Profile + Qt4ProjectManager.Qt4BuildConfiguration + 0 + 0 + 0 + + 3 + + + 0 + Deploy + Deploy + ProjectExplorer.BuildSteps.Deploy + + 1 + + false + ProjectExplorer.DefaultDeployConfiguration + + 1 + + true + true + 0 + true + + 2 + + false + -e cpu-cycles --call-graph dwarf,4096 -F 250 + + ProjectExplorer.CustomExecutableRunConfiguration + + false + true + true + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.FileVersion + 22 + + + Version + 22 + +