原理是利用windows自带的api函数,将过滤条件绑定到接口,再把接口绑定到本地ip地址,实现过滤。但是这种办法不知道如何显示每次的拦截记录,有什么思路可以实现界面显示拦截记录吗?
希望**做过这个的**大大提点自己的意见
CIpFilter::CIpFilter()
{
bCreateInterfaceSuccess = false;
ruleCount = 0;
/* 创建一个根据过滤规则丢弃数据包的过滤接口 */
DWORD retD = PfCreateInterface( 0, PF_ACTION_FORWARD, PF_ACTION_FORWARD,FALSE, TRUE, &drop );
///* 创建一个根据过滤规则放行数据包的过滤接口 */
//DWORD retD = PfCreateInterface( 0, PF_ACTION_DROP, PF_ACTION_DROP,FALSE, FALSE, &drop );
if(retD == NO_ERROR){
bCreateInterfaceSuccess = true;
}
in_addr ip = GetLocalIP();
localInAddr = ip.S_un.S_addr;
}
CIpFilter::~CIpFilter()
{
if(bCreateInterfaceSuccess){
PfDeleteInterface(drop);
}
}
/**
* 通过将过滤接口绑定到本地IP的方法使得过滤器发生作用
*
**/
bool CIpFilter::Filtering()
{
DWORD retD = PfBindInterfaceToIPAddress(drop,PF_IPV4,(PBYTE) & localInAddr);
return (retD == NO_ERROR);
}
/**
* 通过将过滤接口取消与本地IP的绑定的方法使得过滤器不再发生作用
*
**/
bool CIpFilter::UnFiltering()
{
DWORD retD = PfUnBindInterface(drop);
return (retD == NO_ERROR );
}
/**
* 向IP过滤器增加一条规则,先根据规则创建一个Filter描述子,
* 然后把Filter描述子加入到与IP过滤器相关的Interface即可
*
**/
bool CIpFilter::AddRule(RuleInfo rule)
{
PF_FILTER_DESCRIPTOR pf ;
/* 创建Filter描述子 */
pf.dwFilterFlags = FD_FLAGS_NOSYN;
int a = FD_FLAGS_NOSYN;
pf.dwRule = 0;
pf.pfatType = PF_IPV4;
pf.fLateBound = 0;
pf.dwProtocol = rule.protocol;
pf.wSrcPort = rule.sourcePort;
pf.wDstPort = rule.destinationPort;
pf.SrcAddr = (PBYTE) & rule.sourceIp;
pf.SrcMask = (PBYTE) & rule.sourceMask;
pf.DstAddr = (PBYTE) & rule.destinationIp;
pf.DstMask = (PBYTE) & rule.destinationMask;
pf.wSrcPortHighRange = pf.wSrcPort;
pf.wDstPortHighRange = pf.wDstPort;
DWORD ret;
/* 根据规则过滤数据包的方向来把Filter描述子加入到Inteface中 */
if(rule.bOut) ret = PfAddFiltersToInterface(drop,0,NULL,1,&pf,NULL);
else ret = PfAddFiltersToInterface(drop,1,&pf,0,NULL,NULL);
if(ret == NO_ERROR) ruleCount ++;
return ret == NO_ERROR;
}
/**
* 删除与指定规则相关的Interface 中的Filter描述子
*
**/
bool CIpFilter::DeleteRule(RuleInfo rule)
{
PF_FILTER_DESCRIPTOR pf ;
/* 根据规则生成与该规则相应的Filter描述子*/
pf.dwFilterFlags = FD_FLAGS_NOSYN;
int a = FD_FLAGS_NOSYN;
pf.dwRule = 0;
pf.pfatType = PF_IPV4;
pf.fLateBound = 0;
pf.dwProtocol = rule.protocol;
pf.wSrcPort = rule.sourcePort;
pf.wDstPort = rule.destinationPort;
pf.SrcAddr = (PBYTE) & rule.sourceIp;
pf.SrcMask = (PBYTE) & rule.sourceMask;
pf.DstAddr = (PBYTE) & rule.destinationIp;
pf.DstMask = (PBYTE) & rule.destinationMask;
pf.wSrcPortHighRange = pf.wSrcPort;
pf.wDstPortHighRange = pf.wDstPort;
DWORD ret;
/* 根据规则过滤数据包的方向来删除Interface中与它相关的Filter描述子 */
if(rule.bOut) ret = PfRemoveFiltersFromInterface(drop,0,NULL,1,&pf);
else ret = PfRemoveFiltersFromInterface(drop,1,&pf,0,NULL);
if(ret == NO_ERROR) ruleCount --;
return ret == NO_ERROR;
}
/**
* 通过释放与过滤器相关的Interface,
* 再重新生成一个新的Interface,
* 最后把新Interface过滤器关联起来,
* 从而实现了清除所有过滤规则的功能
*
**/
bool CIpFilter::ClearAllRules()
{
bool result = false;
DWORD retDD = PfDeleteInterface(drop);
DWORD retDC = PfCreateInterface( 0, PF_ACTION_DROP, PF_ACTION_DROP,FALSE, TRUE, &drop );
if(UnFiltering()
&& retDD == NO_ERROR
&& retDC == NO_ERROR){
result = true;
}
return result;
}
/**
* 通过Windows Socket来取得本地IP
*
**/
in_addr CIpFilter::GetLocalIP()
{
WORD wVersionRequested;
WSADATA wsaData;
hostent* localHost;
wVersionRequested = MAKEWORD( 2, 2 );
WSAStartup( wVersionRequested, &wsaData );
localHost = gethostbyname("");
WSACleanup();
in_addr* localIP = (struct in_addr *)localHost->h_addr_list[0];
return *localIP;
}
/**
* 调用API 取得与过滤器相关的Interface相关的状态数据
*
**/
PF_INTERFACE_STATS * CIpFilter::GetState()
{
PF_INTERFACE_STATS * ret;
DWORD size = 0, retFlag = 0;
int x = sizeof(PF_INTERFACE_STATS);
ret = (PF_INTERFACE_STATS *)new char[sizeof(PF_INTERFACE_STATS)];
retFlag = PfGetInterfaceStatistics(drop,ret,&size,FALSE);
if(retFlag != NO_ERROR)
{
/*重复一定的调用次数,以提供成功调用的概率*/
for(int i = 0; i < 10; i ++){
delete ret;
ret = (PF_INTERFACE_STATS *)new char[size];
retFlag = PfGetInterfaceStatistics(drop,ret,&size,FALSE);
if(retFlag == NO_ERROR) break;
}
if(retFlag != NO_ERROR) return NULL;
}
return ret;
}
思路就是还是用windows自带的api!
你都有数据了,将数据post到界面线程或者进程,让界面进程显示不就完了。
怎么显示,你查阅下windows的窗口、对话框、按钮等编程实现即可。
你还是去先学习一下windows程序设计吧,http://blog.fishc.com/,
拿到数据后通过WM_COPYDATA SendMessage发送消息给主线程来更新界面。
就是跟应用程序通讯。