223 lines
5.2 KiB
C++
223 lines
5.2 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
|
|
/// 开始监控
|
|
/// @return 成功返回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
|
|
/// 停止监控
|
|
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);
|
|
|
|
/*打开NetLink Socket*/
|
|
socket_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
|
setsockopt(socket_fd, SOL_SOCKET, SO_RCVBUF, &len, sizeof(len));
|
|
|
|
/*设定接收类型并绑定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:
|
|
/*收到些奇怪的信息*/
|
|
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
|
|
}
|
|
|
|
|
|
/// 解析RTA,并存入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
|
|
}
|
|
|
|
///显示连接信息
|
|
///当网卡变动的时候触发这个信息,例如插/拔网线,增/减网卡设备,启用/禁用接口等.
|
|
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
|
|
}
|
|
|
|
///显示地址信息
|
|
///当地址变动的时候触发这个信息,例如通过DHCP获取到地址后
|
|
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
|
|
}
|
|
|
|
/**
|
|
* 显示路由信息
|
|
* 当路由变动的时候触发这个信息
|
|
*/
|
|
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;
|
|
} |