223 lines
5.0 KiB
C++
223 lines
5.0 KiB
C++
|
|
#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;
|
|||
|
|
}
|