📄 netbiostransport.cpp
字号:
{
DWORD dwRet = -1;
HRESULT hr = E_FAIL;
BYTE *pCName;
UINT uiCNameLen;
ncb ncbRequest;
BYTE ncb_err;
PREFAST_ASSERT(_pAdapter);
RecvNode *pNode = (RecvNode *)_pAdapter;
NetBIOSAdapter *pAdapter = pNode->pAdapter;
SMB_PACKET *pNewPacket = NULL;
ref_ncb *pSendNCB = NULL;
ref_ncb *pMainNCB = NULL;
CCritSection csLock(&csActiveRecvListLock);
ASSERT(pAdapter);
TRACEMSG(ZONE_ERROR, (L"SMBSRV-NBRECV:RecvThread listening on LANA: %d LSN:%d", pNode->LANA, pNode->usLSN));
//check to be sure we are in the correct state -- get any persistent data before
// going into main processing loop
if(pAdapter->DuringShutDown()) {
TRACEMSG(ZONE_ERROR, (TEXT("SMBSRV-NBRECV:RecvThread thread not starting -- error before launch")));
hr = E_ABORT;
goto Done;
}
if(NULL == pAdapter) {
TRACEMSG(ZONE_ERROR, (TEXT("SMBSRV-NBRECV:RecvThread thread could not get global adapter object")));
hr = E_UNEXPECTED;
goto Done;
}
if(FAILED(hr = SMB_Globals::GetCName(&pCName, &uiCNameLen)) ||
NULL == pCName ||
0 == uiCNameLen ||
uiCNameLen > 15) {
TRACEMSG(ZONE_ERROR, (TEXT("SMBSRV-NBRECV:Invalid CName returned from globals!")));
if(SUCCEEDED(hr)) //preserve any failure hr
hr = E_FAIL;
goto Done;
}
if(NULL == (pMainNCB = new ref_ncb())) {
hr = E_OUTOFMEMORY;
goto Done;
}
while(!pAdapter->DuringShutDown())
{
ASSERT(NULL == pSendNCB);
ncbRequest.ncb_command = NCBRECV;
ncbRequest.ncb_lana_num = pNode->LANA;
ncbRequest.ncb_lsn = pNode->usLSN;;
memset(ncbRequest.ncb_name, ' ', 16);
memcpy(ncbRequest.ncb_name, pCName, uiCNameLen);
//
// Get some memory out of our free pool
if(NULL == (pNewPacket = SMB_Globals::g_SMB_Pool.Alloc())) {
hr = E_OUTOFMEMORY;
goto Done;
}
pNewPacket->pInSMB = (SMB_HEADER *)pNewPacket->InSMB;
ncbRequest.ncb_buffer = pNewPacket->InSMB;
ncbRequest.ncb_length = SMB_Globals::MAX_PACKET_SIZE;
(pNewPacket->InSMB)[0] = 0;
(pNewPacket->InSMB)[1] = 0;
(pNewPacket->InSMB)[2] = 0;
(pNewPacket->InSMB)[3] = 0;
//read a packet
if(0 == (ncb_err = Netbios(&ncbRequest)) && FALSE == pAdapter->DuringShutDown() &&
(pNewPacket->InSMB)[0] == 0xFF &&
(pNewPacket->InSMB)[1] == 'S' &&
(pNewPacket->InSMB)[2] == 'M' &&
(pNewPacket->InSMB)[3] == 'B') {
TRACEMSG(ZONE_NETBIOS, (L"SMBSRV-NBRECV: got packet on LSN: %d LANA: %d", ncbRequest.ncb_lsn, ncbRequest.ncb_lana_num));
IFDBG(pNewPacket->PerfStartTimer());
pSendNCB = pMainNCB;
pSendNCB->AddRef();
memcpy((void*)&pSendNCB->m_ncb, (void *)&ncbRequest, sizeof(ncb));
pNewPacket->pToken = (void *)pSendNCB;
pNewPacket->uiInSize = ncbRequest.ncb_length;
pNewPacket->pOutSMB = NULL;
pNewPacket->uiOutSize = 0;
pNewPacket->pfnQueueFunction = QueueNBPacketForSend;
pNewPacket->pfnCopyTranportToken = CopyNBTransportToken;
pNewPacket->pfnDeleteTransportToken = DeleteNBTransportToken;
//pNewPacket->pfnGetSocketName = NB_GetSocketName;
pNewPacket->uiPacketType = SMB_NORMAL_PACKET;
pNewPacket->ulConnectionID = (ULONG)(SMB_Globals::NB_TRANSPORT << 16) | ncbRequest.ncb_lsn;
pNewPacket->dwDelayBeforeSending = 0;
#ifdef DEBUG
pNewPacket->uiPacketNumber = InterlockedIncrement(&SMB_Globals::g_PacketID);
#endif
//
// If this connection isnt on our outstanding list put it there
csLock.Lock();
ce::list<ULONG>::iterator it = pNode->OutStandingConnectionIDs.begin();
BOOL fOnList = FALSE;
while(it != pNode->OutStandingConnectionIDs.end()) {
if(pNewPacket->ulConnectionID == (*it)) {
fOnList = TRUE;
break;
}
it ++;
}
if(FALSE == fOnList) {
if(!pNode->OutStandingConnectionIDs.push_front(pNewPacket->ulConnectionID)) {
hr = E_OUTOFMEMORY;
goto Done;
}
}
csLock.UnLock();
//
// Hand off the packet to the SMB cracker
IFDBG(pNewPacket->PerfPrintStatus(L"NB, got all of packet"));
if(FAILED(CrackPacket(pNewPacket))) {
//this should *NEVER* happen... Crack should handle its own errors
TRACEMSG(ZONE_NETBIOS, (TEXT("SMBSRV-NBRECV: UNEXPECTED ERROR IN CRACK()!")));
ASSERT(FALSE);
hr = E_UNEXPECTED;
goto Done;
} else {
// if it DID work, zero out all our pointers as the cracker owns
// our memory
pNewPacket = NULL;
pSendNCB = NULL;
}
} else {
TRACEMSG(ZONE_NETBIOS, (L"SMBSRV-LSTNTHREAD: Hangup LSN(%d)\n", ncbRequest.ncb_lsn));
BOOL fBadLana = (NRC_ADPTMALFN == ncb_err);
//
// Clean up any memory we might have allocated (that would normally
// be send through the cracker
ASSERT(NULL == pSendNCB);
if(pSendNCB)
pSendNCB->Release();
pSendNCB = NULL;
// Hang up this session!
ncbRequest.ncb_command = NCBHANGUP;
ncbRequest.ncb_length = 0;
ncbRequest.ncb_buffer = NULL;
//
// if we are here AND the previous error WASNT BAD_LANA issue a hangup
// request
if(FALSE == fBadLana && (ncb_err = Netbios(&ncbRequest))) {
TRACEMSG(ZONE_ERROR, (L"SMBSRV-NBRECV: Error hanging up LSN(%d)!!! (%s) -- maybe we are shutting down -- if so we will catch that on next iteration of loop?",ncbRequest.ncb_lsn, NETBIOS_TRANSPORT::NCBError(ncb_err)));
} else if(TRUE == fBadLana) {
TRACEMSG(ZONE_ERROR, (L"SMBSRV-NBRECV: bad LANA on LSN(%d)!!!",ncbRequest.ncb_lsn));
}
//
// Purge out the cracker
if(NULL != pNewPacket) {
memset(pNewPacket, 0, sizeof(SMB_PACKET));
pNewPacket->uiPacketType = SMB_CONNECTION_DROPPED;
pNewPacket->ulConnectionID = (ULONG)(SMB_Globals::NB_TRANSPORT << 16) | ncbRequest.ncb_lsn;
pNewPacket->pfnQueueFunction = QueueNBPacketForSend;
pNewPacket->pfnCopyTranportToken = CopyNBTransportToken;
pNewPacket->pfnDeleteTransportToken = DeleteNBTransportToken;
//pNewPacket->pfnGetSocketName = NB_GetSocketName;
pNewPacket->dwDelayBeforeSending = 0;
#ifdef DEBUG
pNewPacket->uiPacketNumber = InterlockedIncrement(&SMB_Globals::g_PacketID);
#endif
TRACEMSG(ZONE_TCPIP, (L"SMBSRV-NBRECV: sending out connection dropped for %d", pNewPacket->ulConnectionID));
//
// And remove this guy from out outstanding list
csLock.Lock();
ce::list<ULONG>::iterator it = pNode->OutStandingConnectionIDs.begin();
while(it != pNode->OutStandingConnectionIDs.end()) {
if(pNewPacket->ulConnectionID == (*it)) {
pNode->OutStandingConnectionIDs.erase(it);
break;
}
it++;
}
csLock.UnLock();
//hand off the packet to the SMB cracker
if(FAILED(CrackPacket(pNewPacket))) {
//this should *NEVER* happen... Crack should handle its own errors
// and when there is one it should return back an error code to the client
TRACEMSG(ZONE_ERROR, (L"SMBSRV-NBRECV: UNEXPECTED ERROR IN CRACK()!"));
ASSERT(FALSE);
hr = E_UNEXPECTED;
goto Done;
} else {
pNewPacket = NULL;
}
}
//
// If the lana is bad, exit out to prevent spining
if(TRUE == fBadLana) {
CCritSection csLockStack(&csAdapterStackList);
csLockStack.Lock();
if(!NBAdapterDeleteStack.push_back(pAdapter)) {
hr = E_OUTOFMEMORY;
}
goto Done;
}
//
// We need to go away now
break;
}
}
hr = S_OK;
Done:
TRACEMSG(ZONE_NETBIOS, (L"SMBSRV-NBRECV:Exiting thread!"));
//
// Drop any connections that might be outstanding
csLock.Lock();
while(pNode->OutStandingConnectionIDs.size()) {
//
// Purge out the cracker
if(NULL == (pNewPacket = SMB_Globals::g_SMB_Pool.Alloc())) {
hr = E_OUTOFMEMORY;
goto Done;
}
if(NULL != pNewPacket) {
memset(pNewPacket, 0, sizeof(SMB_PACKET));
pNewPacket->uiPacketType = SMB_CONNECTION_DROPPED;
pNewPacket->ulConnectionID = (pNode->OutStandingConnectionIDs.front());
pNewPacket->pfnQueueFunction = QueueNBPacketForSend;
pNewPacket->pfnCopyTranportToken = CopyNBTransportToken;
pNewPacket->pfnDeleteTransportToken = DeleteNBTransportToken;
//pNewPacket->pfnGetSocketName = NB_GetSocketName;
pNewPacket->dwDelayBeforeSending = 0;
#ifdef DEBUG
pNewPacket->uiPacketNumber = InterlockedIncrement(&SMB_Globals::g_PacketID);
#endif
TRACEMSG(ZONE_TCPIP, (L"SMBSRV-NBRECV: sending out connection dropped for %d", pNewPacket->ulConnectionID));
//hand off the packet to the SMB cracker
if(FAILED(CrackPacket(pNewPacket))) {
//this should *NEVER* happen... Crack should handle its own errors
// and when there is one it should return back an error code to the client
TRACEMSG(ZONE_ERROR, (L"SMBSRV-NBRECV: UNEXPECTED ERROR IN CRACK()!"));
ASSERT(FALSE);
hr = E_UNEXPECTED;
break;
} else {
pNewPacket = NULL;
}
}
pNode->OutStandingConnectionIDs.pop_front();
}
csLock.UnLock();
if(pNewPacket) {
SMB_Globals::g_SMB_Pool.Free(pNewPacket);
}
if(pSendNCB) {
pSendNCB->Release();
}
if(pMainNCB) {
pMainNCB->Release();
}
//
// Remove ourself from the active list
csLock.Lock();
ce::list<RecvNode, NETBIOS_CONNECTION_ALLOC >::iterator it;
ce::list<RecvNode, NETBIOS_CONNECTION_ALLOC >::iterator itEnd = ActiveRecvList.end();
for(it = ActiveRecvList.begin(); it != itEnd; it++) {
if((*it).MyHandle == pNode->MyHandle) {
ActiveRecvList.erase(it);
break;
}
}
return FAILED(hr) ? -1 : 0;
}
HRESULT NB_GetSocketName(SMB_PACKET *pPacket, struct sockaddr *pSockAddr, int *pNameLen)
{
/* ncb *pNCB = NULL;
NCB newncb;
HRESULT hr = E_FAIL;
//
// If the connection has dropped delete memory
if(SMB_CONNECTION_DROPPED == pPacket->uiPacketType) {
TRACEMSG(ZONE_SMB, (L"NETBIOS: connection dropped packet -- deleting memory"));
hr = S_OK;
goto Done;
}
//
// They (the cracker)must send us a packet!
if(NULL == pPacket) {
ASSERT(FALSE);
hr = E_UNEXPECTED;
goto Done;
}
//
// get a pointer to the NCB... this is our 'token'
if(NULL == (pNCB = (ncb *)(pPacket->pToken))) {
//
// If this happens, we were given a bad token... memory corruption?
ASSERT(FALSE);
hr = E_UNEXPECTED;
goto Done;
}
newncb.LSN = pNCB->ncb_lsn;
newncb.LanaNum = pNCB->ncb_lana_num;
DWORD dwLen = *pNameLen;
if(NETbiosThunk(0, NB_GET_SOCKADDR, &newncb, NULL, (BYTE*)pSockAddr, 0, &dwLen)) {
hr = S_OK;
}
IFDBG(else {ASSERT(FALSE);});
*pNameLen = dwLen;
Done:
return hr;*/
return E_FAIL;
}
HRESULT
NETBIOS_TRANSPORT::QueueNBPacketForSend(SMB_PACKET *pPacket, BOOL fDestruct)
{
ref_ncb *pNCB = NULL;
HRESULT hr = E_FAIL;
UCHAR ncb_err;
CCritSection csLock(&csSendLock);
csLock.Lock();
PREFAST_ASSERT(pPacket);
if(pPacket) {
pNCB = (ref_ncb *)(pPacket->pToken);
}
//
// If the connection has dropped delete memory
if(SMB_NORMAL_PACKET != pPacket->uiPacketType) {
TRACEMSG(ZONE_SMB, (L"NETBIOS: connection dropped packet -- deleting memory"));
hr = S_OK;
goto Done;
}
//
// They (the cracker)must send us a packet!
if(!pPacket) {
ASSERT(FALSE);
hr = E_UNEXPECTED;
goto Done;
}
//
// get a pointer to the NCB... this is our 'token'
if(!pNCB) {
//
// If this happens, we were given a bad token... memory corruption?
ASSERT(FALSE);
hr = E_UNEXPECTED;
goto Done;
}
//
pNCB->m_ncb.ncb_command = NCBSEND;
pNCB->m_ncb.ncb_buffer = (BYTE *)pPacket->pOutSMB;
pNCB->m_ncb.ncb_length = pPacket->uiOutSize;
//
// If we have been shut down dont send out the packet (see table at top for
// meanings for g_fIsAccepting
if(FALSE == g_fIsAccepting) {
TRACEMSG(ZONE_ERROR, (L"SMBSRV-NBSEND: we have shut down -- not sending packet"));
hr = E_FAIL;
goto Done;
}
ncb_err = Netbios(&(pNCB->m_ncb));
if(!ncb_err) {
TRACEMSG(ZONE_NETBIOS, (TEXT("SMBSRV-NBSEND: sent packet!")));
} else {
TRACEMSG(ZONE_ERROR, (TEXT("SMBSRV-NBRECV: Error sending packet! (%s)"),NETBIOS_TRANSPORT::NCBError(ncb_err)));
hr = E_UNEXPECTED;
goto Done;
}
hr = S_OK;
Done:
ASSERT(pPacket);
#ifdef DEBUG
ASSERT(TRUE == Cracker::g_fIsRunning);
if(TRUE == Cracker::g_fIsRunning && SMB_NORMAL_PACKET == pPacket->uiPacketType && pPacket->pInSMB) {
UCHAR SMB = pPacket->pInSMB->Command;
pPacket->PerfStopTimer(SMB);
DWORD dwProcessing = pPacket->TimeProcessing();
CCritSection csLockPerf(&Cracker::g_csPerfLock);
csLockPerf.Lock();
double dwNew = (Cracker::g_dblPerfAvePacketTime[SMB] * Cracker::g_dwPerfPacketsProcessed[SMB]);
Cracker::g_dwPerfPacketsProcessed[SMB] ++;
dwNew += dwProcessing;
dwNew /= Cracker::g_dwPerfPacketsProcessed[SMB];
Cracker::g_dblPerfAvePacketTime[SMB] = dwNew;
csLockPerf.UnLock();
}
#endif
if(TRUE == fDestruct) {
if(pNCB) {
pNCB->Release();
}
if(NULL != pPacket) {
SMB_Globals::g_SMB_Pool.Free(pPacket);
}
}
return hr;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -