NDIS驱动

85 篇文章 6 订阅
83 篇文章 10 订阅

NDIS驱动分为3层

协议层驱动

绑定再所有网卡上,所以能截获接收到的包,但无法截获发送的包

中间层驱动

(P部分)绑定在了所有小端口驱动上(M部分)也被所有的协议驱动绑定,收发都能拦截。所有中间层小端口部分负责处理发送的包,协议部分负责处理接受的包

小端口驱动

网卡驱动

NDIS驱动开始

NdisMInitializeWrapper初始化NDIS句柄,

NdisIMRegisterLayeredMiniport注册小端口特征并获得DriverHandle,提供一组回调函数,用来拦截发送数据包,进行分析解析。

NdisRegisterProtocol注册协议特征并获得ProtHandle,拦截接受数据包,进行能分析解析。

NdisIMAssociateMiniport。将DriverHandle与ProtHandle关联。

收发包处理(协议部分的PtReceive(),小端口部分的MpSend())

协议分析(接收,拒绝,修改)

代码部分

在DriverEntry做了小端口,协议部分初始化,创建设备对象符号链接。初始化各种协议头。


NTSTATUS
DriverEntry(
	IN	PDRIVER_OBJECT		DriverObject,
	IN	PUNICODE_STRING		RegistryPath
	)
    /*------------------------------------------------------------------------------
	逐一设置protocolChar结构中的每一个域。这些域一些是驱动程序所必需的版本号、名字等信息,
	另外一些是函数指针,它们指定了一些NDIS自动执行的函数的入口地址。
	这里指定的每一个函数在程序中必须有它的具体实现。其中有些函数指针可以为NULL,
	表示不指定这个函数。但是,NDIS要求一些函数是必须指定的,它们包括:
	BindAdapterHandler、UnbindAdapterHandler、OpenAdapterCompleteHandler 、
	CloseAdapterCompleteHandler、ReceiveHandler 、ReceiveCompleteHandler、
	TransferCompleteHandler、SendCompleteHandler 、ResetCompleteHandler 、
	 RequestCompleteHandler StatusHandler 、StatusCompleteHandler 、PnPEventHandler 
	------------------------------------------------------------------------------*/
/*++

Routine Description:

	First entry point to be called, when this driver is loaded.
	Register with NDIS as an intermediate driver.

Arguments:

	DriverObject - pointer to the system's driver object structure
		for this driver
	
	RegistryPath - system's registry path for this driver
	
Return Value:

	STATUS_SUCCESS if all initialization is successful, STATUS_XXX
	error code if not.

--*/
{
	NDIS_STATUS						Status;
	NDIS_PROTOCOL_CHARACTERISTICS	PChars;//协议部分回调函数
	NDIS_MINIPORT_CHARACTERISTICS	MChars;//小端口相关回调函数
	PNDIS_CONFIGURATION_PARAMETER	Param;
	NDIS_STRING						Name;
	NDIS_HANDLE						WrapperHandle;

	// add by LornWolf
	UNICODE_STRING nameString, linkString; 
	UINT FuncIndex;
	PDEVICE_OBJECT MyDeviceObject; 
	PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1];
	//end add

	Status = NDIS_STATUS_SUCCESS;
	NdisAllocateSpinLock(&GlobalLock);

	NdisMInitializeWrapper(&NdisWrapperHandle, DriverObject, RegistryPath, NULL);

	do//放在dowhilefalse为了出错直接退出。
	{
		//
		// Register the miniport with NDIS. Note that it is the miniport
		// which was started as a driver and not the protocol. Also the miniport
		// must be registered prior to the protocol since the protocol's BindAdapter
		// handler can be initiated anytime and when it is, it must be ready to
		// start driver instances.
		//
		NdisMInitializeWrapper(&WrapperHandle, DriverObject, RegistryPath, NULL);
		NdisZeroMemory(&MChars, sizeof(NDIS_MINIPORT_CHARACTERISTICS));

		MChars.MajorNdisVersion = PASSTHRU_MAJOR_NDIS_VERSION;
		MChars.MinorNdisVersion = PASSTHRU_MINOR_NDIS_VERSION;

		MChars.InitializeHandler = MPInitialize;
		MChars.QueryInformationHandler = MPQueryInformation;
		MChars.SetInformationHandler = MPSetInformation;
		MChars.ResetHandler = MPReset;
		MChars.TransferDataHandler = MPTransferData;
		MChars.HaltHandler = MPHalt;
#ifdef NDIS51_MINIPORT
		MChars.CancelSendPacketsHandler = MPCancelSendPackets;
		MChars.PnPEventNotifyHandler = MPDevicePnPEvent;
		MChars.AdapterShutdownHandler = MPAdapterShutdown;
#endif // NDIS51_MINIPORT

		//
		// We will disable the check for hang timeout so we do not
		// need a check for hang handler!
		//
		MChars.CheckForHangHandler = NULL;
		MChars.ReturnPacketHandler = MPReturnPacket;//这时候已经没有IRP这个概念了,不能直接找
		//所属进程了。在tdi中维护端口和ip地址的一个表,在ndis中拿到端口去查那个表
		//
		// Either the Send or the SendPackets handler should be specified.
		// If SendPackets handler is specified, SendHandler is ignored
		//下面是用来拦截发包的函数,
		MChars.SendHandler = NULL;	// MPSend;
		MChars.SendPacketsHandler = MPSendPackets;

		Status = NdisIMRegisterLayeredMiniport(NdisWrapperHandle,
   											   &MChars,
   											   sizeof(MChars),
										   	   &DriverHandle);
		if (Status != NDIS_STATUS_SUCCESS)
		{
			break;
		}

#ifndef WIN9X
		NdisMRegisterUnloadHandler(NdisWrapperHandle, PtUnload);
#endif

		//
		// Now register the protocol.
		//
		NdisZeroMemory(&PChars, sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
		PChars.MajorNdisVersion = PASSTHRU_PROT_MAJOR_NDIS_VERSION;
		PChars.MinorNdisVersion = PASSTHRU_PROT_MINOR_NDIS_VERSION;

		//
		// Make sure the protocol-name matches the service-name
		// (from the INF) under which this protocol is installed.
		// This is needed to ensure that NDIS can correctly determine
		// the binding and call us to bind to miniports below.
		//
		NdisInitUnicodeString(&Name, L"Passthru");	// Protocol name
		PChars.Name = Name;
		PChars.OpenAdapterCompleteHandler = PtOpenAdapterComplete;
		PChars.CloseAdapterCompleteHandler = PtCloseAdapterComplete;
		PChars.SendCompleteHandler = PtSendComplete;
		PChars.TransferDataCompleteHandler = PtTransferDataComplete;
	
		PChars.ResetCompleteHandler = PtResetComplete;
		PChars.RequestCompleteHandler = PtRequestComplete;
		PChars.ReceiveHandler = PtReceive;
		PChars.ReceiveCompleteHandler = PtReceiveComplete;
		PChars.StatusHandler = PtStatus;
		PChars.StatusCompleteHandler = PtStatusComplete;
		PChars.BindAdapterHandler = PtBindAdapter;
		PChars.UnbindAdapterHandler = PtUnbindAdapter;
		PChars.UnloadHandler = PtUnloadProtocol;

		PChars.ReceivePacketHandler = PtReceivePacket;
		PChars.PnPEventHandler= PtPNPHandler;

		NdisRegisterProtocol(&Status,
 							&ProtHandle,
 							&PChars,
 							sizeof(NDIS_PROTOCOL_CHARACTERISTICS));

		if (Status != NDIS_STATUS_SUCCESS)
		{
			NdisIMDeregisterLayeredMiniport(DriverHandle);
			break;
		}

		NdisIMAssociateMiniport(DriverHandle, ProtHandle);
	}
	while (FALSE);

//----------------- 创建设备对象与符号连接----------------------------add by xiaoqiang
	RtlInitUnicodeString(&nameString, L"\\Device\\MyPassthru" ); 
	RtlInitUnicodeString(&linkString, L"\\??\\MyPassthru"); 

	for(FuncIndex = 0; FuncIndex <=IRP_MJ_MAXIMUM_FUNCTION; FuncIndex++)
	{
		MajorFunction[FuncIndex] = NULL;
	}
	    
	MajorFunction[IRP_MJ_CREATE]         = MydrvDispatch;
	MajorFunction[IRP_MJ_CLOSE]          = MydrvDispatch;
	MajorFunction[IRP_MJ_DEVICE_CONTROL] = MydrvDispatchIoctl;//下发规则

	Status = NdisMRegisterDevice(
                    WrapperHandle, 
                    &nameString,
                    &linkString,
                    MajorFunction,
                    &MyDeviceObject,
                    &NdisDeviceHandle
                    );

	if(Status != STATUS_SUCCESS)
	{
		DbgPrint("NdisMRegisterDevice failed!\n");
	}

    // 初始化config规则
	DbgPrint("初始化config规则!\n");
	g_Rules.global.fw_status=FWS_ALLOWALL;//放行
	g_Rules.global.log_disable=0;
	g_Rules.global.fw_mode=RM_ALLOW;
	g_Rules.tcp.disable=0;
	g_Rules.udp.disable=0;
	g_Rules.icmp.disable=0;



	// 分配与应用程序共享的内存
	SystemVirtualAddress = ExAllocatePool(NonPagedPool, 1024);
	Mdl = IoAllocateMdl(SystemVirtualAddress, 1024, FALSE, FALSE, NULL);
	MmBuildMdlForNonPagedPool(Mdl);


	if (Status != NDIS_STATUS_SUCCESS)
	{
		NdisTerminateWrapper(NdisWrapperHandle, NULL);
	}

	g_pIPHeader=&g_IPHeader;
	g_pTCPHeader=&g_TCPHeader;
	g_pUDPHeader=&g_UDPHeader;
	g_pICMPHeader=&g_ICMPHeader;
	g_pLog = &g_Log;

	return(Status);
}

//-------------------------------------------------------------add by xiaoqiang
static NTSTATUS MydrvDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP pIrp) 
{ 
	NTSTATUS status; 
	PIO_STACK_LOCATION irpSp; 

//	UNREFERENCED_PARAMETER(DeviceObject); 
	irpSp = IoGetCurrentIrpStackLocation(pIrp); 

	switch (irpSp->MajorFunction) 
	{ 
		case IRP_MJ_CREATE: 
			pIrp->IoStatus.Status = STATUS_SUCCESS; 
			pIrp->IoStatus.Information = 0L; 
			break; 

		case IRP_MJ_CLOSE: 
			pIrp->IoStatus.Status = STATUS_SUCCESS; 
			pIrp->IoStatus.Information = 0L; 
			MmUnmapLockedPages(UserVirtualAddress, Mdl);
			break; 
	} 

	IoCompleteRequest(pIrp, IO_NO_INCREMENT); 
	return STATUS_SUCCESS; 

} 

关于规则定义如下,总体分为全局,TCP,UDP规则,其次每个里面又分为In或者out 


/**************************************************************
				     规则结构
***************************************************************/
//#include "DDKLBLInc.h"

#pragma pack(1)

struct	Fw_Global {
	char			fw_status;			    //防火墙状态
	char			log_disable;				//是否允许记日志
	char			fw_mode;				//除了禁止的都允许、除了允许的都禁止
};

struct	Fw_Rule_Node  {
	u_long			id;				//Rule的号码
	u_char			protocol;       //协议类型  
	u_long			s_ip;			//原IP
	u_long			s_mask;		//掩码
	u_short			s_port;			//原端口
	u_long			d_ip;			//目的IP
	u_long			d_mask;		//掩码
	u_short	d_port;			//目的端口
	u_char			direct;			//方向
	u_char 			action;        //是否拦截
	char		    sMemo[100];//备注	
	struct	Fw_Rule_Node	*next;			//指向下个节点的指针
};

struct	Fw_Rule {
	u_char					disable;			//是否允许协议
	struct	Fw_Rule_Node	*pin, *pout;	//指向下个in, out节点的指针
};


//总体结构:
struct	 	Fw_Rules {
	struct		Fw_Global	global; 
	struct		Fw_Rule		tcp;
	struct		Fw_Rule		udp;
	struct		Fw_Rule		icmp;
	struct		Fw_Rule		ip;
};

#pragma pack()

发包部分代码

 然后看一下send方面的监控,MPSendPackets

VOID
MPSendPackets(
	IN	NDIS_HANDLE				MiniportAdapterContext,
	IN	PPNDIS_PACKET			PacketArray,//存放包的数组
	IN	UINT					NumberOfPackets//包的数量
	)
/*++

Routine Description:

	Send Packet Array handler. Either this or our SendPacket handler is called
	based on which one is enabled in our Miniport Characteristics.

Arguments:

	MiniportAdapterContext	Pointer to our adapter
	PacketArray				Set of packets to send
	NumberOfPackets			Self-explanatory

Return Value:

	None

--*/
{
	PADAPT				pAdapt = (PADAPT)MiniportAdapterContext;
	NDIS_STATUS			Status;
	UINT				i;
	PVOID				MediaSpecificInfo = NULL;
	UINT				MediaSpecificInfoSize = 0;

    //add by xiaoqiang
	UINT   OffsetSize;
	PUCHAR pPacketContent;
	UCHAR  nMatch = ALLOW;

	DbgPrint("==>MPSendPackets(...)\n");

	for (i = 0; i < NumberOfPackets; i++)
	{
		PNDIS_PACKET	Packet, MyPacket;

		Packet = PacketArray[i];

//---------------------------------------------------------add by xiaoqiang Mar 12 2006

		DbgPrint("==>自定义区域\n");
	    if(Packet!=NULL)
		{

					// 分配内存
			DbgPrint(("Packet!=NULL"));
			Status = NdisAllocateMemoryWithTag((PVOID *)&pPacketContent, BUFFER_SIZE, 'maDN');
			if(Status != NDIS_STATUS_SUCCESS) 
			{ 
				DbgPrint("MPSendPackets:NdisAllocateMemory Failed\n"); 
				nMatch=DENY; 
			} 
			if(pPacketContent == NULL) 
			{ 
				DbgPrint("MPSendPackets:pPacketContent==NULL\n"); 
				nMatch=DENY; 
			} 
			NdisZeroMemory(pPacketContent, BUFFER_SIZE);
	
			CopyPacket2Buffer(Packet,pPacketContent,&OffsetSize);	//数据拷贝函数
		    if(OffsetSize!=0)
			{
					nMatch=UTIL_MatchRule(pPacketContent, DT_OUT);
			}
		
			DBGPRINT(("In MPSentPacket And Free Memory\n")); 
			NdisFreeMemory(pPacketContent, BUFFER_SIZE, 0); 
		}
		else
		{ 
			DbgPrint(("Packet=NULL 无法截获数据包"));
		}

		if(nMatch==DENY)
		{
			// 释放资源并返回
			NdisFreePacket(Packet);
			return;
		}
		DbgPrint("<==自定义区域\n");    
//---------------------------------------------------------add end


#ifdef NDIS51

		//
		// Use NDIS 5.1 packet stacking:
		//
		{
			PNDIS_PACKET_STACK		pStack;
			BOOLEAN					Remaining;

			//
			// Packet stacks: Check if we can use the same packet for sending down.
			//
			pStack = NdisIMGetCurrentPacketStack(Packet, &Remaining);
			if (Remaining)
			{
				//
				// We can reuse "Packet".
				//
				// NOTE: if we needed to keep per-packet information in packets
				// sent down, we can use pStack->IMReserved[].
				//


				ASSERT(pStack);

				NdisSend(&Status,
 						 pAdapt->BindingHandle,
 						 Packet);
		
				if (Status != NDIS_STATUS_PENDING)
				{
					NdisMSendComplete(ADAPT_MINIPORT_HANDLE(pAdapt),
  									  Packet,
  									  Status);
				}
				DbgPrint("NdisMSendComplete and Will be continue\n");
				continue;
			}
		}
#endif


		NdisAllocatePacket(&Status,
						   &MyPacket,
						   pAdapt->SendPacketPoolHandle);

		if (Status == NDIS_STATUS_SUCCESS)
		{
			PSEND_RSVD		SendRsvd;

			SendRsvd = (PSEND_RSVD)(MyPacket->ProtocolReserved);
			SendRsvd->OriginalPkt = Packet;

			MyPacket->Private.Flags = NdisGetPacketFlags(Packet);

			MyPacket->Private.Head = Packet->Private.Head;
			MyPacket->Private.Tail = Packet->Private.Tail;
#ifdef WIN9X
			//
			// Work around the fact that NDIS does not initialize this
			// to FALSE on Win9x.
			//
			MyPacket->Private.ValidCounts = FALSE;
#endif // WIN9X

			//
			// Copy the OOB data from the original packet to the new
			// packet.
			//
			NdisMoveMemory(NDIS_OOB_DATA_FROM_PACKET(MyPacket),
						   NDIS_OOB_DATA_FROM_PACKET(Packet),
						   sizeof(NDIS_PACKET_OOB_DATA));
			//
			// Copy relevant parts of the per packet info into the new packet
			//
#ifndef WIN9X
			NdisIMCopySendPerPacketInfo(MyPacket, Packet);
#endif

			//
			// Copy the Media specific information
			//
			NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO(Packet,
												&MediaSpecificInfo,
												&MediaSpecificInfoSize);

			if (MediaSpecificInfo || MediaSpecificInfoSize)
			{
				NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO(MyPacket,
													MediaSpecificInfo,
													MediaSpecificInfoSize);
			}

			NdisSend(&Status,
					 pAdapt->BindingHandle,
					 MyPacket);

			if (Status != NDIS_STATUS_PENDING)
			{
#ifndef WIN9X
				NdisIMCopySendCompletePerPacketInfo (Packet, MyPacket);
#endif
				NdisFreePacket(MyPacket);
			}
		}

		if (Status != NDIS_STATUS_PENDING)
		{
			NdisMSendComplete(ADAPT_MINIPORT_HANDLE(pAdapt),
							  Packet,
							  Status);
		}
	}
	DbgPrint("<==MPSendPackets(...)\n");
}

中间用到的拷贝函数,从包中拷贝数据到缓冲区

//
// Purpose
// 从截获的包描述符里面取出数据到缓冲区
// add by xiaoqiang
void CopyPacket2Buffer(IN PNDIS_PACKET pPacket,IN OUT PUCHAR pBuff,IN OUT PUINT pLength) 
{ 
	PNDIS_BUFFER BuffDT;  //定义一个buffer指示符
	PUCHAR BuffVA;  //指向一个PNDIS_PACKET结构里面的Buffer的虚拟地址
	UINT BuffLen; //Buffer的长度

	*pLength=0;  //数据包内容的总长度,开始先置零 
	BuffLen=0;  

	NdisQueryPacket(pPacket,NULL,NULL,&BuffDT,NULL); //查询Packet的信息,这里查的是Packet的Buffer指示符链表的第一个Buffer
	while(BuffDT!=(PNDIS_BUFFER)NULL) 
	{ 
		NdisQueryBufferSafe(BuffDT,&BuffVA,&BuffLen,32);  //得到BuffDT指向的那个Buffer的虚拟地BuffVA和长度BuffLen 
		NdisMoveMemory(pBuff,BuffVA,BuffLen);   //将BuffVA其中的内容,移动到pBuff指向的那块区域
		pBuff=pBuff+BuffLen;   //pBuff指针后移,前BuffLen个字节已经填入数据
		*pLength+=BuffLen;    //计算pBuff中填入数据的总长度pLength
		NdisGetNextBuffer(BuffDT,&BuffDT);  //获得Buffer指示符链表中的下一个Buffer指示符
	} 
	return; 
} 

 UTIL_MatchRule解析包函数。

UCHAR UTIL_MatchRule(char *pPacketContent, char Direct)
{
	UCHAR		nProtocol;
	USHORT		nEtherType = 0, nIPhdrLen, nIPOffset;
	UCHAR		nAction;
	ULONG 		datetime=0;
	nAction = ALLOW;

	DBGPRINT(("==>UTIL_MatchRule(...)"));
	//如果防火墙状态为切断所有则返回
	if(g_Rules.global.fw_status==FWS_DENYALL) return DENY;
	if(g_Rules.global.fw_status==FWS_ALLOWALL) return ALLOW;

	// Copy the data.
     
	if(1)		
	{
		// Copy the data.
//		DBGPRINT(("判断是否以太网包"));
		NdisMoveMemory(			
			(PUCHAR)&nEtherType,
			(pPacketContent + MEtherType),//MEtherType=12
			sizeof(USHORT)
			);
	    
		nEtherType = UTIL_htons( nEtherType );	//将包类型转换为网络顺序
		if( nEtherType == ETHERTYPE_IP )		//if 包类型是IP包
		{
			//read ip header
			nAction = ALLOW;
			NdisMoveMemory(				
				(PUCHAR )g_pIPHeader,
				pPacketContent + MHdrSize,//MHdrSize=14
				sizeof(*g_pIPHeader)
				);	

			nIPOffset=UTIL_ntohs(g_pIPHeader->ip_off);
			#pragma warning(disable:4554)
			if((nIPOffset&IP_DF==0)&&(nIPOffset&0x1FFF!=0))	//分片非第一片允许通过
				return ALLOW;

			nIPhdrLen=g_pIPHeader->ip_hl*4;//计算IP头长度
			nProtocol=g_pIPHeader->ip_p;

			switch(nProtocol)
			{
				case IPPROTO_TCP:
					NdisMoveMemory(
						(PUCHAR)g_pTCPHeader,
						//包首指针+帧头长度+IP头长度,就是TCP头指针
						pPacketContent + MHdrSize + nIPhdrLen,
						sizeof(*g_pTCPHeader)
						);
					DBGPRINT(("数据包类型:TCP包,方向:%d",Direct));
					nAction=UTIL_MatchTcpRule(g_pIPHeader, g_pTCPHeader, Direct);
					return nAction;
					break;

				case IPPROTO_UDP:
					NdisMoveMemory(						
						(PUCHAR)g_pUDPHeader,
						pPacketContent + MHdrSize + nIPhdrLen,
						sizeof(*g_pUDPHeader)
						);
					DBGPRINT(("数据包类型:UDP包"));
					nAction=UTIL_MatchUdpRule(g_pIPHeader, g_pUDPHeader, Direct);
					return nAction;
					break;

				case IPPROTO_ICMP:
					NdisMoveMemory(						
						(PUCHAR)g_pICMPHeader,
						pPacketContent + MHdrSize + nIPhdrLen,
						sizeof(*g_pICMPHeader)
						);
					DBGPRINT(("数据包类型:ICMP包"));
					nAction=UTIL_MatchIcmpRule(g_pIPHeader, g_pICMPHeader, Direct);
					return nAction;
					break;
			}
		}
		DBGPRINT(("<==UTIL_MatchRule(...)"));
		if(g_Rules.global.fw_mode==RM_DENY)
			return DENY;
		else 
			return ALLOW;
	}
}

 然后匹配TCL函数如下

UCHAR	UTIL_MatchTcpRule(struct ip *pIpHeader, struct tcphdr *pTcpHeader, char Direct)
{
	UCHAR		nAction=NOT_MATCH;
	USHORT		nSrcPort, nDstPort;
	ULONG		nSrcIP, nDstIP;
	struct Fw_Rule	*pTcpRule=NULL;
	struct Fw_Rule_Node	*ptr=NULL;
	
	pTcpRule=&g_Rules.tcp;
	if(pTcpRule->disable) return DENY;	//不允许TCP协议通过 

	DBGPRINT(("==>UTIL_MatchTcpRule TCP包方向:%d",Direct));
	if(Direct==DT_OUT)
	{
		nSrcIP=UTIL_ntohl(pIpHeader->ip_src.s_addr);
		nDstIP=UTIL_ntohl(pIpHeader->ip_dst.s_addr);
		nSrcPort=UTIL_ntohs(pTcpHeader->th_sport);
		nDstPort=UTIL_ntohs(pTcpHeader->th_dport);
		ptr=pTcpRule->pout;
	}
	else
	{
		nSrcIP=UTIL_ntohl(pIpHeader->ip_src.s_addr);
		nDstIP=UTIL_ntohl(pIpHeader->ip_dst.s_addr);
		nSrcPort=UTIL_ntohs(pTcpHeader->th_sport);
		nDstPort=UTIL_ntohs(pTcpHeader->th_dport);
		ptr=pTcpRule->pin;
	}
/*
	DBGPRINT(("Rule direct:%d",ptr->direct));
	DBGPRINT(("Packet Server IP:%d",nSrcIP & ptr->s_mask));
	DBGPRINT(("Rule Server IP:%d",ptr->s_ip));
	DBGPRINT(("Packet Client IP:%d",nDstIP & ptr->d_mask));
	DBGPRINT(("Rule Client IP:%d",ptr->d_ip));
	DBGPRINT(("Packet Server Port:%d",nSrcPort));
	DBGPRINT(("Rule Server Port:%d",ptr->s_port));
	DBGPRINT(("Packet Client Port:%d",nDstPort));
	DBGPRINT(("Rule Client Port:%d",ptr->d_port));
*/
	for(; ptr!=NULL; ptr=ptr->next)
	{
		if(((nSrcPort==ptr->s_port)||(ptr->s_port==0)) && 
			((nDstPort==ptr->d_port)||(ptr->d_port==0)) &&
			((ptr->s_ip==(nSrcIP & ptr->s_mask))||(ptr->s_ip==0))&&
			((ptr->d_ip==(nDstIP & ptr->d_mask))||(ptr->d_ip==0))&&
			(Direct==ptr->direct))
		{
				nAction=ptr->action;
				break;
		}
	}

	UTIL_CountPacket(PT_TCP, Direct, nAction, (int)UTIL_ntohs(pIpHeader->ip_len));
	if (nAction!=NOT_MATCH)
		{
		if (!g_Rules.global.log_disable)
			UTIL_TcpWriteLog(ptr, pIpHeader,pTcpHeader,Direct);
		}
	return nAction;
}

 收包部分代码

收包就是不同函数处理不同协议的情况了,

NDIS_STATUS
PtReceive(
	IN  NDIS_HANDLE			ProtocolBindingContext,
	IN  NDIS_HANDLE			MacReceiveContext,
	IN  PVOID				HeaderBuffer,
	IN  UINT				HeaderBufferSize,
	IN  PVOID				LookAheadBuffer,
	IN  UINT				LookAheadBufferSize,
	IN  UINT				PacketSize
	)
/*++

Routine Description:

	Handle receive data indicated up by the miniport below. We pass
	it along to the protocol above us.

	If the miniport below indicates packets, NDIS would more
	likely call us at our ReceivePacket handler. However we
	might be called here in certain situations even though
	the miniport below has indicated a receive packet, e.g.
	if the miniport had set packet status to NDIS_STATUS_RESOURCES.
		
Arguments:

	<see DDK ref page for ProtocolReceive>

Return Value:

	NDIS_STATUS_SUCCESS if we processed the receive successfully,
	NDIS_STATUS_XXX error code if we discarded it.

--*/
{
	PADAPT			pAdapt =(PADAPT)ProtocolBindingContext;
	PNDIS_PACKET	MyPacket, Packet, MyPacket1;
	NDIS_STATUS		Status = NDIS_STATUS_SUCCESS;
//-----------------------------add by xiaoqiang
	PNDIS_BUFFER pPacketBuffer, pBakBuffer; 
	PUCHAR pPacketContent, pBakContent; 
	UINT PacketLen; 
	UCHAR  nMatch = ALLOW;

	UINT OffsetSize; 
	UINT BytesTransferred; 

	PRECV_RSVD RecvRsvd = NULL; 
	PVOID MediaSpecificInfo = NULL; 
	ULONG MediaSpecificSize= 0; 

	DBGPRINT(("==>PtReceive(...)\n")); 

	if (!pAdapt->MiniportHandle)
	{
		Status = NDIS_STATUS_FAILURE;
	}
	else do
	{
//* ---------------注释掉,不采用这种方法取得数据包。--------------------------
		//
		// Get at the packet, if any, indicated up by the miniport below.
		//
		Packet = NdisGetReceivedPacket(pAdapt->BindingHandle, MacReceiveContext);
		if (Packet != NULL)
		{
			DBGPRINT(("NdisGetReceivedPacket != NULL\n"));
		    //
		    // The miniport below did indicate up a packet. Use information
		    // from that packet to construct a new packet to indicate up.
		    //

#ifdef NDIS51
			//
			// NDIS 5.1 NOTE: Do not reuse the original packet in indicating
			// up a receive, even if there is sufficient packet stack space.
			// If we had to do so, we would have had to overwrite the
			// status field in the original packet to NDIS_STATUS_RESOURCES,
			// and it is not allowed for protocols to overwrite this field
			// in received packets.
			//
#endif // NDIS51

			//
			// Get a packet off the pool and indicate that up
			//
			NdisDprAllocatePacket(&Status,
			   						  &MyPacket,
			   						  pAdapt->RecvPacketPoolHandle);

			if (Status == NDIS_STATUS_SUCCESS)
			{
				//
				// Make our packet point to data from the original
				// packet. NOTE: this works only because we are
				// indicating a receive directly from the context of
				// our receive indication. If we need to queue this
				// packet and indicate it from another thread context,
				// we will also have to allocate a new buffer and copy
				// over the packet contents, OOB data and per-packet
				// information. This is because the packet data
				// is available only for the duration of this
				// receive indication call.
				//
				MyPacket->Private.Head = Packet->Private.Head;
				MyPacket->Private.Tail = Packet->Private.Tail;

				//
				// Get the original packet (it could be the same packet as the
				// one received or a different one based on the number of layered
				// miniports below) and set it on the indicated packet so the OOB
				// data is visible correctly at protocols above.
				//
				NDIS_SET_ORIGINAL_PACKET(MyPacket, NDIS_GET_ORIGINAL_PACKET(Packet));
				NDIS_SET_PACKET_HEADER_SIZE(MyPacket, HeaderBufferSize);

				//
				// Copy packet flags.
				//
				NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet);

				//
				// Force protocols above to make a copy if they want to hang
				// on to data in this packet. This is because we are in our
				// Receive handler (not ReceivePacket) and we can't return a
				// ref count from here.
				//
				NDIS_SET_PACKET_STATUS(MyPacket, NDIS_STATUS_RESOURCES);

				//
				// By setting NDIS_STATUS_RESOURCES, we also know that we can reclaim
				// this packet as soon as the call to NdisMIndicateReceivePacket
				// returns.
				//

				NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &MyPacket, 1);

				//
				// Reclaim the indicated packet. Since we had set its status
				// to NDIS_STATUS_RESOURCES, we are guaranteed that protocols
				// above are done with it.
				//
				NdisDprFreePacket(MyPacket);

				break;
			}
		}
		else
		{
			//
			// The miniport below us uses the old-style (not packet)
			// receive indication. Fall through.
			//
		}

		//
		// Fall through if the miniport below us has either not
		// indicated a packet or we could not allocate one
		//
//-----------------------------------------------------------------------*/
		//-------------------------------------------add by xiaoqiang Mar 16 2006
		if(FALSE){}
		else if(PacketSize <= LookAheadBufferSize)  // 如果 LookAheadBuffer 中包含了全部数据
		{ 
			// 分配内存
		    Status = NdisAllocateMemoryWithTag((PVOID *)&pPacketContent, BUFFER_SIZE, 'maDN'); 
			if(Status != NDIS_STATUS_SUCCESS) 
			{ 
				DbgPrint("PTReceive:NdisAllocateMemory Failed\n"); 
				return(NDIS_STATUS_NOT_ACCEPTED); 
			} 
			if(pPacketContent == NULL) 
			{ 
				DbgPrint("PTReceive:pPacketContent==NULL\n"); 
				return(NDIS_STATUS_NOT_ACCEPTED); 
			} 
			// 将包头和 LookAheadBuffer 复制到新分配的内存中
			NdisZeroMemory(pPacketContent, BUFFER_SIZE); 
			NdisMoveMemory(pPacketContent, HeaderBuffer, HeaderBufferSize); 
			NdisMoveMemory(pPacketContent+ HeaderBufferSize, LookAheadBuffer, LookAheadBufferSize); 
			PacketLen = PacketSize+HeaderBufferSize; 


				nMatch=UTIL_MatchRule(pPacketContent, DT_IN);
				if(nMatch==DENY)
				{
					return NDIS_STATUS_NOT_ACCEPTED;
				}



			// 在包池中分配包描述符
			NdisDprAllocatePacket(&Status, &MyPacket, pAdapt->RecvPacketPoolHandle); 

			if(Status == NDIS_STATUS_SUCCESS) 
			{ 
				// 在缓冲池中分配缓冲描述符,将包描述符与缓冲描述符关联。
				NdisAllocateBuffer(&Status, &pPacketBuffer, pAdapt->RecvBufferPoolHandle, pPacketContent, PacketLen); 
				NdisChainBufferAtFront(MyPacket, pPacketBuffer); 

				MyPacket->Private.Head->Next = NULL; 
				MyPacket->Private.Tail = NULL; 
				RecvRsvd=(PRECV_RSVD)(MyPacket->MiniportReserved); 
				RecvRsvd->OriginalPkt = NULL; 
				NDIS_SET_PACKET_HEADER_SIZE(MyPacket, HeaderBufferSize); 

				// 向上层协议驱动指示数据包,防真网卡行为。
				NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &MyPacket, 1); 
				if(NDIS_GET_PACKET_STATUS(MyPacket) != NDIS_STATUS_PENDING) 
				{ 
					DBGPRINT(("In PtReceive And Free Memory\n")); 
					NdisFreeBuffer(pPacketBuffer); 
					NdisFreeMemory(pPacketContent, BUFFER_SIZE, 0); 
					NdisDprFreePacket(MyPacket); 
				} 
			} 
			break; 
		} 
		else // 如果 LookAheadBuffer 中没有包含全部数据
		{ 
			// 分配内存 pPacketContent,存放要传输的除 LookAheadBuffer 之外的数据。
			Status = NdisAllocateMemoryWithTag((PVOID *)&pPacketContent, BUFFER_SIZE, 'maDN'); 
			if(Status != NDIS_STATUS_SUCCESS) 
			{ 
				DbgPrint("PtReceive:NdisAllocateMemory Failed.\n"); 
				return(NDIS_STATUS_NOT_ACCEPTED); 
			} 
			if(pPacketContent==NULL) 
			{ 
				DbgPrint("PTReceive:pPacketContent==NULL\n"); 
				return(NDIS_STATUS_NOT_ACCEPTED); 
			} 
			NdisZeroMemory(pPacketContent,BUFFER_SIZE); 
			// 分配包描述符 MyPacket。
			NdisDprAllocatePacket(&Status, &MyPacket, pAdapt->RecvPacketPoolHandle); 
			// 分配内存 pBakContent,存放HeaderBuffer + LookAheadBuffer。
			Status = NdisAllocateMemoryWithTag((PVOID *)&pBakContent, BUFFER_SIZE, 'maDN');
			if(Status != NDIS_STATUS_SUCCESS) 
			{ 
				DbgPrint("PtReceive:NdisAllocateMemory Failed.\n"); 
				return(NDIS_STATUS_NOT_ACCEPTED); 
			} 
			if(pBakContent == NULL) 
			{ 
				DbgPrint("PTReceive:pPacketContent==NULL\n"); 
				return(NDIS_STATUS_NOT_ACCEPTED); 
			} 
			// 将 HeaderBuffer + LookAheadBuffer 复制到 pBakContent 指向的内存中。
			NdisZeroMemory(pBakContent, BUFFER_SIZE); 
			NdisMoveMemory(pBakContent, HeaderBuffer, HeaderBufferSize); 
			NdisMoveMemory(pBakContent+HeaderBufferSize, LookAheadBuffer, LookAheadBufferSize); 		

			PacketLen = HeaderBufferSize + PacketSize; 
			
			// 为要传输的除 LookAheadBuffer 之外的数据分配缓冲描述符(该缓冲描述符与 pPacketContent 指向的内存关联)。
			NdisAllocateBuffer(&Status, &pPacketBuffer, pAdapt->RecvBufferPoolHandle, pPacketContent, PacketSize-LookAheadBufferSize); 
			// 关联包描述符 MyPacket 与缓冲描述符 pPacketBuffer。
			NdisChainBufferAtFront(MyPacket, pPacketBuffer); 
			MyPacket->Private.Head->Next=NULL; 
			MyPacket->Private.Tail=NULL; 

			OffsetSize = HeaderBufferSize + LookAheadBufferSize; 
			
			// 分配包描述符 MyPacket1。
			NdisDprAllocatePacket(&Status, &MyPacket1, pAdapt->RecvPacketPoolHandle); 
			// 分配缓冲描述符 pBakBuffer,与 pBakContent 指向的内存关联。
			NdisAllocateBuffer(&Status, &pBakBuffer, pAdapt->RecvBufferPoolHandle, pBakContent, OffsetSize); 
			// 关联包描述符 MyPacket1 与缓冲描述符 pBakBuffer。
			NdisChainBufferAtFront(MyPacket1, pBakBuffer); 

			RecvRsvd = (PRECV_RSVD)(MyPacket->MiniportReserved);     
			RecvRsvd->OriginalPkt = (PNDIS_PACKET)MyPacket1; 

			NDIS_SET_PACKET_HEADER_SIZE(MyPacket, HeaderBufferSize);   //为随后的接收指示设置一个与给定包描述符相连的OOB数据块中的HeaderSize值 
			
			// 取得 LookAheadBuffer 之后的数据
			NdisTransferData(&Status, 
							pAdapt->BindingHandle,
							MacReceiveContext,
							LookAheadBufferSize,			// 数据起始地址
							PacketSize-LookAheadBufferSize,	// 字节数
							MyPacket,
							&BytesTransferred); 

			if(Status != NDIS_STATUS_PENDING) 
			{ 
				PtTransferDataComplete((NDIS_HANDLE)pAdapt, MyPacket, Status, BytesTransferred); 
			} 
			break; 
		} 
		//-----------------------------------------------------------end add

		pAdapt->IndicateRcvComplete = TRUE;
		switch (pAdapt->Medium)
		{
		  case NdisMedium802_3:
		  case NdisMediumWan:
			 NdisMEthIndicateReceive(pAdapt->MiniportHandle,
											 MacReceiveContext,
											 HeaderBuffer,
											 HeaderBufferSize,
											 LookAheadBuffer,
											 LookAheadBufferSize,
											 PacketSize);
			 break;

		  case NdisMedium802_5:
			 NdisMTrIndicateReceive(pAdapt->MiniportHandle,
											MacReceiveContext,
											HeaderBuffer,
											HeaderBufferSize,
											LookAheadBuffer,
											LookAheadBufferSize,
											PacketSize);
			 break;

		  case NdisMediumFddi:
// 			 NdisMFddiIndicateReceive(pAdapt->MiniportHandle,
// 											  MacReceiveContext,
// 											  HeaderBuffer,
// 											  HeaderBufferSize,
// 											  LookAheadBuffer,
// 											  LookAheadBufferSize,
// 											  PacketSize);
			 break;

		  default:
			 ASSERT(FALSE);
			 break;
		}

	} while(FALSE);
	DBGPRINT(("<==PtReceive(...)\n")); 
	return Status;
}


VOID
PtReceiveComplete(
	IN	NDIS_HANDLE		ProtocolBindingContext
	)
/*++

Routine Description:

	Called by the adapter below us when it is done indicating a batch of
	received packets.

Arguments:

	ProtocolBindingContext	Pointer to our adapter structure.

Return Value:

	None

--*/
{
	PADAPT		pAdapt =(PADAPT)ProtocolBindingContext;
	DBGPRINT(("==>PtReceiveComplete(...)\n"));

	if ((pAdapt->MiniportHandle != NULL) && pAdapt->IndicateRcvComplete)
	{
		switch (pAdapt->Medium)
		{
		  case NdisMedium802_3:
		  case NdisMediumWan:
			NdisMEthIndicateReceiveComplete(pAdapt->MiniportHandle);
			break;

		  case NdisMedium802_5:
			NdisMTrIndicateReceiveComplete(pAdapt->MiniportHandle);
			break;

		  case NdisMediumFddi:
			//NdisMFddiIndicateReceiveComplete(pAdapt->MiniportHandle);
			break;

		  default:
			ASSERT(FALSE);
			break;
		}
	}
	DBGPRINT(("<==PtReceiveComplete(...)\n"));

	pAdapt->IndicateRcvComplete = FALSE;
}


INT
PtReceivePacket(
	IN	NDIS_HANDLE			ProtocolBindingContext,
	IN	PNDIS_PACKET		Packet
	)
/*++

Routine Description:

	ReceivePacket handler. Called by NDIS if the miniport below supports
	NDIS 4.0 style receives. Re-package the buffer chain in a new packet
	and indicate the new packet to protocols above us. Any context for
	packets indicated up must be kept in the MiniportReserved field.

	NDIS 5.1 - packet stacking - if there is sufficient "stack space" in
	the packet passed to us, we can use the same packet in a receive
	indication.

Arguments:

	ProtocolBindingContext - Pointer to our adapter structure.
	Packet - Pointer to the packet

Return Value:

	== 0 -> We are done with the packet
	!= 0 -> We will keep the packet and call NdisReturnPackets() this
			many times when done.
--*/
{
	PADAPT				pAdapt =(PADAPT)ProtocolBindingContext;
	NDIS_STATUS			Status;
	PNDIS_PACKET		MyPacket;
	BOOLEAN				Remaining;

	    //add by xiaoqiang
	UINT   OffsetSize;
	PUCHAR pPacketContent;
	UCHAR  nMatch = ALLOW;

	DBGPRINT(("==>PtReceivePacket(...)\n"));

	//
	// Drop the packet silently if the upper miniport edge isn't initialized
	//
	if (!pAdapt->MiniportHandle)
	{
		  return 0;
	}


//-------------------------------------------------------------add by xiaoqiang Mar 12 2006
	DbgPrint("==>自定义区域\n");
    if(Packet!=NULL)
	{

				// 分配内存
		DbgPrint(("Packet!=NULL"));
		Status = NdisAllocateMemoryWithTag((PVOID *)&pPacketContent, BUFFER_SIZE, 'maDN');
		if(Status != NDIS_STATUS_SUCCESS) 
		{ 
			DbgPrint("PtReceivePacket:NdisAllocateMemory Failed\n"); 
			return(NDIS_STATUS_NOT_ACCEPTED); 
		} 
		if(pPacketContent == NULL) 
		{ 
			DbgPrint("PtReceivePacket:pPacketContent==NULL\n"); 
			return(NDIS_STATUS_NOT_ACCEPTED); 
		} 
		NdisZeroMemory(pPacketContent, BUFFER_SIZE);

		CopyPacket2Buffer(Packet,pPacketContent,&OffsetSize);	//数据拷贝函数
	    if(OffsetSize!=0)
		{
			nMatch=UTIL_MatchRule(pPacketContent, DT_IN);

		}
	
		DBGPRINT(("In PtReceivePacket And Free Memory\n")); 
		NdisFreeMemory(pPacketContent, BUFFER_SIZE, 0); 
	}
	else
	{ 
		DBGPRINT(("Packet=NULL"));
	}

	if(nMatch==DENY)
	{
		// 释放资源并返回
		NdisFreePacket(Packet);
		return NDIS_STATUS_NOT_ACCEPTED;
	}
	DbgPrint("<==自定义区域\n");    
//---------------------------------------------------------add end



#ifdef NDIS51
	//
	// Check if we can reuse the same packet for indicating up.
	// See also: PtReceive(). 
	//
	(VOID)NdisIMGetCurrentPacketStack(Packet, &Remaining);
	if (Remaining)
	{
		//
		// We can reuse "Packet". Indicate it up and be done with it.
		//
		Status = NDIS_GET_PACKET_STATUS(Packet);
		NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &Packet, 1);
		return((Status != NDIS_STATUS_RESOURCES) ? 1 : 0);
	}
#endif // NDIS51

	//
	// Get a packet off the pool and indicate that up
	//
	NdisDprAllocatePacket(&Status,
						   &MyPacket,
						   pAdapt->RecvPacketPoolHandle);

	if (Status == NDIS_STATUS_SUCCESS)
	{
		PRECV_RSVD			RecvRsvd;

		RecvRsvd = (PRECV_RSVD)(MyPacket->MiniportReserved);
		RecvRsvd->OriginalPkt = Packet;

		MyPacket->Private.Head = Packet->Private.Head;
		MyPacket->Private.Tail = Packet->Private.Tail;

		//
		// Get the original packet (it could be the same packet as the one
		// received or a different one based on the number of layered miniports
		// below) and set it on the indicated packet so the OOB data is visible
		// correctly to protocols above us.
		//
		NDIS_SET_ORIGINAL_PACKET(MyPacket, NDIS_GET_ORIGINAL_PACKET(Packet));

		//
		// Set Packet Flags
		//
		NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet);

		Status = NDIS_GET_PACKET_STATUS(Packet);

		NDIS_SET_PACKET_STATUS(MyPacket, Status);
		NDIS_SET_PACKET_HEADER_SIZE(MyPacket, NDIS_GET_PACKET_HEADER_SIZE(Packet));

		NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &MyPacket, 1);

		//
		// Check if we had indicated up the packet with NDIS_STATUS_RESOURCES
		// NOTE -- do not use NDIS_GET_PACKET_STATUS(MyPacket) for this since
		// it might have changed! Use the value saved in the local variable.
		//
		if (Status == NDIS_STATUS_RESOURCES)
		{
			//
			// Our ReturnPackets handler will not be called for this packet.
			// We should reclaim it right here.
			//
			NdisDprFreePacket(MyPacket);
		}
		DBGPRINT(("<==PtReceivePacket(...)\n"));

		return((Status != NDIS_STATUS_RESOURCES) ? 1 : 0);
	}
	else
	{
		//
		// We are out of packets. Silently drop it.
		//
		return(0);
	}
}

VOID
PtTransferDataComplete(
	IN  NDIS_HANDLE			ProtocolBindingContext,
	IN  PNDIS_PACKET		Packet,
	IN  NDIS_STATUS			Status,
	IN  UINT				BytesTransferred
	)
/*----------------------------------------------------------------------------------
在底层网卡驱动调用介质相关函数(NdisMXxxIndicateReceive)向上指示 数 据 包 时,如 果

LookAheadBuffer 中不包括全部数据,协议驱动会调用 NdisTransferData 来获得其余的数据,

如果 NdisTransferData 返回PENDING,则这个函数会在传输完成后自动被调用。

由于在 PtReceive 中没有采用介质相关函数(NdisMXxxIndicateReceive)向上指示数据包,而

是用 NdisMIndicateReceivePacket,所以上层协议(tcp/ip等)不会调用 NdisTransferData,

因此这个函数不会被自动调用。
----------------------------------------------------------------------------------*/
/*++

Routine Description:

	Entry point called by NDIS to indicate completion of a call by us
	to NdisTransferData.

	See notes under SendComplete.

Arguments:

Return Value:

--*/
{
	PADAPT pAdapt = (PADAPT)ProtocolBindingContext;  //得到ProtocolBind的信息
	PUCHAR pPacketContent;   //指向 从Packet取出数据存放内存空间 的虚拟地址
	PRECV_RSVD RecvRsvd;  //Rsvd是供包的制造者用的,一般用来在开始时放入一些有用的数据供做回收处理。
	             //Rsvd的结构也是可以自己定义的,只有你制造的包,你才可以访问里边的东西
	UINT OffsetSize, Result, PacketLen; //offsetSize=HeaderBufferSize + LookAheadBufferSize??,初始化定义大小是?????

	PNDIS_BUFFER pPacketBuffer; //看下面说明 the head of the chain of buffer descriptors for a given packet
	PNDIS_PACKET pBakPacket;   //下面有解析
	PNDIS_BUFFER pBakBuffer;   //

	PUCHAR pBakContent;   //pPacketBuffer的虚拟地址
	UINT BufferLen;   //pPacketBuffer里面数据长度
	UCHAR  nMatch = ALLOW;

	DbgPrint("==>PtTransferDataComplete(...)\n"); 

	// 
	// Returning the Send on the Primary, will point to itself if there is no LBFO 
	// 
//	pAdapt = pAdapt->pPrimaryAdapt;    //Pointer to the primary
	RecvRsvd = (PRECV_RSVD)(Packet->MiniportReserved); //Rsvd未保留区
	// pBakPacket 里是 HeaderBuffer + LookAheadBuffer 的内容。
	pBakPacket = (PNDIS_PACKET)(RecvRsvd->OriginalPkt); //Rsvd->OriginalPkt是PtReceive中保留的包描述符

	if(pAdapt->MiniportHandle) //是否有微端口绑定,没有话,那也就是不可能有数据上传了
	{ 
		if(pBakPacket == NULL)  //是否有数据
			NdisMTransferDataComplete(pAdapt->MiniportHandle, Packet, Status, BytesTransferred); 
		else 
		{ 
			Status = NdisAllocateMemoryWithTag((PVOID *)&pPacketContent, BUFFER_SIZE, 'maDN'); //分配内存.xp不能用NdisAllocateMemory
			CopyPacket2Buffer(pBakPacket, pPacketContent, &OffsetSize); 
			CopyPacket2Buffer(Packet, pPacketContent+OffsetSize, &PacketLen); 

//			if(Monitor_flag)
//			{
				nMatch=UTIL_MatchRule(pPacketContent, DT_IN);
//			}
//			else {}

			PacketLen += OffsetSize; 
			// 释放包描述符pBakPacket、缓冲描述符pBakBuffer、内存pBakContent。
			NdisUnchainBufferAtFront(pBakPacket, &pBakBuffer); 
			NdisQueryBufferSafe(pBakBuffer, &pBakContent, &BufferLen, 32); 
			NdisFreeBuffer(pBakBuffer); 
			NdisFreeMemory(pBakContent, BUFFER_SIZE, 0); 
			NdisFreePacket(pBakPacket); 

			//reserved为保留区,有两块,一个是ProtocolReserved,一个是MiniportReserved。顾名思意,一个是为协议层保留的,一个是为MINIPORT保留的。
			memset(Packet->MiniportReserved, 0, sizeof(Packet->MiniportReserved)); 

			//removes the buffer descriptor at the head of the chain of buffer descriptors for a given packet. 
			//so pPacketBuffer 应该是 the head of the chain of buffer descriptors for a given packet
			NdisUnchainBufferAtFront(Packet, &pPacketBuffer);   

			NdisQueryBufferSafe(pPacketBuffer, &pBakContent, &BufferLen, 32);  //32是Priority,看DDK说明
			NdisFreeBuffer(pPacketBuffer); 
			NdisFreeMemory(pBakContent, BUFFER_SIZE, 0); 

			if(nMatch==DENY)
			{
				// 释放资源并返回
				NdisFreePacket(Packet);
				return;
			}

			//请求分配Buffer指示符 
			NdisAllocateBuffer(&Status, &pPacketBuffer, pAdapt->RecvBufferPoolHandle, pPacketContent, PacketLen); 
			NdisChainBufferAtFront(Packet, pPacketBuffer);  //将它挂到Packet的Buffer指示符链表的最前端
			//因为我们只一次性就分配一个足够大的MEMORY,然后分配一个BUFFER链到PACKET上,所以为空
			Packet->Private.Head->Next=NULL; 
			Packet->Private.Tail=NULL; 
			NDIS_SET_PACKET_HEADER_SIZE(Packet,14);  设置包头14个字节 
			
			// 向上层协议驱动指示数据包,防真网卡行为。
			NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &Packet, 1); 

			if(NDIS_GET_PACKET_STATUS(Packet)!=NDIS_STATUS_PENDING) 
			{ 
				MPReturnPacket((NDIS_HANDLE)pAdapt, Packet); 
			} 
		} 
	} 
	DbgPrint("<==PtTransferDataComplete(...)\n");
	return; 
}

总结

就是在小端口拦截发包拿到发包,协议端拿到收包,解析包,读数据到缓存中,用TCPIP头解析数据。根据IP和端口匹配规则。

NDIS是个WDM驱动,需要创建添加设备对象(AddDevice)。

流程如下

加载

插入网卡

PNP Manger(找到中间层驱动),调用AddDevice()

PtBindAdapter

分配收发包池

-NdisOpenAdapter()

-NdisIMInitializeDeviceInstanceEx()

MpInitialize()

-NdisMSetAttributesEx设置上下文

NdisSend->MpSend/MpSendPackets

NdisXXXReceive等函数

NDIS怎么过滤的呢,没有IRP,没有创建过滤设备对象,如何实现过滤监控上层发下来的数据包的呢?

通过分层的函数调用关系实现,通过NdisSend-》MpSend-》NdisSend-》MpSend-》NdisSend-》MiniportSend,MpSend是自己注册地,用来过滤了信息。

receive也是类似。下层调用回调,上层就会被触发。实现分层过滤。

NDIS绑定

绑定实现:调用协议驱动中断PtBindAdapter,绑定,并获得Bindinghandle,以后都在这个handle发数据,具体说上层的协议驱动绑定到中间层的虚拟adapter上,中间层驱动绑定到下层小端口驱动上,每次绑定获得一个绑定句柄。

PNP管理器发现系统中可用的NIC设备-》找到注册过的中间层驱动-》调用中间层

AddDevice-》PtBingdAdapter-》NdisOpenAdapter-》NdisIMInitalizeDeviceInstanceEx-》MpInitialize-》注册适配器上下文NdisMSetAttributerEx

 

 

 

 

 

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
  对于在“蓝网之家”影响下蠢蠢而动搞 Windows 95 远程启动的朋友可能不少,那么大家一定对 NDIS 这几个字母不会感到陌生。其实不只是在远程启动这一层,只要是网卡的驱动盘,大家都会在里面发现有类似 NDIS、NDIS2、NDIS3、NDIS4一样的目录,只是大家在 Windows 9x 或 NT 中安装、设置网卡时没有注意到它罢了。但即使大搞特搞 RPL 的朋友对其大概也是只知其然而不其所以然。    NDIS 是什么?有什么作用?       NDIS 的全称是 Network Device Interface Specification,中文意思就是网络设备接口规范。    根据 OSI 七层模型,物理层定义了对网卡、线缆以及其它物理硬件设备进行配置的标准。节点间建立通信时是由物理层在传输介质上传送二进制信息实现的,因此,在发送端和接收端都还必须有一个程序来格式化这种信息流并将其传送给上一层。NDIS 的作用就是避免在访问网卡每次进行传输时都编写相应的代码。由此说来,NDIS 本质上是一种软件接口,有了 NDIS ,所有的传输就可以采用一种通用的方式来访问由不同厂商制造的网卡了,即它是用来连接协议堆栈和网卡的。   与此相关的软件还有重定向器(Redirector)和服务器(Server)。前者的目的是截获来自 OSI 会话层的网络调用,并通过将其传送到相应的协议驱动程序接口而格式化成 NDIS 能够识别和使用的命令。后者则负责接收从重向器传过来的来自于远程计算机的请求,再将这一请求传送给相应的本地文件系统驱动程序,最后再由该“服务器”将数据沿协议堆栈向下传递给客户机。    TCP协议也是通过调用 NDIS 接口服务来完成传输操作的。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值