/*++ Copyright (c) 1997 Microsoft Corporation Module Name: cdpsend.c Abstract: TDI Send datagram routines. Author: Mike Massa (mikemas) February 20, 1997 Revision History: Who When What -------- -------- ---------------------------------------------- mikemas 02-20-97 created Notes: --*/ #include "precomp.h" #pragma hdrstop #include "cdpsend.tmh" #ifdef ALLOC_PRAGMA #pragma alloc_text(INIT, CdpInitializeSend) #endif // ALLOC_PRAGMA // // Local Types // // CDP_SEND_CONTEXT is currently empty // typedef struct { // } CDP_SEND_CONTEXT, *PCDP_SEND_CONTEXT; typedef PVOID PCDP_SEND_CONTEXT; #define CDP_SEND_REQUEST_POOL_DEPTH 5 // // Local Data // PCN_RESOURCE_POOL CdpSendRequestPool = NULL; PCN_RESOURCE_POOL CdpMcastSendRequestPool = NULL; // // Routines // NTSTATUS CdpInitializeSend( VOID ) { IF_CNDBG(CN_DEBUG_INIT) { CNPRINT(("[CDP] Initializing send...\n")); } CdpSendRequestPool = CnpCreateSendRequestPool( CNP_VERSION_UNICAST, PROTOCOL_CDP, sizeof(CDP_HEADER), 0, // sizeof(CDP_SEND_CONTEXT), CDP_SEND_REQUEST_POOL_DEPTH ); if (CdpSendRequestPool == NULL) { return(STATUS_INSUFFICIENT_RESOURCES); } CdpMcastSendRequestPool = CnpCreateSendRequestPool( CNP_VERSION_MULTICAST, PROTOCOL_CDP, sizeof(CDP_HEADER), 0, // sizeof(CDP_SEND_CONTEXT) CDP_SEND_REQUEST_POOL_DEPTH ); if (CdpMcastSendRequestPool == NULL) { return(STATUS_INSUFFICIENT_RESOURCES); } IF_CNDBG(CN_DEBUG_INIT) { CNPRINT(("[CDP] Send initialized.\n")); } return(STATUS_SUCCESS); } // CdpInitializeSend VOID CdpCleanupSend( VOID ) { IF_CNDBG(CN_DEBUG_INIT) { CNPRINT(("[CDP] Cleaning up send...\n")); } if (CdpSendRequestPool != NULL) { CnpDeleteSendRequestPool(CdpSendRequestPool); } if (CdpMcastSendRequestPool != NULL) { CnpDeleteSendRequestPool(CdpMcastSendRequestPool); } IF_CNDBG(CN_DEBUG_INIT) { CNPRINT(("[CDP] Send cleanup complete.\n")); } return; } // CdpCleanupSend VOID CdpCompleteSendDatagram( IN NTSTATUS Status, IN OUT PULONG BytesSent, IN PCNP_SEND_REQUEST SendRequest, IN PMDL DataMdl ) { PCDP_SEND_CONTEXT sendContext = SendRequest->UpperProtocolContext; PCNP_HEADER cnpHeader = SendRequest->CnpHeader; PCDP_HEADER cdpHeader = SendRequest->UpperProtocolHeader; if (NT_SUCCESS(Status)) { if (*BytesSent >= sizeof(CDP_HEADER)) { *BytesSent -= sizeof(CDP_HEADER); } else { *BytesSent = 0; CnAssert(FALSE); } CnTrace(CDP_SEND_DETAIL, CdpTraceSendComplete, "[CDP] Send of dgram to node %u port %u complete, bytes sent %u.", cnpHeader->DestinationAddress, // LOGULONG cdpHeader->DestinationPort, // LOGUSHORT *BytesSent // LOGULONG ); } else { CnTrace(CDP_SEND_ERROR, CdpTraceSendFailedBelow, "[CDP] Transport failed to send dgram to node %u port %u, " "data len %u, status %!status!", cnpHeader->DestinationAddress, // LOGULONG cdpHeader->DestinationPort, // LOGUSHORT cdpHeader->PayloadLength, // LOGUSHORT Status // LOGSTATUS ); CnAssert(*BytesSent == 0); } CnAssert(sendContext == NULL); if (cnpHeader->DestinationAddress == ClusterAnyNodeId) { // // Dereference the network multicast group data structure. // if (SendRequest->McastGroup != NULL) { CnpDereferenceMulticastGroup(SendRequest->McastGroup); SendRequest->McastGroup = NULL; } } CnFreeResource((PCN_RESOURCE) SendRequest); return; } // CdpCompleteSendDatagram NTSTATUS CxSendDatagram( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) { NTSTATUS status = STATUS_NOT_IMPLEMENTED; PCX_ADDROBJ addrObj; PTDI_REQUEST_KERNEL_SENDDG request; ULONG bytesSent = 0; CN_IRQL cancelIrql; USHORT destPort = 0; CL_NODE_ID destNode = ClusterInvalidNodeId; addrObj = (PCX_ADDROBJ) IrpSp->FileObject->FsContext; request = (PTDI_REQUEST_KERNEL_SENDDG) &(IrpSp->Parameters); if (request->SendLength <= CDP_MAX_SEND_SIZE(CX_SIGNATURE_LENGTH)) { if ( request->SendDatagramInformation->RemoteAddressLength >= sizeof(TA_CLUSTER_ADDRESS) ) { status = CxParseTransportAddress( request->SendDatagramInformation->RemoteAddress, request->SendDatagramInformation->RemoteAddressLength, &destNode, &destPort ); if (status == STATUS_SUCCESS) { if (destPort != 0) { PCNP_SEND_REQUEST sendRequest; if (destNode == ClusterAnyNodeId) { // // This is a CNP multicast. // sendRequest = (PCNP_SEND_REQUEST) CnAllocateResource( CdpMcastSendRequestPool ); } else { // // This is a normal unicast. // sendRequest = (PCNP_SEND_REQUEST) CnAllocateResource( CdpSendRequestPool ); } if (sendRequest != NULL) { PCDP_HEADER cdpHeader; PCDP_SEND_CONTEXT sendContext; BOOLEAN checkState; CL_NETWORK_ID destNet = ClusterAnyNetworkId; checkState = (addrObj->Flags & CX_AO_FLAG_CHECKSTATE) ? TRUE : FALSE; // // Fill in the CDP header. // cdpHeader = sendRequest->UpperProtocolHeader; RtlZeroMemory(cdpHeader, sizeof(CDP_HEADER)); cdpHeader->SourcePort = addrObj->LocalPort; cdpHeader->DestinationPort = destPort; cdpHeader->PayloadLength = (USHORT)request->SendLength; // // Fill in the caller portion of the CNP // send request. // sendRequest->UpperProtocolIrp = Irp; sendRequest->CompletionRoutine = CdpCompleteSendDatagram; // // Fill in our own send context // (currently nothing). // sendContext = sendRequest->UpperProtocolContext; CnAssert(sendContext == NULL); CnVerifyCpuLockMask( 0, // Required CNP_LOCK_RANGE, // Forbidden CNP_PRECEEDING_LOCK_RANGE // Maximum ); // // Send the message. // CnTrace(CDP_SEND_DETAIL, CdpTraceSend, "[CDP] Sending dgram to node %u port %u, " "data len %u.", destNode, // LOGULONG destPort, // LOGUSHORT request->SendLength // LOGULONG ); status = CnpSendPacket( sendRequest, destNode, Irp->MdlAddress, (USHORT) request->SendLength, checkState, destNet ); CnVerifyCpuLockMask( 0, // Required CNP_LOCK_RANGE, // Forbidden CNP_PRECEEDING_LOCK_RANGE // Maximum ); return(status); } else { status = STATUS_INSUFFICIENT_RESOURCES; } } else { status = STATUS_INVALID_ADDRESS_COMPONENT; } } } else { status = STATUS_INVALID_ADDRESS_COMPONENT; } } else { status = STATUS_INVALID_BUFFER_SIZE; } CnTrace(CDP_SEND_ERROR, CdpTraceSendFailedInternal, "[CDP] Failed to send dgram to node %u port %u, data len %u, " "status %!status!", destNode, // LOGULONG destPort, // LOGUSHORT request->SendLength, // LOGULONG status // LOGSTATUS ); Irp->IoStatus.Status = status; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); CnVerifyCpuLockMask( 0, // Required CNP_LOCK_RANGE, // Forbidden CNP_PRECEEDING_LOCK_RANGE // Maximum ); return(status); } // CxSendDatagram