/*++ Copyright (c) 1996 Microsoft Corporation Module Name: cxdisp.c Abstract: Dispatch routines for the Cluster Transport. Author: Mike Massa (mikemas) July 29, 1996 Revision History: Who When What -------- -------- ---------------------------------------------- mikemas 07-29-96 created Notes: --*/ #include "precomp.h" #pragma hdrstop #include "cxdisp.tmh" #include // // Local Prototypes // NTSTATUS CxDispatchRegisterNode( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ); NTSTATUS CxDispatchDeregisterNode( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ); NTSTATUS CxDispatchRegisterNetwork( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ); NTSTATUS CxDispatchDeregisterNetwork( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ); NTSTATUS CxDispatchRegisterInterface( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ); NTSTATUS CxDispatchDeregisterInterface( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ); NTSTATUS CxDispatchOnlineNodeComm( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ); NTSTATUS CxDispatchOfflineNodeComm( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ); NTSTATUS CxDispatchOnlineNetwork( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ); NTSTATUS CxDispatchOfflineNetwork( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ); NTSTATUS CxDispatchSetNetworkRestriction( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ); NTSTATUS CxDispatchGetNetworkPriority( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ); NTSTATUS CxDispatchSetNetworkPriority( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ); NTSTATUS CxDispatchGetInterfacePriority( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ); NTSTATUS CxDispatchSetInterfacePriority( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ); NTSTATUS CxDispatchGetNodeState( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ); NTSTATUS CxDispatchGetNetworkState( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ); NTSTATUS CxDispatchGetInterfaceState( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ); NTSTATUS CxDispatchIgnoreNodeState( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ); NTSTATUS CxDispatchGetNodeMembershipState( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ); NTSTATUS CxDispatchSetNodeMembershipState( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ); NTSTATUS CxDispatchSendPoisonPacket( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ); NTSTATUS CxDispatchSetOuterscreen( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ); NTSTATUS CxDispatchRegroupFinished( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ); NTSTATUS CxDispatchImportSecurityContext( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ); NTSTATUS CxDispatchReserveClusnetEndpoint( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ); NTSTATUS CxDispatchConfigureMulticast( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ); NTSTATUS CxDispatchGetMulticastReachableSet( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ); #if DBG NTSTATUS CxDispatchOnlinePendingInterface( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ); NTSTATUS CxDispatchOnlineInterface( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ); NTSTATUS CxDispatchOfflineInterface( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ); NTSTATUS CxDispatchFailInterface( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ); NTSTATUS CxDispatchSendMmMsg( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ); #endif // DBG #ifdef ALLOC_PRAGMA #pragma alloc_text(PAGE, CxDispatchDeviceControl) #pragma alloc_text(PAGE, CxDispatchRegisterNode) #pragma alloc_text(PAGE, CxDispatchDeregisterNode) #pragma alloc_text(PAGE, CxDispatchRegisterNetwork) #pragma alloc_text(PAGE, CxDispatchDeregisterNetwork) #pragma alloc_text(PAGE, CxDispatchRegisterInterface) #pragma alloc_text(PAGE, CxDispatchDeregisterInterface) #pragma alloc_text(PAGE, CxDispatchOnlineNodeComm) #pragma alloc_text(PAGE, CxDispatchOfflineNodeComm) #pragma alloc_text(PAGE, CxDispatchOnlineNetwork) #pragma alloc_text(PAGE, CxDispatchOfflineNetwork) #pragma alloc_text(PAGE, CxDispatchSetNetworkRestriction) #pragma alloc_text(PAGE, CxDispatchGetNetworkPriority) #pragma alloc_text(PAGE, CxDispatchSetNetworkPriority) #pragma alloc_text(PAGE, CxDispatchGetInterfacePriority) #pragma alloc_text(PAGE, CxDispatchSetInterfacePriority) #pragma alloc_text(PAGE, CxDispatchGetNodeState) #pragma alloc_text(PAGE, CxDispatchGetNetworkState) #pragma alloc_text(PAGE, CxDispatchGetInterfaceState) #pragma alloc_text(PAGE, CxDispatchGetNodeMembershipState) #pragma alloc_text(PAGE, CxDispatchSetNodeMembershipState) #pragma alloc_text(PAGE, CxDispatchSendPoisonPacket) #pragma alloc_text(PAGE, CxDispatchSetOuterscreen) #pragma alloc_text(PAGE, CxDispatchRegroupFinished) #pragma alloc_text(PAGE, CxDispatchImportSecurityContext) #pragma alloc_text(PAGE, CxDispatchReserveClusnetEndpoint) #pragma alloc_text(PAGE, CxDispatchConfigureMulticast) #pragma alloc_text(PAGE, CxDispatchGetMulticastReachableSet) #if DBG #pragma alloc_text(PAGE, CxDispatchOnlinePendingInterface) #pragma alloc_text(PAGE, CxDispatchOnlineInterface) #pragma alloc_text(PAGE, CxDispatchOfflineInterface) #pragma alloc_text(PAGE, CxDispatchFailInterface) #ifdef MM_IN_CLUSNET #pragma alloc_text(PAGE, CxDispatchSendMmMsg) #endif // MM_IN_CLUSNET #endif // DBG #endif // ALLOC_PRAGMA NTSTATUS CxDispatchDeviceControl( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) /*++ Routine Description: Dispatch routine for device control ioctls. Arguments: Irp - Pointer to I/O request packet IrpSp - Pointer to the current stack location in the Irp. Return Value: NTSTATUS -- Indicates whether the request was successfully queued. Notes: Any IRP for which the return value is not STATUS_PENDING will be completed by the calling routine. --*/ { NTSTATUS status; PAGED_CODE(); switch(IrpSp->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_CX_REGISTER_NODE: status = CxDispatchRegisterNode(Irp, IrpSp); break; case IOCTL_CX_DEREGISTER_NODE: status = CxDispatchDeregisterNode(Irp, IrpSp); break; case IOCTL_CX_REGISTER_NETWORK: status = CxDispatchRegisterNetwork(Irp, IrpSp); break; case IOCTL_CX_DEREGISTER_NETWORK: status = CxDispatchDeregisterNetwork(Irp, IrpSp); break; case IOCTL_CX_REGISTER_INTERFACE: status = CxDispatchRegisterInterface(Irp, IrpSp); break; case IOCTL_CX_DEREGISTER_INTERFACE: status = CxDispatchDeregisterInterface(Irp, IrpSp); break; case IOCTL_CX_ONLINE_NODE_COMM: status = CxDispatchOnlineNodeComm(Irp, IrpSp); break; case IOCTL_CX_OFFLINE_NODE_COMM: status = CxDispatchOfflineNodeComm(Irp, IrpSp); break; case IOCTL_CX_ONLINE_NETWORK: status = CxDispatchOnlineNetwork(Irp, IrpSp); break; case IOCTL_CX_OFFLINE_NETWORK: status = CxDispatchOfflineNetwork(Irp, IrpSp); break; case IOCTL_CX_SET_NETWORK_RESTRICTION: status = CxDispatchSetNetworkRestriction(Irp, IrpSp); break; case IOCTL_CX_GET_NETWORK_PRIORITY: status = CxDispatchGetNetworkPriority(Irp, IrpSp); break; case IOCTL_CX_SET_NETWORK_PRIORITY: status = CxDispatchSetNetworkPriority(Irp, IrpSp); break; case IOCTL_CX_GET_INTERFACE_PRIORITY: status = CxDispatchGetInterfacePriority(Irp, IrpSp); break; case IOCTL_CX_SET_INTERFACE_PRIORITY: status = CxDispatchSetInterfacePriority(Irp, IrpSp); break; case IOCTL_CX_GET_NODE_STATE: status = CxDispatchGetNodeState(Irp, IrpSp); break; case IOCTL_CX_GET_NETWORK_STATE: status = CxDispatchGetNetworkState(Irp, IrpSp); break; case IOCTL_CX_GET_INTERFACE_STATE: status = CxDispatchGetInterfaceState(Irp, IrpSp); break; case IOCTL_CX_IGNORE_NODE_STATE: status = CxDispatchIgnoreNodeState(Irp, IrpSp); break; case IOCTL_CX_GET_NODE_MMSTATE: status = CxDispatchGetNodeMembershipState(Irp, IrpSp); break; case IOCTL_CX_SET_NODE_MMSTATE: status = CxDispatchSetNodeMembershipState(Irp, IrpSp); break; case IOCTL_CX_SEND_POISON_PACKET: status = CxDispatchSendPoisonPacket(Irp, IrpSp); break; case IOCTL_CX_SET_OUTERSCREEN: status = CxDispatchSetOuterscreen(Irp, IrpSp); break; case IOCTL_CX_REGROUP_FINISHED: status = CxDispatchRegroupFinished(Irp, IrpSp); break; case IOCTL_CX_IMPORT_SECURITY_CONTEXTS: status = CxDispatchImportSecurityContext(Irp, IrpSp); break; case IOCTL_CX_RESERVE_ENDPOINT: status = CxDispatchReserveClusnetEndpoint(Irp, IrpSp); break; case IOCTL_CX_CONFIGURE_MULTICAST: status = CxDispatchConfigureMulticast(Irp, IrpSp); break; case IOCTL_CX_GET_MULTICAST_REACHABLE_SET: status = CxDispatchGetMulticastReachableSet(Irp, IrpSp); break; #if DBG case IOCTL_CX_ONLINE_PENDING_INTERFACE: status = CxDispatchOnlinePendingInterface(Irp, IrpSp); break; case IOCTL_CX_ONLINE_INTERFACE: status = CxDispatchOnlineInterface(Irp, IrpSp); break; case IOCTL_CX_OFFLINE_INTERFACE: status = CxDispatchOfflineInterface(Irp, IrpSp); break; case IOCTL_CX_FAIL_INTERFACE: status = CxDispatchFailInterface(Irp, IrpSp); break; #ifdef MM_IN_CLUSNET case IOCTL_CX_SEND_MM_MSG: status = CxDispatchSendMmMsg(Irp, IrpSp); break; #endif // MM_IN_CLUSNET #endif // DBG default: status = STATUS_INVALID_DEVICE_REQUEST; break; } return(status); } // CxDispatchDeviceControl NTSTATUS CxDispatchRegisterNode( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_NODE_REG_REQUEST request; ULONG requestSize; PAGED_CODE(); request = (PCX_NODE_REG_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; if (requestSize < sizeof(CX_NODE_REG_REQUEST)) { return(STATUS_INVALID_PARAMETER); } status = CxRegisterNode( request->Id ); return(status); } // CxDispatchRegisterNode NTSTATUS CxDispatchDeregisterNode( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_NODE_DEREG_REQUEST request; ULONG requestSize; PAGED_CODE(); request = (PCX_NODE_DEREG_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; if (requestSize < sizeof(CX_NODE_DEREG_REQUEST)) { return(STATUS_INVALID_PARAMETER); } status = CxDeregisterNode(request->Id, Irp, IrpSp); return(status); } // CxDispatchDeregisterNode NTSTATUS CxDispatchRegisterNetwork( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_NETWORK_REG_REQUEST request; ULONG requestSize; PAGED_CODE(); request = (PCX_NETWORK_REG_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; if (requestSize < sizeof(CX_NETWORK_REG_REQUEST)) { return(STATUS_INVALID_PARAMETER); } status = CxRegisterNetwork( request->Id, request->Priority, request->Restricted ); return(status); } // CxDispatchRegisterNetwork NTSTATUS CxDispatchDeregisterNetwork( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_NETWORK_DEREG_REQUEST request; ULONG requestSize; PAGED_CODE(); request = (PCX_NETWORK_DEREG_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; if (requestSize < sizeof(CX_NETWORK_DEREG_REQUEST)) { return(STATUS_INVALID_PARAMETER); } status = CxDeregisterNetwork(request->Id, Irp, IrpSp); return(status); } // CxDispatchDeregisterNetwork NTSTATUS CxDispatchRegisterInterface( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_INTERFACE_REG_REQUEST request; ULONG requestSize, resid; PCX_INTERFACE_REG_RESPONSE response; ULONG responseSize; PWCHAR adapterId; PAGED_CODE(); // Verify that the request buffer has sufficient size, given the // offsets and lengths. request = (PCX_INTERFACE_REG_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; if (requestSize < sizeof(CX_INTERFACE_REG_REQUEST)) { return(STATUS_INVALID_PARAMETER); } response = (PCX_INTERFACE_REG_RESPONSE) Irp->AssociatedIrp.SystemBuffer; responseSize = IrpSp->Parameters.DeviceIoControl.OutputBufferLength; if (responseSize < sizeof(CX_INTERFACE_REG_RESPONSE)) { return(STATUS_INVALID_PARAMETER); } resid = requestSize - FIELD_OFFSET(CX_INTERFACE_REG_REQUEST, TdiAddress[0]); if (resid < request->TdiAddressLength) { return(STATUS_INVALID_PARAMETER); } resid -= request->TdiAddressLength; if (request->AdapterIdOffset < FIELD_OFFSET(CX_INTERFACE_REG_REQUEST, TdiAddress[0]) + request->TdiAddressLength || request->AdapterIdOffset > requestSize) { return(STATUS_INVALID_PARAMETER); } if (resid < request->AdapterIdLength) { return(STATUS_INVALID_PARAMETER); } // Verify that the string offset is properly aligned adapterId = (PWCHAR)((PUCHAR)request + request->AdapterIdOffset); if (!POINTER_IS_ALIGNED(adapterId, TYPE_ALIGNMENT(WCHAR))) { return(STATUS_INVALID_PARAMETER); } status = CxRegisterInterface( request->NodeId, request->NetworkId, request->Priority, (PUWSTR)((PUCHAR)request + request->AdapterIdOffset), request->AdapterIdLength, request->TdiAddressLength, (PTRANSPORT_ADDRESS) &(request->TdiAddress[0]), &response->MediaStatus ); if (NT_SUCCESS(status)) { Irp->IoStatus.Information = sizeof(CX_INTERFACE_REG_RESPONSE); } return(status); } // CxDispatchRegisterInterface NTSTATUS CxDispatchDeregisterInterface( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_INTERFACE_DEREG_REQUEST request; ULONG requestSize; PAGED_CODE(); request = (PCX_INTERFACE_DEREG_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; if (requestSize < sizeof(CX_INTERFACE_DEREG_REQUEST)) { return(STATUS_INVALID_PARAMETER); } status = CxDeregisterInterface(request->NodeId, request->NetworkId); return(status); } // CxDispatchDeregisterInterface NTSTATUS CxDispatchOnlineNodeComm( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_ONLINE_NODE_COMM_REQUEST request; ULONG requestSize; PAGED_CODE(); request = (PCX_ONLINE_NODE_COMM_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; if (requestSize < sizeof(CX_ONLINE_NODE_COMM_REQUEST)) { return(STATUS_INVALID_PARAMETER); } status = CxOnlineNodeComm(request->Id); return(status); } // CxDispatchOnlineNodeComm NTSTATUS CxDispatchOfflineNodeComm( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_OFFLINE_NODE_COMM_REQUEST request; ULONG requestSize; PAGED_CODE(); request = (PCX_OFFLINE_NODE_COMM_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; if (requestSize < sizeof(CX_OFFLINE_NODE_COMM_REQUEST)) { return(STATUS_INVALID_PARAMETER); } status = CxOfflineNodeComm(request->Id, Irp, IrpSp); return(status); } // CxDispatchOfflineNodeComm NTSTATUS CxDispatchOnlineNetwork( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_ONLINE_NETWORK_REQUEST request; ULONG requestSize; PTDI_ADDRESS_INFO response; ULONG responseSize; ULONG requiredSize = sizeof( CX_ONLINE_NETWORK_REQUEST ); PWCHAR tdiProviderName; PTRANSPORT_ADDRESS tdiBindAddress; PWCHAR adapterName; PAGED_CODE(); // // Validate the request buffer // // First validate that the request buffer size matches the offsets // and lengths. request = (PCX_ONLINE_NETWORK_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; if (requestSize < requiredSize) { return(STATUS_INVALID_PARAMETER); } // Validate that all offset length pairs are within the request // buffer. if ( ( request->TdiProviderNameOffset + request->TdiProviderNameLength < request->TdiProviderNameOffset ) || ( request->TdiProviderNameOffset + request->TdiProviderNameLength > requestSize ) || ( request->TdiBindAddressOffset + request->TdiBindAddressLength < request->TdiBindAddressOffset ) || ( request->TdiBindAddressOffset + request->TdiBindAddressLength > requestSize ) || ( request->AdapterNameOffset + request->AdapterNameLength < request->AdapterNameOffset ) || ( request->AdapterNameOffset + request->AdapterNameLength > requestSize ) ) { return(STATUS_INVALID_PARAMETER); } // Construct pointers to the parameters. tdiBindAddress = (PTRANSPORT_ADDRESS) ( ((PUCHAR) request) + request->TdiBindAddressOffset ); tdiProviderName = (PWCHAR) ( ((PUCHAR) request) + request->TdiProviderNameOffset ); adapterName = (PWCHAR) ( ((PUCHAR) request) + request->AdapterNameOffset ); // Validate that the resulting pointers are properly aligned and // within the request buffer. if ( ( ((PUCHAR) tdiBindAddress) < ((PUCHAR) request) ) || ( ((PUCHAR) tdiBindAddress) > ((PUCHAR) request) + requestSize ) || ( !POINTER_IS_ALIGNED(tdiBindAddress, TYPE_ALIGNMENT(TRANSPORT_ADDRESS)) ) || ( ((PUCHAR) tdiProviderName) < ((PUCHAR) request) ) || ( ((PUCHAR) tdiProviderName) > ((PUCHAR) request) + requestSize ) || ( !POINTER_IS_ALIGNED(tdiProviderName, TYPE_ALIGNMENT(WCHAR)) ) || ( ((PUCHAR) adapterName) < ((PUCHAR) request) ) || ( ((PUCHAR) adapterName) > ((PUCHAR) request) + requestSize ) || ( !POINTER_IS_ALIGNED(adapterName, TYPE_ALIGNMENT(WCHAR)) ) ) { return(STATUS_INVALID_PARAMETER); } // // Validate the response buffer // response = (PTDI_ADDRESS_INFO) Irp->AssociatedIrp.SystemBuffer; responseSize = IrpSp->Parameters.DeviceIoControl.OutputBufferLength; requiredSize = FIELD_OFFSET(TDI_ADDRESS_INFO, Address) + request->TdiBindAddressLength; if (responseSize < requiredSize) { return(STATUS_INVALID_PARAMETER); } status = CxOnlineNetwork( request->Id, tdiProviderName, request->TdiProviderNameLength, tdiBindAddress, request->TdiBindAddressLength, adapterName, request->AdapterNameLength, response, responseSize, Irp ); if (NT_SUCCESS(status)) { Irp->IoStatus.Information = responseSize; } return(status); } // CxDispatchOnlineNetwork NTSTATUS CxDispatchOfflineNetwork( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_OFFLINE_NETWORK_REQUEST request; ULONG requestSize; PAGED_CODE(); request = (PCX_OFFLINE_NETWORK_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; if (requestSize < sizeof(CX_OFFLINE_NETWORK_REQUEST)) { return(STATUS_INVALID_PARAMETER); } status = CxOfflineNetwork(request->Id, Irp, IrpSp); return(status); } // CxDispatchOfflineNetwork NTSTATUS CxDispatchSetNetworkRestriction( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; ULONG requestSize; PCX_SET_NETWORK_RESTRICTION_REQUEST request; PAGED_CODE(); request = (PCX_SET_NETWORK_RESTRICTION_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; if (requestSize < sizeof(CX_SET_NETWORK_RESTRICTION_REQUEST)) { return(STATUS_INVALID_PARAMETER); } status = CxSetNetworkRestriction( request->Id, request->Restricted, request->NewPriority ); return(status); } // CxDispatchSetNetworkRestriction NTSTATUS CxDispatchGetNetworkPriority( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_GET_NETWORK_PRIORITY_REQUEST request; PCX_GET_NETWORK_PRIORITY_RESPONSE response; ULONG requestSize; ULONG responseSize; PAGED_CODE(); request = (PCX_GET_NETWORK_PRIORITY_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; response = (PCX_GET_NETWORK_PRIORITY_RESPONSE) request; responseSize = IrpSp->Parameters.DeviceIoControl.OutputBufferLength; if ( (requestSize < sizeof(CX_GET_NETWORK_PRIORITY_REQUEST)) || (responseSize < sizeof(CX_GET_NETWORK_PRIORITY_RESPONSE)) ) { return(STATUS_INVALID_PARAMETER); } status = CxGetNetworkPriority( request->Id, &(response->Priority) ); if (status == STATUS_SUCCESS) { Irp->IoStatus.Information = sizeof(CX_GET_NETWORK_PRIORITY_RESPONSE); } return(status); } // CxDispatchGetNetworkPriority NTSTATUS CxDispatchSetNetworkPriority( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; ULONG requestSize; PCX_SET_NETWORK_PRIORITY_REQUEST request; PAGED_CODE(); request = (PCX_SET_NETWORK_PRIORITY_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; if (requestSize < sizeof(CX_SET_NETWORK_PRIORITY_REQUEST)) { return(STATUS_INVALID_PARAMETER); } status = CxSetNetworkPriority( request->Id, request->Priority ); return(status); } // CxDispatchSetNetworkPriority NTSTATUS CxDispatchGetInterfacePriority( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_GET_INTERFACE_PRIORITY_REQUEST request; PCX_GET_INTERFACE_PRIORITY_RESPONSE response; ULONG requestSize; ULONG responseSize; PAGED_CODE(); request = (PCX_GET_INTERFACE_PRIORITY_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; response = (PCX_GET_INTERFACE_PRIORITY_RESPONSE) request; responseSize = IrpSp->Parameters.DeviceIoControl.OutputBufferLength; if ( (requestSize < sizeof(CX_GET_INTERFACE_PRIORITY_REQUEST)) || (responseSize < sizeof(CX_GET_INTERFACE_PRIORITY_RESPONSE)) ) { return(STATUS_INVALID_PARAMETER); } status = CxGetInterfacePriority( request->NodeId, request->NetworkId, &(response->InterfacePriority), &(response->NetworkPriority) ); if (status == STATUS_SUCCESS) { Irp->IoStatus.Information = sizeof(CX_GET_INTERFACE_PRIORITY_RESPONSE); } return(status); } // CxDispatchGetInterfacePriority NTSTATUS CxDispatchSetInterfacePriority( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; ULONG requestSize; PCX_SET_INTERFACE_PRIORITY_REQUEST request; PAGED_CODE(); request = (PCX_SET_INTERFACE_PRIORITY_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; if (requestSize < sizeof(CX_SET_INTERFACE_PRIORITY_REQUEST)) { return(STATUS_INVALID_PARAMETER); } status = CxSetInterfacePriority( request->NodeId, request->NetworkId, request->Priority ); return(status); } // CxDispatchSetInterfacePriority NTSTATUS CxDispatchGetNodeState( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_GET_NODE_STATE_REQUEST request; PCX_GET_NODE_STATE_RESPONSE response; ULONG requestSize; ULONG responseSize; PAGED_CODE(); request = (PCX_GET_NODE_STATE_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; response = (PCX_GET_NODE_STATE_RESPONSE) request; responseSize = IrpSp->Parameters.DeviceIoControl.OutputBufferLength; if ( (requestSize < sizeof(CX_GET_NODE_STATE_REQUEST)) || (responseSize < sizeof(CX_GET_NODE_STATE_RESPONSE)) ) { return(STATUS_INVALID_PARAMETER); } status = CxGetNodeCommState( request->Id, &(response->State) ); if (status == STATUS_SUCCESS) { Irp->IoStatus.Information = sizeof(CX_GET_NODE_STATE_RESPONSE); } return(status); } // CxDispatchGetNodeState NTSTATUS CxDispatchGetNetworkState( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_GET_NETWORK_STATE_REQUEST request; PCX_GET_NETWORK_STATE_RESPONSE response; ULONG requestSize; ULONG responseSize; PAGED_CODE(); request = (PCX_GET_NETWORK_STATE_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; response = (PCX_GET_NETWORK_STATE_RESPONSE) request; responseSize = IrpSp->Parameters.DeviceIoControl.OutputBufferLength; if ( (requestSize < sizeof(CX_GET_NETWORK_STATE_REQUEST)) || (responseSize < sizeof(CX_GET_NETWORK_STATE_RESPONSE)) ) { return(STATUS_INVALID_PARAMETER); } status = CxGetNetworkState( request->Id, &(response->State) ); if (status == STATUS_SUCCESS) { Irp->IoStatus.Information = sizeof(CX_GET_NETWORK_STATE_RESPONSE); } return(status); } // CxDispatchGetNetworkState NTSTATUS CxDispatchGetInterfaceState( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_GET_INTERFACE_STATE_REQUEST request; PCX_GET_INTERFACE_STATE_RESPONSE response; ULONG requestSize; ULONG responseSize; PAGED_CODE(); request = (PCX_GET_INTERFACE_STATE_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; response = (PCX_GET_INTERFACE_STATE_RESPONSE) request; responseSize = IrpSp->Parameters.DeviceIoControl.OutputBufferLength; if ( (requestSize < sizeof(CX_GET_INTERFACE_STATE_REQUEST)) || (responseSize < sizeof(CX_GET_INTERFACE_STATE_RESPONSE)) ) { return(STATUS_INVALID_PARAMETER); } status = CxGetInterfaceState( request->NodeId, request->NetworkId, &(response->State) ); if (status == STATUS_SUCCESS) { Irp->IoStatus.Information = sizeof(CX_GET_INTERFACE_STATE_RESPONSE); } return(status); } // CxDispatchGetInterfaceState NTSTATUS CxDispatchIgnoreNodeState( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { PCX_ADDROBJ addrObj = (PCX_ADDROBJ) (IrpSp->FileObject->FsContext); CN_IRQL irql; CnAcquireLock(&(addrObj->Lock), &irql); IF_CNDBG(CN_DEBUG_ADDROBJ) { CNPRINT(("[CDP] Turning off checkstate flag on AO %p\n", addrObj)); } addrObj->Flags &= ~(CX_AO_FLAG_CHECKSTATE); CnReleaseLock(&(addrObj->Lock), irql); return(STATUS_SUCCESS); } // CxDispatchIgnoreNodeState NTSTATUS CxDispatchGetNodeMembershipState( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_GET_NODE_MMSTATE_REQUEST request; PCX_GET_NODE_MMSTATE_RESPONSE response; ULONG requestSize; ULONG responseSize; PAGED_CODE(); request = (PCX_GET_NODE_MMSTATE_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; response = (PCX_GET_NODE_MMSTATE_RESPONSE) request; responseSize = IrpSp->Parameters.DeviceIoControl.OutputBufferLength; if ( (requestSize < sizeof(CX_GET_NODE_MMSTATE_REQUEST)) || (responseSize < sizeof(CX_GET_NODE_MMSTATE_RESPONSE)) ) { return(STATUS_INVALID_PARAMETER); } status = CxGetNodeMembershipState( request->Id, &(response->State)); if (status == STATUS_SUCCESS) { Irp->IoStatus.Information = sizeof(CX_GET_NODE_MMSTATE_RESPONSE); } return(status); } // CxDispatchGetNodeMembershipState NTSTATUS CxDispatchSetNodeMembershipState( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_SET_NODE_MMSTATE_REQUEST request; ULONG requestSize; ULONG responseSize; PAGED_CODE(); request = (PCX_SET_NODE_MMSTATE_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; if (requestSize < sizeof( CX_SET_NODE_MMSTATE_REQUEST ) || request->State >= ClusnetNodeStateLastEntry) { return(STATUS_INVALID_PARAMETER); } status = CxSetNodeMembershipState( request->NodeId, request->State ); Irp->IoStatus.Information = 0; return(status); } // CxDispatchSetNodeMembershipState VOID CxCompleteSendPoisonPacket( IN NTSTATUS Status, IN ULONG BytesSent, IN PVOID Context, IN PVOID MessageData ) { PIRP irp = Context; CnAssert(Status != STATUS_PENDING); IF_CNDBG(( CN_DEBUG_IRP | CN_DEBUG_POISON )) CNPRINT(("[Clusnet] Completing SendPoisonPacket request for " "irp %p, status %08X\n", irp, Status)); // // The irp is completed in the CNP send completion routine. // return; } // CxCompleteSendPoisonPacket NTSTATUS CxDispatchSendPoisonPacket( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_SEND_POISON_PKT_REQUEST request; ULONG requestSize; PAGED_CODE(); request = (PCX_SEND_POISON_PKT_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; // // request size should exactly equal the size of the request struct plus // the data passed in // if ( requestSize != sizeof(CX_SEND_POISON_PKT_REQUEST)) { return(STATUS_INVALID_PARAMETER); } // // We will always return pending, so mark the IRP pending. // The IRP will be completed by CxCompleteSendPoisonPacket // IoMarkIrpPending(Irp); IF_CNDBG(( CN_DEBUG_IRP | CN_DEBUG_POISON )) CNPRINT(("[Clusnet] Posting SendPoisonPacket irp %p\n", Irp)); CxSendPoisonPacket( request->Id, CxCompleteSendPoisonPacket, Irp, Irp ); return(STATUS_PENDING); } // CxDispatchSendPoisonPacket NTSTATUS CxDispatchSetOuterscreen( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_SET_OUTERSCREEN_REQUEST request; ULONG requestSize; ULONG responseSize; PAGED_CODE(); request = (PCX_SET_OUTERSCREEN_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; if ( requestSize < sizeof( CX_SET_OUTERSCREEN_REQUEST )) { return(STATUS_INVALID_PARAMETER); } status = CxSetOuterscreen( request->Outerscreen ); Irp->IoStatus.Information = 0; return(status); } // CxDispatchSetOuterscreen NTSTATUS CxDispatchRegroupFinished( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_REGROUP_FINISHED_REQUEST request; ULONG requestSize; ULONG responseSize; PAGED_CODE(); request = (PCX_REGROUP_FINISHED_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; if ( requestSize < sizeof( CX_REGROUP_FINISHED_REQUEST )) { return(STATUS_INVALID_PARAMETER); } CxRegroupFinished( request->NewEpoch ); Irp->IoStatus.Information = 0; return( STATUS_SUCCESS ); } // CxDispatchRegroupFinished NTSTATUS CxDispatchImportSecurityContext( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_IMPORT_SECURITY_CONTEXT_REQUEST request; ULONG requestSize; ULONG responseSize; PAGED_CODE(); request = (PCX_IMPORT_SECURITY_CONTEXT_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; if ( requestSize < sizeof( CX_IMPORT_SECURITY_CONTEXT_REQUEST )) { return(STATUS_INVALID_PARAMETER); } status = CxImportSecurityContext(request->JoiningNodeId, request->PackageName, request->PackageNameSize, request->SignatureSize, request->ServerContext, request->ClientContext); Irp->IoStatus.Information = 0; return( status ); } // CxDispatchImportSecurityContext NTSTATUS CxDispatchReserveClusnetEndpoint( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; USHORT port; ULONG requestSize; PAGED_CODE(); requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; if (requestSize < sizeof(USHORT)) { status = STATUS_INVALID_PARAMETER; } else { port = *((PUSHORT) Irp->AssociatedIrp.SystemBuffer); status = CxReserveClusnetEndpoint(port); } Irp->IoStatus.Information = 0; return (status); } NTSTATUS CxDispatchConfigureMulticast( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_CONFIGURE_MULTICAST_REQUEST request; ULONG requestSize; ULONG requiredSize; PTRANSPORT_ADDRESS tdiMcastAddress; PVOID key; PVOID salt; PAGED_CODE(); // // Validate the request buffer // // First validate that the request buffer size matches the offsets // and lengths. request = (PCX_CONFIGURE_MULTICAST_REQUEST)Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; // // The required size is based on the size and required alignment // of each field of data following the structure. If there is no // data following the structure, only the structure is required. // requiredSize = sizeof(CX_CONFIGURE_MULTICAST_REQUEST); // // Verify that the required size is present. // if (requestSize < requiredSize) { return(STATUS_INVALID_PARAMETER); } // // Verify that all offset length pairs are within the request size. // if ( ( request->MulticastAddress + request->MulticastAddressLength < request->MulticastAddress ) || ( request->MulticastAddress + request->MulticastAddressLength > requestSize ) || ( request->Key + request->KeyLength < request->Key ) || ( request->Key + request->KeyLength > requestSize ) || ( request->Salt + request->SaltLength < request->Salt ) || ( request->Salt + request->SaltLength > requestSize ) ) { return(STATUS_INVALID_PARAMETER); } // // Construct pointers using the offsets. // tdiMcastAddress = (PTRANSPORT_ADDRESS) ( ((PUCHAR) request) + request->MulticastAddress ); key = (PVOID)( ((PUCHAR) request) + request->Key ); salt = (PVOID)( ((PUCHAR) request) + request->Salt ); // // Validate that the resulting pointers are properly aligned and // within the request data structure. // if ( ( ((PUCHAR) tdiMcastAddress) < ((PUCHAR) request) ) || ( ((PUCHAR) tdiMcastAddress) > ((PUCHAR) request) + requestSize ) || ( !POINTER_IS_ALIGNED(tdiMcastAddress, TYPE_ALIGNMENT(TRANSPORT_ADDRESS))) || ( ((PUCHAR) key) < ((PUCHAR) request) ) || ( ((PUCHAR) key) > ((PUCHAR) request) + requestSize ) || ( !POINTER_IS_ALIGNED(key, TYPE_ALIGNMENT(PVOID))) || ( ((PUCHAR) salt) < ((PUCHAR) request) ) || ( ((PUCHAR) salt) > ((PUCHAR) request) + requestSize ) || ( !POINTER_IS_ALIGNED(salt, TYPE_ALIGNMENT(PVOID))) ) { return(STATUS_INVALID_PARAMETER); } status = CxConfigureMulticast( request->NetworkId, request->MulticastNetworkBrand, tdiMcastAddress, request->MulticastAddressLength, key, request->KeyLength, salt, request->SaltLength, Irp ); // No return data. Irp->IoStatus.Information = 0; return(status); } // CxDispatchConfigureMulticast NTSTATUS CxDispatchGetMulticastReachableSet( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_GET_MULTICAST_REACHABLE_SET_REQUEST request; PCX_GET_MULTICAST_REACHABLE_SET_RESPONSE response; ULONG requestSize; ULONG responseSize; PAGED_CODE(); request = (PCX_GET_MULTICAST_REACHABLE_SET_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; response = (PCX_GET_MULTICAST_REACHABLE_SET_RESPONSE) request; responseSize = IrpSp->Parameters.DeviceIoControl.OutputBufferLength; if ( (requestSize < sizeof(PCX_GET_MULTICAST_REACHABLE_SET_REQUEST)) || (responseSize < sizeof(PCX_GET_MULTICAST_REACHABLE_SET_RESPONSE)) ) { return(STATUS_INVALID_PARAMETER); } status = CxGetMulticastReachableSet( request->Id, &(response->NodeScreen) ); if (status == STATUS_SUCCESS) { Irp->IoStatus.Information = sizeof(CX_GET_MULTICAST_REACHABLE_SET_RESPONSE); } return(status); } // CxDispatchGetMulticastReachableSet // // Test IOCTLs. // #if DBG NTSTATUS CxDispatchOnlinePendingInterface( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_ONLINE_PENDING_INTERFACE_REQUEST request; ULONG requestSize; PAGED_CODE(); request = (PCX_ONLINE_PENDING_INTERFACE_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; if (requestSize < sizeof(CX_ONLINE_PENDING_INTERFACE_REQUEST)) { return(STATUS_INVALID_PARAMETER); } status = CxOnlinePendingInterface(request->NodeId, request->NetworkId); return(status); } // CxDispatchOnlinePendingInterface NTSTATUS CxDispatchOnlineInterface( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_ONLINE_PENDING_INTERFACE_REQUEST request; ULONG requestSize; PAGED_CODE(); request = (PCX_ONLINE_PENDING_INTERFACE_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; if (requestSize < sizeof(CX_ONLINE_PENDING_INTERFACE_REQUEST)) { return(STATUS_INVALID_PARAMETER); } status = CxOnlineInterface(request->NodeId, request->NetworkId); return(status); } // CxDispatchOnlineInterface NTSTATUS CxDispatchOfflineInterface( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_ONLINE_PENDING_INTERFACE_REQUEST request; ULONG requestSize; PAGED_CODE(); request = (PCX_ONLINE_PENDING_INTERFACE_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; if (requestSize < sizeof(CX_ONLINE_PENDING_INTERFACE_REQUEST)) { return(STATUS_INVALID_PARAMETER); } status = CxOfflineInterface(request->NodeId, request->NetworkId); return(status); } // CxDispatchOfflineInterface NTSTATUS CxDispatchFailInterface( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_ONLINE_PENDING_INTERFACE_REQUEST request; ULONG requestSize; PAGED_CODE(); request = (PCX_ONLINE_PENDING_INTERFACE_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; if (requestSize < sizeof(CX_ONLINE_PENDING_INTERFACE_REQUEST)) { return(STATUS_INVALID_PARAMETER); } status = CxFailInterface(request->NodeId, request->NetworkId); return(status); } // CxDispatchFailInterface VOID CxCompleteSendMmMsg( IN NTSTATUS Status, IN ULONG BytesSent, IN PVOID Context, IN PVOID MessageData ) { PIRP irp = Context; CnAssert(Status != STATUS_PENDING); CNPRINT(( "[Clusnet] Completing SendMmMsg irp %p, status %lx, bytes sent %u\n", irp, Status, BytesSent )); // // Complete the irp. // irp->IoStatus.Status = Status; irp->IoStatus.Information = 0; IoCompleteRequest(irp, IO_NETWORK_INCREMENT); return; } // CxCompleteSendMmMsg #ifdef MM_IN_CLUSNET NTSTATUS CxDispatchSendMmMsg( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status; PCX_SEND_MM_MSG_REQUEST request; ULONG requestSize; PAGED_CODE(); request = (PCX_SEND_MM_MSG_REQUEST) Irp->AssociatedIrp.SystemBuffer; requestSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; if (requestSize < sizeof(CX_SEND_MM_MSG_REQUEST)) { return(STATUS_INVALID_PARAMETER); } IoMarkIrpPending(Irp); CNPRINT(("[Clusnet] Posting SendMmMsg irp %p\n", Irp)); status = CxSendMembershipMessage( request->DestNodeId, &(request->MessageData[0]), CX_MM_MSG_DATA_LEN, CxCompleteSendMmMsg, Irp ); return(status); } // CxDispatchSendMmMsg #endif // MM_IN_CLUSNET #endif // DBG