【Windows】 监控路由事件

说明

监控网卡可以使用 NotifyRouteChangeNotifyRouteChange2 函数,通过注册回调实现路由监控

主要步骤

  1. 声明一个回调函数处理通知
  2. 调用notifyRouteChange2注册通知,指定通知类型
  3. 等待通知
  4. 取消通知(可选)
  5. 在回调函数中根据通知类型进行处理

代码

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#define _WINSOCK_DEPRECATED_NO_WARNINGS

#include <iostream>
#include<iomanip>
#include<string>
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>

#pragma comment(lib, "iphlpapi.lib")
#pragma comment(lib, "ws2_32.lib")

using namespace std;

#define NAMEPRINTFORMAT(X) std::left << setw(60)<< #X << "\t\t" << X

std::string ipToString(DWORD dwIP)
{
	std::string strDestIp = "";
	std::string strMaskIp = "";

	struct in_addr network;
	network.S_un.S_addr = dwIP;    //为s_addr赋值--网络字节序
	strDestIp = inet_ntoa(network);

	return strDestIp;
}


void CALLBACK RouteChanged1(void* CallerContext, PMIB_IPFORWARD_ROW2 Table, MIB_NOTIFICATION_TYPE NotificationType)
{
	using context = void(*)(DWORD);

	context ctx = (context)CallerContext;

	auto PrintTable = [](MIB_IPFORWARD_ROW2 table) {
		cout << "---------------" << endl;
		cout << NAMEPRINTFORMAT(table.InterfaceLuid.Info.IfType) << endl;

		cout << NAMEPRINTFORMAT(table.InterfaceLuid.Info.NetLuidIndex) << endl;
		cout << NAMEPRINTFORMAT(table.InterfaceLuid.Info.Reserved) << endl;
		cout << NAMEPRINTFORMAT(table.InterfaceLuid.Value) << endl;

		cout << NAMEPRINTFORMAT(table.InterfaceIndex) << endl;


		cout << NAMEPRINTFORMAT(table.DestinationPrefix.Prefix.si_family) << endl;
		cout << NAMEPRINTFORMAT(table.DestinationPrefix.Prefix.Ipv4.sin_addr.S_un.S_addr) << "\t" << ipToString(table.DestinationPrefix.Prefix.Ipv4.sin_addr.S_un.S_addr) << endl;
		cout << NAMEPRINTFORMAT(table.DestinationPrefix.Prefix.Ipv4.sin_family) << endl;
		cout << NAMEPRINTFORMAT(table.DestinationPrefix.Prefix.Ipv4.sin_port) << endl;
		cout << NAMEPRINTFORMAT(table.DestinationPrefix.Prefix.Ipv4.sin_zero) << endl;

		cout << NAMEPRINTFORMAT(table.DestinationPrefix.Prefix.Ipv6.sin6_addr.u.Byte) << endl;
		cout << NAMEPRINTFORMAT(table.DestinationPrefix.Prefix.Ipv6.sin6_addr.u.Word) << endl;
		cout << NAMEPRINTFORMAT(table.DestinationPrefix.Prefix.Ipv6.sin6_family) << endl;
		cout << NAMEPRINTFORMAT(table.DestinationPrefix.Prefix.Ipv6.sin6_flowinfo) << endl;
		cout << NAMEPRINTFORMAT(table.DestinationPrefix.Prefix.Ipv6.sin6_port) << endl;
		cout << NAMEPRINTFORMAT(table.DestinationPrefix.Prefix.Ipv6.sin6_scope_id) << endl;
		cout << NAMEPRINTFORMAT(table.DestinationPrefix.Prefix.Ipv6.sin6_scope_struct.Level) << endl;
		cout << NAMEPRINTFORMAT(table.DestinationPrefix.Prefix.Ipv6.sin6_scope_struct.Value) << endl;
		cout << NAMEPRINTFORMAT(table.DestinationPrefix.Prefix.Ipv6.sin6_scope_struct.Zone) << endl;
		

		cout << NAMEPRINTFORMAT(table.NextHop.Ipv4.sin_addr.S_un.S_addr) << "\t" << ipToString(table.NextHop.Ipv4.sin_addr.S_un.S_addr) << endl;
		cout << NAMEPRINTFORMAT(table.NextHop.Ipv6.sin6_addr.u.Byte) << endl;
		cout << NAMEPRINTFORMAT(table.NextHop.Ipv6.sin6_addr.u.Word) << endl;
		cout << NAMEPRINTFORMAT(table.SitePrefixLength) << endl;
		cout << NAMEPRINTFORMAT(table.ValidLifetime) << endl;
		cout << NAMEPRINTFORMAT(table.PreferredLifetime) << endl;
		cout << NAMEPRINTFORMAT(table.Metric) << endl;
		cout << NAMEPRINTFORMAT(table.Protocol) << endl;
		cout << NAMEPRINTFORMAT(table.Loopback) << endl;
		cout << NAMEPRINTFORMAT(table.AutoconfigureAddress) << endl;
		cout << NAMEPRINTFORMAT(table.Immortal) << endl;
		cout << NAMEPRINTFORMAT(table.Age) << endl;
		cout << NAMEPRINTFORMAT(table.Origin) << endl;

		cout << "---------------" << endl << endl;
	};
	// 处理路由表变更通知
	switch (NotificationType)
	{
	case MibParameterNotification:
		cout << "1-- 参数被更改" << endl;
		break;
	case MibAddInstance:
		cout << "2-- 添加" << endl;
		PrintTable(*Table);

		ctx(Table->DestinationPrefix.Prefix.Ipv4.sin_addr.S_un.S_addr);
		break;
	case MibDeleteInstance:
		cout << "3-- 删除" << endl;
		PrintTable(*Table);

		ctx(Table->DestinationPrefix.Prefix.Ipv4.sin_addr.S_un.S_addr);
		break;
	case MibInitialNotification:
		cout << "4-- 函数已注册" << endl;
		break;

	default:
		break;
	}
}


void checkIsMyRoute (DWORD ip)
{
	cout << NAMEPRINTFORMAT(ipToString(ip)) << endl;
};

void main()
{
	HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
	HANDLE hNotify = NULL;
	PVOID callerContext = static_cast<PVOID>(&checkIsMyRoute);
	BOOLEAN bSuccess = TRUE;
	ULONG pdwPrevNotified = 0;

	if (callerContext != nullptr && NotifyRouteChange2(AF_UNSPEC, &RouteChanged1, callerContext, bSuccess, &hNotify) != NO_ERROR) {
		printf("Could not register for route change notifications\n");
		return ;
	}

	while (TRUE) {
		DWORD dwWait = WaitForSingleObject(hNotify, INFINITE);
		if (dwWait == WAIT_OBJECT_0) {
			// 接收到异步通知,处理结果
			break;
		}
	}

	// 取消监控
	CancelMibChangeNotify2(hNotify);
	CloseHandle(hNotify);

	return ;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

欧恩意

如有帮助,感谢打赏!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值