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.
2528 lines
64 KiB
2528 lines
64 KiB
/*++
|
|
|
|
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 */
|