Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1449 lines
53 KiB

//////////////////////////////////////////////////////////////////////////
//
//
// 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"));
}