GrabBag/Module/EthMonitor/Src/VrEthMonitor.cpp

223 lines
5.0 KiB
C++
Raw Normal View History

2025-06-08 12:48:04 +08:00
#include "VrEthMonitor.h"
#include "IVrUtils.h"
#include <thread>
#ifndef _WIN32
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <asm/types.h>
#include <arpa/inet.h>
#include <linux/route.h>
#include <unistd.h>
#include <linux/if.h>
#include <linux/rtnetlink.h>
#include <stdio.h>
#include <mutex>
#include <ifaddrs.h>
#endif
CVrEthMonitor::CVrEthMonitor()
: m_fNotify(nullptr)
, m_pParam(nullptr)
, m_bRunning(false)
{
}
CVrEthMonitor::~CVrEthMonitor()
{
}
/// @brief
/// <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>
/// @return <20>ɹ<EFBFBD><C9B9><EFBFBD><EFBFBD><EFBFBD>TRUE
int CVrEthMonitor::StartMonitor(NetNotify func, void* pParam)
{
m_bRunning = true;
std::thread runMonitor(std::bind(&CVrEthMonitor::_MonitorTask, this));
runMonitor.detach();
m_fNotify = func;
m_pParam = pParam;
return SUCCESS;
}
/// @brief
/// ֹͣ<CDA3><D6B9><EFBFBD><EFBFBD>
void CVrEthMonitor::StopMonitor()
{
m_bRunning = false;
}
void CVrEthMonitor::_MonitorTask()
{
#ifndef _WIN32
int socket_fd;
int err = 0;
int read_r;
struct sockaddr_nl sa;
struct nlmsghdr *nh;
const int len = 2048;
char buff[len];
// signal(SIGINT, intHandler);
/*<2A><><EFBFBD><EFBFBD>NetLink Socket*/
socket_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
setsockopt(socket_fd, SOL_SOCKET, SO_RCVBUF, &len, sizeof(len));
/*<2A><EFBFBD><E8B6A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ͳ<EFBFBD><CDB2><EFBFBD><EFBFBD><EFBFBD>Socket*/
bzero(&sa, sizeof(sa));
sa.nl_family = AF_NETLINK;
sa.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_IFADDR | RTMGRP_IPV6_ROUTE;
bind(socket_fd, (struct sockaddr *) &sa, sizeof(sa));
while (m_bRunning)
{
fd_set readFD;
FD_SET(socket_fd, &readFD);
struct timeval waitTime = { 5, 0 };
int nCount = select(socket_fd + 1, &readFD, nullptr, nullptr, &waitTime);
if (nCount > 0)
{
read_r = read(socket_fd, buff, sizeof(buff));
for (nh = (struct nlmsghdr *) buff; NLMSG_OK(nh, read_r); nh = NLMSG_NEXT(nh, read_r))
{
switch (nh->nlmsg_type) {
default:
/*<2A>յ<EFBFBD>Щ<EFBFBD><D0A9><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD>Ϣ*/
break;
case NLMSG_DONE:
case NLMSG_ERROR:
break;
case RTM_NEWLINK:
case RTM_DELLINK:
_ifinfomsg(nh);
break;
case RTM_NEWADDR:
case RTM_DELADDR:
_ifaddrmsg(nh);
break;
case RTM_NEWROUTE:
case RTM_DELROUTE:
_rtmsg(nh);
break;
}
}
}
}
close(socket_fd);
#endif // !_WIN32
}
/// <20><><EFBFBD><EFBFBD>RTA,<2C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>tb
void CVrEthMonitor::_parse_rtattr(struct rtattr **tb, int max, struct rtattr *attr, int len)
{
#ifndef _WIN32
for (; RTA_OK(attr, len); attr = RTA_NEXT(attr, len)) {
if (attr->rta_type <= max) {
tb[attr->rta_type] = attr;
}
}
#endif // !_WIN32
}
///<2F><>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ
///<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E4B6AF>ʱ<EFBFBD>򴥷<EFBFBD><F2B4A5B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ,<2C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>/<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<2C><>/<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>豸,<2C><><EFBFBD><EFBFBD>/<2F><><EFBFBD>ýӿڵ<D3BF>.
void CVrEthMonitor::_ifinfomsg(struct nlmsghdr *nh)
{
#ifndef _WIN32
int len;
struct rtattr *tb[IFLA_MAX + 1];
struct ifinfomsg *ifinfo;
bzero(tb, sizeof(tb));
ifinfo = (ifinfomsg *)NLMSG_DATA(nh);
len = nh->nlmsg_len - NLMSG_SPACE(sizeof(*ifinfo));
_parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifinfo), len);
//LOG_DEBUG("%s %s: %s \n", (char *)RTA_DATA(tb[IFLA_IFNAME]), (nh->nlmsg_type == RTM_NEWLINK) ? "NEWLINK" : "DELLINK", (ifinfo->ifi_flags & IFF_LOWER_UP) ? "up" : "down");
std::string sName = (char *)RTA_DATA(tb[IFLA_IFNAME]);
if (sName.find("eth") != std::string::npos)
{
if (ifinfo->ifi_flags & IFF_LOWER_UP)
{
m_fNotify(sName, NET_STATUS_UP, m_pParam);
}
else
{
m_fNotify(sName, NET_STATUS_DOWN, m_pParam);
}
}
#endif // !_WIN32
}
///<2F><>ʾ<EFBFBD><CABE>ַ<EFBFBD><D6B7>Ϣ
///<2F><><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><E4B6AF>ʱ<EFBFBD>򴥷<EFBFBD><F2B4A5B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ,<2C><><EFBFBD><EFBFBD>ͨ<EFBFBD><CDA8>DHCP<43><50>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7>
void CVrEthMonitor::_ifaddrmsg(struct nlmsghdr *nh)
{
#ifndef _WIN32
int len;
struct rtattr *tb[IFA_MAX + 1];
struct ifaddrmsg *ifaddr;
char tmp[256];
bzero(tb, sizeof(tb));
ifaddr = (ifaddrmsg *)NLMSG_DATA(nh);
len = nh->nlmsg_len - NLMSG_SPACE(sizeof(*ifaddr));
_parse_rtattr(tb, IFA_MAX, IFA_RTA(ifaddr), len);
if (tb[IFA_LABEL] != NULL && tb[IFA_ADDRESS] != NULL && nh->nlmsg_type == RTM_NEWADDR)
{
inet_ntop(ifaddr->ifa_family, RTA_DATA(tb[IFA_ADDRESS]), tmp, sizeof(tmp));
}
std::string sName = (char *)RTA_DATA(tb[IFLA_IFNAME]);
m_fNotify(sName, NET_STATUS_STATUS_CHANGE, m_pParam);
#endif
}
/**
* <EFBFBD><EFBFBD>ʾ·<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ
* <EFBFBD><EFBFBD>·<EFBFBD>ɱ<EFBFBD><EFBFBD>ʱ<EFBFBD>򴥷<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ
*/
void CVrEthMonitor::_rtmsg(struct nlmsghdr *nh)
{
#ifndef _WIN32
int len;
struct rtattr *tb[RTA_MAX + 1];
struct rtmsg *rt;
char tmp[256];
bzero(tb, sizeof(tb));
rt = (rtmsg *)NLMSG_DATA(nh);
len = nh->nlmsg_len - NLMSG_SPACE(sizeof(*rt));
_parse_rtattr(tb, RTA_MAX, RTM_RTA(rt), len);
if (tb[RTA_DST] != NULL) {
inet_ntop(rt->rtm_family, RTA_DATA(tb[RTA_DST]), tmp, sizeof(tmp));
}
if (tb[RTA_SRC] != NULL) {
inet_ntop(rt->rtm_family, RTA_DATA(tb[RTA_SRC]), tmp, sizeof(tmp));
}
if (tb[RTA_GATEWAY] != NULL) {
inet_ntop(rt->rtm_family, RTA_DATA(tb[RTA_GATEWAY]), tmp, sizeof(tmp));
if (nh->nlmsg_type == RTM_NEWROUTE) {
m_fNotify("", NET_STATUS_ROUTE_ADD, m_pParam);
} else {
m_fNotify("", NET_STATUS_ROUTE_DEL, m_pParam);
}
//system("ip rule add from all lookup main pref 0");
}
#endif // !_WIN32
}
bool VrCreateEthMonitor(IVrEthMonitor** ppEthMonitor)
{
CVrEthMonitor* pObj = new CVrEthMonitor;
*ppEthMonitor = pObj;
return true;
}