NDIS网络驱动探秘系列1

本文是对NDIS 5.0以前的网络驱动结构分析系列,对NDIS Filter驱动架构分析将在后续发出。
用Depends看看NDIS.sys导出函数,EthFilterDprIndicateReceive网卡芯片有硬件发送缓冲区和硬件接收缓冲区。小端口驱动在网卡内部接收缓冲区读出所有帧,提交给协议驱动。

NdisAdjustNetBufferCurrentMdl更新NET_BUFFER 结构根据当前data offset。
NdisAdvanceNetBufferDataStart 调整Dataoffset例程
然后就是分配内存函数了。NdisAllocateBufferPool分配用于NdisAllocateBuffer的handle。
NdisAllocateFragmentNetBufferList对NET_BUFFER做分片操作。
NdisAllocateeMdl内存描述符MDL结构分配。
NdisAllocateNetBufferList分配NET_BUFFER_LIST的例程。
NdisClMakeCall来请求微端口建立一条 VC(虚连接) 用来接收呼叫数据
NdisCmActivateVc 激活虚拟连接
NdisCoCreateVc
NdisCoSendPackets
NdisCopyBuffer
NdisCopyFromNetBufferToNetBuffer 对NET_BUFFER的复制操作,可以分配内存。在NDIS Filter使用
NdisDprAllocatePacket NDIS 5.x用的分配数据包函数
NdisFSendNetBufferLists Filter驱动的发送包含书
NdisGetDataBuffer 得到Buffer
NdisIMGetBinddingContext
NdisMAllocatePort
NdisMAllocateSharedMemory
NdisMQueueDpc
NdisMapFile
NdisOpenAdapter
NdisDmaInterruptDpc
Ndis.sys包括模块afilter执行处理包过滤功能也提供了采集分片包和breaking up 一个包到分片包NDIS MAC 驱动。Bus.c处理制定总线。如NdisImmediateReadPciSlotInformation例程从PCI配置空间一个指定长度的字节。Common一些通用例程如NdiscopyBuffer。
NdisMapIoSpace映射虚拟内存地址空间到一个物理地址。NdisRegisterAdapter注册一个Ndis适配器。创建一个FILE_DEVICE_PHYSICAL_NETCARD的Device。Configm是miniport配置和初始化等例程。Efilter执行库例程集处理为Ndis MAC 驱动做包过滤Eth。

VOID
NdisSendPackets(
IN NDIS_HANDLE NdisBindingHandle,
IN PPNDIS_PACKET PacketArray,
IN UINT NumberOfPackets
)
{
(((PNDIS_OPEN_BLOCK)NdisBindingHandle)->SendPacketsHandler)(
((PNDIS_OPEN_BLOCK)NdisBindingHandle)->MacBindingHandle,
PacketArray,
NumberOfPackets);
}

VOID
NdisTransferData(
OUT PNDIS_STATUS Status,
IN NDIS_HANDLE NdisBindingHandle,
IN NDIS_HANDLE MacReceiveContext,
IN UINT ByteOffset,
IN UINT BytesToTransfer,
OUT PNDIS_PACKET Packet,
OUT PUINT BytesTransferred
)
{
*Status = (((PNDIS_OPEN_BLOCK)NdisBindingHandle)->TransferDataHandler)(
((PNDIS_OPEN_BLOCK)NdisBindingHandle)->MacBindingHandle,
MacReceiveContext,
ByteOffset,
BytesToTransfer,
Packet,
BytesTransferred);
}miniport功能,miniport和protocol接口。

NdisInitializeTimer设置一个NdisTimer object。初始化此DPC在定时器到例程和上下文。他Winpcap驱动采用协议驱动, NDIS6.0上版本使用PNDIS_PROTOCOL_CHARACTERISTICS 做参数,填充相应例程信息。然后用NdisRegisterProtocol例程,注册一个协议驱动。然后获取可用网络适配器信息,为每个NIC创建一个设备对象。

使用NdisRequest查询NIC能力或状态或设置NIC状态。参数有NdisRequestSetInformation和NdisRequestQueryInformation。对应MiniportSetInformation和MiniportQueryInformation。

tcpip.sys 有对协议如arp,icmp,igmp,iproute,Rawip处理等模块
。当然还有对TCP和UDP协议的处理了。对TDI地址相关例程,包括TdI Open 地址,TDI close 地址等。本地地址objects存储在一个hash表内,用AddrObjTbleLock保护。ARP相关例程包括表查询,注册等。
在Windows7 下查看一下Tcpip内的arp相关例程:
1: kd> x tcpip!*arp*
8a283acf tcpip!Fl48pAllocateArpPacket =
8a300130 tcpip!FL_ARP_BITMAP_PATTERN_FRIENDLY_NAME =
8a2f3623 tcpip!FlpSetArpNDOffload =
8a300240 tcpip!FL_ARP_OFFLOAD_FRIENDLY_NAME =
8a3215ca tcpip!IPSecClearPacketInboundTunnelPass1 =
8a283491 tcpip!Fl48pSendArpPacket =
8a2543c0 tcpip!WfpAleSetOrClearPeerTokenInformation =
8a299b15 tcpip!Fl48pReceiveArpPackets =

如上看到只是简化为收发Arp包了。UDP包处理例程包括TdiSendDatagram和TdiReceiveDatagram。对ICMP的处理SendEcho 发送一个ICMP Echo反应。SendIcmpMsg发送一个ICMP消息。得到一个Buffer,格式化信息,复制输入header发送这个消息。ICMPTimer是ICMP的定时器。是一个全局IP定时器被定期调用。ICMPRcv接收一个ICMP数据报。
IGMP协议处理例程:info模块对查询和设置IP信息。IpQueryInfo被上层调用当想要查询信息。输入ID和buffer 长度等信息。IP_MIB_STATS_ID。IPSetInfo TdiQueryInformation。对传输层的初始化等处理,IPRegisterProtocol上层协议调用注册一个协议。IPSetMCastAddr设置或删除一个多播地址。
IProute模块包括IP路由相关例程包括路由表查找和管理例程。TCPConnect最终调用TDIConnect

发表评论