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.
 
 
 
 
 
 

1537 lines
49 KiB

//============================================================================
//
// Copyright (C) 2000 Microsoft Corporation
//
// FILE: PGM.c
//
// Description: Parses a PGM frame
// Displays the PGM header
// Displays the PGM options
//
// Note: info for this parser was gleaned from:
// (PGM Documentation)
//
// Modification History
//
// Madhurima Pawar ([email protected]) 08/04/00 Created
//============================================================================
#include "PGM.h"
//============================================================================
//Global variables
//============================================================================
HPROTOCOL hPGM = NULL; //Handle to PGM's parser database properties
DWORD PGMAttached = 0; //Number of times protocol instances that are running
//====================================================================
//External functions used to regester PGM. These function are exported to Netmon
//By putting a _delspec the function is immediatly exported and does not have to
//be exported through a .def file. This is useful when many parsers are in
//one dll and some are included and some are not.
//=================================================================================
extern VOID _declspec(dllexport) WINAPI PGM_Register( HPROTOCOL hPGM);
extern VOID _declspec(dllexport) WINAPI PGM_Deregister( HPROTOCOL hPGM);
extern LPBYTE _declspec(dllexport) WINAPI PGM_RecognizeFrame( HFRAME hFrame,
LPBYTE pMACFrame,
LPBYTE pPGMFrame,
DWORD PGMType,
DWORD BytesLeft,
HPROTOCOL hPrevProtocol,
DWORD nPrevProtOffset,
LPDWORD pProtocolStatus,
LPHPROTOCOL phNextProtocol,
PDWORD_PTR InstData);
extern LPBYTE _declspec(dllexport) WINAPI PGM_AttachProperties( HFRAME hFrame,
LPBYTE pMACFrame,
LPBYTE pPGMFrame,
DWORD PGMType,
DWORD BytesLeft,
HPROTOCOL hPrevProtocol,
DWORD nPrevProtOffset,
DWORD_PTR InstData);
extern DWORD _declspec(dllexport) WINAPI PGM_FormatProperties( HFRAME hFrame,
LPBYTE pMACFrame,
LPBYTE pPGMFrame,
DWORD nPropertyInsts,
LPPROPERTYINST p);
extern VOID WINAPIV PGM_FmtSummary( LPPROPERTYINST pPropertyInst );
//============================================================================
//Format functions customize the format of the data. Network Monitor
//provides baic format structures such as IP version 4 address.
//All other formats must be writen by the programmer.
//============================================================================
VOID WINAPIV PGM_FormatSummary( LPPROPERTYINST pPropertyInst);
//============================================================================
//Define the entry points that we will pass back to NetMon at dll
//entry time
//============================================================================
ENTRYPOINTS PGMEntryPoints =
{
PGM_Register,
PGM_Deregister,
PGM_RecognizeFrame,
PGM_AttachProperties,
PGM_FormatProperties,
};
//====================================================================
//Property Value Labels are tables that map numbers to strings.
//====================================================================
LABELED_BYTE PGMTypes[] = //The types of PGM
{
{ 0, "SPM" },
{ 1, "POLL" },
{ 2, "POLR" },
{ 4, "ODATA" },
{ 5, "RDATA" },
{ 8, "NACK" },
{ 9, "NNACK" },
{ 10, "NCF" } ,
};
LABELED_BIT PGMHeaderOptions[] =
{
{ 7, "Non-Parity ", "PARITY " },
{ 6, "Not a variable-length parity packet", "VARIABLE LENGTH PARITY PACKET" },
{ 1, "Not Network Significant ", "NETWORK SIGNIFICANT " },
{ 0, "No header Options ", "Packet header has options " },
};
LABELED_BIT PGMParityOptions[] =
{
{ 1, "No Pro-Active Parity ", "PRO-ACTIVE Parity enabled" },
{ 0, "Selective NAKs Only ", "ON-DEMAND Parity enabled " },
};
//====================================================================
//Make a set out of the above listings. The set contains the list
//aswell as the size
//====================================================================
SET PGMTypesSET = {(sizeof(PGMTypes)/sizeof(LABELED_BYTE)), PGMTypes };
SET PGMHeaderOptionsSET = {(sizeof(PGMHeaderOptions)/sizeof(LABELED_BIT)), PGMHeaderOptions };
SET PGMParityOptionsSET = {(sizeof(PGMParityOptions)/sizeof(LABELED_BIT)), PGMParityOptions };
//====================================================================
//PGM Database (Properties Table). This table stores the properties
//of each field in an PGM package. Each field property has a name,
//size and format function. FormatPropertyInstance is the standard
//NetMon formatter. The comment is the location of the property in
//the table
//====================================================================
PROPERTYINFO PGMPropertyTable[] =
{
// PGM_SUMMARY (0)
{ 0, 0,
"Summary",
"Summary of the PGM Packet",
PROP_TYPE_SUMMARY,
PROP_QUAL_NONE,
NULL,
PGM_FMT_STR_SIZE,
PGM_FmtSummary
},
// PGM_SOURCE_PORT (1)
{ 0, 0,
"Source Port",
"Source Port",
PROP_TYPE_BYTESWAPPED_WORD,
PROP_QUAL_NONE,
NULL,
PGM_FMT_STR_SIZE,
FormatPropertyInstance
},
// PGM_DESTINATION_PORT (2)
{ 0, 0,
"Destination Port",
"Destination Port",
PROP_TYPE_BYTESWAPPED_WORD,
PROP_QUAL_NONE,
NULL,
PGM_FMT_STR_SIZE,
FormatPropertyInstance
},
// PGM_TYPE (3)
{ 0, 0,
"Type",
"Type of PGM",
PROP_TYPE_BYTE,
PROP_QUAL_LABELED_SET,
&PGMTypesSET,
PGM_FMT_STR_SIZE,
FormatPropertyInstance
},
// PGM_CHECKSUM (4)
{ 0, 0,
"Checksum",
"Checksum for PGM packet",
PROP_TYPE_BYTESWAPPED_WORD,
PROP_QUAL_NONE,
NULL,
PGM_FMT_STR_SIZE,
FormatPropertyInstance
},
// PGM_GLOBAL_SOURCE_ID (5)
{ 0, 0,
"Global Source Id",
"Global Source Id for PGM session",
PROP_TYPE_STRING,
PROP_QUAL_NONE,
NULL,
PGM_FMT_STR_SIZE,
FormatPropertyInstance
},
// PGM_TSDU_LENGTH (6)
{ 0, 0,
"TSDU Length",
"TSDU Length",
PROP_TYPE_BYTESWAPPED_WORD,
PROP_QUAL_NONE,
NULL,
PGM_FMT_STR_SIZE,
FormatPropertyInstance
},
// PGM_SEQUENCE_NUMBER (7)
{ 0, 0,
"Sequence Number",
"Packet Sequence Number",
PROP_TYPE_BYTESWAPPED_DWORD,
PROP_QUAL_NONE,
NULL,
PGM_FMT_STR_SIZE,
FormatPropertyInstance
},
// PGM_TRAILING_EDGE (8)
{ 0, 0,
"Trailing Edge",
"Trailing Edge Sequence Number",
PROP_TYPE_BYTESWAPPED_DWORD,
PROP_QUAL_NONE,
NULL,
PGM_FMT_STR_SIZE,
FormatPropertyInstance
},
// PGM_LEADING_EDGE (9)
{ 0, 0,
"Leading Edge",
"Leading Edge Sequence Number",
PROP_TYPE_BYTESWAPPED_DWORD,
PROP_QUAL_NONE,
NULL,
PGM_FMT_STR_SIZE,
FormatPropertyInstance
},
// PGM_NLA_TYPE_SOURCE (10)
{ 0, 0,
"Source Path NLA",
"Source Path NLA",
PROP_TYPE_SUMMARY,
PROP_QUAL_NONE,
NULL,
PGM_FMT_STR_SIZE,
FormatPropertyInstance
},
// PGM_NLA_TYPE_MCAST_GROUP (11)
{ 0, 0,
"MCAST Group NLA",
"MCAST Group NLA",
PROP_TYPE_SUMMARY,
PROP_QUAL_NONE,
NULL,
PGM_FMT_STR_SIZE,
FormatPropertyInstance
},
// PGM_NLA_AFI (12)
{ 0, 0,
"NLA AFI",
"NLA AFI",
PROP_TYPE_BYTESWAPPED_WORD,
PROP_QUAL_NONE,
NULL,
PGM_FMT_STR_SIZE,
FormatPropertyInstance
},
// PGM_NLA_RESERVED (13)
{ 0, 0,
"NLA RESERVED",
"NLA RESERVED",
PROP_TYPE_BYTESWAPPED_WORD,
PROP_QUAL_NONE,
NULL,
PGM_FMT_STR_SIZE,
FormatPropertyInstance
},
// PGM_NLA_IP (14)
{ 0, 0,
"NLA ADDRESS",
"NLA ADDRESS",
PROP_TYPE_IP_ADDRESS,
PROP_QUAL_NONE,
NULL,
PGM_FMT_STR_SIZE,
FormatPropertyInstance
},
// PGM_OPTIONS (15)
{ 0, 0,
"Options",
"Options of PGM Packet",
PROP_TYPE_BYTE,
PROP_QUAL_NONE,
NULL,
PGM_FMT_STR_SIZE,
FormatPropertyInstance
},
// PGM_OPTIONS_FLAGS (16)
{ 0, 0,
"Options Flags",
"Options Flags",
PROP_TYPE_BYTE,
PROP_QUAL_FLAGS,
&PGMHeaderOptionsSET,
PGM_FMT_STR_SIZE*4,
FormatPropertyInstance
},
// PGM_HEADER_OPTIONS (17)
{ 0, 0,
"Pgm Header Options",
"Pgm Header Options",
PROP_TYPE_SUMMARY,
PROP_QUAL_NONE,
NULL,
PGM_FMT_STR_SIZE,
FormatPropertyInstance
},
// PGM_OPTION_TYPE_NAK_SEQ (18)
{ 0, 0,
"Nak / Ncf Sequences",
"Nak / Ncf Sequences",
PROP_TYPE_SUMMARY,
PROP_QUAL_NONE,
NULL,
PGM_FMT_STR_SIZE,
FormatPropertyInstance
},
// PGM_OPTION_TYPE_FRAGMENT (19)
{ 0, 0,
"Message Fragment",
"Message Fragment",
PROP_TYPE_SUMMARY,
PROP_QUAL_NONE,
NULL,
PGM_FMT_STR_SIZE,
FormatPropertyInstance
},
// PGM_OPTION_TYPE_LATE_JOINER (20)
{ 0, 0,
"Late Joiner",
"Late Joiner",
PROP_TYPE_SUMMARY,
PROP_QUAL_NONE,
NULL,
PGM_FMT_STR_SIZE,
FormatPropertyInstance
},
// PGM_OPTION_TYPE_SYN (21)
{ 0, 0,
"Session SYN",
"Session SYN",
PROP_TYPE_SUMMARY,
PROP_QUAL_NONE,
NULL,
PGM_FMT_STR_SIZE,
FormatPropertyInstance
},
// PGM_OPTION_TYPE_FIN (22)
{ 0, 0,
"Session FIN",
"Session FIN",
PROP_TYPE_SUMMARY,
PROP_QUAL_NONE,
NULL,
PGM_FMT_STR_SIZE,
FormatPropertyInstance
},
// PGM_OPTION_TYPE_RST (23)
{ 0, 0,
"Session Reset",
"Session Reset",
PROP_TYPE_SUMMARY,
PROP_QUAL_NONE,
NULL,
PGM_FMT_STR_SIZE,
FormatPropertyInstance
},
// PGM_OPTION_TYPE_PARITY_PRM (24)
{ 0, 0,
"Parity Parameters",
"Parity Parameters",
PROP_TYPE_SUMMARY,
PROP_QUAL_NONE,
NULL,
PGM_FMT_STR_SIZE,
FormatPropertyInstance
},
// PGM_OPTION_TYPE_PARITY_GRP (25)
{ 0, 0,
"Parity Group Option Present",
"Parity Group Option Present",
PROP_TYPE_SUMMARY,
PROP_QUAL_NONE,
NULL,
PGM_FMT_STR_SIZE,
FormatPropertyInstance
},
// PGM_OPTION_TYPE_PARITY_TGSIZE (26)
{ 0, 0,
"Parity Current TG Size Option Present",
"Parity Current TG Size Option Present",
PROP_TYPE_SUMMARY,
PROP_QUAL_NONE,
NULL,
PGM_FMT_STR_SIZE,
FormatPropertyInstance
},
// PGM_OPTIONS_FIELD_LENGTH (27)
{ 0, 0,
"Options Length",
"Options Length",
PROP_TYPE_BYTESWAPPED_WORD,
PROP_QUAL_NONE,
NULL,
PGM_FMT_STR_SIZE,
FormatPropertyInstance
},
// PGM_OPTIONS_NAK_SEQ (28)
{ 0, 0,
"Nak Sequence",
"Nak Sequence",
PROP_TYPE_BYTESWAPPED_DWORD,
PROP_QUAL_NONE,
NULL,
PGM_FMT_STR_SIZE,
FormatPropertyInstance
},
// PGM_OPTIONS_MESSAGE_FIRST_SEQUENCE (29)
{ 0, 0,
"Message First Sequence",
"Message First Sequence",
PROP_TYPE_BYTESWAPPED_DWORD,
PROP_QUAL_NONE,
NULL,
PGM_FMT_STR_SIZE,
FormatPropertyInstance
},
// PGM_OPTIONS_MESSAGE_OFFSET (30)
{ 0, 0,
"Message Offset",
"Message Offset",
PROP_TYPE_BYTESWAPPED_DWORD,
PROP_QUAL_NONE,
NULL,
PGM_FMT_STR_SIZE,
FormatPropertyInstance
},
// PGM_OPTIONS_MESSAGE_LENGTH (31)
{ 0, 0,
"Message Length",
"Message Length",
PROP_TYPE_BYTESWAPPED_DWORD,
PROP_QUAL_NONE,
NULL,
PGM_FMT_STR_SIZE,
FormatPropertyInstance
},
// PGM_OPTIONS_LATE_JOINER (32)
{ 0, 0,
"Late Joiner Sequence",
"Late Joiner Sequence",
PROP_TYPE_BYTESWAPPED_DWORD,
PROP_QUAL_NONE,
NULL,
PGM_FMT_STR_SIZE,
FormatPropertyInstance
},
// PGM_OPTIONS_PARITY_OPT (33)
{ 0, 0,
"Parity Flags",
"Parity Flags",
PROP_TYPE_BYTE,
PROP_QUAL_FLAGS,
&PGMParityOptionsSET,
PGM_FMT_STR_SIZE,
FormatPropertyInstance
},
// PGM_OPTIONS_PARITY_PRM_GRP_SZ (34)
{ 0, 0,
"Parity Group Size",
"Parity Group Size",
PROP_TYPE_BYTESWAPPED_DWORD,
PROP_QUAL_NONE,
NULL,
PGM_FMT_STR_SIZE,
FormatPropertyInstance
},
// PGM_OPTIONS_PARITY_GRP (35)
{ 0, 0,
"Parity Group Number",
"Parity Group Number",
PROP_TYPE_BYTESWAPPED_DWORD,
PROP_QUAL_NONE,
NULL,
PGM_FMT_STR_SIZE,
FormatPropertyInstance
},
// PGM_OPTIONS_PARITY_TG_SZ (36)
{ 0, 0,
"Parity TG Size",
"Parity TG Size",
PROP_TYPE_BYTESWAPPED_DWORD,
PROP_QUAL_NONE,
NULL,
PGM_FMT_STR_SIZE,
FormatPropertyInstance
},
// PGM_DATA (37)
{ 0,0,
"Data",
"Data contained in PGM packet",
PROP_TYPE_RAW_DATA,
PROP_QUAL_NONE,
NULL,
PGM_FMT_STR_SIZE,
FormatPropertyInstance },
};
//====================================================================
//Number of entries in the property table above
//====================================================================
DWORD nNumPGMProps = (sizeof(PGMPropertyTable)/sizeof(PROPERTYINFO));
//============================================================================
//
// PGM_LoadParser - Tells Netmon which protocol precedes and follows PGM
//
// Modification history: June 30, 1999
//
// Madhurima Pawar 08/04/00 Created
//============================================================================
DWORD PGM_LoadParser(PPF_PARSERINFO pParserInfo)
{
DWORD NumberOfHandOffSets=1;
//
//This information is visible when the parser is selected in NetMon
//
wsprintf( pParserInfo->szProtocolName, "PGM" );
wsprintf( pParserInfo->szComment, "Pragmatic General Multicast (PGM)" );
wsprintf( pParserInfo->szHelpFile, "");
//
//Allocate memory for the handoffset and its two entries
//
pParserInfo->pWhoHandsOffToMe=(PPF_HANDOFFSET)
HeapAlloc (GetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof (PF_HANDOFFSET) +
sizeof (PF_HANDOFFENTRY) * (NumberOfHandOffSets));
if(NULL==pParserInfo->pWhoHandsOffToMe)
{
//
//Unable to create handoffset
//
return 1;
}
pParserInfo->pWhoHandsOffToMe->nEntries=NumberOfHandOffSets;
//
//Indicate the port that belong to PGM.
//
wsprintf (pParserInfo->pWhoHandsOffToMe->Entry[0].szIniFile, "TCPIP.INI");
wsprintf (pParserInfo->pWhoHandsOffToMe->Entry[0].szIniSection, "IP_HandoffSet");
wsprintf (pParserInfo->pWhoHandsOffToMe->Entry[0].szProtocol, "PGM");
pParserInfo->pWhoHandsOffToMe->Entry[0].dwHandOffValue = PGM_PROTOCOL_NUMBER;
pParserInfo->pWhoHandsOffToMe->Entry[0].ValueFormatBase = HANDOFF_VALUE_FORMAT_BASE_DECIMAL;
return 0;
}
//============================================================================
// Function: ParserAutoInstallInfo
//
// Description: Installs the parser into NetMon. Sets up the Handoff set
// The handoffset indicates which protocol hands of to the parser and
// who the parser hands of to.
//
//
// Modification History
//
// Madhurima Pawar 08/04/00 Created
//=============================================================================
PPF_PARSERDLLINFO WINAPI ParserAutoInstallInfo()
{
PPF_PARSERDLLINFO pParserDllInfo;
DWORD NumProtocols, Error;
//The number of protocols in this parser is 1
NumProtocols = 1;
//Allocate memory for parser info:
pParserDllInfo = (PPF_PARSERDLLINFO) HeapAlloc (GetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof (PF_PARSERDLLINFO) +
(NumProtocols) * sizeof (PF_PARSERINFO));
//Failed to allocate memory
if( pParserDllInfo == NULL)
{
//
//Unable to allocate memory
//
return NULL;
}
// fill in the parser DLL info
pParserDllInfo->nParsers = NumProtocols;
// fill in the individual parser infos...
Error = PGM_LoadParser (&(pParserDllInfo->ParserInfo[0]));
if(Error)
{
//
//Unable to allocate memory
//
return(NULL);
}
//Return the parser information to netmon
return (pParserDllInfo);
}
//============================================================================
// Function: DLLEntry
//
// Description: Registers the parser with Netmon and creates the PGM
// Properties table.
//
// Modification History
//
// Madhurima Pawar 08/04/00 Created
//=============================================================================
BOOL WINAPI DLLEntry( HANDLE hInstance, ULONG Command, LPVOID Reserved)
{
// what type of call is this
switch( Command )
{
case DLL_PROCESS_ATTACH:
// are we loading for the first time?
if (PGMAttached == 0)
{
// the first time in we need to tell the kernel
// about ourselves
//Create PGM db it PGM added to Parser
hPGM = CreateProtocol ("PGM", &PGMEntryPoints, ENTRYPOINTS_SIZE);
}
PGMAttached++;
break;
case DLL_PROCESS_DETACH:
// are we detaching our last instance?
PGMAttached--;
if( PGMAttached == 0 )
{
// last guy out needs to clean up
DestroyProtocol( hPGM);
}
break;
}
// Netmon parsers ALWAYS return TRUE.
return TRUE;
}
//============================================================================
// Function: PGM_Register
//
// Description: Create our property database and handoff sets.
//
// Modification History
//
// Madhurima Pawar 08/04/00 Created
//============================================================================
VOID BHAPI PGM_Register( HPROTOCOL hPGM)
{
WORD i;
//
// tell the kernel to make reserve some space for our property table
//
CreatePropertyDatabase (hPGM, nNumPGMProps);
//
// add our properties to the kernel's database
//
for (i = 0; i < nNumPGMProps; i++)
{
AddProperty (hPGM, &PGMPropertyTable[i]);
}
}
//============================================================================
// Function: PGM_Deregister
//
// Description: Destroy our property database and handoff set
//
// Modification History
//
// Madhurima Pawar 08/04/00 Created
//============================================================================
VOID WINAPI PGM_Deregister( HPROTOCOL hPGM)
{
// tell the kernel that it may now free our database
DestroyPropertyDatabase (hPGM);
}
//============================================================================
// Function: PGM_RecognizeFrame
//
// Description: Determine whether we exist in the frame at the spot
// indicated. We also indicate who (if anyone) follows us
// and how much of the frame we claim.
//
//============================================================================
LPBYTE BHAPI PGM_RecognizeFrame( HFRAME hFrame,
LPBYTE pMacFrame,
LPBYTE pPGMFrame,
DWORD MacType,
DWORD BytesLeft,
HPROTOCOL hPrevProtocol,
DWORD nPrevProtOffset,
LPDWORD pProtocolStatus,
LPHPROTOCOL phNextProtocol,
PDWORD_PTR InstData)
{
//
// Since we do not know of any protocol currently on top of Pgm,
// we do not need to do much here.
//
#if 0
PPGM_COMMON_HDR pPGMHdr = (PPGM_COMMON_HDR) pPGMFrame;
SPM_PACKET_HEADER *pSpm = (SPM_PACKET_HEADER *) pPGMFrame;
DATA_PACKET_HEADER *pData = (DATA_PACKET_HEADER *) pPGMFrame;
NAK_NCF_PACKET_HEADER *pNakNcf = (NAK_NCF_PACKET_HEADER *) pPGMFrame;
DWORD BytesRequired = sizeof (PGM_COMMON_HDR);
BYTE PacketType;
tPACKET_OPTION_LENGTH UNALIGNED *pPacketExtension = NULL;
// do we have the minimum header
if (BytesLeft < BytesRequired)
{
//
// This not a valid Pgm frame
//
*pProtocolStatus = PROTOCOL_STATUS_NOT_RECOGNIZED;
return NULL;
}
PacketType = pPGMHdr->Type & 0x0f;
switch (PacketType)
{
case (PACKET_TYPE_SPM):
{
BytesRequired = sizeof (SPM_PACKET_HEADER);
pPacketExtension = (tPACKET_OPTION_LENGTH UNALIGNED *) (pSpm + 1);
break;
}
case (PACKET_TYPE_ODATA):
case (PACKET_TYPE_RDATA):
{
BytesRequired = sizeof (DATA_PACKET_HEADER);
pPacketExtension = (tPACKET_OPTION_LENGTH UNALIGNED *) (pData + 1);
break;
}
case (PACKET_TYPE_NAK):
case (PACKET_TYPE_NCF):
{
BytesTaken = sizeof (NAK_NCF_PACKET_HEADER);
pPacketExtension = (tPACKET_OPTION_LENGTH UNALIGNED *) (pNakNcf + 1);
break;
}
default:
{
//
// This not a recognized Pgm frame
//
*pProtocolStatus = PROTOCOL_STATUS_NOT_RECOGNIZED;
return NULL;
}
}
if ((pPGMHdr->Options & PACKET_HEADER_OPTIONS_PRESENT) &&
(BytesLeft >= BytesRequired + (sizeof(tPACKET_OPTION_LENGTH) + sizeof(tPACKET_OPTION_GENERIC))))
{
BytesRequired += pPacketExtension->TotalOptionsLength;
}
// do we have a complete header
if (BytesLeft < BytesRequired)
{
//
// This not a valid Pgm frame
//
*pProtocolStatus = PROTOCOL_STATUS_NOT_RECOGNIZED;
return NULL;
}
if (BytesLeft <= BytesRequired)
{
// No protocol follows us so claim whole packet
*pProtocolStatus = PROTOCOL_STATUS_CLAIMED;
return NULL;
}
*pProtocolStatus = PROTOCOL_STATUS_RECOGNIZED;
return NULL;
#endif // 0
// this is a Pgm frame but we don't know the next protocol
*pProtocolStatus = PROTOCOL_STATUS_CLAIMED;
return NULL;
}
//============================================================================
//============================================================================
DWORD
ProcessOptions(
HFRAME hFrame,
tPACKET_OPTION_LENGTH UNALIGNED *pPacketExtension,
DWORD BytesLeft,
BYTE PacketType
)
{
tPACKET_OPTION_GENERIC UNALIGNED *pOptionHeader;
USHORT TotalOptionsLength;
DWORD BytesProcessed = 0;
UCHAR i;
if ((BytesLeft < ((sizeof(tPACKET_OPTION_LENGTH) + sizeof(tPACKET_OPTION_GENERIC)))) || // Ext+opt
(pPacketExtension->Type != PACKET_OPTION_LENGTH) ||
(pPacketExtension->Length != 4) ||
(BytesLeft < (TotalOptionsLength = ntohs (pPacketExtension->TotalOptionsLength)))) // Verify length
{
//
// Need to get at least our header from transport!
//
return (BytesProcessed);
}
AttachPropertyInstance (hFrame,
PGMPropertyTable[PGM_HEADER_OPTIONS].hProperty,
TotalOptionsLength,
pPacketExtension,
0,1,0); // HELPID, Level, Errorflag
AttachPropertyInstance (hFrame,
PGMPropertyTable[PGM_OPTIONS_FIELD_LENGTH].hProperty,
sizeof (WORD),
&pPacketExtension->TotalOptionsLength,
0,2,0); // HELPID, Level, Errorflag
pOptionHeader = (tPACKET_OPTION_GENERIC UNALIGNED *) (pPacketExtension + 1);
BytesLeft -= PACKET_OPTION_LENGTH;
BytesProcessed += PGM_PACKET_EXTENSION_LENGTH;
do
{
if (pOptionHeader->Length > BytesLeft)
{
return (BytesProcessed);
}
switch (pOptionHeader->OptionType & ~PACKET_OPTION_TYPE_END_BIT)
{
case (PACKET_OPTION_NAK_LIST):
{
if (((PacketType != PACKET_TYPE_NAK) &&
(PacketType != PACKET_TYPE_NCF) &&
(PacketType != PACKET_TYPE_NNAK)) ||
(pOptionHeader->Length < PGM_PACKET_OPT_MIN_NAK_LIST_LENGTH) ||
(pOptionHeader->Length > PGM_PACKET_OPT_MAX_NAK_LIST_LENGTH))
{
return (BytesProcessed);
}
AttachPropertyInstance (hFrame,
PGMPropertyTable[PGM_OPTION_TYPE_NAK_SEQ].hProperty,
pOptionHeader->Length,
pOptionHeader,
0,2,0); // HELPID, Level, Errorflag
for (i=0; i < (pOptionHeader->Length-4)/4; i++)
{
AttachPropertyInstance (hFrame,
PGMPropertyTable[PGM_OPTIONS_NAK_SEQ].hProperty,
sizeof (DWORD),
&((PULONG)(pOptionHeader+1))[i],
0,3,0); // HELPID, Level, Errorflag
}
break;
}
case (PACKET_OPTION_FRAGMENT):
{
if (pOptionHeader->Length != PGM_PACKET_OPT_FRAGMENT_LENGTH)
{
return (BytesProcessed);
}
AttachPropertyInstance (hFrame,
PGMPropertyTable[PGM_OPTION_TYPE_FRAGMENT].hProperty,
PGM_PACKET_OPT_FRAGMENT_LENGTH,
pOptionHeader,
0,2,0); // HELPID, Level, Errorflag
AttachPropertyInstance (hFrame,
PGMPropertyTable[PGM_OPTIONS_MESSAGE_FIRST_SEQUENCE].hProperty,
sizeof (DWORD),
&((PULONG)(pOptionHeader+1))[0],
0,3,0); // HELPID, Level, Errorflag
AttachPropertyInstance (hFrame,
PGMPropertyTable[PGM_OPTIONS_MESSAGE_OFFSET].hProperty,
sizeof (DWORD),
&((PULONG)(pOptionHeader+1))[1],
0,3,0); // HELPID, Level, Errorflag
AttachPropertyInstance (hFrame,
PGMPropertyTable[PGM_OPTIONS_MESSAGE_LENGTH].hProperty,
sizeof (DWORD),
&((PULONG)(pOptionHeader+1))[2],
0,3,0); // HELPID, Level, Errorflag
break;
}
case (PACKET_OPTION_JOIN):
{
if (pOptionHeader->Length != PGM_PACKET_OPT_JOIN_LENGTH)
{
return (BytesProcessed);
}
AttachPropertyInstance (hFrame,
PGMPropertyTable[PGM_OPTION_TYPE_LATE_JOINER].hProperty,
PGM_PACKET_OPT_JOIN_LENGTH,
pOptionHeader,
0,2,0); // HELPID, Level, Errorflag
AttachPropertyInstance (hFrame,
PGMPropertyTable[PGM_OPTIONS_LATE_JOINER].hProperty,
sizeof (DWORD),
&((PULONG)(pOptionHeader+1))[0],
0,3,0); // HELPID, Level, Errorflag
break;
}
case (PACKET_OPTION_SYN):
{
if (pOptionHeader->Length != PGM_PACKET_OPT_SYN_LENGTH)
{
return (BytesProcessed);
}
AttachPropertyInstance (hFrame,
PGMPropertyTable[PGM_OPTION_TYPE_SYN].hProperty,
PGM_PACKET_OPT_SYN_LENGTH,
pOptionHeader,
0, 2, 0);
break;
}
case (PACKET_OPTION_FIN):
{
if (pOptionHeader->Length != PGM_PACKET_OPT_FIN_LENGTH)
{
return (BytesProcessed);
}
AttachPropertyInstance (hFrame,
PGMPropertyTable[PGM_OPTION_TYPE_FIN].hProperty,
PGM_PACKET_OPT_FIN_LENGTH,
pOptionHeader,
0, 2, 0);
break;
}
case (PACKET_OPTION_RST):
{
if (pOptionHeader->Length != PGM_PACKET_OPT_RST_LENGTH)
{
return (BytesProcessed);
}
AttachPropertyInstance (hFrame,
PGMPropertyTable[PGM_OPTION_TYPE_RST].hProperty,
PGM_PACKET_OPT_RST_LENGTH,
pOptionHeader,
0, 2, 0);
break;
}
//
// FEC options
//
case (PACKET_OPTION_PARITY_PRM):
{
if (pOptionHeader->Length != PGM_PACKET_OPT_PARITY_PRM_LENGTH)
{
return (BytesProcessed);
}
AttachPropertyInstance (hFrame,
PGMPropertyTable[PGM_OPTION_TYPE_PARITY_PRM].hProperty,
PGM_PACKET_OPT_PARITY_PRM_LENGTH,
pOptionHeader,
0, 2, 0);
AttachPropertyInstance (hFrame,
PGMPropertyTable[PGM_OPTIONS_PARITY_OPT].hProperty,
sizeof (BYTE),
&pOptionHeader->OptionSpecific,
0,3,0); // HELPID, Level, Errorflag
AttachPropertyInstance (hFrame,
PGMPropertyTable[PGM_OPTIONS_PARITY_PRM_GRP_SZ].hProperty,
sizeof (DWORD),
&((PULONG)(pOptionHeader+1))[0],
0,3,0); // HELPID, Level, Errorflag
break;
}
case (PACKET_OPTION_PARITY_GRP):
{
if (pOptionHeader->Length != PGM_PACKET_OPT_PARITY_GRP_LENGTH)
{
return (BytesProcessed);
}
AttachPropertyInstance (hFrame,
PGMPropertyTable[PGM_OPTION_TYPE_PARITY_GRP].hProperty,
PGM_PACKET_OPT_PARITY_GRP_LENGTH,
pOptionHeader,
0, 2, 0);
AttachPropertyInstance (hFrame,
PGMPropertyTable[PGM_OPTIONS_PARITY_GRP].hProperty,
sizeof (DWORD),
&((PULONG)(pOptionHeader+1))[0],
0,3,0); // HELPID, Level, Errorflag
break;
}
case (PACKET_OPTION_CURR_TGSIZE):
{
if (pOptionHeader->Length != PGM_PACKET_OPT_PARITY_CUR_TGSIZE_LENGTH)
{
return (BytesProcessed);
}
AttachPropertyInstance (hFrame,
PGMPropertyTable[PGM_OPTION_TYPE_PARITY_TGSIZE].hProperty,
PGM_PACKET_OPT_PARITY_CUR_TGSIZE_LENGTH,
pOptionHeader,
0, 2, 0);
AttachPropertyInstance (hFrame,
PGMPropertyTable[PGM_OPTIONS_PARITY_TG_SZ].hProperty,
sizeof (DWORD),
&((PULONG)(pOptionHeader+1))[0],
0,3,0); // HELPID, Level, Errorflag
break;
}
default:
{
return (BytesProcessed);
}
}
BytesLeft -= pOptionHeader->Length;
BytesProcessed += pOptionHeader->Length;
if (pOptionHeader->OptionType & PACKET_OPTION_TYPE_END_BIT)
{
break;
}
pOptionHeader = (tPACKET_OPTION_GENERIC UNALIGNED *)
(((UCHAR *) pOptionHeader) + pOptionHeader->Length);
} while (BytesLeft >= sizeof(tPACKET_OPTION_GENERIC));
return (BytesProcessed);
}
VOID
PGM_FmtNLA(
HFRAME hFrame,
NLA *pNLA,
BOOL fIsSourceNLA
)
{
//The type of the PGM frame
if (fIsSourceNLA)
{
AttachPropertyInstance (hFrame,
PGMPropertyTable[PGM_NLA_TYPE_SOURCE].hProperty,
sizeof (NLA),
pNLA,
0,1,0); // HELPID, Level, Errorflag
}
else
{
AttachPropertyInstance (hFrame,
PGMPropertyTable[PGM_NLA_TYPE_MCAST_GROUP].hProperty,
sizeof (NLA),
pNLA,
0,1,0); // HELPID, Level, Errorflag
}
AttachPropertyInstance (hFrame,
PGMPropertyTable[PGM_NLA_AFI].hProperty,
sizeof (WORD),
&pNLA->NLA_AFI,
0,2,0); // HELPID, Level, Errorflag
AttachPropertyInstance (hFrame,
PGMPropertyTable[PGM_NLA_RESERVED].hProperty,
sizeof (WORD),
&pNLA->Reserved,
0,2,0); // HELPID, Level, Errorflag
AttachPropertyInstance (hFrame,
PGMPropertyTable[PGM_NLA_IP].hProperty,
sizeof (DWORD),
&pNLA->IpAddress,
0,2,0); // HELPID, Level, Errorflag
}
//============================================================================
// Function: PGM_AttachProperties
//
// Description: Indicate where in the frame each of our properties live.
//
// Modification History
//
// Madhurima Pawar 08/04/00 Created
//============================================================================
LPBYTE BHAPI PGM_AttachProperties( HFRAME hFrame,
LPBYTE pMacFrame,
LPBYTE pPGMFrame,
DWORD MacType,
DWORD BytesLeft,
HPROTOCOL hPrevProtocol,
DWORD nPrevProtOffset,
DWORD_PTR InstData)
{
PPGM_COMMON_HDR pPGMHdr = (PPGM_COMMON_HDR)pPGMFrame;
BYTE PacketType;
USHORT TSIPort;
UCHAR pGlobalSrcId [SOURCE_ID_LENGTH*2+1+sizeof(USHORT)*2+1];
SPM_PACKET_HEADER *pSpm = (SPM_PACKET_HEADER *) pPGMHdr;
DATA_PACKET_HEADER *pData = (DATA_PACKET_HEADER *) pPGMHdr;
NAK_NCF_PACKET_HEADER *pNakNcf = (NAK_NCF_PACKET_HEADER *) pPGMHdr;
tPACKET_OPTION_LENGTH *pOptionsHeader = NULL;
DWORD BytesTaken = 0;
DWORD OptionsLength = 0;
PUCHAR pPgmData;
PacketType = pPGMHdr->Type & 0x0f;
if ((PacketType == PACKET_TYPE_NAK) ||
(PacketType == PACKET_TYPE_NNAK) ||
(PacketType == PACKET_TYPE_SPMR) ||
(PacketType == PACKET_TYPE_POLR))
{
TSIPort = ntohs (pPGMHdr->DestPort);
}
else
{
TSIPort = ntohs (pPGMHdr->SrcPort);
}
wsprintf (pGlobalSrcId, "%02X%02X%02X%02X%02X%02X.%04X",
pPGMHdr->gSourceId[0],
pPGMHdr->gSourceId[1],
pPGMHdr->gSourceId[2],
pPGMHdr->gSourceId[3],
pPGMHdr->gSourceId[4],
pPGMHdr->gSourceId[5],
TSIPort);
//Add the PGM header information
//PGM summary information transaction ID and Message type
//Has a special formater PGM_FormatSummary
AttachPropertyInstance( hFrame,
PGMPropertyTable[PGM_SUMMARY].hProperty,
(WORD) BytesLeft,
(LPBYTE)pPGMFrame,
0, 0, 0 );
//The source port of the PGM frame
AttachPropertyInstance (hFrame,
PGMPropertyTable[PGM_SOURCE_PORT].hProperty,
sizeof(WORD),
&pPGMHdr->SrcPort,
0, 1, 0);
AttachPropertyInstance (hFrame,
PGMPropertyTable[PGM_DESTINATION_PORT].hProperty,
sizeof(WORD),
&pPGMHdr->DestPort,
0, 1, 0);
//The type of the PGM frame
AttachPropertyInstanceEx( hFrame,
PGMPropertyTable[PGM_TYPE].hProperty,
sizeof(BYTE),
&pPGMHdr->Type,
sizeof(BYTE),
&PacketType,
0, 1, 0);
AttachPropertyInstance (hFrame,
PGMPropertyTable[PGM_OPTIONS].hProperty,
sizeof (BYTE),
&pPGMHdr->Options,
0,1,0); // HELPID, Level, Errorflag
AttachPropertyInstance (hFrame,
PGMPropertyTable[PGM_OPTIONS_FLAGS].hProperty,
sizeof (BYTE),
&pPGMHdr->Options,
0,2,0); // HELPID, Level, Errorflag
//The checksum of the PGM frame
AttachPropertyInstance( hFrame,
PGMPropertyTable[PGM_CHECKSUM].hProperty,
sizeof(WORD),
&(pPGMHdr->Checksum),
0, 1, 0);
//The Global Session Id
AttachPropertyInstanceEx (hFrame,
PGMPropertyTable[PGM_GLOBAL_SOURCE_ID].hProperty,
SOURCE_ID_LENGTH,
pPGMHdr->gSourceId,
(SOURCE_ID_LENGTH*2+1+sizeof(USHORT)*2+1),
pGlobalSrcId,
0, 1, 0);
//The source port of the PGM frame
AttachPropertyInstance( hFrame,
PGMPropertyTable[PGM_TSDU_LENGTH].hProperty,
sizeof(WORD),
&pPGMHdr->TSDULength,
0, 1, 0);
switch (PacketType)
{
case (PACKET_TYPE_SPM):
{
// Spm Sequence Number
AttachPropertyInstance (hFrame,
PGMPropertyTable[PGM_SEQUENCE_NUMBER].hProperty,
sizeof(DWORD),
&pSpm->SpmSequenceNumber,
0, 1, 0);
// Sender's trailing edge
AttachPropertyInstance (hFrame,
PGMPropertyTable[PGM_TRAILING_EDGE].hProperty,
sizeof(DWORD),
&pSpm->TrailingEdgeSeqNumber,
0, 1, 0);
// Sender's trailing edge
AttachPropertyInstance (hFrame,
PGMPropertyTable[PGM_LEADING_EDGE].hProperty,
sizeof(DWORD),
&pSpm->LeadingEdgeSeqNumber,
0, 1, 0);
PGM_FmtNLA (hFrame, &pSpm->PathNLA, TRUE);
BytesTaken = sizeof (SPM_PACKET_HEADER);
pOptionsHeader = (tPACKET_OPTION_LENGTH *) (pSpm + 1);
break;
}
case (PACKET_TYPE_ODATA):
case (PACKET_TYPE_RDATA):
{
// Sender's sequence number
AttachPropertyInstance (hFrame,
PGMPropertyTable[PGM_SEQUENCE_NUMBER].hProperty,
sizeof(DWORD),
&pData->DataSequenceNumber,
0, 1, 0);
// Sender's trailing edge
AttachPropertyInstance (hFrame,
PGMPropertyTable[PGM_TRAILING_EDGE].hProperty,
sizeof(DWORD),
&pData->TrailingEdgeSequenceNumber,
0, 1, 0);
BytesTaken = sizeof (DATA_PACKET_HEADER);
pOptionsHeader = (tPACKET_OPTION_LENGTH *) (pData + 1);
break;
}
case (PACKET_TYPE_NAK):
case (PACKET_TYPE_NCF):
{
AttachPropertyInstance (hFrame,
PGMPropertyTable[PGM_SEQUENCE_NUMBER].hProperty,
sizeof(DWORD),
&pNakNcf->RequestedSequenceNumber,
0, 1, 0);
PGM_FmtNLA (hFrame, &pNakNcf->SourceNLA, TRUE);
PGM_FmtNLA (hFrame, &pNakNcf->MCastGroupNLA, FALSE);
BytesTaken = sizeof (NAK_NCF_PACKET_HEADER);
pOptionsHeader = (tPACKET_OPTION_LENGTH *) (pNakNcf + 1);
break;
}
default:
{
break;
}
}
if ((pPGMHdr->Options & PACKET_HEADER_OPTIONS_PRESENT) &&
(pOptionsHeader))
{
OptionsLength = ProcessOptions (hFrame, pOptionsHeader, (BytesLeft-BytesTaken), PacketType);
}
if (((PacketType == PACKET_TYPE_ODATA) ||
(PacketType == PACKET_TYPE_RDATA)) &&
(BytesLeft > (BytesTaken+OptionsLength)))
{
BytesLeft -= (BytesTaken+OptionsLength);
pPgmData = ((PUCHAR) pPGMHdr) + BytesTaken + OptionsLength;
AttachPropertyInstance (hFrame,
PGMPropertyTable[PGM_DATA].hProperty,
BytesLeft,
pPgmData,
0,1,0); // HELPID, Level, Errorflag
}
//Always returns NULL
return NULL;
}
//============================================================================
// Function: PGM_FormatProperties
//
// Description: Format the given properties on the given frame.
//
// Modification History
//
// Madhurima Pawar 08/04/00 Created
//============================================================================
DWORD BHAPI PGM_FormatProperties( HFRAME hFrame,
LPBYTE pMacFrame,
LPBYTE pPGMFrame,
DWORD nPropertyInsts,
LPPROPERTYINST p)
{
// loop through the property instances
while( nPropertyInsts-- > 0)
{
// and call the formatter for each
( (FORMAT)(p->lpPropertyInfo->InstanceData) )( p);
p++;
}
return NMERR_SUCCESS;
}
//*****************************************************************************
//
// Name: PGM_FmtSummary
//
// Description:
//
// Parameters: LPPROPERTYINST lpPropertyInst: pointer to property instance.
//
// Return Code: VOID.
//
// History:
// 10/15/2000 MAlam Created.
//
//*****************************************************************************
VOID WINAPIV
PGM_FmtSummary(
LPPROPERTYINST pPropertyInst
)
{
LPBYTE pReturnedString = pPropertyInst->szPropertyText;
PPGM_COMMON_HDR pPgmHeader = (PPGM_COMMON_HDR) (pPropertyInst->lpData);
SPM_PACKET_HEADER *pSpm = (SPM_PACKET_HEADER *) pPgmHeader;
DATA_PACKET_HEADER *pData = (DATA_PACKET_HEADER *) pPgmHeader;
NAK_NCF_PACKET_HEADER *pNakNcf = (NAK_NCF_PACKET_HEADER *) pPgmHeader;
UCHAR PacketType = pPgmHeader->Type & 0x0f;
UCHAR *szPacketDesc = NULL;
USHORT TSIPort;
if ((PacketType == PACKET_TYPE_NAK) ||
(PacketType == PACKET_TYPE_NNAK) ||
(PacketType == PACKET_TYPE_SPMR) ||
(PacketType == PACKET_TYPE_POLR))
{
TSIPort = ntohs (pPgmHeader->DestPort);
}
else
{
TSIPort = ntohs (pPgmHeader->SrcPort);
}
szPacketDesc = LookupByteSetString (&PGMTypesSET, PacketType);
wsprintf (pReturnedString,
"%s%s:",
szPacketDesc, (pPgmHeader->Options & PACKET_HEADER_OPTIONS_PARITY ? " (P)" : ""));
switch (PacketType)
{
case (PACKET_TYPE_SPM):
{
wsprintf (&pReturnedString [strlen(pReturnedString)],
" Seq: %d, Window: %d-%d",
ntohl (pSpm->SpmSequenceNumber), ntohl (pSpm->TrailingEdgeSeqNumber), ntohl (pSpm->LeadingEdgeSeqNumber));
break;
}
case (PACKET_TYPE_ODATA):
case (PACKET_TYPE_RDATA):
{
wsprintf (&pReturnedString [strlen(pReturnedString)],
" Seq: %d, Trail: %d, DataBytes: %d",
ntohl (pData->DataSequenceNumber), ntohl (pData->TrailingEdgeSequenceNumber),
((ULONG) ntohs (pPgmHeader->TSDULength)));
break;
}
case (PACKET_TYPE_NAK):
case (PACKET_TYPE_NCF):
{
wsprintf (&pReturnedString [strlen(pReturnedString)],
" Seq: %d%s",
ntohl (pNakNcf->RequestedSequenceNumber),
(pPgmHeader->Options & PACKET_HEADER_OPTIONS_PRESENT ? " ..." : ""));
break;
}
default:
{
break;
}
}
wsprintf (&pReturnedString [strlen(pReturnedString)],
" TSIPort = %hu", TSIPort);
}