340 lines
11 KiB
C
340 lines
11 KiB
C
/*++
|
||
|
||
Copyright (c) 1989 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
transport.c
|
||
|
||
Abstract:
|
||
|
||
This module implements all transport related functions in the SMB connection
|
||
engine
|
||
|
||
--*/
|
||
|
||
#ifndef _TRANSPRT_H_
|
||
#define _TRANSPRT_H_
|
||
|
||
// The SMBCE_TRANSPORT data structure encapsulates all the information w.r.t a
|
||
// particular transport for the connection engine. All the transports that are
|
||
// of interest to the SMB mini redirector are maintained in a doubly linked list
|
||
//
|
||
// The connection engine tries all the transports in this list when trying to
|
||
// establish a connection to a server. Currently only connection oriented
|
||
// transports are handled.
|
||
|
||
typedef struct _SMBCE_TRANSPORT_ {
|
||
SMBCE_OBJECT_HEADER;
|
||
|
||
LIST_ENTRY TransportsList;
|
||
RXCE_TRANSPORT_HANDLE hTransport;
|
||
RXCE_ADDRESS_HANDLE hAddress;
|
||
ULONG Priority; // the priority in the binding list.
|
||
|
||
BOOLEAN Active;
|
||
|
||
// Additional information regarding quality of service and other selection
|
||
// criterion for a transport will be included here.
|
||
|
||
} SMBCE_TRANSPORT, *PSMBCE_TRANSPORT;
|
||
|
||
typedef struct _SMBCE_TRANSPORTS_ {
|
||
RX_SPIN_LOCK Lock;
|
||
LONG Count;
|
||
LIST_ENTRY ListHead;
|
||
} SMBCE_TRANSPORTS, *PSMBCE_TRANSPORTS;
|
||
|
||
extern SMBCE_TRANSPORTS MRxSmbTransports;
|
||
|
||
// Transport entries are added to the list of known transports upon receipt of
|
||
// PnP notifications. Currently the list is static since transport disabling
|
||
// notifications are not handled by the underlying TDI/PnP layer.
|
||
// The following routines provide the ability for adding/deleting entries to
|
||
// this list.
|
||
|
||
extern VOID
|
||
SmbCeAddTransport(PSMBCE_TRANSPORT pTransport);
|
||
|
||
extern VOID
|
||
SmbCeRemoveTransport(PSMBCE_TRANSPORT pTransport);
|
||
|
||
extern
|
||
PSMBCE_TRANSPORT
|
||
SmbCeGetNextTransport(PSMBCE_TRANSPORT pTransport);
|
||
|
||
// The connection engine maintains a reference count associated with each transport
|
||
// which indicates the number of servers that are using the transport. This will
|
||
// eventually provide the mechanism for disabling/enabling transport on receipt
|
||
// of PnP notifications.
|
||
|
||
#define SmbCeReferenceTransport(pTransport) \
|
||
InterlockedIncrement(&pTransport->SwizzleCount)
|
||
|
||
#define SmbCeDereferenceTransport(pTransport) \
|
||
InterlockedDecrement(&pTransport->SwizzleCount)
|
||
|
||
|
||
// The server transport types encapsulate the various usages of the underlying
|
||
// transport to communicate with a server. For example the type of interactions
|
||
// with a mailslot server ( primarily datagrams ) is very different from the
|
||
// interactions with a FILE SERVER ( connection oriented send/receives). The
|
||
// type of interactions can be further classified by the underlying connection
|
||
// characterstics, e.g., connecting to a FILE_SERVER over a RAS connection as
|
||
// opposed to connecting to a file server over EtherNet.
|
||
//
|
||
// The interactions are currently classified into four types, MAILSOT, Virtual
|
||
// Circuit, Datagram and Htbrid ( VC + Datagram ).
|
||
//
|
||
// The type chosen will depend upon the characterstics of the available
|
||
// connection. Each type is associated with its own dispatch vector which
|
||
// encapsulates the interaction between the connection engine and the transport.
|
||
//
|
||
// This includes Send,Receive, Receive Ind. etc. These are modelled after the
|
||
// TDI interfaces.
|
||
|
||
typedef enum _SMBCE_SERVER_TRANSPORT_TYPE_ {
|
||
SMBCE_STT_MAILSLOT,
|
||
SMBCE_STT_VC,
|
||
SMBCE_STT_DATAGRAM,
|
||
SMBCE_STT_HYBRID
|
||
} SMBCE_SERVER_TRANSPORT_TYPE, *PSMBCE_SERVER_TRANSPORT_TYPE;
|
||
|
||
typedef struct SMBCE_SERVER_TRANSPORT {
|
||
SMBCE_OBJECT_HEADER;
|
||
|
||
struct TRANSPORT_DISPATCH_VECTOR *pDispatchVector;
|
||
struct _SMBCE_TRANSPORT_ *pTransport;
|
||
|
||
PKEVENT pRundownEvent; // used for finalization.
|
||
|
||
ULONG MaximumSendSize; // max data size for bulk I/O
|
||
} SMBCE_SERVER_TRANSPORT, *PSMBCE_SERVER_TRANSPORT;
|
||
|
||
// The SMBCE_SERVER_TRANSPORT instances are reference counted. The following
|
||
// routines provide the referencing mechanism. Defining them as macros also
|
||
// provides us with a easy debugging capability, i.e., it can be easily modified
|
||
// to include a FILE/LINE number each time an instance is referenced and
|
||
// dereferenced
|
||
|
||
#define SmbCeReferenceServerTransport(pServerEntry) \
|
||
SmbCepReferenceServerTransport(pServerEntry)
|
||
|
||
#define SmbCeDereferenceServerTransport(pServerEntry) \
|
||
SmbCepDereferenceServerTransport(pServerEntry)
|
||
|
||
// The SERVER transport dispatch vector prototypes
|
||
|
||
typedef
|
||
NTSTATUS
|
||
(*PTRANSPORT_DISPATCH_SEND)(
|
||
PSMBCEDB_SERVER_ENTRY pServerEntry,
|
||
ULONG SendOptions,
|
||
PMDL pSmbMdl,
|
||
ULONG SendLength,
|
||
PVOID pSendCompletionContext);
|
||
|
||
typedef
|
||
NTSTATUS
|
||
(*PTRANSPORT_DISPATCH_SEND_DATAGRAM)(
|
||
PSMBCEDB_SERVER_ENTRY pServerEntry,
|
||
ULONG SendOptions,
|
||
PMDL pSmbMdl,
|
||
ULONG SendLength,
|
||
PVOID pSendCompletionContext);
|
||
|
||
typedef
|
||
NTSTATUS
|
||
(*PTRANSPORT_DISPATCH_TRANCEIVE)(
|
||
PSMBCEDB_SERVER_ENTRY pServerEntry,
|
||
PSMB_EXCHANGE pExchange,
|
||
ULONG SendOptions,
|
||
PMDL pSmbMdl,
|
||
ULONG SendLength,
|
||
PVOID pSendCompletionContext);
|
||
|
||
typedef
|
||
NTSTATUS
|
||
(*PTRANSPORT_DISPATCH_RECEIVE)(
|
||
PSMBCEDB_SERVER_ENTRY pServerEntry,
|
||
PSMB_EXCHANGE pExchange);
|
||
|
||
typedef
|
||
NTSTATUS
|
||
(*PTRANSPORT_DISPATCH_INITIALIZE_EXCHANGE)(
|
||
PSMB_EXCHANGE pExchange);
|
||
|
||
typedef
|
||
NTSTATUS
|
||
(*PTRANSPORT_DISPATCH_UNINITIALIZE_EXCHANGE)(
|
||
PSMB_EXCHANGE pExchange);
|
||
|
||
typedef
|
||
VOID
|
||
(*PTRANSPORT_DISPATCH_TEARDOWN)(
|
||
PSMBCE_SERVER_TRANSPORT pTransport);
|
||
|
||
typedef struct TRANSPORT_DISPATCH_VECTOR {
|
||
PTRANSPORT_DISPATCH_SEND Send;
|
||
PTRANSPORT_DISPATCH_SEND_DATAGRAM SendDatagram;
|
||
PTRANSPORT_DISPATCH_TRANCEIVE Tranceive;
|
||
PTRANSPORT_DISPATCH_RECEIVE Receive;
|
||
PRX_WORKERTHREAD_ROUTINE TimerEventHandler;
|
||
PTRANSPORT_DISPATCH_INITIALIZE_EXCHANGE InitializeExchange;
|
||
PTRANSPORT_DISPATCH_UNINITIALIZE_EXCHANGE UninitializeExchange;
|
||
PTRANSPORT_DISPATCH_TEARDOWN TearDown;
|
||
} TRANSPORT_DISPATCH_VECTOR, *PTRANSPORT_DISPATCH_VECTOR;
|
||
|
||
// A macro for invoking a routine through the SMBCE_SERVER_TRANSPORT
|
||
// dispatch vector.
|
||
|
||
#define SMBCE_TRANSPORT_DISPATCH(pServerEntry,Routine,Arguments) \
|
||
(*((pServerEntry)->pTransport->pDispatchVector->Routine))##Arguments
|
||
|
||
// The currently known transport type dispatch vectors and the mechanisms
|
||
// for instanting an instance.
|
||
|
||
extern TRANSPORT_DISPATCH_VECTOR MRxSmbVctTransportDispatch;
|
||
extern TRANSPORT_DISPATCH_VECTOR MRxSmbMsTransportDispatch;
|
||
|
||
extern NTSTATUS
|
||
MsInstantiateServerTransport(
|
||
IN OUT PSMBCEDB_SERVER_ENTRY pServerEntry,
|
||
OUT PSMBCE_SERVER_TRANSPORT *pServerTransportPtr);
|
||
|
||
extern NTSTATUS
|
||
VctInstantiateServerTransport(
|
||
IN OUT PSMBCEDB_SERVER_ENTRY pServerEntry,
|
||
OUT PSMBCE_SERVER_TRANSPORT *pServerTransportPtr);
|
||
|
||
// The following routines constitute the interface by which the clients of
|
||
// the connection engine initialize/send/receive/uninitialize data to the
|
||
// remote servers
|
||
|
||
extern NTSTATUS
|
||
SmbCeInitializeServerTransport(
|
||
IN OUT PSMBCEDB_SERVER_ENTRY pServerEntry);
|
||
|
||
extern NTSTATUS
|
||
SmbCeUninitializeServerTransport(
|
||
IN OUT PSMBCEDB_SERVER_ENTRY pServerEntry);
|
||
|
||
extern NTSTATUS
|
||
SmbCepReferenceServerTransport(
|
||
IN OUT PSMBCEDB_SERVER_ENTRY pServerEntry);
|
||
|
||
extern NTSTATUS
|
||
SmbCepDereferenceServerTransport(
|
||
IN OUT PSMBCEDB_SERVER_ENTRY pServerEntry);
|
||
|
||
//
|
||
// INLINE functions to hide dispatch vector related details for invoking Transport methods
|
||
//
|
||
|
||
|
||
|
||
INLINE NTSTATUS
|
||
SmbCeInitializeExchangeTransport(
|
||
PSMB_EXCHANGE pExchange)
|
||
{
|
||
if (pExchange->SmbStatus == STATUS_SUCCESS) {
|
||
if (pExchange->SmbCeContext.pServerEntry->pTransport != NULL) {
|
||
pExchange->SmbCeFlags |= SMBCE_EXCHANGE_TRANSPORT_INITIALIZED;
|
||
return (pExchange->SmbCeContext.pServerEntry->pTransport->pDispatchVector->InitializeExchange)(
|
||
pExchange);
|
||
} else {
|
||
return STATUS_CONNECTION_DISCONNECTED;
|
||
}
|
||
} else {
|
||
return pExchange->SmbStatus;
|
||
}
|
||
}
|
||
|
||
|
||
INLINE NTSTATUS
|
||
SmbCeUninitializeExchangeTransport(
|
||
PSMB_EXCHANGE pExchange)
|
||
{
|
||
if (FlagOn(pExchange->SmbCeFlags,SMBCE_EXCHANGE_TRANSPORT_INITIALIZED)) {
|
||
if (pExchange->SmbCeContext.pServerEntry->pTransport != NULL) {
|
||
return (pExchange->SmbCeContext.pServerEntry->pTransport->pDispatchVector->UninitializeExchange)(
|
||
pExchange);
|
||
} else {
|
||
return STATUS_CONNECTION_DISCONNECTED;
|
||
}
|
||
} else {
|
||
return pExchange->SmbStatus;
|
||
}
|
||
}
|
||
|
||
extern NTSTATUS
|
||
SmbCeSend(
|
||
PSMB_EXCHANGE pExchange,
|
||
ULONG SendOptions,
|
||
PMDL pSmbMdl,
|
||
ULONG SendLength);
|
||
|
||
extern NTSTATUS
|
||
SmbCeSendToServer(
|
||
PSMBCEDB_SERVER_ENTRY pServerEntry,
|
||
ULONG SendOptions,
|
||
PMDL pSmbMdl,
|
||
ULONG SendLength);
|
||
|
||
extern NTSTATUS
|
||
SmbCeSendDatagram(
|
||
PSMB_EXCHANGE pExchange,
|
||
ULONG SendOptions,
|
||
PMDL pSmbMdl,
|
||
ULONG SendLength);
|
||
|
||
extern NTSTATUS
|
||
SmbCeTranceive(
|
||
PSMB_EXCHANGE pExchange,
|
||
ULONG SendOptions,
|
||
PMDL pRxCeDataBuffer,
|
||
ULONG SendLength);
|
||
|
||
extern NTSTATUS
|
||
SmbCeReceive(
|
||
PSMB_EXCHANGE pExchange);
|
||
|
||
|
||
//
|
||
// Call ups from the transport to the connection engine
|
||
//
|
||
|
||
extern NTSTATUS
|
||
SmbCeReceiveInd(
|
||
IN PSMBCEDB_SERVER_ENTRY pServerEntry,
|
||
IN ULONG BytesIndicated,
|
||
IN ULONG BytesAvailable,
|
||
OUT ULONG *pBytesTaken,
|
||
IN PVOID pTsdu, // pointer describing this TSDU, typically a lump of bytes
|
||
OUT PMDL *pDataBufferPointer, // the buffer in which data is to be copied.
|
||
OUT PULONG pDataBufferSize // amount of data to copy
|
||
);
|
||
|
||
extern NTSTATUS
|
||
SmbCeDataReadyInd(
|
||
IN PSMBCEDB_SERVER_ENTRY pServerEntry,
|
||
IN PMDL pBuffer,
|
||
IN ULONG DataSize,
|
||
IN NTSTATUS DataReadyStatus
|
||
);
|
||
|
||
extern NTSTATUS
|
||
SmbCeErrorInd(
|
||
IN PSMBCEDB_SERVER_ENTRY pServerEntry,
|
||
IN NTSTATUS IndicatedStatus
|
||
);
|
||
|
||
extern NTSTATUS
|
||
SmbCeSendCompleteInd(
|
||
IN PSMBCEDB_SERVER_ENTRY pServerEntry,
|
||
IN PVOID pCompletionContext,
|
||
IN NTSTATUS SendCompletionStatus
|
||
);
|
||
|
||
#endif // _TRANSPRT_H_
|
||
|