windows-nt/Source/XPSP1/NT/base/cluster/bh/parsers/clusnet/ccmp.c

641 lines
20 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
//=============================================================================
// 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;
}