2529 lines
62 KiB
C
2529 lines
62 KiB
C
/*++
|
||
|
||
Copyright (c) 1989, 1990, 1991 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
framesnd.c
|
||
|
||
Abstract:
|
||
|
||
This module contains routines which build and send NetBIOS Frames Protocol
|
||
frames and data link frames for other modules. These routines call on the
|
||
ones in FRAMECON.C to do the construction work.
|
||
|
||
Author:
|
||
|
||
David Beaver (dbeaver) 1-July-1991
|
||
|
||
Environment:
|
||
|
||
Kernel mode
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "precomp.h"
|
||
#pragma hdrstop
|
||
|
||
#if DBG
|
||
ULONG NbfSendsIssued = 0;
|
||
ULONG NbfSendsCompletedInline = 0;
|
||
ULONG NbfSendsCompletedOk = 0;
|
||
ULONG NbfSendsCompletedFail = 0;
|
||
ULONG NbfSendsPended = 0;
|
||
ULONG NbfSendsCompletedAfterPendOk = 0;
|
||
ULONG NbfSendsCompletedAfterPendFail = 0;
|
||
|
||
ULONG NbfPacketPanic = 0;
|
||
#endif
|
||
|
||
|
||
NTSTATUS
|
||
NbfSendAddNameQuery(
|
||
IN PTP_ADDRESS Address
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine sends a ADD_NAME_QUERY frame to register the specified
|
||
address.
|
||
|
||
Arguments:
|
||
|
||
Address - Pointer to a transport address object.
|
||
|
||
|
||
Return Value:
|
||
|
||
none.
|
||
|
||
--*/
|
||
|
||
{
|
||
NTSTATUS Status;
|
||
PDEVICE_CONTEXT DeviceContext;
|
||
PTP_UI_FRAME RawFrame;
|
||
PUCHAR SingleSR;
|
||
UINT SingleSRLength;
|
||
UINT HeaderLength;
|
||
|
||
DeviceContext = Address->Provider;
|
||
|
||
|
||
//
|
||
// Allocate a UI frame from the pool.
|
||
//
|
||
|
||
Status = NbfCreateConnectionlessFrame (DeviceContext, &RawFrame);
|
||
if (!NT_SUCCESS (Status)) { // couldn't make frame.
|
||
return STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
|
||
IF_NBFDBG (NBF_DEBUG_FRAMESND) {
|
||
NbfPrint3 ("NbfSendAddNameQuery: Sending Frame: %lx, NdisPacket: %lx MacHeader: %lx\n",
|
||
RawFrame, RawFrame->NdisPacket, RawFrame->Header);
|
||
}
|
||
|
||
|
||
//
|
||
// Build the MAC header. ADD_NAME_QUERY frames go out as
|
||
// single-route source routing.
|
||
//
|
||
|
||
MacReturnSingleRouteSR(
|
||
&DeviceContext->MacInfo,
|
||
&SingleSR,
|
||
&SingleSRLength);
|
||
|
||
MacConstructHeader (
|
||
&DeviceContext->MacInfo,
|
||
RawFrame->Header,
|
||
DeviceContext->NetBIOSAddress.Address,
|
||
DeviceContext->LocalAddress.Address,
|
||
sizeof (DLC_FRAME) + sizeof (NBF_HDR_CONNECTIONLESS),
|
||
SingleSR,
|
||
SingleSRLength,
|
||
&HeaderLength);
|
||
|
||
|
||
//
|
||
// Build the DLC UI frame header.
|
||
//
|
||
|
||
NbfBuildUIFrameHeader(&RawFrame->Header[HeaderLength]);
|
||
HeaderLength += sizeof(DLC_FRAME);
|
||
|
||
|
||
//
|
||
// Build the appropriate Netbios header based on the type
|
||
// of the address.
|
||
//
|
||
|
||
if ((Address->Flags & ADDRESS_FLAGS_GROUP) != 0) {
|
||
|
||
ConstructAddGroupNameQuery (
|
||
(PNBF_HDR_CONNECTIONLESS)&(RawFrame->Header[HeaderLength]),
|
||
0, // correlator we don't use.
|
||
Address->NetworkName->NetbiosName);
|
||
|
||
} else {
|
||
|
||
ConstructAddNameQuery (
|
||
(PNBF_HDR_CONNECTIONLESS)&(RawFrame->Header[HeaderLength]),
|
||
0, // correlator we don't use.
|
||
Address->NetworkName->NetbiosName);
|
||
|
||
}
|
||
|
||
HeaderLength += sizeof(NBF_HDR_CONNECTIONLESS);
|
||
|
||
|
||
//
|
||
// Munge the packet length and send the it.
|
||
//
|
||
|
||
NbfSetNdisPacketLength(RawFrame->NdisPacket, HeaderLength);
|
||
|
||
NbfSendUIFrame (
|
||
DeviceContext,
|
||
RawFrame,
|
||
FALSE); // no loopback (MC frame).
|
||
|
||
return STATUS_SUCCESS;
|
||
} /* NbfSendAddNameQuery */
|
||
|
||
|
||
VOID
|
||
NbfSendNameQuery(
|
||
IN PTP_CONNECTION Connection,
|
||
IN BOOLEAN SourceRoutingOptional
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine sends a NAME_QUERY frame of the appropriate type given the
|
||
state of the specified connection.
|
||
|
||
Arguments:
|
||
|
||
Connection - Pointer to a transport connection object.
|
||
|
||
SourceRoutingOptional - TRUE if source routing should be removed if
|
||
we are configured that way.
|
||
|
||
Return Value:
|
||
|
||
none.
|
||
|
||
--*/
|
||
|
||
{
|
||
NTSTATUS Status;
|
||
PDEVICE_CONTEXT DeviceContext;
|
||
PTP_ADDRESS Address;
|
||
PTP_UI_FRAME RawFrame;
|
||
PUCHAR NameQuerySR;
|
||
UINT NameQuerySRLength;
|
||
PUCHAR NameQueryAddress;
|
||
UINT HeaderLength;
|
||
UCHAR Lsn;
|
||
UCHAR NameType;
|
||
|
||
Address = Connection->AddressFile->Address;
|
||
DeviceContext = Address->Provider;
|
||
|
||
|
||
//
|
||
// Allocate a UI frame from the pool.
|
||
//
|
||
|
||
Status = NbfCreateConnectionlessFrame(DeviceContext, &RawFrame);
|
||
if (!NT_SUCCESS (Status)) { // couldn't make frame.
|
||
return;
|
||
}
|
||
|
||
IF_NBFDBG (NBF_DEBUG_FRAMESND) {
|
||
NbfPrint2 ("NbfSendNameQuery: Sending Frame: %lx, NdisPacket: %lx\n",
|
||
RawFrame, RawFrame->NdisPacket);
|
||
}
|
||
|
||
|
||
//
|
||
// Build the MAC header.
|
||
//
|
||
|
||
if (((Connection->Flags2 & CONNECTION_FLAGS2_WAIT_NR) != 0) &&
|
||
((Connection->Flags2 & CONNECTION_FLAGS2_GROUP_LSN) == 0)) {
|
||
|
||
//
|
||
// This is the second find name to a unique name; this
|
||
// means that we already have a link and we can send this
|
||
// frame directed to it.
|
||
//
|
||
|
||
ASSERT (Connection->Link != NULL);
|
||
|
||
MacReturnSourceRouting(
|
||
&DeviceContext->MacInfo,
|
||
Connection->Link->Header,
|
||
&NameQuerySR,
|
||
&NameQuerySRLength);
|
||
|
||
NameQueryAddress = Connection->Link->HardwareAddress.Address;
|
||
|
||
} else {
|
||
|
||
//
|
||
// Standard NAME_QUERY frames go out as
|
||
// single-route source routing, except if
|
||
// it is optional and we are configured
|
||
// that way.
|
||
//
|
||
|
||
if (SourceRoutingOptional &&
|
||
Connection->Provider->MacInfo.QueryWithoutSourceRouting) {
|
||
|
||
NameQuerySR = NULL;
|
||
NameQuerySRLength = 0;
|
||
|
||
} else {
|
||
|
||
MacReturnSingleRouteSR(
|
||
&DeviceContext->MacInfo,
|
||
&NameQuerySR,
|
||
&NameQuerySRLength);
|
||
|
||
}
|
||
|
||
NameQueryAddress = DeviceContext->NetBIOSAddress.Address;
|
||
|
||
}
|
||
|
||
MacConstructHeader (
|
||
&DeviceContext->MacInfo,
|
||
RawFrame->Header,
|
||
NameQueryAddress,
|
||
DeviceContext->LocalAddress.Address,
|
||
sizeof (DLC_FRAME) + sizeof (NBF_HDR_CONNECTIONLESS),
|
||
NameQuerySR,
|
||
NameQuerySRLength,
|
||
&HeaderLength);
|
||
|
||
|
||
//
|
||
// Build the DLC UI frame header.
|
||
//
|
||
|
||
NbfBuildUIFrameHeader(&RawFrame->Header[HeaderLength]);
|
||
HeaderLength += sizeof(DLC_FRAME);
|
||
|
||
|
||
//
|
||
// Build the Netbios header.
|
||
//
|
||
|
||
Lsn = (UCHAR)((Connection->Flags2 & CONNECTION_FLAGS2_WAIT_NR_FN) ?
|
||
NAME_QUERY_LSN_FIND_NAME : Connection->Lsn);
|
||
|
||
NameType = (UCHAR)((Connection->AddressFile->Address->Flags & ADDRESS_FLAGS_GROUP) ?
|
||
NETBIOS_NAME_TYPE_GROUP : NETBIOS_NAME_TYPE_UNIQUE);
|
||
|
||
ConstructNameQuery (
|
||
(PNBF_HDR_CONNECTIONLESS)&(RawFrame->Header[HeaderLength]),
|
||
NameType, // type of our name.
|
||
Lsn, // calculated, above.
|
||
(USHORT)Connection->ConnectionId, // corr. in 1st NAME_RECOGNIZED.
|
||
Address->NetworkName->NetbiosName, // NetBIOS name of sender.
|
||
Connection->CalledAddress.NetbiosName); // NetBIOS name of receiver.
|
||
|
||
HeaderLength += sizeof(NBF_HDR_CONNECTIONLESS);
|
||
|
||
|
||
//
|
||
// Munge the packet length and send the it.
|
||
//
|
||
|
||
NbfSetNdisPacketLength(RawFrame->NdisPacket, HeaderLength);
|
||
|
||
NbfSendUIFrame (
|
||
DeviceContext,
|
||
RawFrame,
|
||
FALSE); // no loopback (MC frame)
|
||
|
||
} /* NbfSendNameQuery */
|
||
|
||
|
||
VOID
|
||
NbfSendNameRecognized(
|
||
IN PTP_ADDRESS Address,
|
||
IN UCHAR LocalSessionNumber, // LSN assigned to session.
|
||
IN PNBF_HDR_CONNECTIONLESS Header,
|
||
IN PHARDWARE_ADDRESS SourceAddress,
|
||
IN PUCHAR SourceRouting,
|
||
IN UINT SourceRoutingLength
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine sends a NAME_RECOGNIZED frame of the appropriate type
|
||
in response to the NAME_QUERY pointed to by Header.
|
||
|
||
Arguments:
|
||
|
||
Address - Pointer to a transport address object.
|
||
|
||
LocalSessionNumber - The LSN to use in the frame.
|
||
|
||
Header - Pointer to the connectionless NetBIOS header of the
|
||
NAME_QUERY frame.
|
||
|
||
SourceAddress - Pointer to the source hardware address in the received
|
||
frame.
|
||
|
||
SourceRoutingInformation - Pointer to source routing information, if any.
|
||
|
||
Return Value:
|
||
|
||
none.
|
||
|
||
--*/
|
||
|
||
{
|
||
NTSTATUS Status;
|
||
PDEVICE_CONTEXT DeviceContext;
|
||
PTP_UI_FRAME RawFrame;
|
||
UINT HeaderLength;
|
||
PUCHAR ReplySR;
|
||
UINT ReplySRLength;
|
||
UCHAR TempSR[MAX_SOURCE_ROUTING];
|
||
UCHAR NameType;
|
||
|
||
DeviceContext = Address->Provider;
|
||
|
||
|
||
//
|
||
// Allocate a UI frame from the pool.
|
||
//
|
||
|
||
Status = NbfCreateConnectionlessFrame (DeviceContext, &RawFrame);
|
||
if (!NT_SUCCESS (Status)) { // couldn't make frame.
|
||
return;
|
||
}
|
||
|
||
IF_NBFDBG (NBF_DEBUG_FRAMESND) {
|
||
NbfPrint2 ("NbfSendNameRecognized: Sending Frame: %lx, NdisPacket: %lx\n",
|
||
RawFrame, RawFrame->NdisPacket);
|
||
}
|
||
|
||
|
||
//
|
||
// Build the MAC header. NAME_RECOGNIZED frames go out as
|
||
// directed source routing unless configured for general-route.
|
||
//
|
||
|
||
if (DeviceContext->MacInfo.AllRoutesNameRecognized) {
|
||
|
||
MacReturnGeneralRouteSR(
|
||
&DeviceContext->MacInfo,
|
||
&ReplySR,
|
||
&ReplySRLength);
|
||
|
||
} else {
|
||
|
||
if (SourceRouting != NULL) {
|
||
|
||
RtlCopyMemory(
|
||
TempSR,
|
||
SourceRouting,
|
||
SourceRoutingLength);
|
||
|
||
MacCreateNonBroadcastReplySR(
|
||
&DeviceContext->MacInfo,
|
||
TempSR,
|
||
SourceRoutingLength,
|
||
&ReplySR);
|
||
|
||
ReplySRLength = SourceRoutingLength;
|
||
|
||
} else {
|
||
|
||
ReplySR = NULL;
|
||
}
|
||
}
|
||
|
||
|
||
MacConstructHeader (
|
||
&DeviceContext->MacInfo,
|
||
RawFrame->Header,
|
||
SourceAddress->Address,
|
||
DeviceContext->LocalAddress.Address,
|
||
sizeof (DLC_FRAME) + sizeof (NBF_HDR_CONNECTIONLESS),
|
||
ReplySR,
|
||
ReplySRLength,
|
||
&HeaderLength);
|
||
|
||
|
||
//
|
||
// Build the DLC UI frame header.
|
||
//
|
||
|
||
NbfBuildUIFrameHeader(&RawFrame->Header[HeaderLength]);
|
||
HeaderLength += sizeof(DLC_FRAME);
|
||
|
||
|
||
//
|
||
// Build the Netbios header.
|
||
//
|
||
|
||
NameType = (UCHAR)((Address->Flags & ADDRESS_FLAGS_GROUP) ?
|
||
NETBIOS_NAME_TYPE_GROUP : NETBIOS_NAME_TYPE_UNIQUE);
|
||
|
||
ConstructNameRecognized ( // build a good response.
|
||
(PNBF_HDR_CONNECTIONLESS)&(RawFrame->Header[HeaderLength]),
|
||
NameType, // type of local name.
|
||
LocalSessionNumber, // return our LSN.
|
||
RESPONSE_CORR(Header), // new xmit corr.
|
||
0, // our response correlator (unused).
|
||
Header->DestinationName, // our NetBIOS name.
|
||
Header->SourceName); // his NetBIOS name.
|
||
|
||
//
|
||
// Use Address->NetworkName->Address[0].Address[0].NetbiosName
|
||
// instead of Header->DestinationName?
|
||
//
|
||
|
||
HeaderLength += sizeof(NBF_HDR_CONNECTIONLESS);
|
||
|
||
|
||
//
|
||
// Munge the packet length and send the it.
|
||
//
|
||
|
||
NbfSetNdisPacketLength(RawFrame->NdisPacket, HeaderLength);
|
||
|
||
NbfSendUIFrame (
|
||
DeviceContext,
|
||
RawFrame,
|
||
FALSE); // no loopback (MC frame)
|
||
|
||
} /* NbfSendNameRecognized */
|
||
|
||
|
||
VOID
|
||
NbfSendNameInConflict(
|
||
IN PTP_ADDRESS Address,
|
||
IN PUCHAR ConflictingName
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine sends a NAME_IN_CONFLICT frame.
|
||
|
||
Arguments:
|
||
|
||
Address - Pointer to a transport address object.
|
||
|
||
ConflictingName - The NetBIOS name which is in conflict.
|
||
|
||
Return Value:
|
||
|
||
none.
|
||
|
||
--*/
|
||
|
||
{
|
||
NTSTATUS Status;
|
||
PDEVICE_CONTEXT DeviceContext;
|
||
PTP_UI_FRAME RawFrame;
|
||
UINT HeaderLength;
|
||
PUCHAR SingleSR;
|
||
UINT SingleSRLength;
|
||
|
||
DeviceContext = Address->Provider;
|
||
|
||
|
||
//
|
||
// Allocate a UI frame from the pool.
|
||
//
|
||
|
||
Status = NbfCreateConnectionlessFrame (DeviceContext, &RawFrame);
|
||
if (!NT_SUCCESS (Status)) { // couldn't make frame.
|
||
return;
|
||
}
|
||
|
||
IF_NBFDBG (NBF_DEBUG_FRAMESND) {
|
||
NbfPrint2 ("NbfSendNameRecognized: Sending Frame: %lx, NdisPacket: %lx\n",
|
||
RawFrame, RawFrame->NdisPacket);
|
||
}
|
||
|
||
|
||
//
|
||
// Build the MAC header. ADD_NAME_QUERY frames go out as
|
||
// single-route source routing.
|
||
//
|
||
|
||
MacReturnSingleRouteSR(
|
||
&DeviceContext->MacInfo,
|
||
&SingleSR,
|
||
&SingleSRLength);
|
||
|
||
MacConstructHeader (
|
||
&DeviceContext->MacInfo,
|
||
RawFrame->Header,
|
||
DeviceContext->NetBIOSAddress.Address,
|
||
DeviceContext->LocalAddress.Address,
|
||
sizeof (DLC_FRAME) + sizeof (NBF_HDR_CONNECTIONLESS),
|
||
SingleSR,
|
||
SingleSRLength,
|
||
&HeaderLength);
|
||
|
||
|
||
//
|
||
// Build the DLC UI frame header.
|
||
//
|
||
|
||
NbfBuildUIFrameHeader(&RawFrame->Header[HeaderLength]);
|
||
HeaderLength += sizeof(DLC_FRAME);
|
||
|
||
|
||
//
|
||
// Build the Netbios header.
|
||
//
|
||
|
||
ConstructNameInConflict (
|
||
(PNBF_HDR_CONNECTIONLESS)&(RawFrame->Header[HeaderLength]),
|
||
ConflictingName, // his NetBIOS name.
|
||
DeviceContext->ReservedNetBIOSAddress); // our reserved NetBIOS name.
|
||
|
||
HeaderLength += sizeof(NBF_HDR_CONNECTIONLESS);
|
||
|
||
|
||
//
|
||
// Munge the packet length and send the it.
|
||
//
|
||
|
||
NbfSetNdisPacketLength(RawFrame->NdisPacket, HeaderLength);
|
||
|
||
NbfSendUIFrame (
|
||
DeviceContext,
|
||
RawFrame,
|
||
FALSE); // no loopback (MC frame)
|
||
|
||
} /* NbfSendNameInConflict */
|
||
|
||
|
||
VOID
|
||
NbfSendSessionInitialize(
|
||
IN PTP_CONNECTION Connection
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine sends a SESSION_INITIALIZE frame on the specified connection.
|
||
|
||
NOTE: THIS ROUTINE MUST BE CALLED AT DPC LEVEL.
|
||
|
||
Arguments:
|
||
|
||
Connection - Pointer to a transport connection object.
|
||
|
||
|
||
Return Value:
|
||
|
||
none.
|
||
|
||
--*/
|
||
|
||
{
|
||
NTSTATUS Status;
|
||
PTP_PACKET Packet;
|
||
PDEVICE_CONTEXT DeviceContext;
|
||
PTP_LINK Link;
|
||
|
||
NbfReferenceConnection("send Session Initialize", Connection, CREF_FRAME_SEND);
|
||
|
||
DeviceContext = Connection->Provider;
|
||
Link = Connection->Link;
|
||
Status = NbfCreatePacket (DeviceContext, Connection->Link, &Packet);
|
||
|
||
if (!NT_SUCCESS (Status)) { // if we couldn't make frame.
|
||
#if DBG
|
||
if (NbfPacketPanic) {
|
||
PANIC ("NbfSendSessionInitialize: NbfCreatePacket failed.\n");
|
||
}
|
||
#endif
|
||
NbfWaitPacket (Connection, CONNECTION_FLAGS_SEND_SI);
|
||
NbfDereferenceConnection("Couldn't get SI packet", Connection, CREF_FRAME_SEND);
|
||
return;
|
||
}
|
||
|
||
|
||
//
|
||
// Initialize the Netbios header.
|
||
//
|
||
|
||
ConstructSessionInitialize (
|
||
(PNBF_HDR_CONNECTION)&(Packet->Header[Link->HeaderLength + sizeof(DLC_I_FRAME)]),
|
||
SESSION_INIT_OPTIONS_20 | SESSION_INIT_NO_ACK |
|
||
SESSION_INIT_OPTIONS_LF, // supported options Set LF correctly.
|
||
(USHORT)(Connection->Link->MaxFrameSize - sizeof(NBF_HDR_CONNECTION) - sizeof(DLC_I_FRAME)),
|
||
// maximum frame size/this session.
|
||
Connection->NetbiosHeader.TransmitCorrelator, // correlator from NAME_RECOGNIZED.
|
||
0, // correlator for expected SESSION_CONFIRM.
|
||
Connection->Lsn, // our local session number.
|
||
Connection->Rsn); // his session number (our RSN).
|
||
|
||
//
|
||
// Now send the packet on the connection via the link. If there are
|
||
// conditions on the link which make it impossible to send the packet,
|
||
// then the packet will be queued to the WackQ, and then timeouts will
|
||
// restart the link. This is acceptable when the traffic level is so
|
||
// high that we encounter this condition.
|
||
//
|
||
|
||
//
|
||
// Set this so NbfDestroyPacket will dereference the connection.
|
||
//
|
||
|
||
Packet->Owner = Connection;
|
||
Packet->Action = PACKET_ACTION_CONNECTION;
|
||
|
||
Packet->NdisIFrameLength =
|
||
Link->HeaderLength + sizeof(DLC_I_FRAME) + sizeof(NBF_HDR_CONNECTION);
|
||
|
||
MacModifyHeader(
|
||
&DeviceContext->MacInfo,
|
||
Packet->Header,
|
||
sizeof(DLC_I_FRAME) + sizeof(NBF_HDR_CONNECTION));
|
||
|
||
NbfSetNdisPacketLength(
|
||
Packet->NdisPacket,
|
||
Packet->NdisIFrameLength);
|
||
|
||
ACQUIRE_DPC_SPIN_LOCK (Connection->LinkSpinLock);
|
||
|
||
Status = SendOnePacket (Connection, Packet, FALSE, NULL); // fire and forget.
|
||
|
||
if (Status == STATUS_LINK_FAILED) {
|
||
NbfDereferencePacket (Packet); // destroy the packet.
|
||
}
|
||
|
||
return;
|
||
} /* NbfSendSessionInitialize */
|
||
|
||
|
||
VOID
|
||
NbfSendSessionConfirm(
|
||
IN PTP_CONNECTION Connection
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine sends a SESSION_CONFIRM frame on the specified connection.
|
||
|
||
Arguments:
|
||
|
||
Connection - Pointer to a transport connection object.
|
||
|
||
|
||
Return Value:
|
||
|
||
none.
|
||
|
||
--*/
|
||
|
||
{
|
||
NTSTATUS Status;
|
||
PTP_PACKET Packet;
|
||
PDEVICE_CONTEXT DeviceContext;
|
||
PTP_LINK Link;
|
||
|
||
NbfReferenceConnection("send Session Confirm", Connection, CREF_FRAME_SEND);
|
||
|
||
DeviceContext = Connection->Provider;
|
||
Link = Connection->Link;
|
||
Status = NbfCreatePacket (DeviceContext, Connection->Link, &Packet);
|
||
|
||
if (!NT_SUCCESS (Status)) { // if we couldn't make frame.
|
||
#if DBG
|
||
if (NbfPacketPanic) {
|
||
PANIC ("NbfSendSessionConfirm: NbfCreatePacket failed.\n");
|
||
}
|
||
#endif
|
||
NbfWaitPacket (Connection, CONNECTION_FLAGS_SEND_SC);
|
||
NbfDereferenceConnection("Couldn't get SC packet", Connection, CREF_FRAME_SEND);
|
||
return;
|
||
}
|
||
|
||
|
||
//
|
||
// Initialize the Netbios header.
|
||
//
|
||
|
||
ConstructSessionConfirm (
|
||
(PNBF_HDR_CONNECTION)&(Packet->Header[Link->HeaderLength + sizeof(DLC_I_FRAME)]),
|
||
SESSION_CONFIRM_OPTIONS_20 | SESSION_CONFIRM_NO_ACK, // supported options.
|
||
(USHORT)(Connection->Link->MaxFrameSize - sizeof(NBF_HDR_CONNECTION) - sizeof(DLC_I_FRAME)),
|
||
// maximum frame size/this session.
|
||
Connection->NetbiosHeader.TransmitCorrelator, // correlator from NAME_RECOGNIZED.
|
||
Connection->Lsn, // our local session number.
|
||
Connection->Rsn); // his session number (our RSN).
|
||
|
||
//
|
||
// Now send the packet on the connection via the link. If there are
|
||
// conditions on the link which make it impossible to send the packet,
|
||
// then the packet will be queued to the WackQ, and then timeouts will
|
||
// restart the link. This is acceptable when the traffic level is so
|
||
// high that we encounter this condition.
|
||
//
|
||
|
||
//
|
||
// Set this so NbfDestroyPacket will dereference the connection.
|
||
//
|
||
|
||
Packet->Owner = Connection;
|
||
Packet->Action = PACKET_ACTION_CONNECTION;
|
||
|
||
Packet->NdisIFrameLength =
|
||
Link->HeaderLength + sizeof(DLC_I_FRAME) + sizeof(NBF_HDR_CONNECTION);
|
||
|
||
MacModifyHeader(
|
||
&DeviceContext->MacInfo,
|
||
Packet->Header,
|
||
sizeof(DLC_I_FRAME) + sizeof(NBF_HDR_CONNECTION));
|
||
|
||
NbfSetNdisPacketLength(
|
||
Packet->NdisPacket,
|
||
Packet->NdisIFrameLength);
|
||
|
||
ACQUIRE_DPC_SPIN_LOCK (Connection->LinkSpinLock);
|
||
|
||
Status = SendOnePacket (Connection, Packet, FALSE, NULL); // fire and forget.
|
||
|
||
if (Status == STATUS_LINK_FAILED) {
|
||
NbfDereferencePacket (Packet); // destroy the packet.
|
||
}
|
||
|
||
return;
|
||
} /* NbfSendSessionConfirm */
|
||
|
||
|
||
VOID
|
||
NbfSendSessionEnd(
|
||
IN PTP_CONNECTION Connection,
|
||
IN BOOLEAN Abort
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine sends a SESSION_END frame on the specified connection.
|
||
|
||
Arguments:
|
||
|
||
Connection - Pointer to a transport connection object.
|
||
|
||
Abort - Boolean set to TRUE if the connection is abnormally terminating.
|
||
|
||
Return Value:
|
||
|
||
none.
|
||
|
||
--*/
|
||
|
||
{
|
||
NTSTATUS Status;
|
||
PTP_PACKET Packet;
|
||
PDEVICE_CONTEXT DeviceContext;
|
||
PTP_LINK Link;
|
||
|
||
NbfReferenceConnection("send Session End", Connection, CREF_FRAME_SEND);
|
||
|
||
DeviceContext = Connection->Provider;
|
||
Link = Connection->Link;
|
||
|
||
Status = NbfCreatePacket (DeviceContext, Connection->Link, &Packet);
|
||
|
||
if (!NT_SUCCESS (Status)) { // if we couldn't make frame.
|
||
#if DBG
|
||
if (NbfPacketPanic) {
|
||
PANIC ("NbfSendSessionEnd: NbfCreatePacket failed.\n");
|
||
}
|
||
#endif
|
||
NbfWaitPacket (Connection, CONNECTION_FLAGS_SEND_SE);
|
||
NbfDereferenceConnection("Couldn't get SE packet", Connection, CREF_FRAME_SEND);
|
||
return;
|
||
}
|
||
|
||
//
|
||
// The following statements instruct the packet destructor to run
|
||
// down this connection when the packet is acknowleged.
|
||
//
|
||
|
||
Packet->Owner = Connection;
|
||
Packet->Action = PACKET_ACTION_END;
|
||
|
||
|
||
//
|
||
// Initialize the Netbios header.
|
||
//
|
||
|
||
ConstructSessionEnd (
|
||
(PNBF_HDR_CONNECTION)&(Packet->Header[Link->HeaderLength + sizeof(DLC_I_FRAME)]),
|
||
(USHORT)(Abort ? // reason for termination.
|
||
SESSION_END_REASON_ABEND :
|
||
SESSION_END_REASON_HANGUP),
|
||
Connection->Lsn, // our local session number.
|
||
Connection->Rsn); // his session number (our RSN).
|
||
|
||
//
|
||
// Now send the packet on the connection via the link. If there are
|
||
// conditions on the link which make it impossible to send the packet,
|
||
// then the packet will be queued to the WackQ, and then timeouts will
|
||
// restart the link. This is acceptable when the traffic level is so
|
||
// high that we encounter this condition.
|
||
//
|
||
// Note that we force an ack for this packet, as we want to make sure we
|
||
// run down the connection and link correctly.
|
||
//
|
||
|
||
Packet->NdisIFrameLength =
|
||
Link->HeaderLength + sizeof(DLC_I_FRAME) + sizeof(NBF_HDR_CONNECTION);
|
||
|
||
MacModifyHeader(
|
||
&DeviceContext->MacInfo,
|
||
Packet->Header,
|
||
sizeof(DLC_I_FRAME) + sizeof(NBF_HDR_CONNECTION));
|
||
|
||
NbfSetNdisPacketLength(
|
||
Packet->NdisPacket,
|
||
Packet->NdisIFrameLength);
|
||
|
||
ACQUIRE_DPC_SPIN_LOCK (Connection->LinkSpinLock);
|
||
|
||
Status = SendOnePacket (Connection, Packet, TRUE, NULL); // fire and forget.
|
||
|
||
if (Status == STATUS_LINK_FAILED) {
|
||
NbfDereferencePacket (Packet); // destroy the packet.
|
||
}
|
||
|
||
return;
|
||
} /* NbfSendSessionEnd */
|
||
|
||
|
||
VOID
|
||
NbfSendNoReceive(
|
||
IN PTP_CONNECTION Connection
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine sends a NO_RECEIVE frame on the specified connection.
|
||
|
||
Arguments:
|
||
|
||
Connection - Pointer to a transport connection object.
|
||
|
||
|
||
Return Value:
|
||
|
||
none.
|
||
|
||
--*/
|
||
|
||
{
|
||
NTSTATUS Status;
|
||
PTP_PACKET Packet;
|
||
PDEVICE_CONTEXT DeviceContext;
|
||
PTP_LINK Link;
|
||
USHORT MessageBytesToAck;
|
||
|
||
NbfReferenceConnection("send No Receive", Connection, CREF_FRAME_SEND);
|
||
|
||
DeviceContext = Connection->Provider;
|
||
Link = Connection->Link;
|
||
Status = NbfCreatePacket (DeviceContext, Connection->Link, &Packet);
|
||
|
||
if (!NT_SUCCESS (Status)) { // if we couldn't make frame.
|
||
#if DBG
|
||
if (NbfPacketPanic) {
|
||
PANIC ("NbfSendNoReceive: NbfCreatePacket failed.\n");
|
||
}
|
||
#endif
|
||
NbfDereferenceConnection("Couldn't get NR packet", Connection, CREF_FRAME_SEND);
|
||
return;
|
||
}
|
||
|
||
|
||
ACQUIRE_DPC_SPIN_LOCK (Connection->LinkSpinLock);
|
||
|
||
MessageBytesToAck = (USHORT)
|
||
(Connection->MessageBytesReceived + Connection->MessageInitAccepted - Connection->MessageBytesAcked);
|
||
Connection->Flags |= CONNECTION_FLAGS_W_RESYNCH;
|
||
|
||
//
|
||
// Initialize the Netbios header.
|
||
//
|
||
|
||
ConstructNoReceive (
|
||
(PNBF_HDR_CONNECTION)&(Packet->Header[Link->HeaderLength + sizeof(DLC_I_FRAME)]),
|
||
(USHORT)0, // options
|
||
MessageBytesToAck, // number of bytes accepted.
|
||
Connection->Lsn, // our local session number.
|
||
Connection->Rsn); // his session number (our RSN).
|
||
|
||
//
|
||
// Now send the packet on the connection via the link. If there are
|
||
// conditions on the link which make it impossible to send the packet,
|
||
// then the packet will be queued to the WackQ, and then timeouts will
|
||
// restart the link. This is acceptable when the traffic level is so
|
||
// high that we encounter this condition.
|
||
//
|
||
|
||
//
|
||
// Set this so NbfDestroyPacket will dereference the connection.
|
||
//
|
||
|
||
Packet->Owner = Connection;
|
||
Packet->Action = PACKET_ACTION_CONNECTION;
|
||
|
||
Packet->NdisIFrameLength =
|
||
Link->HeaderLength + sizeof(DLC_I_FRAME) + sizeof(NBF_HDR_CONNECTION);
|
||
|
||
MacModifyHeader(
|
||
&DeviceContext->MacInfo,
|
||
Packet->Header,
|
||
sizeof(DLC_I_FRAME) + sizeof(NBF_HDR_CONNECTION));
|
||
|
||
NbfSetNdisPacketLength(
|
||
Packet->NdisPacket,
|
||
Packet->NdisIFrameLength);
|
||
|
||
Status = SendOnePacket (Connection, Packet, FALSE, NULL); // fire and forget.
|
||
|
||
if (Status != STATUS_LINK_FAILED) {
|
||
ExInterlockedAddUlong(
|
||
&Connection->MessageBytesAcked,
|
||
MessageBytesToAck,
|
||
Connection->LinkSpinLock);
|
||
} else {
|
||
NbfDereferencePacket (Packet); // destroy the packet.
|
||
}
|
||
|
||
return;
|
||
} /* NbfSendNoReceive */
|
||
|
||
|
||
VOID
|
||
NbfSendReceiveContinue(
|
||
IN PTP_CONNECTION Connection
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine sends a RECEIVE_CONTINUE frame on the specified connection.
|
||
|
||
Arguments:
|
||
|
||
Connection - Pointer to a transport connection object.
|
||
|
||
|
||
Return Value:
|
||
|
||
none.
|
||
|
||
--*/
|
||
|
||
{
|
||
NTSTATUS Status;
|
||
PTP_PACKET Packet;
|
||
PDEVICE_CONTEXT DeviceContext;
|
||
PTP_LINK Link;
|
||
USHORT MessageBytesToAck;
|
||
|
||
NbfReferenceConnection("send Receive Continue", Connection, CREF_FRAME_SEND);
|
||
|
||
DeviceContext = Connection->Provider;
|
||
Link = Connection->Link;
|
||
Status = NbfCreatePacket (DeviceContext, Connection->Link, &Packet);
|
||
|
||
if (!NT_SUCCESS (Status)) { // if we couldn't make frame.
|
||
#if DBG
|
||
if (NbfPacketPanic) {
|
||
PANIC ("NbfSendReceiveContinue: NbfCreatePacket failed.\n");
|
||
}
|
||
#endif
|
||
NbfWaitPacket (Connection, CONNECTION_FLAGS_SEND_RC);
|
||
NbfDereferenceConnection("Couldn't get RC packet", Connection, CREF_FRAME_SEND);
|
||
return;
|
||
}
|
||
|
||
//
|
||
// Save this variable now since it is what we are implicitly ack'ing.
|
||
//
|
||
|
||
ACQUIRE_DPC_SPIN_LOCK (Connection->LinkSpinLock);
|
||
MessageBytesToAck = (USHORT)
|
||
(Connection->MessageBytesReceived + Connection->MessageInitAccepted - Connection->MessageBytesAcked);
|
||
|
||
//
|
||
// Initialize the Netbios header.
|
||
//
|
||
|
||
ConstructReceiveContinue (
|
||
(PNBF_HDR_CONNECTION)&(Packet->Header[Link->HeaderLength + sizeof(DLC_I_FRAME)]),
|
||
Connection->NetbiosHeader.TransmitCorrelator, // correlator from DFM
|
||
Connection->Lsn, // our local session number.
|
||
Connection->Rsn); // his session number (our RSN).
|
||
|
||
//
|
||
// Now send the packet on the connection via the link. If there are
|
||
// conditions on the link which make it impossible to send the packet,
|
||
// then the packet will be queued to the WackQ, and then timeouts will
|
||
// restart the link. This is acceptable when the traffic level is so
|
||
// high that we encounter this condition.
|
||
//
|
||
|
||
//
|
||
// Set this so NbfDestroyPacket will dereference the connection.
|
||
//
|
||
|
||
Packet->Owner = Connection;
|
||
Packet->Action = PACKET_ACTION_CONNECTION;
|
||
|
||
Packet->NdisIFrameLength =
|
||
Link->HeaderLength + sizeof(DLC_I_FRAME) + sizeof(NBF_HDR_CONNECTION);
|
||
|
||
MacModifyHeader(
|
||
&DeviceContext->MacInfo,
|
||
Packet->Header,
|
||
sizeof(DLC_I_FRAME) + sizeof(NBF_HDR_CONNECTION));
|
||
|
||
NbfSetNdisPacketLength(
|
||
Packet->NdisPacket,
|
||
Packet->NdisIFrameLength);
|
||
|
||
Status = SendOnePacket (Connection, Packet, FALSE, NULL); // fire and forget.
|
||
|
||
if (Status != STATUS_LINK_FAILED) {
|
||
ExInterlockedAddUlong(
|
||
&Connection->MessageBytesAcked,
|
||
MessageBytesToAck,
|
||
Connection->LinkSpinLock);
|
||
} else {
|
||
NbfDereferencePacket (Packet); // destroy the packet.
|
||
}
|
||
|
||
return;
|
||
} /* NbfSendReceiveContinue */
|
||
|
||
|
||
VOID
|
||
NbfSendReceiveOutstanding(
|
||
IN PTP_CONNECTION Connection
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine sends a RECEIVE_OUTSTANDING frame on the specified connection.
|
||
|
||
Arguments:
|
||
|
||
Connection - Pointer to a transport connection object.
|
||
|
||
|
||
Return Value:
|
||
|
||
none.
|
||
|
||
--*/
|
||
|
||
{
|
||
NTSTATUS Status;
|
||
PTP_PACKET Packet;
|
||
PDEVICE_CONTEXT DeviceContext;
|
||
PTP_LINK Link;
|
||
USHORT MessageBytesToAck;
|
||
|
||
NbfReferenceConnection("send Receive Outstanding", Connection, CREF_FRAME_SEND);
|
||
|
||
DeviceContext = Connection->Provider;
|
||
Link = Connection->Link;
|
||
Status = NbfCreatePacket (DeviceContext, Connection->Link, &Packet);
|
||
|
||
if (!NT_SUCCESS (Status)) { // if we couldn't make frame.
|
||
#if DBG
|
||
if (NbfPacketPanic) {
|
||
PANIC ("NbfSendReceiveOutstanding: NbfCreatePacket failed.\n");
|
||
}
|
||
#endif
|
||
NbfWaitPacket (Connection, CONNECTION_FLAGS_SEND_RO);
|
||
NbfDereferenceConnection("Couldn't get RO packet", Connection, CREF_FRAME_SEND);
|
||
return;
|
||
}
|
||
|
||
|
||
ACQUIRE_DPC_SPIN_LOCK (Connection->LinkSpinLock);
|
||
|
||
MessageBytesToAck = (USHORT)
|
||
(Connection->MessageBytesReceived + Connection->MessageInitAccepted - Connection->MessageBytesAcked);
|
||
Connection->Flags |= CONNECTION_FLAGS_W_RESYNCH;
|
||
|
||
//
|
||
// Initialize the Netbios header.
|
||
//
|
||
|
||
ConstructReceiveOutstanding (
|
||
(PNBF_HDR_CONNECTION)&(Packet->Header[Link->HeaderLength + sizeof(DLC_I_FRAME)]),
|
||
MessageBytesToAck, // number of bytes accepted.
|
||
Connection->Lsn, // our local session number.
|
||
Connection->Rsn); // his session number (our RSN).
|
||
|
||
|
||
//
|
||
// Now send the packet on the connection via the link. If there are
|
||
// conditions on the link which make it impossible to send the packet,
|
||
// then the packet will be queued to the WackQ, and then timeouts will
|
||
// restart the link. This is acceptable when the traffic level is so
|
||
// high that we encounter this condition.
|
||
//
|
||
|
||
//
|
||
// Set this so NbfDestroyPacket will dereference the connection.
|
||
//
|
||
|
||
Packet->Owner = Connection;
|
||
Packet->Action = PACKET_ACTION_CONNECTION;
|
||
|
||
Packet->NdisIFrameLength =
|
||
Link->HeaderLength + sizeof(DLC_I_FRAME) + sizeof(NBF_HDR_CONNECTION);
|
||
|
||
MacModifyHeader(
|
||
&DeviceContext->MacInfo,
|
||
Packet->Header,
|
||
sizeof(DLC_I_FRAME) + sizeof(NBF_HDR_CONNECTION));
|
||
|
||
NbfSetNdisPacketLength(
|
||
Packet->NdisPacket,
|
||
Packet->NdisIFrameLength);
|
||
|
||
Status = SendOnePacket (Connection, Packet, FALSE, NULL); // fire and forget.
|
||
|
||
if (Status != STATUS_LINK_FAILED) {
|
||
ExInterlockedAddUlong(
|
||
&Connection->MessageBytesAcked,
|
||
MessageBytesToAck,
|
||
Connection->LinkSpinLock);
|
||
} else {
|
||
NbfDereferencePacket (Packet); // destroy the packet.
|
||
}
|
||
|
||
return;
|
||
} /* NbfSendReceiveOutstanding */
|
||
|
||
|
||
VOID
|
||
NbfSendDataAck(
|
||
IN PTP_CONNECTION Connection
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine sends a DATA_ACK frame on the specified connection.
|
||
|
||
Arguments:
|
||
|
||
Connection - Pointer to a transport connection object.
|
||
|
||
|
||
Return Value:
|
||
|
||
none.
|
||
|
||
--*/
|
||
|
||
{
|
||
NTSTATUS Status;
|
||
PTP_PACKET Packet;
|
||
PDEVICE_CONTEXT DeviceContext;
|
||
PTP_LINK Link;
|
||
|
||
NbfReferenceConnection("send Data Ack", Connection, CREF_FRAME_SEND);
|
||
|
||
DeviceContext = Connection->Provider;
|
||
Link = Connection->Link;
|
||
Status = NbfCreatePacket (DeviceContext, Connection->Link, &Packet);
|
||
|
||
if (!NT_SUCCESS (Status)) { // if we couldn't make frame.
|
||
#if DBG
|
||
if (NbfPacketPanic) {
|
||
PANIC ("NbfSendDataAck: NbfCreatePacket failed.\n");
|
||
}
|
||
#endif
|
||
NbfWaitPacket (Connection, CONNECTION_FLAGS_SEND_DA);
|
||
NbfDereferenceConnection("Couldn't get DA packet", Connection, CREF_FRAME_SEND);
|
||
return;
|
||
}
|
||
|
||
|
||
//
|
||
// Initialize the Netbios header.
|
||
//
|
||
|
||
ConstructDataAck (
|
||
(PNBF_HDR_CONNECTION)&(Packet->Header[Link->HeaderLength + sizeof(DLC_I_FRAME)]),
|
||
Connection->NetbiosHeader.TransmitCorrelator, // correlator from DATA_ONLY_LAST.
|
||
Connection->Lsn, // our local session number.
|
||
Connection->Rsn); // his session number (our RSN).
|
||
|
||
//
|
||
// Now send the packet on the connection via the link. If there are
|
||
// conditions on the link which make it impossible to send the packet,
|
||
// then the packet will be queued to the WackQ, and then timeouts will
|
||
// restart the link. This is acceptable when the traffic level is so
|
||
// high that we encounter this condition. Note that Data Ack will be
|
||
// seeing this condition frequently when send windows close after large
|
||
// sends.
|
||
//
|
||
|
||
//
|
||
// Set this so NbfDestroyPacket will dereference the connection.
|
||
//
|
||
|
||
Packet->Owner = Connection;
|
||
Packet->Action = PACKET_ACTION_CONNECTION;
|
||
|
||
Packet->NdisIFrameLength =
|
||
Link->HeaderLength + sizeof(DLC_I_FRAME) + sizeof(NBF_HDR_CONNECTION);
|
||
|
||
MacModifyHeader(
|
||
&DeviceContext->MacInfo,
|
||
Packet->Header,
|
||
sizeof(DLC_I_FRAME) + sizeof(NBF_HDR_CONNECTION));
|
||
|
||
NbfSetNdisPacketLength(
|
||
Packet->NdisPacket,
|
||
Packet->NdisIFrameLength);
|
||
|
||
ACQUIRE_DPC_SPIN_LOCK (Connection->LinkSpinLock);
|
||
|
||
Status = SendOnePacket (Connection, Packet, FALSE, NULL); // fire and forget.
|
||
|
||
if (Status == STATUS_LINK_FAILED) {
|
||
NbfDereferencePacket (Packet); // destroy the packet.
|
||
}
|
||
|
||
return;
|
||
} /* NbfSendDataAck */
|
||
|
||
|
||
VOID
|
||
NbfSendDm(
|
||
IN PTP_LINK Link,
|
||
IN BOOLEAN PollFinal
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine sends a DM-r/x DLC frame on the specified link.
|
||
|
||
NOTE: This routine is called with the link spinlock held,
|
||
and returns with it released. IT MUST BE CALLED AT DPC
|
||
LEVEL.
|
||
|
||
Arguments:
|
||
|
||
Link - Pointer to a transport link object.
|
||
|
||
PollFinal - TRUE if poll/final bit should be set.
|
||
|
||
Return Value:
|
||
|
||
none.
|
||
|
||
--*/
|
||
|
||
{
|
||
NTSTATUS Status;
|
||
PTP_PACKET RawFrame;
|
||
PDLC_U_FRAME DlcHeader; // S-format frame alias.
|
||
|
||
Status = NbfCreatePacket (Link->Provider, Link, &RawFrame);
|
||
if (NT_SUCCESS (Status)) {
|
||
|
||
RawFrame->Owner = NULL;
|
||
RawFrame->Action = PACKET_ACTION_NULL;
|
||
|
||
//
|
||
// set the packet length correctly (Note that the NDIS_BUFFER
|
||
// gets returned to the proper length in NbfDestroyPacket)
|
||
//
|
||
|
||
MacModifyHeader(&Link->Provider->MacInfo, RawFrame->Header, sizeof(DLC_FRAME));
|
||
NbfSetNdisPacketLength (RawFrame->NdisPacket, Link->HeaderLength + sizeof(DLC_FRAME));
|
||
|
||
//
|
||
// Format LLC DM-r/x header.
|
||
//
|
||
|
||
DlcHeader = (PDLC_U_FRAME)&(RawFrame->Header[Link->HeaderLength]);
|
||
DlcHeader->Dsap = DSAP_NETBIOS_OVER_LLC;
|
||
DlcHeader->Ssap = DSAP_NETBIOS_OVER_LLC | DLC_SSAP_RESPONSE;
|
||
DlcHeader->Command = (UCHAR)(DLC_CMD_DM | (PollFinal ? DLC_U_PF : 0));
|
||
|
||
//
|
||
// This releases the spin lock.
|
||
//
|
||
|
||
SendControlPacket (Link, RawFrame);
|
||
|
||
} else {
|
||
RELEASE_DPC_SPIN_LOCK(&Link->SpinLock);
|
||
#if DBG
|
||
if (NbfPacketPanic) {
|
||
PANIC ("NbfSendDm: packet not sent.\n");
|
||
}
|
||
#endif
|
||
}
|
||
} /* NbfSendDm */
|
||
|
||
|
||
VOID
|
||
NbfSendUa(
|
||
IN PTP_LINK Link,
|
||
IN BOOLEAN PollFinal
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine sends a UA-r/x DLC frame on the specified link.
|
||
|
||
NOTE: This routine is called with the link spinlock held,
|
||
and returns with it released. IT MUST BE CALLED AT DPC
|
||
LEVEL.
|
||
|
||
Arguments:
|
||
|
||
Link - Pointer to a transport link object.
|
||
|
||
PollFinal - TRUE if poll/final bit should be set.
|
||
|
||
OldIrql - The IRQL at which Link->SpinLock was acquired.
|
||
|
||
Return Value:
|
||
|
||
none.
|
||
|
||
--*/
|
||
|
||
{
|
||
NTSTATUS Status;
|
||
PTP_PACKET RawFrame;
|
||
PDLC_U_FRAME DlcHeader; // U-format frame alias.
|
||
|
||
Status = NbfCreatePacket (Link->Provider, Link, &RawFrame);
|
||
if (NT_SUCCESS (Status)) {
|
||
|
||
RawFrame->Owner = NULL;
|
||
RawFrame->Action = PACKET_ACTION_NULL;
|
||
|
||
//
|
||
// set the packet length correctly (Note that the NDIS_BUFFER
|
||
// gets returned to the proper length in NbfDestroyPacket)
|
||
//
|
||
|
||
MacModifyHeader(&Link->Provider->MacInfo, RawFrame->Header, sizeof(DLC_FRAME));
|
||
NbfSetNdisPacketLength (RawFrame->NdisPacket, Link->HeaderLength + sizeof(DLC_FRAME));
|
||
|
||
// Format LLC UA-r/x header.
|
||
//
|
||
|
||
DlcHeader = (PDLC_U_FRAME)&(RawFrame->Header[Link->HeaderLength]);
|
||
DlcHeader->Dsap = DSAP_NETBIOS_OVER_LLC;
|
||
DlcHeader->Ssap = DSAP_NETBIOS_OVER_LLC | DLC_SSAP_RESPONSE;
|
||
DlcHeader->Command = (UCHAR)(DLC_CMD_UA | (PollFinal ? DLC_U_PF : 0));
|
||
|
||
//
|
||
// This releases the spin lock.
|
||
//
|
||
|
||
SendControlPacket (Link, RawFrame);
|
||
|
||
} else {
|
||
RELEASE_DPC_SPIN_LOCK(&Link->SpinLock);
|
||
#if DBG
|
||
if (NbfPacketPanic) {
|
||
PANIC ("NbfSendUa: packet not sent.\n");
|
||
}
|
||
#endif
|
||
}
|
||
} /* NbfSendUa */
|
||
|
||
|
||
VOID
|
||
NbfSendSabme(
|
||
IN PTP_LINK Link,
|
||
IN BOOLEAN PollFinal
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine sends a SABME-c/x DLC frame on the specified link.
|
||
|
||
NOTE: This routine is called with the link spinlock held,
|
||
and returns with it released.
|
||
|
||
Arguments:
|
||
|
||
Link - Pointer to a transport link object.
|
||
|
||
PollFinal - TRUE if poll/final bit should be set.
|
||
|
||
Return Value:
|
||
|
||
none.
|
||
|
||
--*/
|
||
|
||
{
|
||
NTSTATUS Status;
|
||
PLIST_ENTRY p;
|
||
PTP_PACKET RawFrame, packet;
|
||
PDLC_U_FRAME DlcHeader; // S-format frame alias.
|
||
|
||
Status = NbfCreatePacket (Link->Provider, Link, &RawFrame);
|
||
if (NT_SUCCESS (Status)) {
|
||
|
||
RawFrame->Owner = NULL;
|
||
RawFrame->Action = PACKET_ACTION_NULL;
|
||
|
||
//
|
||
// set the packet length correctly (Note that the NDIS_BUFFER
|
||
// gets returned to the proper length in NbfDestroyPacket)
|
||
//
|
||
|
||
MacModifyHeader(&Link->Provider->MacInfo, RawFrame->Header, sizeof(DLC_FRAME));
|
||
NbfSetNdisPacketLength (RawFrame->NdisPacket, Link->HeaderLength + sizeof(DLC_FRAME));
|
||
|
||
//
|
||
// Format LLC SABME-c/x header.
|
||
//
|
||
|
||
DlcHeader = (PDLC_U_FRAME)&(RawFrame->Header[Link->HeaderLength]);
|
||
DlcHeader->Dsap = DSAP_NETBIOS_OVER_LLC;
|
||
DlcHeader->Ssap = DSAP_NETBIOS_OVER_LLC;
|
||
DlcHeader->Command = (UCHAR)(DLC_CMD_SABME | (PollFinal ? DLC_U_PF : 0));
|
||
|
||
//
|
||
// Set up so that T1 will be started when the send
|
||
// completes.
|
||
//
|
||
|
||
if (PollFinal) {
|
||
if (Link->Provider->MacInfo.MediumAsync) {
|
||
RawFrame->NdisIFrameLength = Link->HeaderLength + sizeof(DLC_S_FRAME);
|
||
RawFrame->Link = Link;
|
||
NbfReferenceLink ("Sabme/p", Link, LREF_START_T1);
|
||
} else {
|
||
StartT1 (Link, Link->HeaderLength + sizeof(DLC_S_FRAME));
|
||
}
|
||
}
|
||
|
||
//
|
||
// This releases the spin lock.
|
||
//
|
||
|
||
SendControlPacket (Link, RawFrame);
|
||
|
||
//
|
||
// Reset the link state based on having sent this packet..
|
||
// Note that a SABME can be sent under some conditions on an existing
|
||
// link. If it is, it means we want to reset this link to a known state.
|
||
// We'll do that; note that that involves ditching any packets outstanding
|
||
// on the link.
|
||
//
|
||
|
||
ACQUIRE_DPC_SPIN_LOCK (&Link->SpinLock);
|
||
Link->NextSend = 0;
|
||
Link->LastAckReceived = 0;
|
||
Link->NextReceive = 0; // expect next packet to be sequence 0
|
||
Link->NextReceive = 0;
|
||
Link->LastAckSent = 0;
|
||
Link->NextReceive = 0;
|
||
Link->LastAckSent = 0;
|
||
|
||
while (!IsListEmpty (&Link->WackQ)) {
|
||
p = RemoveHeadList (&Link->WackQ);
|
||
RELEASE_DPC_SPIN_LOCK (&Link->SpinLock);
|
||
packet = CONTAINING_RECORD (p, TP_PACKET, Linkage);
|
||
NbfDereferencePacket (packet);
|
||
ACQUIRE_DPC_SPIN_LOCK (&Link->SpinLock);
|
||
}
|
||
|
||
RELEASE_DPC_SPIN_LOCK (&Link->SpinLock);
|
||
} else {
|
||
if (PollFinal) {
|
||
StartT1 (Link, Link->HeaderLength + sizeof(DLC_S_FRAME));
|
||
}
|
||
RELEASE_DPC_SPIN_LOCK(&Link->SpinLock);
|
||
#if DBG
|
||
if (NbfPacketPanic) {
|
||
PANIC ("NbfSendSabme: packet not sent.\n");
|
||
}
|
||
#endif
|
||
}
|
||
} /* NbfSendSabme */
|
||
|
||
|
||
VOID
|
||
NbfSendDisc(
|
||
IN PTP_LINK Link,
|
||
IN BOOLEAN PollFinal
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine sends a DISC-c/x DLC frame on the specified link.
|
||
|
||
Arguments:
|
||
|
||
Link - Pointer to a transport link object.
|
||
|
||
PollFinal - TRUE if poll/final bit should be set.
|
||
|
||
Return Value:
|
||
|
||
none.
|
||
|
||
--*/
|
||
|
||
{
|
||
NTSTATUS Status;
|
||
PTP_PACKET RawFrame;
|
||
PDLC_U_FRAME DlcHeader; // S-format frame alias.
|
||
KIRQL oldirql;
|
||
|
||
KeRaiseIrql (DISPATCH_LEVEL, &oldirql);
|
||
|
||
Status = NbfCreatePacket (Link->Provider, Link, &RawFrame);
|
||
if (NT_SUCCESS (Status)) {
|
||
|
||
RawFrame->Owner = NULL;
|
||
RawFrame->Action = PACKET_ACTION_NULL;
|
||
|
||
//
|
||
// set the packet length correctly (Note that the NDIS_BUFFER
|
||
// gets returned to the proper length in NbfDestroyPacket)
|
||
//
|
||
|
||
MacModifyHeader(&Link->Provider->MacInfo, RawFrame->Header, sizeof(DLC_FRAME));
|
||
NbfSetNdisPacketLength (RawFrame->NdisPacket, Link->HeaderLength + sizeof(DLC_FRAME));
|
||
|
||
//
|
||
// Format LLC DISC-c/x header.
|
||
//
|
||
|
||
DlcHeader = (PDLC_U_FRAME)&(RawFrame->Header[Link->HeaderLength]);
|
||
DlcHeader->Dsap = DSAP_NETBIOS_OVER_LLC;
|
||
DlcHeader->Ssap = DSAP_NETBIOS_OVER_LLC;
|
||
DlcHeader->Command = (UCHAR)(DLC_CMD_DISC | (PollFinal ? DLC_U_PF : 0));
|
||
|
||
ACQUIRE_DPC_SPIN_LOCK (&Link->SpinLock);
|
||
|
||
//
|
||
// This releases the spin lock.
|
||
//
|
||
|
||
SendControlPacket (Link, RawFrame);
|
||
|
||
} else {
|
||
#if DBG
|
||
if (NbfPacketPanic) {
|
||
PANIC ("NbfSendDisc: packet not sent.\n");
|
||
}
|
||
#endif
|
||
}
|
||
|
||
KeLowerIrql (oldirql);
|
||
|
||
} /* NbfSendDisc */
|
||
|
||
|
||
VOID
|
||
NbfSendRr(
|
||
IN PTP_LINK Link,
|
||
IN BOOLEAN Command,
|
||
IN BOOLEAN PollFinal
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine sends a RR-x/x DLC frame on the specified link.
|
||
|
||
NOTE: This routine is called with the link spinlock held,
|
||
and returns with it released. THIS ROUTINE MUST BE CALLED
|
||
AT DPC LEVEL.
|
||
|
||
Arguments:
|
||
|
||
Link - Pointer to a transport link object.
|
||
|
||
Command - TRUE if command bit should be set.
|
||
|
||
PollFinal - TRUE if poll/final bit should be set.
|
||
|
||
Return Value:
|
||
|
||
none.
|
||
|
||
--*/
|
||
|
||
{
|
||
NTSTATUS Status;
|
||
PTP_PACKET RawFrame;
|
||
PDLC_S_FRAME DlcHeader; // S-format frame alias.
|
||
|
||
Status = NbfCreateRrPacket (Link->Provider, Link, &RawFrame);
|
||
if (NT_SUCCESS (Status)) {
|
||
|
||
RawFrame->Owner = NULL;
|
||
|
||
//
|
||
// RawFrame->Action will be set to PACKET_ACTION_RR if
|
||
// NbfCreateRrPacket got a packet from the RrPacketPool
|
||
// and PACKET_ACTION_NULL if it got one from the regular
|
||
// pool.
|
||
//
|
||
|
||
//
|
||
// set the packet length correctly (Note that the NDIS_BUFFER
|
||
// gets returned to the proper length in NbfDestroyPacket)
|
||
//
|
||
|
||
MacModifyHeader(&Link->Provider->MacInfo, RawFrame->Header, sizeof(DLC_S_FRAME));
|
||
NbfSetNdisPacketLength (RawFrame->NdisPacket, Link->HeaderLength + sizeof(DLC_S_FRAME));
|
||
|
||
//
|
||
// Format LLC RR-x/x header.
|
||
//
|
||
|
||
DlcHeader = (PDLC_S_FRAME)&(RawFrame->Header[Link->HeaderLength]);
|
||
DlcHeader->Dsap = DSAP_NETBIOS_OVER_LLC;
|
||
DlcHeader->Ssap = (UCHAR)(DSAP_NETBIOS_OVER_LLC | (Command ? 0 : DLC_SSAP_RESPONSE));
|
||
DlcHeader->Command = DLC_CMD_RR;
|
||
DlcHeader->RcvSeq = (UCHAR)(PollFinal ? DLC_S_PF : 0);
|
||
|
||
//
|
||
// If this is a command frame (which will always be a
|
||
// poll with the current code) set up so that T1 will
|
||
// be started when the send completes.
|
||
//
|
||
|
||
if (Command) {
|
||
if (Link->Provider->MacInfo.MediumAsync) {
|
||
RawFrame->NdisIFrameLength = Link->HeaderLength + sizeof(DLC_S_FRAME);
|
||
RawFrame->Link = Link;
|
||
NbfReferenceLink ("Rr/p", Link, LREF_START_T1);
|
||
} else {
|
||
StartT1 (Link, Link->HeaderLength + sizeof(DLC_S_FRAME));
|
||
}
|
||
}
|
||
|
||
//
|
||
// This puts Link->NextReceive into DlcHeader->RcvSeq
|
||
// and releases the spinlock.
|
||
//
|
||
|
||
SendControlPacket (Link, RawFrame);
|
||
|
||
} else {
|
||
if (Command) {
|
||
StartT1 (Link, Link->HeaderLength + sizeof(DLC_S_FRAME));
|
||
}
|
||
RELEASE_DPC_SPIN_LOCK(&Link->SpinLock);
|
||
#if DBG
|
||
if (NbfPacketPanic) {
|
||
PANIC ("NbfSendRr: packet not sent.\n");
|
||
}
|
||
#endif
|
||
}
|
||
} /* NbfSendRr */
|
||
|
||
#if 0
|
||
|
||
//
|
||
// These functions are not currently called, so they are commented
|
||
// out.
|
||
//
|
||
|
||
|
||
VOID
|
||
NbfSendRnr(
|
||
IN PTP_LINK Link,
|
||
IN BOOLEAN Command,
|
||
IN BOOLEAN PollFinal
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine sends a RNR-x/x DLC frame on the specified link.
|
||
|
||
Arguments:
|
||
|
||
Link - Pointer to a transport link object.
|
||
|
||
Command - TRUE if command bit should be set.
|
||
|
||
PollFinal - TRUE if poll/final bit should be set.
|
||
|
||
Return Value:
|
||
|
||
none.
|
||
|
||
--*/
|
||
|
||
{
|
||
NTSTATUS Status;
|
||
PTP_PACKET RawFrame;
|
||
PDLC_S_FRAME DlcHeader; // S-format frame alias.
|
||
KIRQL oldirql;
|
||
|
||
KeRaiseIrql (DISPATCH_LEVEL, &oldirql);
|
||
|
||
Status = NbfCreatePacket (Link->Provider, Link, &RawFrame);
|
||
if (NT_SUCCESS (Status)) {
|
||
|
||
RawFrame->Owner = NULL;
|
||
RawFrame->Action = PACKET_ACTION_NULL;
|
||
|
||
//
|
||
// set the packet length correctly (Note that the NDIS_BUFFER
|
||
// gets returned to the proper length in NbfDestroyPacket)
|
||
//
|
||
|
||
MacModifyHeader(&Link->Provider->MacInfo, RawFrame->Header, sizeof(DLC_S_FRAME));
|
||
NbfSetNdisPacketLength (RawFrame->NdisPacket, Link->HeaderLength + sizeof(DLC_S_FRAME));
|
||
|
||
//
|
||
// Format LLC RR-x/x header.
|
||
//
|
||
|
||
DlcHeader = (PDLC_S_FRAME)&(RawFrame->Header[Link->HeaderLength]);
|
||
DlcHeader->Dsap = DSAP_NETBIOS_OVER_LLC;
|
||
DlcHeader->Ssap = (UCHAR)(DSAP_NETBIOS_OVER_LLC | (Command ? 0 : DLC_SSAP_RESPONSE));
|
||
DlcHeader->Command = DLC_CMD_RNR;
|
||
DlcHeader->RcvSeq = (UCHAR)(PollFinal ? DLC_S_PF : 0);
|
||
|
||
ACQUIRE_DPC_SPIN_LOCK (&Link->SpinLock);
|
||
|
||
//
|
||
// This puts Link->NextReceive into DlcHeader->RcvSeq
|
||
// and releases the spin lock.
|
||
//
|
||
|
||
SendControlPacket (Link, RawFrame);
|
||
|
||
} else {
|
||
#if DBG
|
||
if (NbfPacketPanic) {
|
||
PANIC ("NbfSendRnr: packet not sent.\n");
|
||
}
|
||
#endif
|
||
}
|
||
KeLowerIrql (oldirql);
|
||
} /* NbfSendRnr */
|
||
|
||
|
||
VOID
|
||
NbfSendTest(
|
||
IN PTP_LINK Link,
|
||
IN BOOLEAN Command,
|
||
IN BOOLEAN PollFinal,
|
||
IN PMDL Psdu
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine sends a TEST-x/x DLC frame on the specified link.
|
||
|
||
Arguments:
|
||
|
||
Link - Pointer to a transport link object.
|
||
|
||
Command - TRUE if command bit should be set.
|
||
|
||
PollFinal - TRUE if poll/final bit should be set.
|
||
|
||
Psdu - Pointer to an MDL chain describing received TEST-c frame's storage.
|
||
|
||
Return Value:
|
||
|
||
none.
|
||
|
||
--*/
|
||
|
||
{
|
||
Link, Command, PollFinal, Psdu; // prevent compiler warnings
|
||
|
||
PANIC ("NbfSendTest: Entered.\n");
|
||
} /* NbfSendTest */
|
||
|
||
|
||
VOID
|
||
NbfSendFrmr(
|
||
IN PTP_LINK Link,
|
||
IN BOOLEAN PollFinal
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine sends a FRMR-r/x DLC frame on the specified link.
|
||
|
||
Arguments:
|
||
|
||
Link - Pointer to a transport link object.
|
||
|
||
PollFinal - TRUE if poll/final bit should be set.
|
||
|
||
Return Value:
|
||
|
||
none.
|
||
|
||
--*/
|
||
|
||
{
|
||
Link, PollFinal; // prevent compiler warnings
|
||
|
||
IF_NBFDBG (NBF_DEBUG_FRAMESND) {
|
||
NbfPrint0 ("NbfSendFrmr: Entered.\n");
|
||
}
|
||
} /* NbfSendFrmr */
|
||
|
||
#endif
|
||
|
||
|
||
VOID
|
||
NbfSendXid(
|
||
IN PTP_LINK Link,
|
||
IN BOOLEAN Command,
|
||
IN BOOLEAN PollFinal
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine sends an XID-x/x DLC frame on the specified link.
|
||
|
||
NOTE: This routine is called with the link spinlock held,
|
||
and returns with it released.
|
||
|
||
Arguments:
|
||
|
||
Link - Pointer to a transport link object.
|
||
|
||
Command - TRUE if command bit should be set.
|
||
|
||
PollFinal - TRUE if poll/final bit should be set.
|
||
|
||
Return Value:
|
||
|
||
none.
|
||
|
||
--*/
|
||
|
||
{
|
||
Link, Command, PollFinal; // prevent compiler warnings
|
||
|
||
RELEASE_DPC_SPIN_LOCK(&Link->SpinLock);
|
||
PANIC ("NbfSendXid: Entered.\n");
|
||
} /* NbfSendXid */
|
||
|
||
|
||
VOID
|
||
NbfSendRej(
|
||
IN PTP_LINK Link,
|
||
IN BOOLEAN Command,
|
||
IN BOOLEAN PollFinal
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine sends a REJ-x/x DLC frame on the specified link.
|
||
|
||
NOTE: This function is called with Link->SpinLock held and
|
||
returns with it released. THIS MUST BE CALLED AT DPC LEVEL.
|
||
|
||
Arguments:
|
||
|
||
Link - Pointer to a transport link object.
|
||
|
||
Command - TRUE if command bit should be set.
|
||
|
||
PollFinal - TRUE if poll/final bit should be set.
|
||
|
||
Return Value:
|
||
|
||
none.
|
||
|
||
--*/
|
||
|
||
{
|
||
NTSTATUS Status;
|
||
PTP_PACKET RawFrame;
|
||
PDLC_S_FRAME DlcHeader; // S-format frame alias.
|
||
|
||
IF_NBFDBG (NBF_DEBUG_FRAMESND) {
|
||
NbfPrint0 ("NbfSendRej: Entered.\n");
|
||
}
|
||
|
||
Status = NbfCreatePacket (Link->Provider, Link, &RawFrame);
|
||
if (NT_SUCCESS (Status)) {
|
||
|
||
RawFrame->Owner = NULL;
|
||
RawFrame->Action = PACKET_ACTION_NULL;
|
||
|
||
//
|
||
// set the packet length correctly (Note that the NDIS_BUFFER
|
||
// gets returned to the proper length in NbfDestroyPacket)
|
||
//
|
||
|
||
MacModifyHeader(&Link->Provider->MacInfo, RawFrame->Header, sizeof(DLC_S_FRAME));
|
||
NbfSetNdisPacketLength (RawFrame->NdisPacket, Link->HeaderLength + sizeof(DLC_S_FRAME));
|
||
|
||
//
|
||
// Format LLC REJ-x/x header.
|
||
//
|
||
|
||
DlcHeader = (PDLC_S_FRAME)&(RawFrame->Header[Link->HeaderLength]);
|
||
DlcHeader->Dsap = DSAP_NETBIOS_OVER_LLC;
|
||
DlcHeader->Ssap = (UCHAR)(DSAP_NETBIOS_OVER_LLC | (Command ? 0 : DLC_SSAP_RESPONSE));
|
||
DlcHeader->Command = DLC_CMD_REJ;
|
||
DlcHeader->RcvSeq = (UCHAR)(PollFinal ? DLC_S_PF : 0);
|
||
|
||
//
|
||
// This puts Link->NextReceive into DlcHeader->RcvSeq
|
||
// and releases the spin lock.
|
||
//
|
||
|
||
SendControlPacket (Link, RawFrame);
|
||
|
||
} else {
|
||
RELEASE_DPC_SPIN_LOCK(&Link->SpinLock);
|
||
#if DBG
|
||
if (NbfPacketPanic) {
|
||
PANIC ("NbfSendRej: packet not sent.\n");
|
||
}
|
||
#endif
|
||
}
|
||
} /* NbfSendRej */
|
||
|
||
|
||
NTSTATUS
|
||
NbfCreateConnectionlessFrame(
|
||
PDEVICE_CONTEXT DeviceContext,
|
||
PTP_UI_FRAME *RawFrame
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine allocates a connectionless frame (either from the local
|
||
device context pool or out of non-paged pool).
|
||
|
||
Arguments:
|
||
|
||
DeviceContext - Pointer to our device context to charge the frame to.
|
||
|
||
RawFrame - Pointer to a place where we will return a pointer to the
|
||
allocated frame.
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS - status of operation.
|
||
|
||
--*/
|
||
|
||
{
|
||
KIRQL oldirql;
|
||
PTP_UI_FRAME UIFrame;
|
||
PLIST_ENTRY p;
|
||
|
||
IF_NBFDBG (NBF_DEBUG_FRAMESND) {
|
||
NbfPrint0 ("NbfCreateConnectionlessFrame: Entered.\n");
|
||
}
|
||
|
||
//
|
||
// Make sure that structure padding hasn't happened.
|
||
//
|
||
|
||
ASSERT (sizeof(NBF_HDR_CONNECTIONLESS) == 44);
|
||
|
||
p = ExInterlockedRemoveHeadList (
|
||
&DeviceContext->UIFramePool,
|
||
&DeviceContext->Interlock);
|
||
|
||
if (p == NULL) {
|
||
#if DBG
|
||
if (NbfPacketPanic) {
|
||
PANIC ("NbfCreateConnectionlessFrame: PANIC! no more UI frames in pool!\n");
|
||
}
|
||
#endif
|
||
ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock, &oldirql);
|
||
++DeviceContext->UIFrameExhausted;
|
||
RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);
|
||
return STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
|
||
UIFrame = (PTP_UI_FRAME) CONTAINING_RECORD (p, TP_UI_FRAME, Linkage);
|
||
|
||
*RawFrame = UIFrame;
|
||
|
||
return STATUS_SUCCESS;
|
||
} /* NbfCreateConnectionlessFrame */
|
||
|
||
|
||
VOID
|
||
NbfDestroyConnectionlessFrame(
|
||
PDEVICE_CONTEXT DeviceContext,
|
||
PTP_UI_FRAME RawFrame
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine destroys a connectionless frame by either returning it
|
||
to the device context's pool or to the system's non-paged pool.
|
||
|
||
Arguments:
|
||
|
||
DeviceContext - Pointer to our device context to return the frame to.
|
||
|
||
RawFrame - Pointer to a frame to be returned.
|
||
|
||
Return Value:
|
||
|
||
none.
|
||
|
||
--*/
|
||
|
||
{
|
||
PNDIS_BUFFER HeaderBuffer;
|
||
PNDIS_BUFFER NdisBuffer;
|
||
|
||
IF_NBFDBG (NBF_DEBUG_FRAMESND) {
|
||
NbfPrint0 ("NbfDestroyConnectionlessFrame: Entered.\n");
|
||
}
|
||
|
||
//
|
||
// Strip off and unmap the buffers describing data and header.
|
||
//
|
||
|
||
NdisUnchainBufferAtFront (RawFrame->NdisPacket, &HeaderBuffer);
|
||
|
||
// data buffers get thrown away
|
||
|
||
NdisUnchainBufferAtFront (RawFrame->NdisPacket, &NdisBuffer);
|
||
while (NdisBuffer != NULL) {
|
||
NdisFreeBuffer (NdisBuffer);
|
||
NdisUnchainBufferAtFront (RawFrame->NdisPacket, &NdisBuffer);
|
||
}
|
||
|
||
NDIS_BUFFER_LINKAGE(HeaderBuffer) = (PNDIS_BUFFER)NULL;
|
||
|
||
//
|
||
// If this UI frame has some transport-created data,
|
||
// free the buffer now.
|
||
//
|
||
|
||
if (RawFrame->DataBuffer) {
|
||
ExFreePool (RawFrame->DataBuffer);
|
||
RawFrame->DataBuffer = NULL;
|
||
}
|
||
|
||
NdisChainBufferAtFront (RawFrame->NdisPacket, HeaderBuffer);
|
||
|
||
ExInterlockedInsertTailList (
|
||
&DeviceContext->UIFramePool,
|
||
&RawFrame->Linkage,
|
||
&DeviceContext->Interlock);
|
||
|
||
} /* NbfDestroyConnectionlessFrame */
|
||
|
||
|
||
VOID
|
||
NbfSendUIFrame(
|
||
PDEVICE_CONTEXT DeviceContext,
|
||
PTP_UI_FRAME RawFrame,
|
||
IN BOOLEAN Loopback
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine sends a connectionless frame by calling the physical
|
||
provider's Send service. When the request completes, or if the service
|
||
does not return successfully, then the frame is deallocated.
|
||
|
||
Arguments:
|
||
|
||
DeviceContext - Pointer to our device context.
|
||
|
||
RawFrame - Pointer to a connectionless frame to be sent.
|
||
|
||
Loopback - A boolean flag set to TRUE if the source hardware address
|
||
of the packet should be set to zeros.
|
||
|
||
SourceRoutingInformation - Pointer to optional source routing information.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
NDIS_STATUS NdisStatus;
|
||
PUCHAR DestinationAddress;
|
||
|
||
UNREFERENCED_PARAMETER(Loopback);
|
||
|
||
#if DBG
|
||
IF_NBFDBG (NBF_DEBUG_FRAMESND) {
|
||
NbfPrint2 ("NbfSendUIFrame: Entered, RawFrame: %lx NdisPacket %lx\n",
|
||
RawFrame, RawFrame->NdisPacket);
|
||
DbgPrint ("NbfSendUIFrame: MacHeader: %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x \n",
|
||
RawFrame->Header[0],
|
||
RawFrame->Header[1],
|
||
RawFrame->Header[2],
|
||
RawFrame->Header[3],
|
||
RawFrame->Header[4],
|
||
RawFrame->Header[5],
|
||
RawFrame->Header[6],
|
||
RawFrame->Header[7],
|
||
RawFrame->Header[8],
|
||
RawFrame->Header[9],
|
||
RawFrame->Header[10],
|
||
RawFrame->Header[11],
|
||
RawFrame->Header[12],
|
||
RawFrame->Header[13]);
|
||
}
|
||
#endif
|
||
|
||
//
|
||
// Send the packet.
|
||
//
|
||
|
||
#if DBG
|
||
NbfSendsIssued++;
|
||
#endif
|
||
|
||
//
|
||
// Loopback will be FALSE for multicast frames or other
|
||
// frames that we know are not directly addressed to
|
||
// our hardware address.
|
||
//
|
||
|
||
if (Loopback) {
|
||
|
||
//
|
||
// See if this frame should be looped back.
|
||
//
|
||
|
||
MacReturnDestinationAddress(
|
||
&DeviceContext->MacInfo,
|
||
RawFrame->Header,
|
||
&DestinationAddress);
|
||
|
||
if (RtlEqualMemory(
|
||
DestinationAddress,
|
||
DeviceContext->LocalAddress.Address,
|
||
DeviceContext->MacInfo.AddressLength)) {
|
||
|
||
NbfInsertInLoopbackQueue(
|
||
DeviceContext,
|
||
RawFrame->NdisPacket,
|
||
LOOPBACK_UI_FRAME
|
||
);
|
||
|
||
NdisStatus = NDIS_STATUS_PENDING;
|
||
|
||
goto NoNdisSend;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
INCREMENT_COUNTER (DeviceContext, PacketsSent);
|
||
|
||
if (DeviceContext->NdisBindingHandle) {
|
||
|
||
NdisSend (
|
||
&NdisStatus,
|
||
(NDIS_HANDLE)DeviceContext->NdisBindingHandle,
|
||
RawFrame->NdisPacket);
|
||
}
|
||
else {
|
||
NdisStatus = STATUS_INVALID_DEVICE_STATE;
|
||
}
|
||
|
||
NoNdisSend:
|
||
|
||
if (NdisStatus != NDIS_STATUS_PENDING) {
|
||
|
||
#if DBG
|
||
if (NdisStatus == NDIS_STATUS_SUCCESS) {
|
||
NbfSendsCompletedOk++;
|
||
} else {
|
||
NbfSendsCompletedFail++;
|
||
IF_NBFDBG (NBF_DEBUG_FRAMESND) {
|
||
NbfPrint1 ("NbfSendUIFrame: NdisSend failed, status other Pending or Complete: %s.\n",
|
||
NbfGetNdisStatus(NdisStatus));
|
||
}
|
||
}
|
||
#endif
|
||
|
||
NbfDestroyConnectionlessFrame (DeviceContext, RawFrame);
|
||
|
||
} else {
|
||
|
||
#if DBG
|
||
NbfSendsPended++;
|
||
#endif
|
||
}
|
||
|
||
} /* NbfSendUIFrame */
|
||
|
||
|
||
VOID
|
||
NbfSendUIMdlFrame(
|
||
PTP_ADDRESS Address
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine sends a connectionless frame by calling the NbfSendUIFrame.
|
||
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 and
|
||
UI frames are sequenced through the address they are sent on.
|
||
|
||
Arguments:
|
||
|
||
Address - pointer to the address from which to send this datagram.
|
||
|
||
SourceRoutingInformation - Pointer to optional source routing information.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
// NTSTATUS Status;
|
||
NDIS_STATUS NdisStatus;
|
||
PDEVICE_CONTEXT DeviceContext;
|
||
PUCHAR DestinationAddress;
|
||
|
||
IF_NBFDBG (NBF_DEBUG_FRAMESND) {
|
||
NbfPrint0 ("NbfSendUIMdlFrame: Entered.\n");
|
||
}
|
||
|
||
|
||
//
|
||
// Send the packet.
|
||
//
|
||
|
||
DeviceContext = Address->Provider;
|
||
|
||
INCREMENT_COUNTER (DeviceContext, PacketsSent);
|
||
|
||
MacReturnDestinationAddress(
|
||
&DeviceContext->MacInfo,
|
||
Address->UIFrame->Header,
|
||
&DestinationAddress);
|
||
|
||
if (RtlEqualMemory(
|
||
DestinationAddress,
|
||
DeviceContext->LocalAddress.Address,
|
||
DeviceContext->MacInfo.AddressLength)) {
|
||
|
||
//
|
||
// This packet is sent to ourselves; we should loop it
|
||
// back.
|
||
//
|
||
|
||
NbfInsertInLoopbackQueue(
|
||
DeviceContext,
|
||
Address->UIFrame->NdisPacket,
|
||
LOOPBACK_UI_FRAME
|
||
);
|
||
|
||
NdisStatus = NDIS_STATUS_PENDING;
|
||
|
||
} else {
|
||
|
||
#ifndef NO_STRESS_BUG
|
||
Address->SendFlags |= ADDRESS_FLAGS_SENT_TO_NDIS;
|
||
Address->SendFlags &= ~ADDRESS_FLAGS_RETD_BY_NDIS;
|
||
#endif
|
||
|
||
if (Address->Provider->NdisBindingHandle) {
|
||
|
||
NdisSend (
|
||
&NdisStatus,
|
||
(NDIS_HANDLE)Address->Provider->NdisBindingHandle,
|
||
Address->UIFrame->NdisPacket);
|
||
}
|
||
else {
|
||
NdisStatus = STATUS_INVALID_DEVICE_STATE;
|
||
}
|
||
}
|
||
|
||
if (NdisStatus != NDIS_STATUS_PENDING) {
|
||
|
||
NbfSendDatagramCompletion (Address, Address->UIFrame->NdisPacket, NdisStatus);
|
||
|
||
#if DBG
|
||
if (NdisStatus != NDIS_STATUS_SUCCESS) { // This is an error, trickle it up
|
||
IF_NBFDBG (NBF_DEBUG_FRAMESND) {
|
||
NbfPrint1 ("NbfSendUIMdlFrame: NdisSend failed, status other Pending or Complete: %s.\n",
|
||
NbfGetNdisStatus(NdisStatus));
|
||
}
|
||
}
|
||
#endif
|
||
}
|
||
|
||
} /* NbfSendUIMdlFrame */
|
||
|
||
|
||
VOID
|
||
NbfSendDatagramCompletion(
|
||
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
|
||
NbfSendUIMdlFrame send request is completed. Because this handler is only
|
||
associated with NbfSendUIMdlFrame, and because NbfSendUIMdlFrame 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.
|
||
|
||
--*/
|
||
|
||
{
|
||
PIRP Irp;
|
||
PLIST_ENTRY p;
|
||
KIRQL oldirql;
|
||
PNDIS_BUFFER HeaderBuffer;
|
||
|
||
NdisPacket; // prevent compiler warnings.
|
||
|
||
IF_NBFDBG (NBF_DEBUG_FRAMESND) {
|
||
NbfPrint0 ("NbfSendDatagramCompletion: Entered.\n");
|
||
}
|
||
|
||
#ifndef NO_STRESS_BUG
|
||
Address->SendFlags |= ADDRESS_FLAGS_RETD_BY_NDIS;
|
||
#endif
|
||
|
||
//
|
||
// 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. If this is the case, we added a
|
||
// special reference to the address, so we still want to deref
|
||
// when we are done (I don't think this is true - adb 3/22/93).
|
||
//
|
||
|
||
ACQUIRE_SPIN_LOCK (&Address->SpinLock, &oldirql);
|
||
p = RemoveHeadList (&Address->SendDatagramQueue);
|
||
|
||
if (p != &Address->SendDatagramQueue) {
|
||
|
||
RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);
|
||
|
||
Irp = CONTAINING_RECORD (p, IRP, Tail.Overlay.ListEntry);
|
||
|
||
IF_NBFDBG (NBF_DEBUG_FRAMESND) {
|
||
NbfPrint0 ("NbfDestroyConnectionlessFrame: Entered.\n");
|
||
}
|
||
|
||
//
|
||
// Strip off and unmap the buffers describing data and header.
|
||
//
|
||
|
||
NdisUnchainBufferAtFront (Address->UIFrame->NdisPacket, &HeaderBuffer);
|
||
|
||
// drop the rest of the packet
|
||
|
||
NdisReinitializePacket (Address->UIFrame->NdisPacket);
|
||
|
||
NDIS_BUFFER_LINKAGE(HeaderBuffer) = (PNDIS_BUFFER)NULL;
|
||
NdisChainBufferAtFront (Address->UIFrame->NdisPacket, HeaderBuffer);
|
||
|
||
//
|
||
// Ignore NdisStatus; datagrams always "succeed". The Information
|
||
// field was filled in when we queued the datagram.
|
||
//
|
||
|
||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||
IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
|
||
|
||
#ifndef NO_STRESS_BUG
|
||
Address->SendFlags &= ~ADDRESS_FLAGS_SENT_TO_NDIS;
|
||
Address->SendFlags &= ~ADDRESS_FLAGS_RETD_BY_NDIS;
|
||
#endif
|
||
|
||
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.
|
||
//
|
||
|
||
NbfSendDatagramsOnAddress (Address); // do more datagrams.
|
||
|
||
} else {
|
||
|
||
ASSERT (FALSE);
|
||
|
||
Address->Flags &= ~ADDRESS_FLAGS_SEND_IN_PROGRESS;
|
||
RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);
|
||
|
||
}
|
||
|
||
NbfDereferenceAddress ("Complete datagram", Address, AREF_REQUEST);
|
||
|
||
} /* NbfSendDatagramCompletion */
|