mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
371 lines
8.0 KiB
371 lines
8.0 KiB
/*++
|
|
|
|
Copyright (c) 1989-1993 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
framesnd.c
|
|
|
|
Abstract:
|
|
|
|
This module contains routines which build and send Sample transport
|
|
frames for other modules.
|
|
|
|
Environment:
|
|
|
|
Kernel mode
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "st.h"
|
|
|
|
|
|
|
|
NTSTATUS
|
|
StSendConnect(
|
|
IN PTP_CONNECTION Connection
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine sends a CONNECT frame of the appropriate type given the
|
|
state of the specified connection.
|
|
|
|
Arguments:
|
|
|
|
Connection - Pointer to a transport connection object.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
PDEVICE_CONTEXT DeviceContext;
|
|
PUCHAR SourceRouting;
|
|
UINT SourceRoutingLength;
|
|
UINT HeaderLength;
|
|
PSEND_PACKET_TAG SendTag;
|
|
PTP_PACKET Packet;
|
|
PST_HEADER StHeader;
|
|
|
|
|
|
DeviceContext = Connection->Provider;
|
|
|
|
//
|
|
// Allocate a packet from the pool.
|
|
//
|
|
|
|
Status = StCreatePacket (DeviceContext, &Packet);
|
|
if (!NT_SUCCESS (Status)) { // couldn't make frame.
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
SendTag = (PSEND_PACKET_TAG)(Packet->NdisPacket->ProtocolReserved);
|
|
SendTag->Type = TYPE_C_FRAME;
|
|
SendTag->Packet = Packet;
|
|
SendTag->Owner = (PVOID)Connection;
|
|
|
|
//
|
|
// Build the MAC header.
|
|
//
|
|
|
|
//
|
|
// CONNECT frames go out as
|
|
// single-route source routing.
|
|
//
|
|
|
|
MacReturnSingleRouteSR(
|
|
&DeviceContext->MacInfo,
|
|
&SourceRouting,
|
|
&SourceRoutingLength);
|
|
|
|
MacConstructHeader (
|
|
&DeviceContext->MacInfo,
|
|
Packet->Header,
|
|
DeviceContext->MulticastAddress.Address,
|
|
DeviceContext->LocalAddress.Address,
|
|
sizeof(ST_HEADER),
|
|
SourceRouting,
|
|
SourceRoutingLength,
|
|
&HeaderLength);
|
|
|
|
|
|
//
|
|
// Build the header: 'C', dest, source
|
|
//
|
|
|
|
StHeader = (PST_HEADER)(&Packet->Header[HeaderLength]);
|
|
|
|
StHeader->Signature = ST_SIGNATURE;
|
|
StHeader->Command = ST_CMD_CONNECT;
|
|
StHeader->Flags = 0;
|
|
|
|
RtlCopyMemory (StHeader->Destination, Connection->CalledAddress.NetbiosName, 16);
|
|
RtlCopyMemory (StHeader->Source, Connection->AddressFile->Address->NetworkName->NetbiosName, 16);
|
|
|
|
HeaderLength += sizeof(ST_HEADER);
|
|
|
|
//
|
|
// Modify the packet length and send the it.
|
|
//
|
|
|
|
StSetNdisPacketLength(Packet->NdisPacket, HeaderLength);
|
|
|
|
StNdisSend (Packet);
|
|
|
|
return STATUS_SUCCESS;
|
|
} /* StSendConnect */
|
|
|
|
|
|
NTSTATUS
|
|
StSendDisconnect(
|
|
IN PTP_CONNECTION Connection
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine sends a DISCONNECT frame of the appropriate type given the
|
|
state of the specified connection.
|
|
|
|
Arguments:
|
|
|
|
Connection - Pointer to a transport connection object.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
PDEVICE_CONTEXT DeviceContext;
|
|
PUCHAR SourceRouting;
|
|
UINT SourceRoutingLength;
|
|
UINT HeaderLength;
|
|
PSEND_PACKET_TAG SendTag;
|
|
PTP_PACKET Packet;
|
|
PST_HEADER StHeader;
|
|
|
|
|
|
DeviceContext = Connection->Provider;
|
|
|
|
//
|
|
// Allocate a packet from the pool.
|
|
//
|
|
|
|
Status = StCreatePacket (DeviceContext, &Packet);
|
|
if (!NT_SUCCESS (Status)) { // couldn't make frame.
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
SendTag = (PSEND_PACKET_TAG)(Packet->NdisPacket->ProtocolReserved);
|
|
SendTag->Type = TYPE_D_FRAME;
|
|
SendTag->Packet = Packet;
|
|
SendTag->Owner = (PVOID)Connection;
|
|
|
|
//
|
|
// Build the MAC header.
|
|
//
|
|
|
|
//
|
|
// CONNECT frames go out as
|
|
// single-route source routing.
|
|
//
|
|
|
|
MacReturnSingleRouteSR(
|
|
&DeviceContext->MacInfo,
|
|
&SourceRouting,
|
|
&SourceRoutingLength);
|
|
|
|
MacConstructHeader (
|
|
&DeviceContext->MacInfo,
|
|
Packet->Header,
|
|
DeviceContext->MulticastAddress.Address,
|
|
DeviceContext->LocalAddress.Address,
|
|
sizeof(ST_HEADER),
|
|
SourceRouting,
|
|
SourceRoutingLength,
|
|
&HeaderLength);
|
|
|
|
|
|
//
|
|
// Build the header: 'D', dest, source
|
|
//
|
|
|
|
StHeader = (PST_HEADER)(&Packet->Header[HeaderLength]);
|
|
|
|
StHeader->Signature = ST_SIGNATURE;
|
|
StHeader->Command = ST_CMD_DISCONNECT;
|
|
StHeader->Flags = 0;
|
|
|
|
RtlCopyMemory (StHeader->Destination, Connection->CalledAddress.NetbiosName, 16);
|
|
RtlCopyMemory (StHeader->Source, Connection->AddressFile->Address->NetworkName->NetbiosName, 16);
|
|
|
|
HeaderLength += sizeof(ST_HEADER);
|
|
|
|
//
|
|
// Modify the packet length and send the it.
|
|
//
|
|
|
|
StSetNdisPacketLength(Packet->NdisPacket, HeaderLength);
|
|
|
|
StNdisSend (Packet);
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
} /* StSendDisconnect */
|
|
|
|
|
|
NTSTATUS
|
|
StSendAddressFrame(
|
|
PTP_ADDRESS Address
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
It is intended that this routine be used for sending datagrams and
|
|
braodcast datagrams.
|
|
|
|
The datagram to be sent is described in the NDIS packet contained
|
|
in the Address. When the send completes, the send completion handler
|
|
returns the NDIS buffer describing the datagram to the buffer pool and
|
|
marks the address ndis packet as usable again. Thus, all datagram
|
|
frames are sequenced through the address they are sent on.
|
|
|
|
Arguments:
|
|
|
|
Address - pointer to the address from which to send this datagram.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS - status of operation.
|
|
|
|
--*/
|
|
|
|
{
|
|
PDEVICE_CONTEXT DeviceContext;
|
|
|
|
|
|
//
|
|
// Send the packet.
|
|
//
|
|
|
|
DeviceContext = Address->Provider;
|
|
|
|
INCREMENT_COUNTER (DeviceContext, PacketsSent);
|
|
|
|
StNdisSend (Address->Packet);
|
|
|
|
return STATUS_PENDING;
|
|
} /* StSendAddressFrame */
|
|
|
|
|
|
VOID
|
|
StSendDatagramCompletion(
|
|
IN PTP_ADDRESS Address,
|
|
IN PNDIS_PACKET NdisPacket,
|
|
IN NDIS_STATUS NdisStatus
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called as an I/O completion handler at the time a
|
|
StSendUIMdlFrame send request is completed. Because this handler is only
|
|
associated with StSendUIMdlFrame, and because StSendUIMdlFrame is only
|
|
used with datagrams and broadcast datagrams, we know that the I/O being
|
|
completed is a datagram. Here we complete the in-progress datagram, and
|
|
start-up the next one if there is one.
|
|
|
|
Arguments:
|
|
|
|
Address - Pointer to a transport address on which the datagram
|
|
is queued.
|
|
|
|
NdisPacket - pointer to the NDIS packet describing this request.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
--*/
|
|
|
|
{
|
|
PTP_REQUEST Request;
|
|
PLIST_ENTRY p;
|
|
KIRQL oldirql;
|
|
PNDIS_BUFFER HeaderBuffer;
|
|
|
|
UNREFERENCED_PARAMETER(NdisPacket);
|
|
|
|
StReferenceAddress ("Complete datagram", Address);
|
|
|
|
//
|
|
// Dequeue the current request and return it to the client. Release
|
|
// our hold on the send datagram queue.
|
|
//
|
|
// *** There may be no current request, if the one that was queued
|
|
// was aborted or timed out.
|
|
//
|
|
|
|
ACQUIRE_SPIN_LOCK (&Address->SpinLock, &oldirql);
|
|
p = RemoveHeadList (&Address->SendDatagramQueue);
|
|
|
|
if (p != &Address->SendDatagramQueue) {
|
|
|
|
RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);
|
|
|
|
Request = CONTAINING_RECORD (p, TP_REQUEST, Linkage);
|
|
|
|
//
|
|
// Strip off and unmap the buffers describing data and header.
|
|
//
|
|
|
|
NdisUnchainBufferAtFront (Address->Packet->NdisPacket, &HeaderBuffer);
|
|
|
|
// drop the rest of the packet
|
|
|
|
NdisReinitializePacket (Address->Packet->NdisPacket);
|
|
|
|
NDIS_BUFFER_LINKAGE(HeaderBuffer) = (PNDIS_BUFFER)NULL;
|
|
NdisChainBufferAtFront (Address->Packet->NdisPacket, HeaderBuffer);
|
|
|
|
//
|
|
// Ignore NdisStatus; datagrams always "succeed".
|
|
//
|
|
|
|
StCompleteRequest (Request, STATUS_SUCCESS, Request->Buffer2Length);
|
|
|
|
ACQUIRE_SPIN_LOCK (&Address->SpinLock, &oldirql);
|
|
Address->Flags &= ~ADDRESS_FLAGS_SEND_IN_PROGRESS;
|
|
RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);
|
|
|
|
//
|
|
// Send more datagrams on the Address if possible.
|
|
//
|
|
|
|
StSendDatagramsOnAddress (Address); // do more datagrams.
|
|
|
|
} else {
|
|
|
|
Address->Flags &= ~ADDRESS_FLAGS_SEND_IN_PROGRESS;
|
|
RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);
|
|
|
|
}
|
|
|
|
StDereferenceAddress ("Complete datagram", Address);
|
|
|
|
} /* StSendDatagramCompletion */
|