351 lines
10 KiB
C
351 lines
10 KiB
C
/*++
|
|
|
|
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
|
|
|