|
|
//=============================================================================
// MODULE: ccmp.c
//
// Description:
//
// Bloodhound Parser DLL for the Cluster Control Message Protocol
//
// Modification History
//
// Mike Massa 03/21/97 Created
//=============================================================================
#include "precomp.h"
#pragma hdrstop
//
// Constants
//
#define ClusterDefaultMaxNodes 16 // from clusdef.h
#define ClusterMinNodeId 1 // from clusdef.h
#define MAX_CLUSTER_SIZE ClusterDefaultMaxNodes
#define BYTEL 8 // number of bits in a uint8
#define BYTES_IN_CLUSTER ((MAX_CLUSTER_SIZE + BYTEL - 1) / BYTEL)
#define BYTE(cluster, node) ( (cluster)[(node) / BYTEL] ) // byte# in array
#define BIT(node) ( (node) % BYTEL ) // bit# in byte
typedef UCHAR cluster_t [BYTES_IN_CLUSTER]; typedef SHORT node_t;
typedef union _CX_CLUSTERSCREEN { ULONG UlongScreen; cluster_t ClusterScreen; } CX_CLUSTERSCREEN;
//
// converts external node number to internal
//
#define LOWEST_NODENUM ((node_t)ClusterMinNodeId) // starting node number
#define INT_NODE(ext_node) ((node_t)(ext_node - LOWEST_NODENUM))
#define EXT_NODE(int_node) ((node_t)(int_node + LOWEST_NODENUM))
#define CnpClusterScreenMember(c, i) \
((BOOLEAN)((BYTE(c,i) >> (BYTEL-1-BIT(i))) & 1))
#define CnpClusterScreenInsert(c, i) \
(BYTE(c, i) |= (1 << (BYTEL-1-BIT(i))))
#define CnpClusterScreenDelete(c, i) \
(BYTE(c, i) &= ~(1 << (BYTEL-1-BIT(i))))
//
// Types
//
typedef enum { CcmpInvalidMsgType = 0, CcmpHeartbeatMsgType = 1, CcmpPoisonMsgType = 2, CcmpMembershipMsgType = 3, CcmpMcastHeartbeatMsgType = 4 } CCMP_MSG_TYPE;
typedef enum { CcmpInvalidMsgCode = 0 } CCMP_MSG_CODE;
typedef struct { ULONG SeqNumber; ULONG AckNumber; } CCMP_HEARTBEAT_MSG, *PCCMP_HEARTBEAT_MSG;
typedef struct { ULONG NodeCount; CX_CLUSTERSCREEN McastTargetNodes; } CCMP_MCAST_HEARTBEAT_HEADER, *PCCMP_MCAST_HEARTBEAT_MSG;
typedef struct _CX_HB_NODE_INFO { ULONG SeqNumber; ULONG AckNumber; } CX_HB_NODE_INFO, *PCX_HB_NODE_INFO;
typedef struct { ULONG SeqNumber; } CCMP_POISON_MSG, *PCCMP_POISON_MSG;
typedef struct { UCHAR Type; UCHAR Code; USHORT Checksum;
union { CCMP_HEARTBEAT_MSG Heartbeat; CCMP_POISON_MSG Poison; CCMP_MCAST_HEARTBEAT_HEADER McastHeartbeat; } Message;
} CCMP_HEADER, *PCCMP_HEADER;
//
// Data
//
LPSTR HeartbeatTypeString = "Heartbeat"; LPSTR MembershipTypeString = "Membership"; LPSTR PoisonTypeString = "Poison"; LPSTR UnknownTypeString = "Unknown";
//=============================================================================
// Forward references.
//=============================================================================
VOID WINAPIV CcmpFormatSummary(LPPROPERTYINST lpPropertyInst);
DWORD WINAPIV CcmpFormatMcastNodeInfo(LPPROPERTYINST lpPropertyInst);
DWORD WINAPIV CcmpFormatMcastNodeData(LPPROPERTYINST lpPropertyInst);
LABELED_BYTE lbCcmpPacketTypes[] = { { CcmpHeartbeatMsgType, "Heartbeat" },
{ CcmpPoisonMsgType, "Poison" },
{ CcmpMembershipMsgType, "Membership" },
{ CcmpMcastHeartbeatMsgType, "Multicast Heartbeat" }, };
#define NUM_CCMP_PACKET_TYPES (sizeof(lbCcmpPacketTypes) / sizeof(LABELED_BYTE))
SET sCcmpPacketTypes = { NUM_CCMP_PACKET_TYPES, lbCcmpPacketTypes };
//=============================================================================
// CCMP database.
//=============================================================================
#define CCMP_SUMMARY 0
#define CCMP_TYPE 1
#define CCMP_CODE 2
#define CCMP_RESERVED 3
#define CCMP_HB_SEQ_NUMBER 4
#define CCMP_HB_ACK_NUMBER 5
#define CCMP_POISON_SEQ_NUMBER 6
#define CCMP_MCASTHB_NODE_COUNT 7
#define CCMP_MCASTHB_NODE_DATA 8
#define CCMP_MCASTHB_NODE_INFO 9
#define CCMP_MCASTHB_NODE_MASK 10
PROPERTYINFO CcmpDatabase[] = { { // CCMP_SUMMARY 0
0,0, "Summary", "Summary of the CCMP packet", PROP_TYPE_SUMMARY, PROP_QUAL_NONE, NULL, 132, CcmpFormatSummary},
{ // CCMP_TYPE 1
0,0, "Type", "Type of CCMP packet", PROP_TYPE_BYTE, PROP_QUAL_LABELED_SET, &sCcmpPacketTypes, FMT_STR_SIZE, FormatPropertyInstance},
{ // CCMP_CODE 2
0,0, "Code", "Identifying code (Type Specific)", PROP_TYPE_BYTE, PROP_QUAL_NONE, NULL, 80, FormatPropertyInstance},
{ // CCMP_RESERVED 3
0,0, "Reserved", "Reserved field", PROP_TYPE_WORD, PROP_QUAL_NONE, NULL, 80, FormatPropertyInstance},
{ // CCMP_HB_SEQ_NUMBER 4
0,0, "Sequence Number", "Sequence number identifying this heartbeat", PROP_TYPE_DWORD, PROP_QUAL_NONE, NULL, 80, FormatPropertyInstance},
{ // CCMP_HB_ACK_NUMBER 5
0,0, "Acknowledgement Number", "Acknowledgement of the last heartbeat received from the destination", PROP_TYPE_DWORD, PROP_QUAL_NONE, NULL, 80, FormatPropertyInstance},
{ // CCMP_POISON_SEQ_NUMBER 6
0,0, "Sequence Number", "Sequence number identifying this poison packet", PROP_TYPE_DWORD, PROP_QUAL_NONE, NULL, 80, FormatPropertyInstance},
{ // CCMP_MCASTHB_NODE_COUNT 7
0,0, "Node Count", "Maximum number of nodes for which this message contains data", PROP_TYPE_WORD, PROP_QUAL_NONE, NULL, 80, FormatPropertyInstance},
{ // CCMP_MCASTHB_NODE_DATA 8
0,0, "Multicast Node Data", "Array of heartbeat sequence and acknowledgement numbers", PROP_TYPE_SUMMARY, PROP_QUAL_NONE, NULL, 80, CcmpFormatMcastNodeData},
{ // CCMP_MCASTHB_NODE_INFO 9
0,0, "Multicast Node Info", "Heartbeat sequence and acknowledgement number for a target node", PROP_TYPE_SUMMARY, PROP_QUAL_NONE, NULL, 80, CcmpFormatMcastNodeInfo},
{ // CCMP_MCASTHB_NODE_MASK 10
0,0, "Multicast Target Node Mask", "Bitmask of nodes for which this heartbeat message contains data", PROP_TYPE_DWORD, PROP_QUAL_NONE, NULL, 80, FormatPropertyInstance},
};
DWORD nCcmpProperties = ((sizeof CcmpDatabase) / PROPERTYINFO_SIZE);
//=============================================================================
// FUNCTION: CcmpRegister()
//
// Modification History
//
// Steve Hiskey 07/07/94 Created
//=============================================================================
VOID WINAPI CcmpRegister(HPROTOCOL hCcmpProtocol) { register DWORD i;
//=========================================================================
// Create the property database.
//=========================================================================
CreatePropertyDatabase(hCcmpProtocol, nCcmpProperties);
for(i = 0; i < nCcmpProperties; ++i) { AddProperty(hCcmpProtocol, &CcmpDatabase[i]); }
}
//=============================================================================
// FUNCTION: Deregister()
//
// Modification History
//
// Steve Hiskey 07/07/94 Created
//=============================================================================
VOID WINAPI CcmpDeregister(HPROTOCOL hCcmpProtocol) { DestroyPropertyDatabase(hCcmpProtocol); }
//=============================================================================
// FUNCTION: CcmpRecognizeFrame()
//
// Modification History
//
// Steve Hiskey 07/07/94 Created
//=============================================================================
LPBYTE WINAPI CcmpRecognizeFrame(HFRAME hFrame, //... frame handle.
LPBYTE MacFrame, //... Frame pointer.
LPBYTE MyFrame, //... Relative pointer.
DWORD MacType, //... MAC type.
DWORD BytesLeft, //... Bytes left.
HPROTOCOL hPreviousProtocol, //... Previous protocol or NULL if none.
DWORD nPreviousProtocolOffset, //... Offset of previous protocol.
LPDWORD ProtocolStatusCode, //... Pointer to return status code in.
LPHPROTOCOL hNextProtocol, //... Next protocol to call (optional).
LPDWORD InstData) //... Next protocol instance data.
{ CCMP_HEADER UNALIGNED * ccmpHeader = (CCMP_HEADER UNALIGNED *) MyFrame; LPBYTE lpNextByte = (LPBYTE) (ccmpHeader + 1);
if (ccmpHeader->Type == CcmpMcastHeartbeatMsgType) { lpNextByte += (ccmpHeader->Message.McastHeartbeat.NodeCount * sizeof(CX_HB_NODE_INFO)); *ProtocolStatusCode = PROTOCOL_STATUS_CLAIMED; } else { #ifdef SSP_DECODE
*hNextProtocol = GetProtocolFromName("SSP"); *ProtocolStatusCode = PROTOCOL_STATUS_NEXT_PROTOCOL; #else
*ProtocolStatusCode = PROTOCOL_STATUS_CLAIMED; #endif
}
return lpNextByte; }
//=============================================================================
// FUNCTION: CcmpAttachProperties()
//
// Modification History
//
// Steve Hiskey 07/07/94 Created
//=============================================================================
LPBYTE WINAPI CcmpAttachProperties(HFRAME hFrame, LPBYTE Frame, LPBYTE MyFrame, DWORD MacType, DWORD BytesLeft, HPROTOCOL hPreviousProtocol, DWORD nPreviousProtocolOffset, DWORD InstData) { CCMP_HEADER UNALIGNED * ccmpHeader = (CCMP_HEADER UNALIGNED *) MyFrame;
AttachPropertyInstance(hFrame, CcmpDatabase[CCMP_SUMMARY].hProperty, #ifdef SSP_DECODE
sizeof(CCMP_HEADER), #else
BytesLeft, #endif
ccmpHeader, 0, 0, 0);
AttachPropertyInstance(hFrame, CcmpDatabase[CCMP_TYPE].hProperty, sizeof(BYTE), &(ccmpHeader->Type), 0, 1, 0);
AttachPropertyInstance(hFrame, CcmpDatabase[CCMP_CODE].hProperty, sizeof(BYTE), &(ccmpHeader->Code), 0, 1, 0);
AttachPropertyInstance(hFrame, CcmpDatabase[CCMP_RESERVED].hProperty, sizeof(WORD), &(ccmpHeader->Checksum), 0, 1, 0);
if (ccmpHeader->Type == CcmpHeartbeatMsgType) {
AttachPropertyInstance(hFrame, CcmpDatabase[CCMP_HB_SEQ_NUMBER].hProperty, sizeof(DWORD), &(ccmpHeader->Message.Heartbeat.SeqNumber), 0, 1, 0);
AttachPropertyInstance(hFrame, CcmpDatabase[CCMP_HB_ACK_NUMBER].hProperty, sizeof(DWORD), &(ccmpHeader->Message.Heartbeat.AckNumber), 0, 1, 0);
} else if (ccmpHeader->Type == CcmpPoisonMsgType) {
AttachPropertyInstance(hFrame, CcmpDatabase[CCMP_POISON_SEQ_NUMBER].hProperty, sizeof(DWORD), &(ccmpHeader->Message.Poison.SeqNumber), 0, 1, 0); } else if (ccmpHeader->Type == CcmpMcastHeartbeatMsgType) {
CX_HB_NODE_INFO UNALIGNED * nodeInfo; DWORD i;
//
// Header
//
AttachPropertyInstance(hFrame, CcmpDatabase[CCMP_MCASTHB_NODE_COUNT].hProperty, sizeof(DWORD), &(ccmpHeader->Message.McastHeartbeat.NodeCount), 0, 1, 0);
AttachPropertyInstance(hFrame, CcmpDatabase[CCMP_MCASTHB_NODE_MASK].hProperty, sizeof(DWORD), &(ccmpHeader->Message.McastHeartbeat.McastTargetNodes.UlongScreen), 0, 1, 0);
//
// Format the heartbeat data.
//
nodeInfo = (CX_HB_NODE_INFO UNALIGNED *)(ccmpHeader + 1);
AttachPropertyInstance(hFrame, CcmpDatabase[CCMP_MCASTHB_NODE_DATA].hProperty, sizeof(nodeInfo[0]) * ccmpHeader->Message.McastHeartbeat.NodeCount, &(nodeInfo[0]), 0, 1, 0);
for (i = ClusterMinNodeId; i < (DWORD) EXT_NODE(ccmpHeader->Message.McastHeartbeat.NodeCount); i++) { if (CnpClusterScreenMember( ccmpHeader->Message.McastHeartbeat.McastTargetNodes.ClusterScreen, INT_NODE(i) )) { AttachPropertyInstanceEx(hFrame, CcmpDatabase[CCMP_MCASTHB_NODE_INFO].hProperty, sizeof(nodeInfo[INT_NODE(i)]), &(nodeInfo[INT_NODE(i)]), sizeof(i), &i, 0, 2, 0); } } }
return NULL; }
//==============================================================================
// FUNCTION: CcmpFormatMcastNodeData()
//
// Modification History
//
// David Dion 04/10/2001 Created
//==============================================================================
DWORD WINAPIV CcmpFormatMcastNodeData(LPPROPERTYINST lpPropertyInst) { wsprintf( lpPropertyInst->szPropertyText, "Node Data:" );
return NMERR_SUCCESS; }
//==============================================================================
// FUNCTION: CcmpFormatMcastNodeInfo()
//
// Modification History
//
// David Dion 04/10/2001 Created
//==============================================================================
DWORD WINAPIV CcmpFormatMcastNodeInfo(LPPROPERTYINST lpPropertyInst) { DWORD Length; LPPROPERTYINSTEX lpPropertyInstEx = lpPropertyInst->lpPropertyInstEx; CX_HB_NODE_INFO UNALIGNED * nodeInfo = lpPropertyInstEx->lpData; DWORD node = (lpPropertyInstEx->Dword[0]);
Length = wsprintf( lpPropertyInst->szPropertyText, "Node %u Heartbeat: Seq = %u (0x%x); Ack = %u (0x%x)", node, nodeInfo->SeqNumber, nodeInfo->SeqNumber, nodeInfo->AckNumber, nodeInfo->AckNumber );
return NMERR_SUCCESS; }
//==============================================================================
// FUNCTION: CcmpFormatSummary()
//
// Modification History
//
// Steve Hiskey 07/07/94 Created
//==============================================================================
VOID WINAPIV CcmpFormatSummary(LPPROPERTYINST lpPropertyInst) { LPSTR typeString; LPSTR SummaryStr; DWORD Length; CCMP_HEADER UNALIGNED * ccmpHeader = (CCMP_HEADER UNALIGNED *) lpPropertyInst->lpData;
if (ccmpHeader->Type == CcmpHeartbeatMsgType) { Length = wsprintf( lpPropertyInst->szPropertyText, "Heartbeat: Seq = %u (0x%x); Ack = %u (0x%x)", ccmpHeader->Message.Heartbeat.SeqNumber, ccmpHeader->Message.Heartbeat.SeqNumber, ccmpHeader->Message.Heartbeat.AckNumber, ccmpHeader->Message.Heartbeat.AckNumber ); } else if (ccmpHeader->Type == CcmpPoisonMsgType) { Length = wsprintf( lpPropertyInst->szPropertyText, "Poison: Seq = %u (0x%x)", ccmpHeader->Message.Poison.SeqNumber, ccmpHeader->Message.Poison.SeqNumber ); } else if (ccmpHeader->Type == CcmpMembershipMsgType) { Length = wsprintf( lpPropertyInst->szPropertyText, "Membership" ); } else if (ccmpHeader->Type == CcmpMcastHeartbeatMsgType) { CX_HB_NODE_INFO UNALIGNED * nodeInfo; DWORD i; LPSTR strbuf = lpPropertyInst->szPropertyText;
nodeInfo = (CX_HB_NODE_INFO UNALIGNED *)(ccmpHeader + 1); Length = wsprintf( strbuf, "Multicast Heartbeat: " ); for (i = ClusterMinNodeId; i < (DWORD) EXT_NODE(ccmpHeader->Message.McastHeartbeat.NodeCount); i++) {
if (CnpClusterScreenMember( ccmpHeader->Message.McastHeartbeat.McastTargetNodes.ClusterScreen, INT_NODE(i) )) { strbuf = (LPSTR)((PUCHAR)strbuf + Length); Length = wsprintf( strbuf, "(N%u: S%u, A%u) ", i, nodeInfo[INT_NODE(i)].SeqNumber, nodeInfo[INT_NODE(i)].AckNumber ); } }
} else { Length = wsprintf( lpPropertyInst->szPropertyText, "Unknown CCMP message type: %u", ccmpHeader->Type ); } }
//==============================================================================
// FUNCTION: CcmpFormatProperties()
//
// Modification History
//
// Steve Hiskey 07/07/94 Created
//==============================================================================
DWORD WINAPI CcmpFormatProperties(HFRAME hFrame, LPBYTE MacFrame, LPBYTE FrameData, DWORD nPropertyInsts, LPPROPERTYINST p) { //=========================================================================
// Format each property in the property instance table.
//
// The property-specific instance data was used to store the address of a
// property-specific formatting function so all we do here is call each
// function via the instance data pointer.
//=========================================================================
while (nPropertyInsts--) { ((FORMAT) p->lpPropertyInfo->InstanceData)(p);
p++; }
return NMERR_SUCCESS; }
|