|
|
//////////////////////////////////////////////////////////////////////////
//
//
// Copyright (c) 1996, 1997 Microsoft Corporation
//
//
// Module Name:
// recv.c
//
// Abstract:
//
//
// Author:
//
// P Porzuczek
//
// Environment:
//
// Revision History:
//
//
//////////////////////////////////////////////////////////////////////////////
#include <wdm.h>
#include <strmini.h>
#include <ksmedia.h>
#include "slip.h"
#include "main.h"
#include "recv.h"
//////////////////////////////////////////////////////////////////////////////
//
// Init 802.3 header template
//
Header802_3 h802_3Template = { {0x01, 0x00, 0x5e, 0, 0, 0} , {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} , {0x08, 0x00} };
#if DBG
UCHAR MyBuffer [1600] = {0};
UCHAR TestBuffer [] = { 0xC0, 0xC0, 0x00, 0xC7, 0xD3, 0x97, 0x00, 0x00, 0x5E, 0x56, 0x23, 0x11, 0x07, 0x00, 0x00, 0x00, 0x2C, 0x01, 0x00, 0x00, 0xAA, 0x58, 0x00, 0x00, 0x3D, 0xC5, 0x00, 0x00, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0xDC, 0xA2, 0x3B, 0x82, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0xE9, 0xCE, 0xFA, 0x7D, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x53, 0x60, 0xBB, 0x03, 0xC0 };
//////////////////////////////////////////////////////////////////////////////
VOID DumpData ( PUCHAR pData, ULONG ulSize ) //////////////////////////////////////////////////////////////////////////////
{ ULONG ulCount; ULONG ul; UCHAR uc;
DbgPrint("Dump - Data: %x, Size: %x\n", pData, ulSize); while (ulSize) { ulCount = 16 < ulSize ? 16 : ulSize;
for (ul = 0; ul < ulCount; ul++) { uc = *pData;
DbgPrint("%02X ", uc); ulSize -= 1; pData += 1; }
DbgPrint("\n"); } if(TestDebugFlag & TEST_DBG_ASSERT) { DEBUG_BREAKPOINT(); } }
///////////////////////////////////////////////////////////////////////////////////////
VOID DumpNabStream ( PNAB_STREAM pNabStream ) ///////////////////////////////////////////////////////////////////////////////////////
{
TEST_DEBUG (TEST_DBG_NAB, ("pszBuffer......: %08X\n", pNabStream->pszBuffer)); TEST_DEBUG (TEST_DBG_NAB, ("ulcbSize.......: %08X\n", pNabStream->ulcbSize)); TEST_DEBUG (TEST_DBG_NAB, ("ulOffset.......: %08X\n", pNabStream->ulOffset)); TEST_DEBUG (TEST_DBG_NAB, ("ulMpegCrc......: %08X\n", pNabStream->ulMpegCrc)); TEST_DEBUG (TEST_DBG_NAB, ("ulCrcBytesIndex: %08X\n", pNabStream->ulCrcBytesIndex)); TEST_DEBUG (TEST_DBG_NAB, ("ulLastCrcBytes.: %08X\n", pNabStream->ulLastCrcBytes)); TEST_DEBUG (TEST_DBG_NAB, ("ulIPStreamIndex: %08X\n", pNabStream->ulIPStreamIndex));
return; }
ULONG Checksum ( char * psz, ULONG ulSize ) //////////////////////////////////////////////////////////////////////////////
{ ULONG Checksum = 0; ULONG uli = 0;
if(ulSize < 0x41d && ulSize) { for ( uli=0; uli <= ulSize-2; uli += 2) { Checksum += ((ULONG) (psz[uli]) << 8) + (ULONG) (psz[uli+1]); }
Checksum = (Checksum >> 16) + (Checksum & 0xffff); Checksum += (Checksum >> 16); Checksum = ~Checksum; } return Checksum; }
ULONG ulNumPacketsSent = 0; ULONG ulIndicateEvery = 10; ULONG ulIndicated = 0;
#endif //DBG
///////////////////////////////////////////////////////////////////////////////////////
VOID ResetNabStream ( PSLIP_FILTER pFilter, PNAB_STREAM pNabStream, PHW_STREAM_REQUEST_BLOCK pSrb, PVOID pBuffer, ULONG ulBufSize ) ///////////////////////////////////////////////////////////////////////////////////////
{
if (pNabStream->ulOffset > sizeof (Header802_3)) { pFilter->Stats.ulTotalSlipFramesIncomplete += 1; pFilter->Stats.ulTotalSlipBytesDropped += pNabStream->ulOffset - sizeof (Header802_3); }
//
// Reset the NAB_STREAM structure for this group ID
//
pNabStream->pSrb = pSrb; pNabStream->pszBuffer = pBuffer; pNabStream->ulcbSize = ulBufSize; pNabStream->ulOffset = 0; pNabStream->ulMpegCrc = 0xFFFFFFFF; pNabStream->ulCrcBytesIndex = 0l; pNabStream->ulLastCrcBytes = 0l;
if(pBuffer) { // Copy the 802.3 header template into the frame. We will replace
// the destination address and protocol on receive.
//
RtlCopyMemory (pNabStream->pszBuffer, &h802_3Template, sizeof (Header802_3));
//
//$$PFP update buffer offset
//
pNabStream->ulOffset = sizeof (Header802_3); }
return;
}
///////////////////////////////////////////////////////////////////////////////////////
VOID CancelNabStreamSrb ( PSLIP_FILTER pFilter, PHW_STREAM_REQUEST_BLOCK pSrb ) ///////////////////////////////////////////////////////////////////////////////////////
{ PLIST_ENTRY pFlink = NULL; PLIST_ENTRY pQueue = NULL; BOOLEAN bFound = FALSE; PNAB_STREAM pNSTemp = NULL;
KIRQL Irql = {0};
pQueue = &pFilter->StreamContxList;
KeAcquireSpinLock(&pFilter->StreamUserSpinLock, &Irql);
if ( !IsListEmpty (pQueue)) { pFlink = pQueue->Flink; while ((pFlink != pQueue ) && !bFound) { pNSTemp = CONTAINING_RECORD (pFlink, NAB_STREAM, Linkage);
if (pSrb && pSrb == pNSTemp->pSrb) { pNSTemp->pSrb->Status = STATUS_CANCELLED; StreamClassStreamNotification (StreamRequestComplete, pNSTemp->pSrb->StreamObject, pNSTemp->pSrb); TEST_DEBUG (TEST_DBG_TRACE, ("SLIP: StreamRequestComplete on pSrb: %08X\n", pNSTemp->pSrb));
pNSTemp->pSrb = NULL; bFound = TRUE; }
pFlink = pFlink->Flink; }
if (bFound) { vDestroyNabStreamContext (pFilter, pNSTemp, FALSE); }
}
KeReleaseSpinLock(&pFilter->StreamUserSpinLock, Irql);
} ///////////////////////////////////////////////////////////////////////////////////////
VOID DeleteNabStreamQueue ( PSLIP_FILTER pFilter ) ///////////////////////////////////////////////////////////////////////////////////////
{ PLIST_ENTRY pFlink = NULL; PLIST_ENTRY pQueue = NULL; PNAB_STREAM pNSTemp = NULL; KIRQL Irql={0}; pQueue = &pFilter->StreamContxList; KeAcquireSpinLock(&pFilter->StreamUserSpinLock, &Irql); while ( !IsListEmpty (pQueue)) { pFlink = RemoveHeadList (pQueue); pNSTemp = CONTAINING_RECORD (pFlink, NAB_STREAM, Linkage);
if(pNSTemp && pNSTemp->pSrb) { pNSTemp->pSrb->Status = STATUS_CANCELLED; StreamClassStreamNotification (StreamRequestComplete, pNSTemp->pSrb->StreamObject, pNSTemp->pSrb); TEST_DEBUG (TEST_DBG_TRACE, ("SLIP: StreamRequestComplete on pSrb: %08X\n", pNSTemp->pSrb));
pNSTemp->pSrb = NULL;
vDestroyNabStreamContext (pFilter, pNSTemp, FALSE); } } KeReleaseSpinLock(&pFilter->StreamUserSpinLock, Irql);
return; }
//////////////////////////////////////////////////////////////////////////////
ULONG CalculateCrc ( PUCHAR pPacket, ULONG ulSize ) //////////////////////////////////////////////////////////////////////////////
{ ULONG ul = 0; ULONG ulLastCrcBytes = 0; ULONG ulMpegCrc = 0xFFFFFFFF; PUCHAR ptr = NULL; PCL pcl = (PCL)&ulLastCrcBytes;
for (ptr = pPacket, ul = 0; ul < ulSize; ul++, ptr++) { //if (ul > 3)
//{
//MpegCrcUpdate (&ulMpegCrc, 1, &pcl->c.uc[3]);
MpegCrcUpdate (&ulMpegCrc, 1, ptr); //}
//pcl->l.ul = (ULONG)(pcl->l.ul) << 8;
//pcl->c.uc[0] = *ptr;
TEST_DEBUG( TEST_DBG_CRC, ("SLIP: char: %02X ul: %d MpegCrc: %08X\n", *ptr, ul, ulMpegCrc));
}
return ulMpegCrc; }
//////////////////////////////////////////////////////////////////////////////
VOID vNabtsUpdateCrc ( PNAB_STREAM pNabStream, UCHAR ucToCopy ) //////////////////////////////////////////////////////////////////////////////
{
PCL pcl = (PCL)&pNabStream->ulLastCrcBytes;
if (pNabStream->ulCrcBytesIndex++ > 3) { MpegCrcUpdate (&pNabStream->ulMpegCrc, 1, &pcl->c.uc[3]); }
pcl->l.ul = (ULONG)(pcl->l.ul) << 8; pcl->c.uc[0] = ucToCopy;
#ifdef DUMP_CRC
TEST_DEBUG( TEST_DBG_CRC, ("SLIP: char: %02X ulLastCrcBytes: %08X MpegCrc: %08X ulCrcBytesIndex: %d\n", ucToCopy, pNabStream->ulLastCrcBytes, pNabStream->ulMpegCrc, pNabStream->ulCrcBytesIndex));
#endif // DUMP_CRC
}
//////////////////////////////////////////////////////////////////////////////
VOID ComputeIPChecksum ( PHeaderIP pIPHeader ) //////////////////////////////////////////////////////////////////////////////
{ ULONG Checksum; PUCHAR NextChar;
pIPHeader->ucChecksumHigh = pIPHeader->ucChecksumLow = 0; Checksum = 0; for ( NextChar = (PUCHAR) pIPHeader ; (NextChar - (PUCHAR) pIPHeader) <= (sizeof(HeaderIP) - 2) ; NextChar += 2) { Checksum += ((ULONG) (NextChar[0]) << 8) + (ULONG) (NextChar[1]); }
Checksum = (Checksum >> 16) + (Checksum & 0xffff); Checksum += (Checksum >> 16); Checksum = ~Checksum;
pIPHeader->ucChecksumHigh = (UCHAR) ((Checksum >> 8) & 0xff); pIPHeader->ucChecksumLow = (UCHAR) (Checksum & 0xff); }
//////////////////////////////////////////////////////////////////////////////
//
// Looks in the user's StreamContxList for a matching
// Nabts Group ID.
// It uses it if it finds one - otherwise we allocate one.
//
NTSTATUS ntFindNabtsStream( PSLIP_FILTER pFilter, PNABTSFEC_BUFFER pNabData, PNAB_STREAM *ppNabStream ) //////////////////////////////////////////////////////////////////////////////
{ NTSTATUS status = STATUS_SUCCESS; PLIST_ENTRY pFlink; PNAB_STREAM pNabStream = NULL;
//
// Check to see if the groupid is within the valid range.
//
if(pNabData->groupID > NABTSIP_GROUP_ID_RANGE_HI ) { status = STATUS_INVALID_PARAMETER; ASSERT(status == STATUS_INVALID_PARAMETER); *ppNabStream = NULL; return status; }
//
// Go through the list one stream context at a time.
//
for (pFlink = pFilter->StreamContxList.Flink; pFlink != &pFilter->StreamContxList; pFlink = pFlink->Flink) { PNAB_STREAM pNSTemp;
pNSTemp = CONTAINING_RECORD (pFlink, NAB_STREAM, Linkage); if(pNSTemp->groupID == pNabData->groupID) { pNabStream = pNSTemp;
//
// Mark the stream as having been used. This flag is checked
// in vCheckNabStreamLife.
//
pNabStream->fUsed = TRUE;
break; } }
//
// if we did not find a stream then create one.
//
if (pNabStream == NULL) { status = ntCreateNabStreamContext(pFilter, pNabData->groupID, &pNabStream); if(status == STATUS_SUCCESS) { #if DBG
TEST_DEBUG( TEST_DBG_NAB, ("SLIP Creating new NAB_STREAM for data...Group ID: %08X\n", pNabStream->groupID));
#ifdef TEST_DBG_NAB
DumpNabStream (pNabStream); #endif
#endif //DBG
} } else { TEST_DEBUG( TEST_DBG_NAB, ("SLIP Using existing NAB_STREAM for data. Group ID: %08X\n", pNabStream->groupID)); #ifdef TEST_DBG_NAB
DumpNabStream (pNabStream); #endif
}
*ppNabStream = pNabStream;
return status; }
///////////////////////////////////////////////////////////////////////////////////////
NTSTATUS GetOutputSrbForStream ( PSLIP_FILTER pFilter, PNAB_STREAM pNabStream ) ///////////////////////////////////////////////////////////////////////////////////////
{ NTSTATUS status = STATUS_INSUFFICIENT_RESOURCES; PKSSTREAM_HEADER pStreamHdr = NULL; PHW_STREAM_REQUEST_BLOCK pSrbIPv4 = NULL;
if (QueueRemove( &pSrbIPv4, &pFilter->IpV4StreamDataSpinLock, &pFilter->IpV4StreamDataQueue)) { //
// Save the SRB References.
//
pNabStream->pSrb = pSrbIPv4; pStreamHdr = pSrbIPv4->CommandData.DataBufferArray;
TEST_DEBUG (TEST_DBG_WRITE_DATA, ("SLIP: OUTPUT SRB...FrameExtent: %d DataUsed: %d Data: %08X\n", pStreamHdr->FrameExtent, pStreamHdr->DataUsed, pStreamHdr->Data )); status = STATUS_SUCCESS;
} return status; }
//////////////////////////////////////////////////////////////////////////////
void UpdateMACHeader ( PHeader802_3 pMAC, PHeaderIP pIP ) //////////////////////////////////////////////////////////////////////////////
{ ASSERT (pMAC); ASSERT (pIP);
//
// Now we copy the low order 23 bits of the IP destination addresss to the 802.3 Header
//
if (pMAC && pIP) { pMAC->DestAddress [3] = pIP->ipaddrDst.ucHighLSB & 0x7F; pMAC->DestAddress [4] = pIP->ipaddrDst.ucLowMSB & 0xFF; pMAC->DestAddress [5] = pIP->ipaddrDst.ucLowLSB & 0xFF; } }
//////////////////////////////////////////////////////////////////////////////
void vRebuildIPPacketHeader ( PNAB_STREAM pNabStream ) //////////////////////////////////////////////////////////////////////////////
{ PNAB_HEADER_CACHE pPacketHeader; PNAB_HEADER_CACHE pSavedHeader = &pNabStream->NabHeader[pNabStream->ulIPStreamIndex]; PUCHAR psz;
//
// Copy the uncompressed packet header to the buffer.
//
//The following assert never fails since all of parameters are constants. So RtlCopyMemory is safe
ASSERT(sizeof(Header802_3)+sizeof(HeaderIP) + sizeof(HeaderUDP)<MAX_STREAM_PAYLOAD);
RtlCopyMemory((pNabStream->pszBuffer + sizeof(Header802_3)), ((PUCHAR)&pNabStream->NabHeader[pNabStream->ulIPStreamIndex]), sizeof(HeaderIP) + sizeof(HeaderUDP));
//
// Copy the compressed header items into the uncompressed packet header.
//
pPacketHeader = (PNAB_HEADER_CACHE)pNabStream->pszBuffer + sizeof(Header802_3);
//
// Copy IP Packet ID.
//
psz = (PUCHAR)pNabStream->NabCState[pNabStream->ulIPStreamIndex].usrgCompressedHeader;
//NabCState[pNabStream->ulIPStreamIndex].usrgCompressedHeader is USHORT and RtlCopyMemory copies discrete number of bytes
//No vulnerability is seen in the RtlCopyMemory blocks below
RtlCopyMemory(&pPacketHeader->ipHeader.ucIDHigh, psz, IP_ID_SIZE);
//
// Copy UDP Check Sum.
//
psz = (PUCHAR)(pNabStream->NabCState[pNabStream->ulIPStreamIndex].usrgCompressedHeader + 2);
RtlCopyMemory(&pPacketHeader->udpHeader.ucChecksumHigh, psz, UDP_CHKSUM_SIZE);
}
//////////////////////////////////////////////////////////////////////////////
__inline VOID CopyNabToPacketNew( UCHAR uchToCopy, PNAB_STREAM pNabStream, PSLIP_FILTER pFilter ) //////////////////////////////////////////////////////////////////////////////
{ if (pNabStream->ulOffset >= pNabStream->ulcbSize) { //
// The packet is too big. Resync the SLIP stream.
//
pNabStream->ulFrameState = NABTS_FS_SYNC; pFilter->Stats.ulTotalSlipFramesTooBig += 1; } else { ULONG ulIPStream = pNabStream->ulIPStreamIndex;
if(pNabStream->NabCState[ulIPStream].usCompressionState == NABTS_CS_UNCOMPRESSED) { //
// Copy the byte to the actual Packet buffer.
//
pNabStream->pszBuffer[pNabStream->ulOffset] = uchToCopy;
//
// Update the MpegCrc check.
//
vNabtsUpdateCrc (pNabStream, uchToCopy);
//
// If we are collecting the IP Header data then copy it to
// a buffer so that we can use it later for uncompression.
//
if(pNabStream->ulOffset < sizeof (Header802_3) + sizeof(HeaderIP) + sizeof(HeaderUDP)) { PUCHAR psz = (PUCHAR)&pNabStream->NabHeader[pNabStream->ulIPStreamIndex].ipHeader; *(psz + pNabStream->ulOffset - sizeof (Header802_3)) = uchToCopy; }
//
// Increment the data pointer.
//
pNabStream->ulOffset++; } else if(pNabStream->NabCState[ulIPStream].usCompressionState == NABTS_CS_COMPRESSED) { if(pNabStream->NabCState[ulIPStream].uscbHeaderOffset < pNabStream->NabCState[ulIPStream].uscbRequiredSize) { PUCHAR psz = (PUCHAR)pNabStream->NabCState[ulIPStream].usrgCompressedHeader;
*(psz + pNabStream->NabCState[ulIPStream].uscbHeaderOffset++) = uchToCopy;
//
// Update the MpegCrc check.
//
vNabtsUpdateCrc (pNabStream, uchToCopy);
if(pNabStream->NabCState[ulIPStream].uscbHeaderOffset == pNabStream->NabCState[ulIPStream].uscbRequiredSize) {
ASSERT(pNabStream->ulOffset == sizeof(Header802_3)); //
// Use the saved IP Packet header and the compressed IP Header
// to rebuil the IP Header to send up.
//
vRebuildIPPacketHeader( pNabStream );
//
// Set the buffer offset past the end of the IP/UDP headers
// We should start coping data now.
//
pNabStream->ulOffset += (sizeof(HeaderIP) + sizeof(HeaderUDP));
} } else { //
// We already have the header rebuilt. Now copy the payload.
//
pNabStream->pszBuffer[pNabStream->ulOffset++] = uchToCopy;
//
// Update the MpegCrc check.
//
vNabtsUpdateCrc (pNabStream, uchToCopy); } } else { DbgBreakPoint(); } } }
//////////////////////////////////////////////////////////////////////////////
__inline VOID CopyNabToPacketOld( UCHAR uchToCopy, PNAB_STREAM pNabStream, PSLIP_FILTER pFilter
) //////////////////////////////////////////////////////////////////////////////
{ if (pNabStream->ulOffset >= pNabStream->ulcbSize) { //
// The packet is too big. Resync the SLIP stream.
//
pNabStream->ulFrameState = NABTS_FS_SYNC; pFilter->Stats.ulTotalSlipFramesTooBig += 1; } else { // Copy the byte.
//
pNabStream->pszBuffer[pNabStream->ulOffset++] = uchToCopy; } }
//////////////////////////////////////////////////////////////////////////////
__inline VOID CopyNabToPacket( UCHAR uchToCopy, PNAB_STREAM pNabStream, PSLIP_FILTER pFilter
) //////////////////////////////////////////////////////////////////////////////
{
if(pNabStream->ulProtoID == PROTO_ID) { CopyNabToPacketNew(uchToCopy, pNabStream, pFilter); } else { CopyNabToPacketOld(uchToCopy, pNabStream, pFilter); } }
//////////////////////////////////////////////////////////////////////////////
NTSTATUS ntNabtsRecv( PSLIP_FILTER pFilter, PNABTSFEC_BUFFER pNabData ) //////////////////////////////////////////////////////////////////////////////
{ NTSTATUS status = STATUS_SUCCESS; PNAB_STREAM pNabStream = NULL; PUCHAR pszNabIn = NULL; PKSSTREAM_HEADER pStreamHdr = NULL; LARGE_INTEGER liCurrentTime = {0}; LARGE_INTEGER liTimeToLive = {0}; LARGE_INTEGER liStatusInterval = {0}; KIRQL Irql = {0}; ULONG ulIPStream = 0; ULONG ulNabIn = 0;
TEST_DEBUG( TEST_DBG_RECV, ("\nEntering - ntNabtsRecv\n"));
//
// Get the current system time.
//
KeQuerySystemTime(&liCurrentTime);
//
// See if it is time the check for dead GroupIDs and Streams.
// Get a lock so no one else is modifying the Stream list while we are looking.
//
KeAcquireSpinLock(&pFilter->StreamUserSpinLock, &Irql);
liTimeToLive.QuadPart = NAB_STREAM_LIFE; if( (LONGLONG)(liCurrentTime.QuadPart - pFilter->liLastTimeChecked.QuadPart) > liTimeToLive.QuadPart) { vCheckNabStreamLife( pFilter ); pFilter->liLastTimeChecked = liCurrentTime; }
//
// Find the Stream Context.
//
status = ntFindNabtsStream( pFilter, pNabData, &pNabStream ); if(status != STATUS_SUCCESS) { ASSERT( status == STATUS_SUCCESS); pFilter->Stats.ulTotalSlipBuffersDropped += 1; KeReleaseSpinLock(&pFilter->StreamUserSpinLock, Irql); goto ret; }
KeReleaseSpinLock(&pFilter->StreamUserSpinLock, Irql);
liStatusInterval.QuadPart = NAB_STATUS_INTERVAL; if( (LONGLONG)(liCurrentTime.QuadPart - pFilter->liLastTimeStatsDumped.QuadPart) > liStatusInterval.QuadPart) { pFilter->liLastTimeStatsDumped = liCurrentTime; TEST_DEBUG (TEST_DBG_INFO, (" ")); TEST_DEBUG (TEST_DBG_INFO, ("SLIP: ulTotalDataSRBWrites: %d\n.", pFilter->Stats.ulTotalDataSRBWrites)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalBadPinSRBWrites: %d\n.", pFilter->Stats.ulTotalBadPinSRBWrites)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalDataSRBReads: %d\n.", pFilter->Stats.ulTotalDataSRBReads)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalBadPinSRBReads: %d\n.", pFilter->Stats.ulTotalBadPinSRBReads)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalSlipBuffersReceived: %d\n.", pFilter->Stats.ulTotalSlipBuffersReceived)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalSlipBuffersDropped: %d\n.", pFilter->Stats.ulTotalSlipBuffersDropped)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalSlipZeroLengthBuffers: %d\n.", pFilter->Stats.ulTotalSlipZeroLengthBuffers)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalSlipBytesReceived: %d\n.", pFilter->Stats.ulTotalSlipBytesReceived)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalSlipBytesDropped: %d\n.", pFilter->Stats.ulTotalSlipBytesDropped)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalSlipFramesReceived: %d\n.", pFilter->Stats.ulTotalSlipFramesReceived)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalSlipOldProtoFramesStarted: %d\n.", pFilter->Stats.ulTotalSlipOldProtoFramesStarted)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalSlipNewProtoFramesStarted: %d\n.", pFilter->Stats.ulTotalSlipNewProtoFramesStarted)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalSlipFramesIncomplete: %d\n.", pFilter->Stats.ulTotalSlipFramesIncomplete)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalSlipFramesBadCRC: %d\n.", pFilter->Stats.ulTotalSlipFramesBadCRC)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalSlipFramesTooBig: %d\n.", pFilter->Stats.ulTotalSlipFramesTooBig)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalSlipFramesTooSmall: %d\n.", pFilter->Stats.ulTotalSlipFramesTooSmall)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalIPPacketsFound: %d\n.", pFilter->Stats.ulTotalIPPacketsFound)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalIPBytesFound: %d\n.", pFilter->Stats.ulTotalIPBytesFound)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalIPPacketsSent: %d\n.", pFilter->Stats.ulTotalIPPacketsSent)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalIPBytesSent: %d\n.", pFilter->Stats.ulTotalIPBytesSent)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalIPPacketsTooBig: %d\n.", pFilter->Stats.ulTotalIPPacketsTooBig)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalIPPacketsTooSmall: %d\n.", pFilter->Stats.ulTotalIPPacketsTooSmall)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalIPPacketsDropped: %d\n.", pFilter->Stats.ulTotalIPPacketsDropped)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalIPBytesDropped: %d\n.", pFilter->Stats.ulTotalIPBytesDropped)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalNabStreamsCreated: %d\n.", pFilter->Stats.ulTotalNabStreamsCreated)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalNabStreamsTimedOut: %d\n.", pFilter->Stats.ulTotalNabStreamsTimedOut)); TEST_DEBUG (TEST_DBG_INFO, (" "));
}
//
// Set the last time used for this stream.
//
pNabStream->liLastTimeUsed = liCurrentTime;
//
// Get a pointer to the input buffer. We copy data from this pointer to
// the output buffer
//
pszNabIn = (LPSTR) pNabData->data;
// Validate the data size and that the start+end of the buffer are accessible
ASSERT(pNabData->dataSize <= sizeof(pNabData->data) );
// What is really needed here is something like "MmIsValidAddress()", but for WDM drivers
// These assert just look at the start & end addresses of the buffer w/o regard to values.
// ASSERT( (*(pszNabIn) + 1 > 0) );
// ASSERT( (*(pszNabIn+pNabData->dataSize-1) + 1 > 0) );
for (ulNabIn = pNabData->dataSize; ulNabIn; ulNabIn--, pszNabIn++) { switch (pNabStream->ulFrameState) {
case NABTS_FS_SYNC:
switch (*pszNabIn) { case FRAME_END: //
// We found the start of frame sync. Look for the
// protocol character.
//
TEST_DEBUG( TEST_DBG_RECV, ("SLIP Found Possible Start of Frame... pszNabIn %08X ulNabIn: %08X\n", pszNabIn, ulNabIn)); pNabStream->ulFrameState = NABTS_FS_SYNC_PROTO;
ResetNabStream (pFilter, pNabStream, NULL, NULL, 0);
break; } break;
case NABTS_FS_SYNC_PROTO:
switch (*pszNabIn) { case PROTO_ID: case PROTO_ID_OLD:
TEST_DEBUG( TEST_DBG_RECV, ("SLIP Found Start of Protocol...Building Packet.... pszNabIn %08X ulNabIn: %08X\n", pszNabIn, ulNabIn));
// Record the stream type.
//
pNabStream->ulProtoID = *pszNabIn;
// This is our protocol. Setup NAB_STREAM with an output
// data buffer from the output SRB Queue
//
TEST_DEBUG( TEST_DBG_RECV, ("SLIP Setting Up Output buffer\n")); ResetNabStream( pFilter, pNabStream, NULL, pNabStream->rgBuf, sizeof(pNabStream->rgBuf));
// Copy the 802.3 header template into the frame. We will replace
// the destination address and protocol on receive.
//
RtlCopyMemory (pNabStream->pszBuffer, &h802_3Template, sizeof (Header802_3));
// Update buffer offset
//
pNabStream->ulOffset = sizeof (Header802_3);
if(pNabStream->ulProtoID == PROTO_ID) { //
// Set the state to check the IP compression.
//
pFilter->Stats.ulTotalSlipNewProtoFramesStarted += 1; TEST_DEBUG( TEST_DBG_RECV, ("SLIP Protocol ID is Compressed\n")); pNabStream->ulFrameState = NABTS_FS_COMPRESSION; } else { //
// Start collecting data.
//
pFilter->Stats.ulTotalSlipOldProtoFramesStarted += 1; TEST_DEBUG( TEST_DBG_RECV, ("SLIP Protocol ID is not Compressed\n")); pNabStream->ulFrameState = NABTS_FS_COLLECT; }
// Update the MpegCrc check.
//
vNabtsUpdateCrc( pNabStream, *pszNabIn);
break;
case FRAME_END: TEST_DEBUG( TEST_DBG_RECV, ("SLIP State is FRAME_END....going to FS_SYNC_PROTO\n")); pNabStream->ulFrameState = NABTS_FS_SYNC_PROTO; break;
default: TEST_DEBUG( TEST_DBG_RECV, ("SLIP Protocol Not Found...ReSyncing... pszNabIn %08X ulNabIn: %08X\n", pszNabIn, ulNabIn)); pNabStream->ulFrameState = NABTS_FS_SYNC; break; } break;
case NABTS_FS_COMPRESSION: {
TEST_DEBUG( TEST_DBG_RECV, ("SLIP State is NABTS_FS_COMPRESSION\n"));
//
// Get the index to the IP Compression Stream.
//
ulIPStream = IP_STREAM_INDEX(*pszNabIn);
//
// Check to see if this IP Packet has a compressed header.
//
if(!PACKET_COMPRESSED(*pszNabIn)) { pNabStream->NabCState[ulIPStream].usCompressionState = NABTS_CS_UNCOMPRESSED; } else if (PACKET_COMPRESSED (*pszNabIn)) { pNabStream->NabCState[ulIPStream].usCompressionState = NABTS_CS_COMPRESSED; pNabStream->NabCState[ulIPStream].uscbRequiredSize = NORMAL_COMPRESSED_HEADER; }
//
// Retain the IP Stream Index.
//
pNabStream->ulIPStreamIndex = ulIPStream;
//
// Set the stats Last Used Time for this stream.
//
pNabStream->NabCState[pNabStream->ulIPStreamIndex].liLastUsed = liCurrentTime;
//
// Set the IP Header Data Length to zero.
//
pNabStream->NabCState[pNabStream->ulIPStreamIndex].uscbHeaderOffset = 0;
//
// Start collecting data.
//
pNabStream->ulFrameState = NABTS_FS_COLLECT;
//
// Update the MpegCrc check.
//
vNabtsUpdateCrc (pNabStream, *pszNabIn);
break; }
case NABTS_FS_COLLECT:
switch (*pszNabIn) { case FRAME_ESCAPE: //
// We want to escape the next character.
//
TEST_DEBUG( TEST_DBG_RECV, ("SLIP NABTS_FS_COLLECT_ESCAPE\n")); pNabStream->ulFrameState = NABTS_FS_COLLECT_ESCAPE; break;
case FRAME_END:
if (pNabStream->ulOffset >= sizeof(HeaderIP)) { PHeaderIP pHeaderIp = (PHeaderIP)(PUCHAR)(pNabStream->pszBuffer + sizeof(Header802_3)); PUSHORT pusIpLen = (PUSHORT)&pHeaderIp->ucTotalLenHigh;
TEST_DEBUG( TEST_DBG_RECV, ("SLIP End of Packet Found... pszNabIn %08X ulNabIn: %08X ulOffset: %d\n", pszNabIn, ulNabIn, pNabStream->ulOffset));
TEST_DEBUG( TEST_DBG_RECV, ("SLIP ulProtoID %d ulMpegCrc: %08X ulLastCrcBytes: %08X IpLen: %d\n", pNabStream->ulProtoID, pNabStream->ulMpegCrc, pNabStream->ulLastCrcBytes, *pusIpLen));
// If header compression is being used, we must
// calculate the IP and UDP lengths and regenerate
// the packet checksums.
//
if (pNabStream->ulProtoID == PROTO_ID) { PHeaderUDP pHeaderUDP = (PHeaderUDP)(PUCHAR)(pNabStream->pszBuffer + sizeof(Header802_3) + sizeof(HeaderIP)); PUSHORT pusUdpLen = (PUSHORT)&pHeaderUDP->ucMsgLenHigh;
TEST_DEBUG( TEST_DBG_CRC, ("SLIP: GroupID: %d Stream CRC: %08X Calculated CRC: %08X", pNabStream->groupID, pNabStream->ulLastCrcBytes, pNabStream->ulMpegCrc));
// All PROTO_ID packets have an MpegCrc on the end. It is not
// part of the IP packet and needs to be stripped off.
//
pNabStream->ulOffset -= 4;
if (pNabStream->NabCState[pNabStream->ulIPStreamIndex].usCompressionState == NABTS_CS_COMPRESSED) { // We use the ulOffset less the MAC Header and IP Header
// sizes for the UDP Packet length.
//
// Note! Fragmented UDP datagrams cannot be compressed
//
*pusUdpLen = htons ((USHORT)(pNabStream->ulOffset - sizeof(Header802_3) - sizeof(HeaderIP))); // We use the ulOffset less the MAC Header size for the
// IP Packet length.
//
*pusIpLen = htons ((USHORT)(pNabStream->ulOffset - sizeof(Header802_3))); // Recalculate the IP header Checksum
//
ComputeIPChecksum (pHeaderIp); }
// If the CRC was bad then invalidate
// the IP Checksum
//
if (pNabStream->ulMpegCrc != pNabStream->ulLastCrcBytes) { TEST_DEBUG (TEST_DBG_CRC, (" FAILED*****\n")); pFilter->Stats.ulTotalSlipFramesBadCRC += 1;
pHeaderIp->ucChecksumHigh = ~(pHeaderIp->ucChecksumHigh); pHeaderIp->ucChecksumLow = 0xff; } else { TEST_DEBUG (TEST_DBG_CRC, (" PASSED\n")); } } else if (pNabStream->ulProtoID != PROTO_ID_OLD) { TEST_DEBUG( TEST_DBG_RECV, ("SLIP End of Packet Found....Bad PROTO_ID... pszNabIn %08X ulNabIn: %08X ulOffset: %d\n", pszNabIn, ulNabIn, pNabStream->ulOffset)); ASSERT( (pNabStream->ulProtoID == PROTO_ID_OLD) || (pNabStream->ulProtoID == PROTO_ID) ); ResetNabStream (pFilter, pNabStream, NULL, NULL, 0); pNabStream->ulFrameState = NABTS_FS_SYNC; goto ret; } if (NabtsNtoHs(*pusIpLen) <= NABTSIP_MAX_LOOKAHEAD) { // Update the MAC address
//
UpdateMACHeader( (PHeader802_3)(pNabStream->pszBuffer), pHeaderIp );
// Get an SRB for outputting the data.
//
status = GetOutputSrbForStream(pFilter, pNabStream ); if(status != STATUS_SUCCESS) { ASSERT(status == STATUS_SUCCESS); pFilter->Stats.ulTotalIPPacketsDropped += 1; ResetNabStream( pFilter, pNabStream, NULL, NULL, 0); pNabStream->ulFrameState = NABTS_FS_SYNC; goto ret; }
ASSERT(pNabStream->pSrb); if (!pNabStream->pSrb) { pFilter->Stats.ulTotalIPPacketsDropped += 1; ResetNabStream (pFilter, pNabStream, NULL, NULL, 0); pNabStream->ulFrameState = NABTS_FS_SYNC; goto ret; }
// Get the StreamHdr.
//
pStreamHdr = (PKSSTREAM_HEADER) pNabStream->pSrb->CommandData.DataBufferArray; ASSERT( pStreamHdr); if (!pStreamHdr) { pFilter->Stats.ulTotalIPPacketsDropped += 1; ResetNabStream (pFilter, pNabStream, NULL, NULL, 0); pNabStream->ulFrameState = NABTS_FS_SYNC; goto ret; }
// If we had a discontinuity, we flag it.
//
if (pFilter->bDiscontinuity) { pStreamHdr->OptionsFlags |= KSSTREAM_HEADER_OPTIONSF_DATADISCONTINUITY; pFilter->bDiscontinuity = FALSE; }
// Copy the data from the rgBuf to the Srb.
//
RtlCopyMemory (pStreamHdr->Data, pNabStream->pszBuffer, pNabStream->ulOffset );
// Update the datasize field of the Output SRB
//
pStreamHdr->DataUsed = pNabStream->ulOffset;
// Complete the output SRB
//
pFilter->Stats.ulTotalIPPacketsSent += 1; pNabStream->ulOffset = 0; StreamClassStreamNotification( StreamRequestComplete, pNabStream->pSrb->StreamObject, pNabStream->pSrb ); TEST_DEBUG (TEST_DBG_SRB, ("SLIP: Completed SRB....Ptr %08X Size %d\n", pStreamHdr->Data, pStreamHdr->DataUsed));
TEST_DEBUG (TEST_DBG_TRACE, ("SLIP: StreamRequestComplete on pSrb: %08X\n", pNabStream->pSrb)); } else { // The packet is too big. Resync the SLIP stream.
//
pFilter->Stats.ulTotalIPPacketsDropped += 1; pFilter->Stats.ulTotalIPPacketsTooBig += 1; TEST_DEBUG( TEST_DBG_RECV, ("SLIP End of Packet Found....Packet Too BIG... pszNabIn %08X ulNabIn: %08X ulOffset: %d\n", pszNabIn, ulNabIn, pNabStream->ulOffset)); } } else { // The packet is too small. Resync the SLIP stream.
//
pFilter->Stats.ulTotalIPPacketsDropped += 1; pFilter->Stats.ulTotalIPPacketsTooSmall += 1; TEST_DEBUG( TEST_DBG_RECV, ("SLIP End of Packet Found....Packet Too SMALL... pszNabIn %08X ulNabIn: %08X ulOffset: %d\n", pszNabIn, ulNabIn, pNabStream->ulOffset)); }
// Reset state for new packet.
//
ResetNabStream (pFilter, pNabStream, NULL, NULL, 0); pNabStream->ulFrameState = NABTS_FS_SYNC; break;
default: // Just copy the byte to the NDIS packet.
//
CopyNabToPacket( *pszNabIn, pNabStream, pFilter); break;
} break;
case NABTS_FS_COLLECT_ESCAPE:
pNabStream->ulFrameState = NABTS_FS_COLLECT;
switch (*pszNabIn) { case TRANS_FRAME_ESCAPE: //
// Special way to insert a FRAME_ESCAPE
// character as part of the data.
//
TEST_DEBUG( TEST_DBG_RECV, ("SLIP NABTS_FS_COLLECT_ESCAPE....TRANS_FRAME_ESCAPE\n")); CopyNabToPacket( (UCHAR) FRAME_ESCAPE, pNabStream, pFilter); break;
case TRANS_FRAME_END: //
// Special way to insert a FRAME_END
// character as part of the data.
//
TEST_DEBUG( TEST_DBG_RECV, ("SLIP NABTS_FS_COLLECT_ESCAPE.....TRANS_FRAME_END\n")); CopyNabToPacket( (UCHAR) FRAME_END, pNabStream, pFilter); break;
default: // Any other character that follows FRAME_ESCAPE
// is just inserted into the packet.
//
CopyNabToPacket( *pszNabIn, pNabStream, pFilter); break; } break;
default: //
// We should never be in an unknown state.
//
TEST_DEBUG( TEST_DBG_RECV, ("SLIP UNKNOWN STATE.....ReSyncing\n")); ASSERT( pNabStream->ulFrameState); ResetNabStream (pFilter, pNabStream, NULL, NULL, 0); pNabStream->ulFrameState = NABTS_FS_SYNC;
break; }
}
ret:
TEST_DEBUG( TEST_DBG_RECV, ("SLIP Completed ntNabtsRecv\n")); return status; }
//////////////////////////////////////////////////////////////////////////////
//
// Create a NAB Stream Context.
//
NTSTATUS ntCreateNabStreamContext( PSLIP_FILTER pFilter, ULONG groupID, PNAB_STREAM *ppNabStream ) //////////////////////////////////////////////////////////////////////////////
{ NTSTATUS status = STATUS_SUCCESS; PNAB_STREAM pNabStream = NULL;
TEST_DEBUG (TEST_DBG_NAB, ("******************************** Creating NAB STREAM for group ID %d\n", groupID));
//
// Initialize output paramter
//
*ppNabStream = NULL;
//
// Allocate a Nab Stream structure.
//
status = ntAllocateNabStreamContext (&pNabStream); if(status == STATUS_SUCCESS) { pNabStream->ulType = (ULONG)NAB_STREAM_SIGNATURE; pNabStream->ulSize = sizeof (NAB_STREAM); pNabStream->ulFrameState = NABTS_FS_SYNC; pNabStream->ulMpegCrc = 0xFFFFFFFF; pNabStream->fUsed = TRUE; pNabStream->groupID = groupID;
//
// Add the new Stream Context to the User's Stream Context List.
//
InsertTailList (&pFilter->StreamContxList, &pNabStream->Linkage);
*ppNabStream = pNabStream; }
return status; }
//////////////////////////////////////////////////////////////////////////////
NTSTATUS ntAllocateNabStreamContext( PNAB_STREAM *ppNabStream ) //////////////////////////////////////////////////////////////////////////////
{ NTSTATUS status = STATUS_SUCCESS; PNAB_STREAM pNabStream = NULL;
pNabStream = ExAllocatePool (NonPagedPool, sizeof(NAB_STREAM));
if (pNabStream == NULL) { *ppNabStream = NULL; return (STATUS_NO_MEMORY); }
RtlZeroMemory (pNabStream, sizeof(NAB_STREAM));
*ppNabStream = pNabStream;
return status; }
//////////////////////////////////////////////////////////////////////////////
VOID vDestroyNabStreamContext( PSLIP_FILTER pFilter, PNAB_STREAM pNabStream, BOOLEAN fUseSpinLock ) //////////////////////////////////////////////////////////////////////////////
{ KIRQL Irql;
if(fUseSpinLock) { //
// Lock the user.
//
KeAcquireSpinLock( &pFilter->StreamUserSpinLock, &Irql); }
//
// Remove the stream context from the user's list.
//
RemoveEntryList (&pNabStream->Linkage);
if(fUseSpinLock) { //
// UnLock the user.
//
KeReleaseSpinLock( &pFilter->StreamUserSpinLock, Irql); }
//
// Free the stream's SRB, if any.
//
if (pNabStream->pSrb) { StreamClassStreamNotification (StreamRequestComplete, pNabStream->pSrb->StreamObject, pNabStream->pSrb); TEST_DEBUG (TEST_DBG_TRACE, ("SLIP: StreamRequestComplete on pSrb: %08X\n", pNabStream->pSrb)); pNabStream->pSrb = NULL; }
//
// Free the stream context memory.
//
TEST_DEBUG (TEST_DBG_NAB, ("Deleting NAB STREAM for group ID: %d... ", pNabStream->groupID)); ExFreePool (pNabStream);
}
//////////////////////////////////////////////////////////////////////////////
VOID vCheckNabStreamLife ( PSLIP_FILTER pFilter ) //////////////////////////////////////////////////////////////////////////////
{ PNAB_STREAM pNabStream; PLIST_ENTRY pFlink;
TEST_DEBUG( TEST_DBG_RECV, ("Entering - vCheckNabStreamLife - pFilter: %x\n", pFilter));
//
// Go through the StreamContextList. Remove any stream context structures that have
// expired their life span.
//
for (pFlink = pFilter->StreamContxList.Flink; pFlink != &pFilter->StreamContxList; pFlink = pFlink->Flink) { pNabStream = CONTAINING_RECORD (pFlink, NAB_STREAM, Linkage);
TEST_DEBUG (TEST_DBG_NAB, ("Checking NAB STREAM life for group ID %d ... ", pNabStream->groupID));
if (pNabStream->fUsed) { TEST_DEBUG (TEST_DBG_NAB, (" USED\n")); } else { TEST_DEBUG (TEST_DBG_NAB, (" NOT USED\n")); }
if(!pNabStream->fUsed) {
// Point at the previous Stream;
pFlink = pFlink->Blink;
//
// Remove the stream from the User's stream context list.
//
//
// vDestroyNabStreamContext returns the active NDIS Packet (if any) to
// the adapter's free list, remove the stream context from the user list
// (if specified) and free the stream context structure memory.
//
vDestroyNabStreamContext( pFilter, pNabStream, FALSE); pFilter->Stats.ulTotalNabStreamsTimedOut += 1; } else { //
// This flag must be set back to TRUE before the next DPC fires or
// this stream will be removed.
//
pNabStream->fUsed = FALSE; } }
TEST_DEBUG ( TEST_DBG_RECV, ("Leaving - vCheckNabStreamLife\n")); }
|