您的位置:首页 > 理论基础 > 计算机网络

tdi总结 -- 发文于2013-12-14

2016-01-15 22:49 260 查看
1.入口函数

  创建设备对象,绑定到\\Device\\Tcp,\\Device\\Udp,\\Device\\RawIp设备栈上。

  设置dispatch分发函数处理创建,清理和内部外部DEVICE_CONTROL设置irp请求。

2.create请求

   在create请求中获取进程名,pid上抛应用层。

   应用层createfile时,在EaBuffer中传递传输层操作指令,可以是TdiTransportAddress(生成传输层地址,即给协议驱动使用的网络地址,即ip地址)

   或者TdiConnectionContext(生成连接终端,在本机上维护一个连接的数据结构)。因为只有在生成传输层地址结束后,才可以查询到这个ip地址。所以通过

   TdiBuildInternalDeviceControlIrp(不能调用在dispatch级别,可以在分发函数的passive级别,所以提前建立一个空请求,不下发,在tdi_create_addrobj_complete设置下发)建立irp

查询请求,在tdi_create_addrobj_complete完成函数中发送查询请求。在tdi_create_addrobj_complete2完成函数中完成查询请求,解析ip地址和端口号。

   tdi建立连接方式:先生成传输层地址,再生成连接终端,然后用一个控制请求将两者联系。连接终端生成只代表一个连接意图,没有实质性操作,以便于后面有控制请求时获取信

息.connection_context代表一个连接终端。在deviceiocontrol请求中,得到的都是文件对象,所以在tdi_create函数中根据fileobj计算哈希,保存一张哈希表,把文件对象和context对应

起来。在tdi_create_addrobj_complete2完成查询后在表中保存地址信息。

3.控制请求

  即IRP_MJ_DEVICE_CONTROL和IRP_MJ_INTERNAL_DEVICE_CONTROL请求。前者用于应用层向驱动层发送设备,后者用于内核内部发送设备控制命令。以后者为例:

   如果是TDI_ASSOCIATE_ADDRESS请求,用于把一个传输层地址对象和一个连接终端对象联系起来。IRP当前栈空间的FileObject域保存的文件对象指针是连接终端的文件对象指针

connobj_handle,可以通过ot_find_fileobj找到先前保存的连接终端对象。ObReferenceObjectByHandle获得应用层传进来的irp参数中的地址对象,通过ote_conn->associated_fileobj = 

addrobj;将地址和先前保存的连接终端对象联系起来。为了能通过context指针获得地址对象,通过ot_add_conn_ctx再建立一张对应表。这样有两张表,一张通过连接终端对象

可以获取地址,另一张可以通过context指针获取地址。

  TDI_DISASSOCIATE_ADDRESS请求是上面的逆操作。

  TDI_CONNECT请求发生在本地试图主动连接外界时,此处判断用户进程使用本地什么地址,连接远程什么地址,是否允许连接,是否记录此次连接日志。

当前irp栈空间的fileobj是连接终端对象,先通过ot_find_fileobj找到连接对象,然后找出地址对象就是本地地址。远程地址可以通过ip的参数部分得到。然后

生成flt_request过滤请求对象,调用规则过滤函数。

 tdi_send_datagram,tdi_receive_datagram用于udp数据报式接收发送,tdi_send,tdi_receive用于tcp流式的接收发送。

 在过滤函数中可以通过irps->fileobj得到连接文件对象,然后获得连接终端对象,从中得到上下文指针,地址端口等,统计流量。

4.设置请求

  设置事件本质是客户指定一个回调函数,当网络上某事件发生时,下层协议调用次函数通知应用程序该事件的发生。

比如用户用socket调用listen时,类型为TDI_EVENT_CONNECT的设置请求将从应用层发送到下层协议,下层协议得到一个回调函数指针。

处理设置请求的是IRP_MJ_INTERNAL_DEVICE_CONTROL中的TDI_SET_EVENT_HANDLER子类型请求。

  当前irps的参数是PTDI_REQUEST_KERNEL_SET_EVENT结构,保存了事件的设备对象,文件对象,事件类型,事件回调函数指针等。如果事件回调函数指针为空,则是

取消事件回调函数。

  TDI_EVENT_CONNECT类型回调函数请求。对于tcp协议,外部连接我方,肯定有我方侦听。当外部连接我方端口时,我们用用自己的回调函数取代原回调函数,然后再

调用原来的回调函数。这个请求只是设置回调,用于从应用层到tdi下层协议的方向。

  当设置的回调函数tdi_event_connect被调用时,说明有外部主机在试图连接侦听端口。在该函数的TdiEventContext自定义结构中自己存储事件原来的回调函数,上下文,地址的文件对象

等。

5.直接获取发送函数的过滤

  对于IRP_MJ_DEVICE_CONTROL中的IOCTL_TDI_QUERY_DIRECT_SNED_HANDLER请求,Tcpip.sys将返回TcpSendData函数的指针,这个函数就可以用于发送数据.将它替换成自己的过滤函数即可。

6.清理请求的过滤

  句柄全部关闭之后会收到IRP_MJ_CLEANUP请求.但不代表文件对象的引用计数减少到0,因为引用计数不一定打开句柄才能增加。引用计数减少到0时文件对象会被销毁.此时,收到

IRP_MJ_CLOSE请求.在cleanup时删除连接或者地址对象.

  对于IRP_MJ_DEVICE_CONTROL的请求可以通过TdiMapUserRequest转换成IRP_MJ_INTERNAL_DEVICE_CONTROL请求.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息