tcp filter例子

tcp filter例子
我先描述一下2000/nt下的tcp/ip协议的一些情况。2000/nt下,ip,tcp,udp是在
一个驱动程序里实现的,叫做tcp.sys,这个驱动程序创建了3个设备,就是ip,tcp,udp

首先描述一下driverentry。首先当然是iocreatedevice,用file_device_unknown,
因为tcp设备就是用的这个参数。代码如下:
rtlinitunicodestring(&usdevicename,filter_name);
status=iocreatedevice(driverobject,
sizeof(device_extension),
&usdevicename,
file_device_unknown,
0,
false,
&pdevobj);
然后就调用iogetdeviceobjectpointer来得到tcp设备的指针。
代码如下:
rtlinitunicodestring(&ustargetname,target_name);
status=iogetdeviceobjectpointer(&ustargetname,
file_all_access,
&ptargetfileobj,
&ptargetdevobj);
注意target_name是大小写区分的,我是用#definetarget_namel\\device\\tcp,
不能写成#definetarget_namel\\device\\tcp。
然后我们就开始调用ioattachdevicetodeviestatck插入到tcp设备。
调用完成后,我们要让我们的设备表现的和tcp一样,于是把它的所有
特性都从tcpobj复制(pdevobj->xxx=ptcpobj->xxx)。
再扫描他tcpdriverobject的majorfunction,我们的driver必须都
支持。最后设置driverunload,因为为了方便调试,我们必须写一个unload 前面已经讲过driverentry了,经过driverentry,所有的原来应该发送到
tcp设备的irp现在都发送到我们的设备的处理函数了,如果什么事情都不做,
那么可以简单的调用iocalldriver把这个irp发到tcp设备去让它处理。
当然,我们是要做些事情的,于是代码如下:
ucharmajorfunction,minorfunction;
pdevice_extensionpdevext=(pdevice_extension)deviceobject->deviceext
ension;
pio_stack_locationpirpstack=iogetcurrentirpstacklocation(irp);
majorfunction=pirpstack->majorfunction;
minorfunction=pirpstack->minorfunction;
//dbgprint(...)
parseirp(irp);
iocopycurrentirpstacklocationtonext(irp);
iosetcompletionroutine(irp,
completionroutine,
null,//context
true,//invokeonsuccess
true,//invokeonerror
true);//invokeoncancel
returniocalldriver(pdevext->targetdevobj,irp);
代码很简单,除了parseirp之外,其他都是例行公事。对于tcp设备的前期处理
就在这个函数里。后期处理的函数可以放在completionroution里。
好了,我们已经得到了发向tcp设备的所有irp了,这个时候我们的任务就是要了解
tcp设备到底是如何工作的.
这种情况下数据不经过tcp设备,filter也就无从得到了。
为了了解如何从发向tcp设备的irp中得到信息,首先我先描述一下tdiclient是如何
与tcp通讯以及tdiclient一般是如何工作的。
driverstdio里面有好几个例子都是关于tdiclient的,但是这些例子都是基于它自己
的类库的,不过这些例子功能都很强大,其中一个usb+web的温度计的创意简直让我目瞪
口呆。
因为我也做过pci温度计的driver,但是我从来就没有想到还可以加上一个webserver在
里面。
因为driverstdio里的例子太复杂,我在这里简单描述一下,给一个小例子。
因为发送过程较为简单,先描述发送。
首先调用pirp=tdibuildinternaldevicecontrolirp(
tdi_send_datagram,//sub
function
pdeviceobject,//poin
tertodeviceobject
ptransportobject,//poin
tertoudpobject
null,//poin
tertoevent
null);//poin
tertoreturnbuffer
分配一块irp,然后调用
tdibuildsenddatagram(
pirp,//poin
tertoirp
pdeviceobject,//poin
tertodeviceobject
ptransportobject,//poin
tertofileobject
null,//comp
letionroutine
null,//comp
letioncontext
pmdl,//poin
tertodata
dbuffersize,//size
ofdata
pconnectinfo);//conn
ectioninformation
不用我说也应该知道,数据是放在一个buf里面,调用这个函数之前,要先构件一个mdl
,把这个buf
放进去。
然后...irp已经好了,只要iocalldriver(pudpobject,pirp)就行了...
上面用的是udp的例子(datagram),但是tcp也是一样,虽然函数有点差别,但是也是大
同小异(tdibuildsend)。
为了搞清楚上面的两个函数到底做了些什么(到底构建的irp是什么样子),没有必要去
跟踪,实际上,tdibuildxxx
都不过是一个宏,你可以在tdikrnl.h里找到。打开tdikrnl.h看看,发现每个宏里都有
这么一句:
_irpsp->majorfunction=irp_mj_internal_device_control;
于是我们知道tdiclient就是通过majorfunction=irp_mj_internal_device_control,m
inorfunction=send/recv/...
和tcp通讯的。这就使得我们确信,这种方法是可行的。(不是直接调用tdi函数,而是
发irp)
接收的过程较为复杂(tdiclient的选择较多,因此要考虑各种情况)
开始的时候,我在ddkdocument里看到这么一个宏:tdibuildreceive,我想ok,
和send一样,我当时想的很简单,以为tdiclient要接受数据了,它就向tcp发一个
irp,然后返回pending,当有数据来的时候,tcp处理完这个irp,然后tdiclient只要在
这个irp的
irp_complete里处理得到的数据就行了。这的确是tdiclient的一个选择,但是
当我试验的时候,我发现至少wsock不是这样做的,因为我打开了一个ie,浏览了一个网
页,
但是我发现我发出的数据都很好的捕获到了,但是接收的数据一个也没有,而且事实上

tcp似乎就没有受到minorfunction=tdi_receive的irp。我因为这件事苦恼了一段时间,
后来我仔细的读了读ddkdocument,发现tdiclient还有第2种选择,首先向tcp发送一

irp,minorfunction=tdi_sethandler,设置一些回调函数,然后当事情发生的时候,tc
p
就会调用这些回调函数,这些函数名字是clienteventxxx。这个过程可以仔细看ddkdo
cument,
看tdibuildseteventhandler,就知道哪些过程可以用这个方法。receive也是其中的一
个,于是
我们的方法得到了。首先我们得到了irp,如果是set_eventhandler,那么就修改tdic
lient
向tcp设置的回调函数的入口,把它指向我们自己写的一个函数,同时保留原来的入口,
然后在我们自己写的函数里里调用它。
代码如下:
pio_stack_locationpirpstack=iogetcurrentirpstacklocation(irp);
majorfunction=pirpstack->majorfunction;
minorfunction=pirpstack->minorfunction;
fileobject=pirpstack->fileobject;
....
switch(majorfunction)
{
...
caseirp_mj_internal_device_control:
{
switch(minorfunction)
{
...
casetdi_set_event_handler:
prequestsetevent=(ptdi_request_kernel_set_event)(&(pirpstack->pa
rameters.deviceiocontrol));
eventtype=prequestsetevent->eventtype;
eventhandler=prequestsetevent->eventhandler;
eventcontext=prequestsetevent->eventcontext;
...
switch(eventtype)
{
...
casetdi_event_receive:
prequestsetevent->eventhandler=ourclienteventreceive;
g_eventreceive=eventhandler;
break;
...
值得注意的是,就算是set_eventhandler,也不一定就是tdi_event_receive里接受数据

这个tdi_client的选择很多,还有clienteventchainedreceive什么的,详情可看ddk,
winsock似乎都是没有用过这个。不过这个不影响,我们可以把ddk里面所有可能的情况
全部列出来,一一判断,然后分别处理。对于clienteventreceive,这里还有几句话要

清楚,并不是每次调用这个函数就得到了数据,这还要根据receiveflags参数,tdicl
ient
要根据这个参数决定是否要发tdi_receiveirp得到数据。于是我们的处理函数就要判断
这个
参数,以便做出相应的处理,我自己的代码在实际的环境中运行了一段时间,似乎没有
问题,但是
我也不敢说,对于各种情况我都考虑到了。

VCR TV通 断控制电路
IMAX参展2021 ChinaJoy “空间站”主题展区炫酷来袭
具有方波输出的快速倍频器
传IBM欲出售半导体业务 连续甩卖震惊业界
引起三相不平衡的原因看了就知道
tcp filter例子
一加6T在售价基本不变的基础上给用户体验上带来了极大的提升
静电的特点和危害方式
开源:理想向左,现实向右
2018年智能家居尚未规模化应用 目前依旧是供给大于需求
相位噪声定义 相位噪声来源 相位噪声对信号的影响
FPC连接器如何使用
电路交换和分组交换的区别
心系天下三星W21 5G正式全国首销
有源滤波器中的相位关系
福玛特智能扫地机器人,运用F-SLAM Ⅲ系统,做到精准高效矩阵式清扫
串联或并联白光LED的供电方案:电荷泵与升压型DC-DC转换
基于RX140的低功耗触摸按键解决方案
细数机器学习在金融领域的七大应用
IT基础设施建设需求扩大,2020年中国IT支出将达到20683.5亿元