/*++ Copyright (c) 1996 Microsoft Corporation Module Name: cnpdef.h Abstract: Main private header file for the Cluster Network Protocol. Author: Mike Massa (mikemas) July 29, 1996 Revision History: Who When What -------- -------- ---------------------------------------------- mikemas 07-29-96 created Notes: --*/ #ifndef _CNPDEF_INCLUDED_ #define _CNPDEF_INCLUDED_ #include #include // // Forward declarations // typedef struct _CNP_INTERFACE *PCNP_INTERFACE; // // Priority definitions // #define CnpIsHigherPriority(_p1, _p2) ((_p1) < (_p2)) #define CnpIsLowerPriority(_p1, _p2) ((_p1) > (_p2)) #define CnpIsEqualPriority(_p1, _p2) ((_p1) == (_p2)) // // Multicast Group Object // // This structure contains the data needed to implement a multicast // endpoint on a network. // typedef struct _CNP_MULTICAST_GROUP { ULONG McastNetworkBrand; PTRANSPORT_ADDRESS McastTdiAddress; ULONG McastTdiAddressLength; PVOID Key; ULONG KeyLength; DESTable DesTable; PVOID Salt; ULONG SaltLength; ULONG SignatureLength; ULONG RefCount; } CNP_MULTICAST_GROUP, *PCNP_MULTICAST_GROUP; // // Network Object // // This structure represents a communication link between the nodes of a // cluster. It references a particular transport protocol and interface // configured on the local system. It also links together all of the // interface objects for the nodes attached to the network. // // Networks are identified by a small integer assigned by the Cluster // Service. Network objects are stored in a global array indexed by // the network ID. // typedef struct { LIST_ENTRY Linkage; CN_SIGNATURE_FIELD CL_NETWORK_ID Id; CN_LOCK Lock; CN_IRQL Irql; ULONG RefCount; ULONG ActiveRefCount; CLUSNET_NETWORK_STATE State; ULONG Flags; ULONG Priority; HANDLE DatagramHandle; PFILE_OBJECT DatagramFileObject; PDEVICE_OBJECT DatagramDeviceObject; TDI_PROVIDER_INFO ProviderInfo; PIRP PendingDeleteIrp; PIRP PendingOfflineIrp; WORK_QUEUE_ITEM ExWorkItem; PCNP_MULTICAST_GROUP CurrentMcastGroup; PCNP_MULTICAST_GROUP PreviousMcastGroup; CX_CLUSTERSCREEN McastReachableNodes; ULONG McastReachableCount; } CNP_NETWORK, *PCNP_NETWORK; #define CNP_NETWORK_SIG 'kwtn' extern LIST_ENTRY CnpNetworkList; extern CN_LOCK CnpNetworkListLock; #define CNP_NET_FLAG_DELETING 0x00000001 #define CNP_NET_FLAG_PARTITIONED 0x00000002 #define CNP_NET_FLAG_RESTRICTED 0x00000004 #define CNP_NET_FLAG_LOCALDISCONN 0x00000008 #define CNP_NET_FLAG_MULTICAST 0x00000010 #define CNP_NET_FLAG_MCASTSORTED 0x00000020 #define CnpIsNetworkDeleting(_network) \ (((_network)->Flags & CNP_NET_FLAG_DELETING) != 0) #define CnpIsValidNetworkId(_id) ( ((_id) != ClusterAnyNetworkId ) && \ ((_id) != ClusterInvalidNetworkId)) #define CnpIsNetworkRestricted(_network) \ (((_network)->Flags & CNP_NET_FLAG_RESTRICTED) != 0) #define CnpIsNetworkLocalDisconn(_network) \ (((_network)->Flags & CNP_NET_FLAG_LOCALDISCONN) != 0) #define CnpIsNetworkMulticastCapable(_network) \ (((_network)->Flags & CNP_NET_FLAG_MULTICAST) != 0) #define CnpIsNetworkMulticastSorted(_network) \ (((_network)->Flags & CNP_NET_FLAG_MCASTSORTED) != 0) #define CnpNetworkResetMcastReachableNodes(_network) \ (RtlZeroMemory( \ &((_network)->McastReachableNodes), \ sizeof((_network)->McastReachableNodes) \ )) /* (BYTE((_network)->McastReachableNodes, INT_NODE(CnLocalNodeId)) \ = (1 << (BYTEL-1-BIT(INT_NODE(CnLocalNodeId))))) */ // // Node Object // // This structure represents a cluster node. One exists for each // defined member of a cluster. // // Nodes are identified by a small integer assigned by the Cluster Service. // Node objects are stored in a global array indexed by node ID. // // Note that the order of the CLUSTER_NODE_COMM_STATE enumeration *is* important. // typedef struct { LIST_ENTRY Linkage; CN_SIGNATURE_FIELD CL_NODE_ID Id; CN_LOCK Lock; CN_IRQL Irql; ULONG RefCount; CLUSNET_NODE_COMM_STATE CommState; CLUSNET_NODE_STATE MMState; ULONG Flags; LIST_ENTRY InterfaceList; PCNP_INTERFACE CurrentInterface; PIRP PendingDeleteIrp; BOOLEAN HBWasMissed; BOOLEAN NodeDownIssued; ULONG MissedHBs; } CNP_NODE, *PCNP_NODE; #define CNP_NODE_SIG 'edon' extern PCNP_NODE * CnpNodeTable; extern CN_LOCK CnpNodeTableLock; extern PCNP_NODE CnpLocalNode; #define CNP_NODE_FLAG_DELETING 0x00000001 #define CNP_NODE_FLAG_UNREACHABLE 0x00000002 #define CNP_NODE_FLAG_LOCAL 0x00000010 #define CnpIsNodeDeleting(_node) \ ((_node)->Flags & CNP_NODE_FLAG_DELETING) #define CnpIsNodeLocal(_node) \ ((_node)->Flags & CNP_NODE_FLAG_LOCAL) #define CnpIsNodeUnreachable(_node) \ ((_node)->Flags & CNP_NODE_FLAG_UNREACHABLE) //++ // // Routine Description: // // Callback routine for CnpWalkNodeTable. Performs an operation on // the specified node. // // Arguments: // // UpdateNode - A pointer to the node on which to operate. // // UpdateContext - Operation-specific context // // NodeTableIrql - The IRQL at which the CnpNodeTableLock was acquired. // // Return Value: // // Returns TRUE if the CnpNodeTable lock is still held. // Returns FALSE if the CnpNodeTable lock is released. // // Notes: // // Called with both the CnpNodeTable and node object locks held. // The node object lock is released upon return. // //-- typedef BOOLEAN (*PCNP_NODE_UPDATE_ROUTINE)( IN PCNP_NODE UpdateNode, IN PVOID UpdateContext, IN CN_IRQL NodeTableIrql ); // // Interface Object // // This structure represents a node's transport interface to a network. // It contains a transport address which may be used to communicate // with the specified node using the specified network. // // Interface objects are linked onto lists in the associated node objects. // They are identified by a {node, network} tuple. // // The interfaces on a node are ranked based on their state and priority. // Numerically higher state values are ranked ahead of lower values. // For interfaces with the same state, Numerically lower priority values // are ranked ahead of lower values. Priority values fall in the range // 0x1-0xFFFFFFFF. State values are defined by CLUSNET_INTERFACE_STATE // enumeration. By default, interfaces inherit their priority from the // associated network. In this case, the Priority field will contain the // network's priority value, and the CNP_IF_FLAG_USE_NETWORK_PRIORITY flag // will be set in the Flags field. // // Note that the order of the CLUSNET_INTERFACE_STATE enumeration // *is* important. // typedef struct _CNP_INTERFACE { LIST_ENTRY NodeLinkage; CN_SIGNATURE_FIELD PCNP_NODE Node; PCNP_NETWORK Network; CLUSNET_INTERFACE_STATE State; ULONG Priority; ULONG Flags; ULONG MissedHBs; ULONG SequenceToSend; ULONG LastSequenceReceived; ULONG McastDiscoverCount; ULONG McastRediscoveryCountdown; ULONG AdapterWMIProviderId; ULONG TdiAddressLength; TRANSPORT_ADDRESS TdiAddress; } CNP_INTERFACE; #define CNP_INTERFACE_SIG ' fi' #define CNP_INTERFACE_MCAST_DISCOVERY 0x5 #define CNP_INTERFACE_MCAST_REDISCOVERY 3000 // 1 hr at 1.2 hbs/sec #define CNP_IF_FLAG_USE_NETWORK_PRIORITY 0x00000001 #define CNP_IF_FLAG_RECVD_MULTICAST 0x00000002 #define CnpIsInterfaceUsingNetworkPriority(_if) \ ( (_if)->Flags & CNP_IF_FLAG_USE_NETWORK_PRIORITY ) #define CnpInterfaceQueryReceivedMulticast(_if) \ ( (_if)->Flags & CNP_IF_FLAG_RECVD_MULTICAST ) #define CnpInterfaceSetReceivedMulticast(_if) \ ( (_if)->Flags |= CNP_IF_FLAG_RECVD_MULTICAST ) #define CnpInterfaceClearReceivedMulticast(_if) \ ( (_if)->Flags &= ~CNP_IF_FLAG_RECVD_MULTICAST ) //++ // // Routine Description: // // Callback routine for CnpWalkInterfacesOnNetwork and // CnpWalkInterfacesOnNode routines. Performs a specified // operation on all interfaces. // // Arguments: // // UpdateInterface - A pointer to the interface on which to operate. // // Return Value: // // None. // // Notes: // // Called with the associated node and network object locks held. // Mut return with the network object lock released. // May not release node object lock at any time. // //-- typedef VOID (*PCNP_INTERFACE_UPDATE_ROUTINE)( IN PCNP_INTERFACE UpdateInterface ); // // Send Request Pool // typedef struct { USHORT UpperProtocolHeaderLength; ULONG UpperProtocolContextSize; UCHAR UpperProtocolNumber; UCHAR CnpVersionNumber; UCHAR Pad[2]; } CNP_SEND_REQUEST_POOL_CONTEXT, *PCNP_SEND_REQUEST_POOL_CONTEXT; // // Forward Declaration // typedef struct _CNP_SEND_REQUEST *PCNP_SEND_REQUEST; typedef VOID (*PCNP_SEND_COMPLETE_ROUTINE)( IN NTSTATUS Status, IN OUT PULONG BytesSent, IN PCNP_SEND_REQUEST SendRequest, IN PMDL DataMdl ); // // Send Request Structure // typedef struct _CNP_SEND_REQUEST { CN_RESOURCE CnResource; PMDL HeaderMdl; PVOID CnpHeader; PIRP UpperProtocolIrp; PVOID UpperProtocolHeader; USHORT UpperProtocolHeaderLength; KPROCESSOR_MODE UpperProtocolIrpMode; UCHAR Pad; PMDL UpperProtocolMdl; PVOID UpperProtocolContext; PCNP_SEND_COMPLETE_ROUTINE CompletionRoutine; PCNP_NETWORK Network; PCNP_MULTICAST_GROUP McastGroup; TDI_CONNECTION_INFORMATION TdiSendDatagramInfo; } CNP_SEND_REQUEST; // // Internal Init/Cleanup routines // // // Internal Node Routines // VOID CnpWalkNodeTable( PCNP_NODE_UPDATE_ROUTINE UpdateRoutine, PVOID UpdateContext ); NTSTATUS CnpValidateAndFindNode( IN CL_NODE_ID NodeId, OUT PCNP_NODE * Node ); PCNP_NODE CnpLockedFindNode( IN CL_NODE_ID NodeId, IN CN_IRQL NodeTableIrql ); PCNP_NODE CnpFindNode( IN CL_NODE_ID NodeId ); VOID CnpOfflineNode( PCNP_NODE Node ); VOID CnpDeclareNodeUnreachable( PCNP_NODE Node ); VOID CnpDeclareNodeReachable( PCNP_NODE Node ); VOID CnpReferenceNode( PCNP_NODE Node ); VOID CnpDereferenceNode( PCNP_NODE Node ); // // Internal Network Routines // VOID CnpReferenceNetwork( PCNP_NETWORK Network ); VOID CnpDereferenceNetwork( PCNP_NETWORK Network ); VOID CnpActiveReferenceNetwork( PCNP_NETWORK Network ); VOID CnpActiveDereferenceNetwork( PCNP_NETWORK Network ); PCNP_NETWORK CnpFindNetwork( IN CL_NETWORK_ID NetworkId ); VOID CnpDeleteNetwork( PCNP_NETWORK Network, CN_IRQL NetworkListIrql ); VOID CnpFreeMulticastGroup( IN PCNP_MULTICAST_GROUP Group ); #define CnpReferenceMulticastGroup(_group) \ (InterlockedIncrement(&((_group)->RefCount))) #define CnpDereferenceMulticastGroup(_group) \ if (InterlockedDecrement(&((_group)->RefCount)) == 0) { \ CnpFreeMulticastGroup(_group); \ } BOOLEAN CnpSortMulticastNetwork( IN PCNP_NETWORK Network, IN BOOLEAN RaiseEvent, OUT CX_CLUSTERSCREEN * McastReachableNodes OPTIONAL ); BOOLEAN CnpMulticastChangeNodeReachability( IN PCNP_NETWORK Network, IN PCNP_NODE Node, IN BOOLEAN Reachable, IN BOOLEAN RaiseEvent, OUT CX_CLUSTERSCREEN * NewMcastReachableNodes OPTIONAL ); PCNP_NETWORK CnpGetBestMulticastNetwork( VOID ); // // Internal Interface Routines // VOID CnpWalkInterfacesOnNode( PCNP_NODE Node, PCNP_INTERFACE_UPDATE_ROUTINE UpdateRoutine ); VOID CnpWalkInterfacesOnNetwork( PCNP_NETWORK Network, PCNP_INTERFACE_UPDATE_ROUTINE UpdateRoutine ); NTSTATUS CnpOnlinePendingInterface( PCNP_INTERFACE Interface ); VOID CnpOnlinePendingInterfaceWrapper( PCNP_INTERFACE Interface ); NTSTATUS CnpOfflineInterface( PCNP_INTERFACE Interface ); VOID CnpOfflineInterfaceWrapper( PCNP_INTERFACE Interface ); NTSTATUS CnpOnlineInterface( PCNP_INTERFACE Interface ); NTSTATUS CnpFailInterface( PCNP_INTERFACE Interface ); VOID CnpDeleteInterface( IN PCNP_INTERFACE Interface ); VOID CnpReevaluateInterfaceRole( IN PCNP_INTERFACE Interface ); VOID CnpRecalculateInterfacePriority( IN PCNP_INTERFACE Interface ); VOID CnpUpdateNodeCurrentInterface( PCNP_NODE Node ); VOID CnpResetAndOnlinePendingInterface( IN PCNP_INTERFACE Interface ); NTSTATUS CnpFindInterface( IN CL_NODE_ID NodeId, IN CL_NETWORK_ID NetworkId, OUT PCNP_INTERFACE * Interface ); // // Send Routines. // PCN_RESOURCE_POOL CnpCreateSendRequestPool( IN UCHAR CnpVersionNumber, IN UCHAR UpperProtocolNumber, IN USHORT UpperProtocolHeaderSize, IN USHORT UpperProtocolContextSize, IN USHORT PoolDepth ); #define CnpDeleteSendRequestPool(_pool) \ { \ CnDrainResourcePool(_pool); \ CnFreePool(_pool); \ } NTSTATUS CnpSendPacket( IN PCNP_SEND_REQUEST SendRequest, IN CL_NODE_ID DestNodeId, IN PMDL DataMdl, IN USHORT DataLength, IN BOOLEAN CheckDestState, IN CL_NETWORK_ID NetworkId OPTIONAL ); VOID CcmpSendPoisonPacket( IN PCNP_NODE Node, IN PCX_SEND_COMPLETE_ROUTINE CompletionRoutine, OPTIONAL IN PVOID CompletionContext, OPTIONAL IN PCNP_NETWORK Network, OPTIONAL IN PIRP Irp OPTIONAL ); // // Receive Routines // NTSTATUS CcmpReceivePacketHandler( IN PCNP_NETWORK Network, IN CL_NODE_ID SourceNodeId, IN ULONG CnpReceiveFlags, IN ULONG TdiReceiveDatagramFlags, IN ULONG BytesIndicated, IN ULONG BytesAvailable, OUT PULONG BytesTaken, IN PVOID Tsdu, OUT PIRP * Irp ); VOID CnpReceiveHeartBeatMessage( IN PCNP_NETWORK Network, IN CL_NODE_ID SourceNodeId, IN ULONG SeqNumber, IN ULONG AckNumber, IN BOOLEAN Multicast ); VOID CnpReceivePoisonPacket( IN PCNP_NETWORK Network, IN CL_NODE_ID SourceNodeId, IN ULONG SeqNumber ); // // TDI routines // NTSTATUS CnpTdiReceiveDatagramHandler( IN PVOID TdiEventContext, IN LONG SourceAddressLength, IN PVOID SourceAddress, IN LONG OptionsLength, IN PVOID Options, IN ULONG ReceiveDatagramFlags, IN ULONG BytesIndicated, IN ULONG BytesAvailable, OUT PULONG BytesTaken, IN PVOID Tsdu, OUT PIRP * IoRequestPacket ); NTSTATUS CnpTdiErrorHandler( IN PVOID TdiEventContext, IN NTSTATUS Status ); NTSTATUS CnpTdiSetEventHandler( IN PFILE_OBJECT FileObject, IN PDEVICE_OBJECT DeviceObject, IN ULONG EventType, IN PVOID EventHandler, IN PVOID EventContext, IN PIRP ClientIrp OPTIONAL ); NTSTATUS CnpIssueDeviceControl ( IN PFILE_OBJECT FileObject, IN PDEVICE_OBJECT DeviceObject, IN PVOID IrpParameters, IN ULONG IrpParametersLength, IN PVOID MdlBuffer, IN ULONG MdlBufferLength, IN UCHAR MinorFunction, IN PIRP ClientIrp OPTIONAL ); VOID CnpAttachSystemProcess( VOID ); VOID CnpDetachSystemProcess( VOID ); NTSTATUS CnpOpenDevice( IN LPWSTR DeviceName, OUT HANDLE *Handle ); NTSTATUS CnpZwDeviceControl( IN HANDLE Handle, IN ULONG IoControlCode, IN PVOID InputBuffer, IN ULONG InputBufferLength, IN PVOID OutputBuffer, IN ULONG OutputBufferLength ); NTSTATUS CnpSetTcpInfoEx( IN HANDLE Handle, IN ULONG Entity, IN ULONG Class, IN ULONG Type, IN ULONG Id, IN PVOID Value, IN ULONG ValueLength ); #define CnpIsIrpStackSufficient(_irp, _targetdevice) \ ((_irp)->CurrentLocation - (_targetdevice)->StackSize >= 1) #define CnpIsIPv4McastTransportAddress(_ta) \ ( (((PTA_IP_ADDRESS)(_ta))->Address[0].AddressType \ == TDI_ADDRESS_TYPE_IP \ ) \ && ((((PTA_IP_ADDRESS)(_ta))->Address[0].Address[0].in_addr \ & 0xf0) \ == 0xe0 \ ) \ ) #define CnpIsIPv4McastSameGroup(_ta1, _ta2) \ ( ((PTA_IP_ADDRESS)(_ta1))->Address[0].Address[0].in_addr == \ ((PTA_IP_ADDRESS)(_ta2))->Address[0].Address[0].in_addr \ ) // // Signature mechanisms. // extern FIPS_FUNCTION_TABLE CxFipsFunctionTable; // Pad the signature length to be an even multiple of DES_BLOCKLEN. #define CX_SIGNATURE_LENGTH \ (((A_SHA_DIGEST_LEN % DES_BLOCKLEN) == 0) ? \ A_SHA_DIGEST_LEN : \ A_SHA_DIGEST_LEN + DES_BLOCKLEN - (A_SHA_DIGEST_LEN % DES_BLOCKLEN)) NTSTATUS CnpSignMulticastMessage( IN PCNP_SEND_REQUEST SendRequest, IN PMDL DataMdl, IN OUT CL_NETWORK_ID * NetworkId, OUT ULONG * SigLen OPTIONAL ); NTSTATUS CnpVerifyMulticastMessage( IN PCNP_NETWORK Network, IN PVOID Tsdu, IN ULONG TsduLength, IN ULONG ExpectedPayload, OUT ULONG * BytesTaken, OUT BOOLEAN * CurrentGroup ); #endif // ifndef _CNPDEF_INCLUDED_