windows-nt/Source/XPSP1/NT/net/rras/ndis/ndiswan/io.c
2020-09-26 16:20:57 +08:00

6476 lines
174 KiB
C

/*++
Copyright (c) 1990-1995 Microsoft Corporation
Module Name:
io.c
Abstract:
This file contains the procedures to process I/O requests from
a User Mode entity. All OS dependent I/O interface functions
will be conditionally coded, and will be responsible for translating
the I/O functions from the OS format to buffers that are useable by
the main I/O handling routine.
Author:
Tony Bell (TonyBe) June 06, 1995
Environment:
Kernel Mode
Revision History:
TonyBe 06/06/95 Created
--*/
#include "wan.h"
#define __FILE_SIG__ IO_FILESIG
//
// Local function prototypes
//
NTSTATUS
ExecuteIo(
IN ULONG ulFuncCode,
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
MapConnectionId(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
GetBundleHandle(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
SetFriendlyName(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
ActivateRoute(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
BundleLink(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
EnumLinksInBundle(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
SetProtocolPriority(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
SetBandwidthOnDemand(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
SetThresholdEvent(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
IoSendPacket(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
IoReceivePacket(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
FlushReceivePacket(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
GetStatistics(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
SetLinkInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
GetLinkInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
SetCompressionInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
GetCompressionInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
SetVJInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
GetVJInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
SetEncryptionInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
GetEncryptionInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
GetIdleTime(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
SetDebugInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
EnumActiveBundles(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
GetBandwidthUtilization(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
EnumProtocolUtilization(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
FlushThresholdEvents(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
GetWanInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
DeactivateRoute(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
GetDriverInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
SetProtocolEvent(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
GetProtocolEvent(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
FlushProtocolEvent(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
IoGetProtocolInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
SetHibernateEvent(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
FlushHibernateEvent(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
GetBundleInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
NTSTATUS
UnmapConnectionId(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
VOID
CancelThresholdEvents(
VOID
);
VOID
CancelIoReceivePackets(
VOID
);
VOID
AddProtocolCBToBundle(
PPROTOCOLCB ProtocolCB,
PBUNDLECB BundleCB
);
VOID
SortProtocolListByPriority(
IN PBUNDLECB BundleCB
);
NDIS_HANDLE
AssignProtocolCBHandle(
PBUNDLECB BundleCB,
PPROTOCOLCB ProtocolCB
);
VOID
FreeProtocolCBHandle(
PBUNDLECB BundleCB,
PPROTOCOLCB ProtocolCB
);
NTSTATUS
NotImplemented(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
);
//
// End of local function prototypes
//
CONST
IO_DISPATCH_TABLE IoDispatchTable[] =
{
{FUNC_MAP_CONNECTION_ID , MapConnectionId},
{FUNC_GET_BUNDLE_HANDLE , GetBundleHandle},
{FUNC_SET_FRIENDLY_NAME , SetFriendlyName},
{FUNC_ROUTE , ActivateRoute},
{FUNC_ADD_LINK_TO_BUNDLE , BundleLink},
{FUNC_ENUM_LINKS_IN_BUNDLE , EnumLinksInBundle},
{FUNC_SET_PROTOCOL_PRIORITY , SetProtocolPriority},
{FUNC_SET_BANDWIDTH_ON_DEMAND, SetBandwidthOnDemand},
{FUNC_SET_THRESHOLD_EVENT , SetThresholdEvent},
{FUNC_FLUSH_THRESHOLD_EVENTS, FlushThresholdEvents},
{FUNC_SEND_PACKET , IoSendPacket},
{FUNC_RECEIVE_PACKET , IoReceivePacket},
{FUNC_FLUSH_RECEIVE_PACKETS , FlushReceivePacket},
{FUNC_GET_STATS , GetStatistics},
{FUNC_SET_LINK_INFO , SetLinkInfo},
{FUNC_GET_LINK_INFO , GetLinkInfo},
{FUNC_SET_COMPRESSION_INFO , SetCompressionInfo},
{FUNC_GET_COMPRESSION_INFO , GetCompressionInfo},
{FUNC_SET_BRIDGE_INFO , NotImplemented},
{FUNC_GET_BRIDGE_INFO , NotImplemented},
{FUNC_SET_VJ_INFO , SetVJInfo},
{FUNC_GET_VJ_INFO , GetVJInfo},
{FUNC_SET_CIPX_INFO , NotImplemented},
{FUNC_GET_CIPX_INFO , NotImplemented},
{FUNC_SET_ENCRYPTION_INFO , SetEncryptionInfo},
{FUNC_GET_ENCRYPTION_INFO , GetEncryptionInfo},
{FUNC_SET_DEBUG_INFO , SetDebugInfo},
{FUNC_ENUM_ACTIVE_BUNDLES , EnumActiveBundles},
{FUNC_GET_NDISWANCB , NotImplemented},
{FUNC_GET_MINIPORTCB , NotImplemented},
{FUNC_GET_OPENCB , NotImplemented},
{FUNC_GET_BANDWIDTH_UTILIZATION, GetBandwidthUtilization},
{FUNC_ENUM_PROTOCOL_UTILIZATION, EnumProtocolUtilization},
{FUNC_ENUM_MINIPORTCB , NotImplemented},
{FUNC_ENUM_OPENCB , NotImplemented},
{FUNC_GET_WAN_INFO , GetWanInfo},
{FUNC_GET_IDLE_TIME , GetIdleTime},
{FUNC_UNROUTE , DeactivateRoute},
{FUNC_GET_DRIVER_INFO , GetDriverInfo},
{FUNC_SET_PROTOCOL_EVENT , SetProtocolEvent},
{FUNC_GET_PROTOCOL_EVENT , GetProtocolEvent},
{FUNC_FLUSH_PROTOCOL_EVENT , FlushProtocolEvent},
{FUNC_GET_PROTOCOL_INFO , IoGetProtocolInfo},
{FUNC_SET_HIBERNATE_EVENT , SetHibernateEvent},
{FUNC_FLUSH_HIBERNATE_EVENT , FlushHibernateEvent},
{FUNC_GET_BUNDLE_INFO , GetBundleInfo},
{FUNC_UNMAP_CONNECTION_ID , UnmapConnectionId}
};
#define MAX_FUNC_CODES sizeof(IoDispatchTable)/sizeof(IO_DISPATCH_TABLE)
#ifdef NT
NTSTATUS
NdisWanIoctl(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NTSTATUS Status, ReturnStatus;
ULONG ulBytesWritten = 0;
//
// Get current Irp stack location
//
PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
//
// Ioctl Function Code
//
ULONG ulFuncCode = (pIrpSp->Parameters.DeviceIoControl.IoControlCode >> 2) & 0x00000FFF ;
ULONG ulDeviceType = (pIrpSp->Parameters.DeviceIoControl.IoControlCode >> 16) & 0x0000FFFF;
ULONG ulMethod = pIrpSp->Parameters.DeviceIoControl.IoControlCode & 0x00000003;
//
// Input buffer, Output buffer, and lengths
//
PUCHAR pInputBuffer = pIrp->AssociatedIrp.SystemBuffer;
PUCHAR pOutputBuffer = pInputBuffer;
ULONG ulInputBufferLength = pIrpSp->Parameters.DeviceIoControl.InputBufferLength;
ULONG ulOutputBufferLength = pIrpSp->Parameters.DeviceIoControl.OutputBufferLength;
//
// if this is win64 make sure the calling process is 64bit
// since this interface is only used by rasman and rasman
// will always be 64bit on 64bit systems we will not bother
// with thunking. if the process is not a 64bit process get
// out.
#ifdef _WIN64
if (IoIs32bitProcess(pIrp)) {
pIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return (STATUS_NOT_SUPPORTED);
}
#endif
// NdisWanDbgOut(DBG_TRACE, DBG_IO, ("NdisWanIoctl: FunctionCode: 0x%x, MajorFunction: 0x%x, DeviceType: 0x%x",
// ulFuncCode, pIrpSp->MajorFunction, ulDeviceType));
#ifdef MY_DEVICE_OBJECT
//
// Make sure that this is for us
//
if ((pIrpSp->MajorFunction != IRP_MJ_DEVICE_CONTROL) ||
(ulDeviceType != FILE_DEVICE_NDISWAN) ||
(ulMethod != METHOD_BUFFERED) ||
(pDeviceObject != NdisWanCB.pDeviceObject)) {
if (NdisWanCB.MajorFunction[pIrpSp->MajorFunction] == NULL) {
pIrp->IoStatus.Information = 0;
pIrp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(pIrp, IO_NETWORK_INCREMENT);
return(STATUS_SUCCESS);
}
return(NdisWanCB.MajorFunction[pIrpSp->MajorFunction](pDeviceObject, pIrp));
}
#else
if (pIrpSp->MajorFunction != IRP_MJ_DEVICE_CONTROL ||
ulDeviceType != FILE_DEVICE_NETWORK ||
ulMethod != METHOD_BUFFERED) {
pIrp->IoStatus.Information = 0;
pIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return (STATUS_NOT_SUPPORTED);
}
#endif
//
// If this is a function code that requires an irp to be pended and completed
// later, we need to queue the irp up somewhere. In order for this to be somewhat
// portable we will pass the irp in as the input buffer and store it in a
// a structure that it has it's own linkage for queueing.
//
if ((ulFuncCode == FUNC_SET_THRESHOLD_EVENT) ||
(ulFuncCode == FUNC_RECEIVE_PACKET) ||
(ulFuncCode == FUNC_SET_PROTOCOL_EVENT) ||
(ulFuncCode == FUNC_SET_HIBERNATE_EVENT)) {
pInputBuffer = (PUCHAR)pIrp;
}
Status = ExecuteIo(ulFuncCode,
pInputBuffer,
ulInputBufferLength,
pOutputBuffer,
ulOutputBufferLength,
&ulBytesWritten);
// NdisWanDbgOut(DBG_TRACE, DBG_IO, ("NdisWanIoctl: Status: 0x%x, BytesWritten: %d",
// Status, ulBytesWritten));
switch (Status) {
case STATUS_SUCCESS:
ReturnStatus = Status;
pIrp->IoStatus.Information = ulBytesWritten;
break;
case STATUS_PENDING:
return(Status);
case STATUS_INFO_LENGTH_MISMATCH:
//
// See if this was a request to get size needed for
// ioctl.
//
if (ulOutputBufferLength >= sizeof(ULONG)) {
*(PULONG)pOutputBuffer = ulBytesWritten;
ulBytesWritten = sizeof(ULONG);
pIrp->IoStatus.Information = sizeof(ULONG);
} else {
pIrp->IoStatus.Information = 0;
}
ReturnStatus = Status =
STATUS_SUCCESS;
break;
default:
if (Status < 0xC0000000) {
Status =
ReturnStatus = STATUS_UNSUCCESSFUL;
} else {
ReturnStatus = Status;
}
pIrp->IoStatus.Information = 0;
break;
}
pIrp->IoStatus.Status = Status;
IoCompleteRequest(pIrp, IO_NETWORK_INCREMENT);
return(ReturnStatus);
}
NTSTATUS
NdisWanIrpStub(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
//
// Get current Irp stack location
//
PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
NdisWanDbgOut(DBG_VERBOSE, DBG_IO, ("NdisWanIrpStub: Entry"));
#ifdef MY_DEVICE_OBJECT
//
// Make sure that this is for us
//
if (pDeviceObject != NdisWanCB.pDeviceObject &&
NdisWanCB.MajorFunction[pIrpSp->MajorFunction] != NULL) {
NdisWanDbgOut(DBG_VERBOSE, DBG_IO, ("NdisWanIrpStub: Exit1"));
return(NdisWanCB.MajorFunction[pIrpSp->MajorFunction](pDeviceObject, pIrp));
}
pIrp->IoStatus.Information = 0;
pIrp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
NdisWanDbgOut(DBG_VERBOSE, DBG_IO, ("NdisWanIrpStub: Exit2"));
return (STATUS_SUCCESS);
#else
pIrp->IoStatus.Information = 0;
pIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
NdisWanDbgOut(DBG_VERBOSE, DBG_IO, ("NdisWanIrpStub: Exit2"));
return (STATUS_NOT_SUPPORTED);
#endif
}
NTSTATUS
NdisWanCreate(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp
)
/*++
Routine Name:
NdisWanCreate
Routine Description:
This routine is called when an app (rasman) opens ndiswan.
Arguments:
Return Values:
--*/
{
//
// Get current Irp stack location
//
PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("NdisWanCreate: Entry"));
#ifdef MY_DEVICE_OBJECT
//
// Make sure that this is for us
//
if (pDeviceObject != NdisWanCB.pDeviceObject &&
NdisWanCB.MajorFunction[pIrpSp->MajorFunction] != NULL) {
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("NdisWanCreate: Exit1"));
return(NdisWanCB.MajorFunction[pIrpSp->MajorFunction](pDeviceObject, pIrp));
}
#endif
if (InterlockedIncrement(&NdisWanCB.RefCount) == 1) {
ULONG i;
ULONG ArraySize;
PPROTOCOL_INFO InfoArray;
BOOLEAN bEvent = FALSE;
//
// This is the first guy!
//
NdisAcquireSpinLock(&ProtocolInfoTable->Lock);
ArraySize = ProtocolInfoTable->ulArraySize;
for (i = 0, InfoArray = ProtocolInfoTable->ProtocolInfo;
i < ArraySize; i++, InfoArray++) {
if (InfoArray->ProtocolType != 0) {
InfoArray->Flags |= PROTOCOL_EVENT_OCCURRED;
bEvent = TRUE;
}
}
if (bEvent) {
ProtocolInfoTable->Flags |= PROTOCOL_EVENT_OCCURRED;
}
NdisReleaseSpinLock(&ProtocolInfoTable->Lock);
}
pIrp->IoStatus.Information = 0;
pIrp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("NdisWanCreate: Exit2"));
return (STATUS_SUCCESS);
}
NTSTATUS
NdisWanCleanup(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp
)
/*++
Routine Name:
NdisWanCleanup
Routine Description:
This routine is called when all apps (rasman) that have opened
ndiswan have gone away. If ndiswan is still routed to any
transports it will complete all sends and do linedowns to
cleanup.
Arguments:
Return Values:
--*/
{
//
// Get current Irp stack location
//
PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("NdisWanCleanup: Entry"));
#ifdef MY_DEVICE_OBJECT
//
// Make sure that this is for us
//
if (pDeviceObject != NdisWanCB.pDeviceObject &&
NdisWanCB.MajorFunction[pIrpSp->MajorFunction] != NULL) {
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("NdisWanCleanup: Exit1"));
return(NdisWanCB.MajorFunction[pIrpSp->MajorFunction](pDeviceObject, pIrp));
}
#endif
pIrp->IoStatus.Information = 0;
pIrp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
InterlockedDecrement(&NdisWanCB.RefCount);
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("NdisWanCleanup: Exit2"));
return (STATUS_SUCCESS);
}
NTSTATUS
NdisWanPnPPower(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
//
// Get current Irp stack location
//
PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("NdisWanPnPPower: Entry"));
#ifdef MY_DEVICE_OBJECT
//
// Make sure that this is for us
//
if (pDeviceObject != NdisWanCB.pDeviceObject &&
NdisWanCB.MajorFunction[pIrpSp->MajorFunction] != NULL) {
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("NdisWanPnPPower: Exit1"));
return(NdisWanCB.MajorFunction[pIrpSp->MajorFunction](pDeviceObject, pIrp));
}
#endif
pIrp->IoStatus.Information = 0;
pIrp->IoStatus.Status = STATUS_SUCCESS;
PoStartNextPowerIrp(pIrp);
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("NdisWanPnPPower: Exit2"));
return (STATUS_SUCCESS);
}
VOID
NdisWanCancelRoutine(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
BOOLEAN Found = FALSE;
PLIST_ENTRY Entry;
ULONG CopySize = 0;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("NdisWanCancelRoutine: Irp 0x%p", pIrp));
IoReleaseCancelSpinLock(pIrp->CancelIrql);
do {
//
// Is this the hibernate event irp?
//
NdisAcquireSpinLock(&NdisWanCB.Lock);
if (pIrp == NdisWanCB.HibernateEventIrp) {
NdisWanCB.HibernateEventIrp = NULL;
Found = TRUE;
}
NdisReleaseSpinLock(&NdisWanCB.Lock);
if (Found) {
break;
}
//
// Is this the protocol event irp?
//
NdisAcquireSpinLock(&ProtocolInfoTable->Lock);
if (pIrp == ProtocolInfoTable->EventIrp) {
ProtocolInfoTable->EventIrp = NULL;
Found = TRUE;
}
NdisReleaseSpinLock(&ProtocolInfoTable->Lock);
if (Found) {
break;
}
//
// We need to walk the async event queue looking for
// the async event that this irp is associated with
//
NdisAcquireSpinLock(&IoRecvList.Lock);
for (Entry = IoRecvList.IrpList.Flink;
Entry != &IoRecvList.IrpList;
Entry = Entry->Flink) {
PIRP MyIrp = CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry);
if (MyIrp == (PVOID)pIrp) {
IoRecvList.ulIrpCount--;
//
// Remove from the list
//
RemoveEntryList(Entry);
Found = TRUE;
((PNDISWAN_IO_PACKET)(pIrp->AssociatedIrp.SystemBuffer))->usHandleType = CANCELEDHANDLE;
INSERT_RECV_EVENT('c');
CopySize = sizeof(NDISWAN_IO_PACKET);
IoRecvList.LastIrp = pIrp;
IoRecvList.LastIrpStatus = STATUS_SUCCESS;
IoRecvList.LastCopySize = CopySize;
IoRecvList.LastPacketNumber =
((PNDISWAN_IO_PACKET)(pIrp->AssociatedIrp.SystemBuffer))->PacketNumber;
break;
}
}
NdisReleaseSpinLock(&IoRecvList.Lock);
if (Found) {
break;
}
NdisAcquireSpinLock(&ThresholdEventQueue.Lock);
for (Entry = ThresholdEventQueue.List.Flink;
Entry != &ThresholdEventQueue.List;
Entry = Entry->Flink) {
PIRP MyIrp = CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry);
if (MyIrp == (PVOID)pIrp) {
ThresholdEventQueue.ulCount--;
//
// Remove from the list
//
RemoveEntryList(Entry);
Found = TRUE;
break;
}
}
NdisReleaseSpinLock(&ThresholdEventQueue.Lock);
} while (FALSE);
//
// Complete the irp
//
pIrp->Cancel = TRUE;
pIrp->IoStatus.Status = STATUS_CANCELLED;
pIrp->IoStatus.Information = CopySize;
IoCompleteRequest(pIrp, IO_NETWORK_INCREMENT);
}
#endif
NTSTATUS
ExecuteIo(
IN ULONG ulFuncCode,
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NTSTATUS Status = STATUS_INVALID_PARAMETER;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("ExecuteIo: FuncCode 0x%x", ulFuncCode));
if (ulFuncCode < MAX_FUNC_CODES) {
Status = (*IoDispatchTable[ulFuncCode].Function)(pInputBuffer,
ulInputBufferLength,
pOutputBuffer,
ulOutputBufferLength,
pulBytesWritten);
}
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("ExecuteIo: Status 0x%x", Status));
return (Status);
}
NTSTATUS
MapConnectionId(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
MapConnectionId
Routine Description:
This functions takes a WAN Wrapper connection id, finds the corresponding
LinkCB and BundleCB, and returns handles to these CB's.
Arguments:
pInputBuffer - Pointer to the input structure that should be NDISWAN_MAP_CONNECTION_ID
ulInputBufferLength - Length of input buffer should be sizeof(NDISWAN_MAP_CONNECTION_ID)
pOutputBuffer - Pointer to the output structure that should be NDISWAN_MAP_CONNNECTION_ID
ulOutputBufferLength - Length of output buffer should be sizeof(NDISWAN_MAP_CONNECTION_ID)
pulBytesWritten - Then number of bytes written to the output buffer is returned here
Return Values:
NDISWAN_ERROR_INVALID_HANDLE
STATUS_INFO_LENGTH_MISMATCH
STATUS_SUCCESS
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
PNDISWAN_MAP_CONNECTION_ID In = (PNDISWAN_MAP_CONNECTION_ID)pInputBuffer;
PNDISWAN_MAP_CONNECTION_ID Out = (PNDISWAN_MAP_CONNECTION_ID)pOutputBuffer;
ULONG SizeNeeded = sizeof(NDISWAN_MAP_CONNECTION_ID);
ULONG i;
POPENCB OpenCB = NULL;
PLINKCB LinkCB = NULL;
PBUNDLECB BundleCB = NULL;
LOCK_STATE LockState;
ULONG Count;
BOOLEAN Found = FALSE;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("MapConnectionId:"));
*pulBytesWritten = SizeNeeded;
if (ulInputBufferLength < SizeNeeded ||
ulOutputBufferLength < SizeNeeded) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("MapConnectionId: Buffer to small: Size: %d, SizeNeeded %d",
ulOutputBufferLength, SizeNeeded));
return (STATUS_INFO_LENGTH_MISMATCH);
}
ASSERT(In->hLinkContext != NULL);
do {
//
// Find the linkcb that has this connection id and return
// both the linkcb index and the bundlecb index
//
NdisAcquireReadWriteLock(&ConnTableLock, FALSE, &LockState);
do {
ULONG index;
PLIST_ENTRY le;
if (PtrToUlong(In->hConnectionID) < ConnectionTable->ulArraySize) {
//
// This might be my handle and thus a direct index
//
LinkCB = *(ConnectionTable->LinkArray +
PtrToUlong(In->hConnectionID));
if ((LinkCB != NULL) &&
(LinkCB->hLinkContext == NULL)) {
Found = TRUE;
break;
}
}
//
// The connectionid was not my handle so find the
// correct linkcb in the connection table. Walk
// the list backward.
//
le = ConnectionTable->LinkList.Blink;
while (le != &ConnectionTable->LinkList) {
LinkCB =
CONTAINING_RECORD(le, LINKCB, ConnTableLinkage);
if (LinkCB != NULL &&
In->hConnectionID == LinkCB->ConnectionWrapperID &&
LinkCB->hLinkContext == NULL) {
Found = TRUE;
break;
}
le = le->Blink;
}
} while (FALSE);
if (!Found) {
NdisReleaseReadWriteLock(&ConnTableLock, &LockState);
break;
}
NdisDprAcquireSpinLock(&LinkCB->Lock);
if (LinkCB->State != LINK_UP) {
Found = FALSE;
NdisDprReleaseSpinLock(&LinkCB->Lock);
NdisReleaseReadWriteLock(&ConnTableLock, &LockState);
break;
}
BundleCB = LinkCB->BundleCB;
//
// We have found the right link, return the link and bundle handles
//
Out->hLinkHandle = LinkCB->hLinkHandle;
Out->hBundleHandle = BundleCB->hBundleHandle;
LinkCB->hLinkContext = In->hLinkContext;
BundleCB->hBundleContext = In->hBundleContext;
REF_LINKCB(LinkCB);
//
// Copy the friendly name to the link
//
{
ULONG CopyLength;
CopyLength = (ulInputBufferLength -
FIELD_OFFSET(NDISWAN_MAP_CONNECTION_ID, szName[0]));
CopyLength = (CopyLength > In->ulNameLength) ?
In->ulNameLength : CopyLength;
CopyLength = (CopyLength > MAX_NAME_LENGTH) ?
MAX_NAME_LENGTH : CopyLength;
NdisMoveMemory(LinkCB->Name, In->szName, CopyLength);
}
OpenCB = LinkCB->OpenCB;
NdisDprReleaseSpinLock(&LinkCB->Lock);
//
// If this link has some recv's pending because
// we did not have a context mapped yet, we could
// get into a state where our recv's stall. We
// will kick start this by scheduling a routine
// to complete the pending recv's.
//
NdisDprAcquireSpinLock(&IoRecvList.Lock);
if (LinkCB->RecvDescCount != 0){
if (!IoRecvList.TimerScheduled) {
WAN_TIME TimeOut;
IoRecvList.TimerScheduled = TRUE;
NdisWanInitWanTime(&TimeOut, 15);
KeSetTimer(&IoRecvList.Timer,
TimeOut,
&IoRecvList.Dpc);
}
}
NdisDprReleaseSpinLock(&IoRecvList.Lock);
NdisReleaseReadWriteLock(&ConnTableLock, &LockState);
} while ( 0 );
if (!Found) {
//
// We did not find a match to the connection id
//
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("MapConnectionId: ConnectionId not found! ConnectionId: 0x%x",
In->hConnectionID));
*pulBytesWritten = 0;
Status = NDISWAN_ERROR_INVALID_HANDLE;
}
if (OpenCB != NULL) {
//
// Wait for initialization to complete
//
NdisWanWaitForNotificationEvent(&OpenCB->InitEvent);
}
return (Status);
}
NTSTATUS
GetBundleHandle(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
GetBundleHandle
Routine Description:
This function takes a handle to a linkcb and returns the handle to the bundlecb
that the linkcb belongs to
Arguments:
pInputBuffer - Pointer to the input structure that should be NDISWAN_GET_BUNDLE_HANDLE
ulInputBufferLength - Length of the input buffer should be sizeof(NDISWAN_GET_BUNDLE_HANDLE)
pOutputBuffer - Pointer to the output structure that should be NDISWAN_GET_BUNDLE_HANDLE
ulOutputBufferLength - Length of the output buffer should be sizeof(NDISWAN_GET_BUNDLE_HANDLE)
Return Values:
NDISWAN_ERROR_INVALID_HANDLE
STATUS_INFO_LENGTH_MISMATCH
STATUS_SUCCESS
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
PNDISWAN_GET_BUNDLE_HANDLE In = (PNDISWAN_GET_BUNDLE_HANDLE)pInputBuffer;
PNDISWAN_GET_BUNDLE_HANDLE Out = (PNDISWAN_GET_BUNDLE_HANDLE)pOutputBuffer;
ULONG SizeNeeded = sizeof(NDISWAN_GET_BUNDLE_HANDLE);
PLINKCB LinkCB = NULL;
PBUNDLECB BundleCB = NULL;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("GetBundleHandle:"));
*pulBytesWritten = SizeNeeded;
do {
if (ulInputBufferLength < SizeNeeded ||
ulOutputBufferLength < SizeNeeded) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetBundleHandle: Buffer to small: Size: %d, SizeNeeded %d",
ulOutputBufferLength, SizeNeeded));
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
if (!AreLinkAndBundleValid(In->hLinkHandle,
TRUE,
&LinkCB,
&BundleCB)) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO,
("GetBundleHandle: Invalid LinkHandle: 0x%x", In->hLinkHandle));
Status = NDISWAN_ERROR_INVALID_HANDLE;
break;
}
//
// Get the bundle handle that this link belongs to
//
Out->hBundleHandle = BundleCB->hBundleHandle;
} while ( 0 );
//
// Derefs for the refs applied in AreLinkAndBundleValid
//
DEREF_LINKCB(LinkCB);
DEREF_BUNDLECB(BundleCB);
return (Status);
}
NTSTATUS
SetFriendlyName(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
SetFriendlyName
Routine Description:
Sets the friendly name of either a bundlecb or a linkcb
Arguments:
pInputBuffer - Pointer to the input structure that should be NDISWAN_SET_FRIENDLY_NAME
ulInputBufferLength - Length of the input buffer should be sizeof(NDISWAN_SET_FRIENDLY_NAME)
pOutputBuffer - Pointer to the output structure that should be NDISWAN_SET_FRIENDLY_NAME
ulOutputBufferLength - Length of the output buffer should be sizeof(NDISWAN_SET_FRIENDLY_NAME)
Return Values:
NDISWAN_ERROR_INVALID_HANDLE_TYPE
NDISWAN_ERROR_INVALID_HANDLE
STATUS_INFO_LENGTH_MISMATCH
STATUS_SUCCESS
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG SizeNeeded = sizeof(NDISWAN_SET_FRIENDLY_NAME);
PLINKCB LinkCB;
PBUNDLECB BundleCB;
PUCHAR Dest;
ULONG CopyLength;
PNDISWAN_SET_FRIENDLY_NAME In =
(PNDISWAN_SET_FRIENDLY_NAME)pInputBuffer;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("SetFriendlyName:"));
*pulBytesWritten = 0;
do {
if (ulInputBufferLength < SizeNeeded) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("SetFriendlyName: Buffer to small: Size: %d, SizeNeeded %d",
ulInputBufferLength, SizeNeeded));
*pulBytesWritten = SizeNeeded;
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
if (In->usHandleType == LINKHANDLE) {
//
// Is this a link handle
//
if (!IsLinkValid(In->hHandle,
TRUE,
&LinkCB)) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("SetFriendlyName: Invalid LinkHandle: %x",
In->hHandle));
Status = NDISWAN_ERROR_INVALID_HANDLE;
break;
}
NdisAcquireSpinLock(&LinkCB->Lock);
Dest = LinkCB->Name;
CopyLength = In->ulNameLength;
if (ulInputBufferLength - FIELD_OFFSET(NDISWAN_SET_FRIENDLY_NAME, szName) < CopyLength) {
CopyLength =
ulInputBufferLength - FIELD_OFFSET(NDISWAN_SET_FRIENDLY_NAME, szName);
}
if (CopyLength > MAX_NAME_LENGTH) {
CopyLength = MAX_NAME_LENGTH;
}
NdisMoveMemory(Dest,
In->szName,
CopyLength);
//
// Deref for the ref applied by IsLinkValid
//
DEREF_LINKCB_LOCKED(LinkCB);
} else if (In->usHandleType == BUNDLEHANDLE) {
//
// Or a bundle handle
//
if (!IsBundleValid(In->hHandle,
TRUE,
&BundleCB)) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("SetFriendlyName: Invalid BundleHandle: 0x%x",
In->hHandle));
Status = NDISWAN_ERROR_INVALID_HANDLE;
break;
}
AcquireBundleLock(BundleCB);
Dest = BundleCB->Name;
CopyLength = In->ulNameLength;
if (ulInputBufferLength - FIELD_OFFSET(NDISWAN_SET_FRIENDLY_NAME, szName) < CopyLength) {
CopyLength =
ulInputBufferLength - FIELD_OFFSET(NDISWAN_SET_FRIENDLY_NAME, szName);
}
if (CopyLength > MAX_NAME_LENGTH) {
CopyLength = MAX_NAME_LENGTH;
}
NdisMoveMemory(Dest,
In->szName,
CopyLength);
//
// Deref for the ref applied by IsBundleValid
//
DEREF_BUNDLECB_LOCKED(BundleCB);
} else {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("SetFriendlyName: Invalid HandleType: 0x%x",
In->usHandleType));
Status = NDISWAN_ERROR_INVALID_HANDLE_TYPE;
break;
}
} while ( 0 );
return (Status);
}
NTSTATUS
ActivateRoute(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
ActivateRoute
Routine Description:
This function routes the bundle given by hbundlehandle to
the protocol give by usprotocoltype.
Arguments:
pInputBuffer - Pointer to the input structure that should be NDISWAN_ACTIVATE_ROUTE
ulInputBufferLength - Length of input buffer should be sizeof(NDISWAN_ACTIVATE_ROUTE)
pOutputBuffer - Pointer to the output structure that should be NDISWAN_ACTIVATE_ROUTE
ulOutputBufferLength - Length of output buffer should be sizeof(NDISWAN_ACTIVATE_ROUTE)
pulBytesWritten - Then number of bytes written to the output buffer is returned here
Return Values:
NDISWAN_ERROR_ALREADY_ROUTED
NDISWAN_ERROR_INVALID_HANDLE
STATUS_INSUFFICIENT_RESOURCES
STATUS_INFO_LENGTH_MISMATCH
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
PNDISWAN_ROUTE In = (PNDISWAN_ROUTE)pInputBuffer;
PNDISWAN_ROUTE Out = (PNDISWAN_ROUTE)pOutputBuffer;
ULONG SizeNeeded = sizeof(NDISWAN_ROUTE);
ULONG AllocationSize, i;
PBUNDLECB BundleCB = NULL;
BOOLEAN RouteExists = FALSE;
PPROTOCOLCB ProtocolCB;
NDIS_HANDLE hProto;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("ActivateRoute:"));
*pulBytesWritten = SizeNeeded;
do {
if (ulInputBufferLength < SizeNeeded ||
ulOutputBufferLength < SizeNeeded ||
In->ulBufferLength > ulInputBufferLength ||
In->usBindingNameLength > ulInputBufferLength) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("ActivateRoute: Buffer to small: Size: %d, SizeNeeded %d",
ulInputBufferLength, SizeNeeded));
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
//
// If this is a valid bundle
//
if (!IsBundleValid(In->hBundleHandle,
TRUE,
&BundleCB)) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("ActivateRoute: Invalid BundleHandle: 0x%x, ProtocolType: 0x%x",
In->hBundleHandle, In->usProtocolType));
Status = NDISWAN_ERROR_INVALID_HANDLE;
break;
}
AcquireBundleLock(BundleCB);
//
// Create and initialize a ProtocolCB for this new route
//
ProtocolCB =
NdisWanAllocateProtocolCB(In);
if (ProtocolCB == NULL) {
//
// Memory allocation failed
//
ReleaseBundleLock(BundleCB);
Status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
//
// Assign a handle for this protocolcb
//
hProto =
AssignProtocolCBHandle(BundleCB, ProtocolCB);
if (hProto == (NDIS_HANDLE)MAX_PROTOCOLS) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("ActivateRoute: No room in ProtocolCB Table: ProtocolType: 0x%2.2x",
ProtocolCB->ProtocolType));
ProtocolCB->State = PROTOCOL_UNROUTING;
NdisWanFreeProtocolCB(ProtocolCB);
ReleaseBundleLock(BundleCB);
Status = NDISWAN_ERROR_NO_ROUTE;
break;
}
//
// Do a new lineup to protocol
//
ReleaseBundleLock(BundleCB);
Status = DoNewLineUpToProtocol(ProtocolCB);
if (Status == NDIS_STATUS_SUCCESS) {
Out->usDeviceNameLength =
(ProtocolCB->OutDeviceName.Length > MAX_NAME_LENGTH) ?
MAX_NAME_LENGTH : ProtocolCB->OutDeviceName.Length;
NdisMoveMemory(&Out->DeviceName[0],
ProtocolCB->OutDeviceName.Buffer,
Out->usDeviceNameLength);
//
// Insert the protocolcb in the bundle's protocolcb table
// and list.
//
AddProtocolCBToBundle(ProtocolCB, BundleCB);
} else {
AcquireBundleLock(BundleCB);
FreeProtocolCBHandle(BundleCB, ProtocolCB);
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("ActivateRoute: Error during LineUp to ProtocolType: 0x%x",
ProtocolCB->ProtocolType));
ProtocolCB->State = PROTOCOL_UNROUTING;
NdisWanFreeProtocolCB(ProtocolCB);
ReleaseBundleLock(BundleCB);
}
} while ( 0 );
//
// Deref for ref applied by IsBundleValid
//
DEREF_BUNDLECB(BundleCB);
return (Status);
}
NTSTATUS
BundleLink(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
BundleLink
Routine Description:
This function bundles the link given by hLinkHandle to the bundle given
by hBundlehandle. The resources used by the bundle that the link used
to belong to are freed.
Arguments:
pInputBuffer - Pointer to the input structure that should be NDISWAN_ADD_LINK_TO_BUNDLE
ulInputBufferLength - Length of input buffer should be sizeof(NDISWAN_ADD_LINK_TO_BUNDLE)
pOutputBuffer - Pointer to the output structure that should be NDISWAN_ADD_LINK_TO_BUNDLE
ulOutputBufferLength - Length of output buffer should be sizeof(NDISWAN_ADD_LINK_TO_BUNDLE)
pulBytesWritten - Then number of bytes written to the output buffer is returned here
Return Values:
NDISWAN_ERROR_INVALID_HANDLE
STATUS_INFO_LENGTH_MISMATCH
--*/
{
ULONG SizeNeeded = sizeof(NDISWAN_ADD_LINK_TO_BUNDLE);
PLINKCB LinkCB = NULL;
PBUNDLECB OldBundleCB = NULL, NewBundleCB = NULL;
NTSTATUS Status = STATUS_SUCCESS;
PPROTOCOLCB IoProtocolCB;
PPACKET_QUEUE PacketQueue;
PACKET_QUEUE TempPacketQueue;
PNDISWAN_ADD_LINK_TO_BUNDLE In =
(PNDISWAN_ADD_LINK_TO_BUNDLE)pInputBuffer;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("BundleLink:"));
*pulBytesWritten = 0;
do {
if (ulInputBufferLength < SizeNeeded) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("BundleLink: Buffer to small: Size: %d, SizeNeeded %d",
ulInputBufferLength, SizeNeeded));
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
if (!AreLinkAndBundleValid(In->hLinkHandle,
TRUE,
&LinkCB,
&OldBundleCB)) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("BundleLink: Invalid LinkHandle: 0x%x",
In->hLinkHandle));
Status = NDISWAN_ERROR_INVALID_HANDLE;
break;
}
if (!IsBundleValid(In->hBundleHandle,
TRUE,
&NewBundleCB)) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("BundleLink: Invalid NewBundleCB: 0x%p, OldBundleCB: 0x%p",
NewBundleCB, OldBundleCB));
Status = NDISWAN_ERROR_INVALID_HANDLE;
break;
}
if (NewBundleCB == OldBundleCB) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("BundleLink: Invalid NewBundleCB: 0x%p, OldBundleCB: 0x%p",
NewBundleCB, OldBundleCB));
Status = NDISWAN_ERROR_INVALID_HANDLE;
break;
}
AcquireBundleLock(OldBundleCB);
ASSERT(OldBundleCB->ulLinkCBCount == 1);
ASSERT(OldBundleCB->ulNumberOfRoutes == 0);
OldBundleCB->State = BUNDLE_GOING_DOWN;
if (OldBundleCB->OutstandingFrames != 0) {
NdisWanClearSyncEvent(&OldBundleCB->OutstandingFramesEvent);
OldBundleCB->Flags |= FRAMES_PENDING_EVENT;
ReleaseBundleLock(OldBundleCB);
NdisWanWaitForSyncEvent(&OldBundleCB->OutstandingFramesEvent);
AcquireBundleLock(OldBundleCB);
}
//
// Remove any ppp packets that might be on the old bundle
// queue so we can move them to the new bundle.
//
IoProtocolCB = OldBundleCB->IoProtocolCB;
PacketQueue = &IoProtocolCB->PacketQueue[MAX_MCML];
NdisZeroMemory(&TempPacketQueue, sizeof(TempPacketQueue));
if (!IsPacketQueueEmpty(PacketQueue)) {
while (!IsPacketQueueEmpty(PacketQueue)) {
PNDIS_PACKET Packet;
UINT PacketLength;
Packet =
RemoveHeadPacketQueue(PacketQueue);
NdisQueryPacket(Packet,
NULL,
NULL,
NULL,
&PacketLength);
InsertTailPacketQueue(&TempPacketQueue,
Packet,
PacketLength);
}
}
//
// Remove the link from the old bundle. This returns
// with the OldBundleCB lock released!
//
RemoveLinkFromBundle(OldBundleCB, LinkCB, TRUE);
AcquireBundleLock(NewBundleCB);
//
// Add the link to the new bundle
//
AddLinkToBundle(NewBundleCB, LinkCB);
SetBundleFlags(NewBundleCB);
//
// If there were any ppp packets on the old bundle
// queue we can now place them on the new bundle.
//
if (!IsPacketQueueEmpty(&TempPacketQueue)) {
IoProtocolCB = NewBundleCB->IoProtocolCB;
PacketQueue = &IoProtocolCB->PacketQueue[MAX_MCML];
while (!IsPacketQueueEmpty(&TempPacketQueue)) {
PNDIS_PACKET Packet;
UINT PacketLength;
Packet =
RemoveHeadPacketQueue(&TempPacketQueue)
NdisQueryPacket(Packet,
NULL,
NULL,
NULL,
&PacketLength);
InsertTailPacketQueue(PacketQueue,
Packet,
PacketLength);
}
}
ReleaseBundleLock(NewBundleCB);
} while ( 0 );
//
// Derefs for the refs applied by AreLinkAndBundleValid
//
DEREF_LINKCB(LinkCB);
DEREF_BUNDLECB(OldBundleCB);
//
// Deref for the ref applied by IsBundleValid
//
DEREF_BUNDLECB(NewBundleCB);
return (Status);
}
NTSTATUS
EnumLinksInBundle(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
ULONG SizeNeeded = 0;
ULONG i;
PBUNDLECB BundleCB = NULL;
PLINKCB LinkCB;
NTSTATUS Status = STATUS_SUCCESS;
PNDISWAN_ENUM_LINKS_IN_BUNDLE In =
(PNDISWAN_ENUM_LINKS_IN_BUNDLE)pInputBuffer;
PNDISWAN_ENUM_LINKS_IN_BUNDLE Out =
(PNDISWAN_ENUM_LINKS_IN_BUNDLE)pOutputBuffer;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("EnumLinksInBundle:"));
do {
if (ulInputBufferLength < sizeof(NDISWAN_ENUM_LINKS_IN_BUNDLE)) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("EnumLinksInBundle: Buffer to small: Size: %d, SizeNeeded %d",
ulInputBufferLength, sizeof(NDISWAN_ENUM_LINKS_IN_BUNDLE)));
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
if (!IsBundleValid(In->hBundleHandle,
TRUE,
&BundleCB)) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("EnumLinksInBundle: Invalid BundleHandle: 0x%x",
In->hBundleHandle));
Status = NDISWAN_ERROR_INVALID_HANDLE;
break;
}
AcquireBundleLock(BundleCB);
SizeNeeded = sizeof(NDISWAN_ENUM_LINKS_IN_BUNDLE) +
(sizeof(NDIS_HANDLE) * BundleCB->ulLinkCBCount);
*pulBytesWritten = SizeNeeded;
if (ulOutputBufferLength < SizeNeeded) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("EnumLinksInBundle: Buffer to small: Size: %d, SizeNeeded %d",
ulOutputBufferLength, SizeNeeded));
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
Out->ulNumberOfLinks = BundleCB->ulLinkCBCount;
//
// Walk the list of linkcb's and put the handle for each
// cb in the output handle array
//
i = 0;
for (LinkCB = (PLINKCB)BundleCB->LinkCBList.Flink;
(PVOID)LinkCB != (PVOID)&BundleCB->LinkCBList;
LinkCB = (PLINKCB)LinkCB->Linkage.Flink) {
Out->hLinkHandleArray[i++] = LinkCB->hLinkHandle;
}
} while ( 0 );
//
// Deref for ref applied by IsBundleValid
//
DEREF_BUNDLECB_LOCKED(BundleCB);
return (Status);
}
NTSTATUS
SetProtocolPriority(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
SetProtocolPriority
Routine Description:
This function sets the the priority, given by uspriority, for the
protocol given by usprotocoltype on the bundle given by hbundlehandle.
Arguments:
pInputBuffer - Pointer to the input structure that should be NDISWAN_SET_PROTOCOL_PRIORITY
ulInputBufferLength - Length of input buffer should be sizeof(NDISWAN_SET_PROTOCOL_PRIORITY)
pOutputBuffer - Pointer to the output structure that should be NDISWAN_SET_PROTOCOL_PRIORITY
ulOutputBufferLength - Length of output buffer should be sizeof(NDISWAN_SET_PROTOCOL_PRIORITY)
pulBytesWritten - Then number of bytes written to the output buffer is returned here
Return Values:
NDISWAN_ERROR_INVALID_HANDLE
STATUS_INFO_LENGTH_MISMATCH
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG SizeNeeded = sizeof(NDISWAN_SET_PROTOCOL_PRIORITY);
PNDISWAN_SET_PROTOCOL_PRIORITY In = (PNDISWAN_SET_PROTOCOL_PRIORITY)pInputBuffer;
PBUNDLECB BundleCB = NULL;
PPROTOCOLCB ProtocolCB;
ULONG BytesPerSecond;
*pulBytesWritten = 0;
return (STATUS_SUCCESS);
}
NTSTATUS
SetBandwidthOnDemand(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
SetBandwidthOnDemand
Routine Description:
This function sets the bandwidth on demand parameters for the bundle given by
hbundlehandle.
Arguments:
pInputBuffer - Pointer to the input structure that should be NDISWAN_SET_BANDWIDTH_ON_DEMAND
ulInputBufferLength - Length of input buffer should be sizeof(NDISWAN_SET_BANDWIDTH_ON_DEMAND)
pOutputBuffer - Pointer to the output structure that should be NDISWAN_SET_BANDWIDTH_ON_DEMAND
ulOutputBufferLength - Length of output buffer should be sizeof(NDISWAN_SET_BANDWIDTH_ON_DEMAND)
pulBytesWritten - Then number of bytes written to the output buffer is returned here
Return Values:
NDISWAN_ERROR_INVALID_HANDLE
STATUS_INFO_LENGTH_MISMATCH
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
PBUNDLECB BundleCB = NULL;
ULONG SizeNeeded = sizeof(NDISWAN_SET_BANDWIDTH_ON_DEMAND);
PNDISWAN_SET_BANDWIDTH_ON_DEMAND In = (PNDISWAN_SET_BANDWIDTH_ON_DEMAND)pInputBuffer;
WAN_TIME Temp1, Temp2;
ULONGLONG SecondsInSamplePeriod;
ULONGLONG BytesPerSecond;
ULONGLONG BytesInSamplePeriod;
ULONGLONG temp;
ULONG LowestSamplePeriod = 0;
PBOND_INFO BonDInfo;
PSAMPLE_TABLE SampleTable;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("SetBandwidthOnDemand:"));
*pulBytesWritten = 0;
if (ulInputBufferLength < SizeNeeded) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("SetBandwidthOnDemand: Buffer to small: Size: %d, SizeNeeded %d",
ulInputBufferLength, SizeNeeded));
*pulBytesWritten = SizeNeeded;
return STATUS_INFO_LENGTH_MISMATCH;
}
//
// If this is a valid bundle handle
//
if (!IsBundleValid(In->hBundleHandle,
TRUE,
&BundleCB)) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO,
("SetBandwidthOnDemand: Invalid BundleHandle: 0x%x",
In->hBundleHandle));
return NDISWAN_ERROR_INVALID_HANDLE;
}
do {
AcquireBundleLock(BundleCB);
if (BundleCB->BonDAllocation == NULL) {
PUCHAR pMem;
NdisWanAllocatePriorityMemory(&pMem,
BONDALLOC_SIZE,
BONDALLOC_TAG,
LowPoolPriority);
if (pMem == NULL) {
// ReleaseBundleLock(BundleCB);
Status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
BundleCB->BonDAllocation = pMem;
BundleCB->SUpperBonDInfo = (PBOND_INFO)pMem;
pMem += (sizeof(BOND_INFO) + sizeof(PVOID));
(ULONG_PTR)pMem &= ~((ULONG_PTR)sizeof(PVOID) - 1);
BundleCB->SLowerBonDInfo = (PBOND_INFO)pMem;
pMem += (sizeof(BOND_INFO) + sizeof(PVOID));
(ULONG_PTR)pMem &= ~((ULONG_PTR)sizeof(PVOID) - 1);
BundleCB->RUpperBonDInfo = (PBOND_INFO)pMem;
pMem += (sizeof(BOND_INFO) + sizeof(PVOID));
(ULONG_PTR)pMem &= ~((ULONG_PTR)sizeof(PVOID) - 1);
BundleCB->RLowerBonDInfo = (PBOND_INFO)pMem;
BonDInfo = BundleCB->SUpperBonDInfo;
BonDInfo->DataType = TRANSMIT_DATA;
BonDInfo->usPercentBandwidth = 0xFFFF;
SampleTable = &BonDInfo->SampleTable;
SampleTable->ulSampleArraySize = SAMPLE_ARRAY_SIZE;
BonDInfo = BundleCB->SLowerBonDInfo;
BonDInfo->DataType = TRANSMIT_DATA;
BonDInfo->usPercentBandwidth = 0xFFFF;
SampleTable = &BonDInfo->SampleTable;
SampleTable->ulSampleArraySize = SAMPLE_ARRAY_SIZE;
BonDInfo = BundleCB->RUpperBonDInfo;
BonDInfo->DataType = RECEIVE_DATA;
BonDInfo->usPercentBandwidth = 0xFFFF;
SampleTable = &BonDInfo->SampleTable;
SampleTable->ulSampleArraySize = SAMPLE_ARRAY_SIZE;
BonDInfo = BundleCB->RLowerBonDInfo;
BonDInfo->DataType = RECEIVE_DATA;
BonDInfo->usPercentBandwidth = 0xFFFF;
SampleTable = &BonDInfo->SampleTable;
SampleTable->ulSampleArraySize = SAMPLE_ARRAY_SIZE;
}
if (In->usLowerXmitThreshold > 0) {
BonDInfo = BundleCB->SLowerBonDInfo;
SampleTable = &BonDInfo->SampleTable;
//
// One second is the smallest sample period we support!
//
if (In->ulLowerXmitSamplePeriod < 1000) {
In->ulLowerXmitSamplePeriod = 1000;
}
//
// We need to init the sample period in 100 nanoseconds
//
NdisWanInitWanTime(&Temp1, MILS_TO_100NANOS);
NdisWanInitWanTime(&Temp2, In->ulLowerXmitSamplePeriod);
NdisWanMultiplyWanTime(&SampleTable->SamplePeriod,
&Temp1,&Temp2);
//
// The sample rate is the sample period divided by the number of
// samples in the sample array
//
NdisWanInitWanTime(&Temp1, SampleTable->ulSampleArraySize);
NdisWanDivideWanTime(&SampleTable->SampleRate,
&SampleTable->SamplePeriod,
&Temp1);
//
// Convert %bandwidth to Bytes/SamplePeriod
// 100bsp * 100 / 8 = BytesPerSecond
// BytesPerSecond * SecondsInSamplePeriod = BytesInSamplePeriod
// BytesInSamplePeriod * %Bandwidth / 100 = BytesInSamplePeriod
//
SecondsInSamplePeriod = BonDInfo->ulSecondsInSamplePeriod =
In->ulLowerXmitSamplePeriod / 1000;
BytesPerSecond =
BundleCB->SFlowSpec.PeakBandwidth;
BytesInSamplePeriod =
BytesPerSecond * SecondsInSamplePeriod;
BonDInfo->ulBytesInSamplePeriod = BytesInSamplePeriod;
BonDInfo->usPercentBandwidth = In->usLowerXmitThreshold;
temp = In->usLowerXmitThreshold;
temp *= BytesInSamplePeriod;
temp /= 100;
BonDInfo->ulBytesThreshold = (ULONG)temp;
if (BonDInfo->State == BonDSignaled) {
BonDInfo->State = BonDIdle;
}
NdisWanGetSystemTime(&BonDInfo->StartTime);
if (In->ulLowerXmitSamplePeriod < LowestSamplePeriod ||
LowestSamplePeriod == 0) {
LowestSamplePeriod = In->ulLowerXmitSamplePeriod;
}
}
if (In->usUpperXmitThreshold > 0) {
BonDInfo = BundleCB->SUpperBonDInfo;
SampleTable = &BonDInfo->SampleTable;
//
// One second is the smallest sample period we support!
//
if (In->ulUpperXmitSamplePeriod < 1000) {
In->ulUpperXmitSamplePeriod = 1000;
}
//
// We need to init the sample period in 100 nanoseconds
//
NdisWanInitWanTime(&Temp1, MILS_TO_100NANOS);
NdisWanInitWanTime(&Temp2, In->ulUpperXmitSamplePeriod);
NdisWanMultiplyWanTime(&SampleTable->SamplePeriod,
&Temp1,
&Temp2);
//
// The sample rate is the sample period divided by the number of
// samples in the sample array
//
NdisWanInitWanTime(&Temp1, SampleTable->ulSampleArraySize);
NdisWanDivideWanTime(&SampleTable->SampleRate,
&SampleTable->SamplePeriod,
&Temp1);
//
// Convert %bandwidth to Bytes/SamplePeriod
// 100bsp * 100 / 8 = BytesPerSecond
// BytesPerSecond * SecondsInSamplePeriod = BytesInSamplePeriod
// BytesInSamplePeriod * %Bandwidth / 100 = BytesInSamplePeriod
//
SecondsInSamplePeriod = BonDInfo->ulSecondsInSamplePeriod =
In->ulUpperXmitSamplePeriod / 1000;
BytesPerSecond =
BundleCB->SFlowSpec.PeakBandwidth;
BytesInSamplePeriod =
BytesPerSecond * SecondsInSamplePeriod;
BonDInfo->ulBytesInSamplePeriod =
(ULONG)BytesInSamplePeriod;
BonDInfo->usPercentBandwidth = In->usUpperXmitThreshold;
temp = In->usUpperXmitThreshold;
temp *= BytesInSamplePeriod;
temp /= 100;
BonDInfo->ulBytesThreshold = (ULONG)temp;
if (BonDInfo->State == BonDSignaled) {
BonDInfo->State = BonDIdle;
}
NdisWanGetSystemTime(&BonDInfo->StartTime);
if (In->ulUpperXmitSamplePeriod < LowestSamplePeriod ||
LowestSamplePeriod == 0) {
LowestSamplePeriod = In->ulUpperXmitSamplePeriod;
}
}
if (In->usLowerRecvThreshold > 0) {
BonDInfo = BundleCB->RLowerBonDInfo;
SampleTable = &BonDInfo->SampleTable;
//
// One second is the smallest sample period we support!
//
if (In->ulLowerRecvSamplePeriod < 1000) {
In->ulLowerRecvSamplePeriod = 1000;
}
//
// We need to init the sample period in 100 nanoseconds
//
NdisWanInitWanTime(&Temp1, MILS_TO_100NANOS);
NdisWanInitWanTime(&Temp2, In->ulLowerRecvSamplePeriod);
NdisWanMultiplyWanTime(&SampleTable->SamplePeriod,
&Temp1,&Temp2);
//
// The sample rate is the sample period divided by the number of
// samples in the sample array
//
NdisWanInitWanTime(&Temp1, SampleTable->ulSampleArraySize);
NdisWanDivideWanTime(&SampleTable->SampleRate,
&SampleTable->SamplePeriod,
&Temp1);
//
// Convert %bandwidth to Bytes/SamplePeriod
// 100bsp * 100 / 8 = BytesPerSecond
// BytesPerSecond * SecondsInSamplePeriod = BytesInSamplePeriod
// BytesInSamplePeriod * %Bandwidth / 100 = BytesInSamplePeriod
//
SecondsInSamplePeriod = BonDInfo->ulSecondsInSamplePeriod =
In->ulLowerRecvSamplePeriod / 1000;
BytesPerSecond =
BundleCB->RFlowSpec.PeakBandwidth;
BytesInSamplePeriod =
BytesPerSecond * SecondsInSamplePeriod;
BonDInfo->ulBytesInSamplePeriod = BytesInSamplePeriod;
BonDInfo->usPercentBandwidth = In->usLowerRecvThreshold;
temp = In->usLowerRecvThreshold;
temp *= BytesInSamplePeriod;
temp /= 100;
BonDInfo->ulBytesThreshold = (ULONG)temp;
if (BonDInfo->State == BonDSignaled) {
BonDInfo->State = BonDIdle;
}
NdisWanGetSystemTime(&BonDInfo->StartTime);
if (In->ulLowerRecvSamplePeriod < LowestSamplePeriod ||
LowestSamplePeriod == 0) {
LowestSamplePeriod = In->ulLowerRecvSamplePeriod;
}
}
if (In->usUpperRecvThreshold > 0) {
BonDInfo = BundleCB->RUpperBonDInfo;
SampleTable = &BonDInfo->SampleTable;
//
// One second is the smallest sample period we support!
//
if (In->ulUpperRecvSamplePeriod < 1000) {
In->ulUpperRecvSamplePeriod = 1000;
}
//
// We need to init the sample period in 100 nanoseconds
//
NdisWanInitWanTime(&Temp1, MILS_TO_100NANOS);
NdisWanInitWanTime(&Temp2, In->ulUpperRecvSamplePeriod);
NdisWanMultiplyWanTime(&SampleTable->SamplePeriod,
&Temp1,
&Temp2);
//
// The sample rate is the sample period divided by the number of
// samples in the sample array
//
NdisWanInitWanTime(&Temp1, SampleTable->ulSampleArraySize);
NdisWanDivideWanTime(&SampleTable->SampleRate,
&SampleTable->SamplePeriod,
&Temp1);
//
// Convert %bandwidth to Bytes/SamplePeriod
// 100bsp * 100 / 8 = BytesPerSecond
// BytesPerSecond * SecondsInSamplePeriod = BytesInSamplePeriod
// BytesInSamplePeriod * %Bandwidth / 100 = BytesInSamplePeriod
//
SecondsInSamplePeriod = BonDInfo->ulSecondsInSamplePeriod =
In->ulUpperRecvSamplePeriod / 1000;
BytesPerSecond =
BundleCB->RFlowSpec.PeakBandwidth;
BytesInSamplePeriod =
BytesPerSecond * SecondsInSamplePeriod;
BonDInfo->ulBytesInSamplePeriod = BytesInSamplePeriod;
BonDInfo->usPercentBandwidth = In->usUpperRecvThreshold;
temp = In->usUpperRecvThreshold;
temp *= BytesInSamplePeriod;
temp /= 100;
BonDInfo->ulBytesThreshold = (ULONG)temp;
if (BonDInfo->State == BonDSignaled) {
BonDInfo->State = BonDIdle;
}
NdisWanGetSystemTime(&BonDInfo->StartTime);
if (In->ulUpperRecvSamplePeriod < LowestSamplePeriod ||
LowestSamplePeriod == 0) {
LowestSamplePeriod = In->ulUpperRecvSamplePeriod;
}
}
#if 0
//
// I want to set a periodic timer with a period equal to
// the smallest non-zero period
//
if (LowestSamplePeriod != 0) {
LARGE_INTEGER FireTime;
BundleCB->TimerPeriod = LowestSamplePeriod/10;
FireTime.QuadPart = Int32x32To64(BundleCB->TimerPeriod, -10000);
KeSetTimerEx(&BundleCB->BonDTimer,
FireTime,
BundleCB->TimerPeriod,
&BundleCB->TimerDpc);
}
#endif
if (!(BundleCB->Flags & BOND_ENABLED) &&
(LowestSamplePeriod != 0)) {
InsertTailGlobalListEx(BonDWorkList, &BundleCB->BonDLinkage, 1000, 1000);
BundleCB->Flags |= BOND_ENABLED;
}
} while ( 0 );
//
// Deref for ref applied by IsBundleValid. This release the
// BundleCB->Lock.
//
DEREF_BUNDLECB_LOCKED(BundleCB);
return (Status);
}
#ifdef NT
NTSTATUS
SetThresholdEvent(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
SetThresholdEvent
Routine Description:
This function queues up an asyncevent for bandwidth on demand
events.
Arguments:
pInputBuffer - Pointer to the input structure that should be WAN_ASYNC_EVENT
ulInputBufferLength - Length of input buffer should be sizeof(WAN_ASYNC_EVENT)
pOutputBuffer - Pointer to the output structure that should be WAN_ASYNC_EVENT
ulOutputBufferLength - Length of output buffer should be sizeof(WAN_ASYNC_EVENT)
pulBytesWritten - Then number of bytes written to the output buffer is returned here
Return Values:
--*/
{
ULONG SizeNeeded = sizeof(NDISWAN_SET_THRESHOLD_EVENT);
PIRP pIrp = (PIRP)pInputBuffer;
KIRQL Irql;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("SetThresholdEvent:"));
*pulBytesWritten = 0;
if (ulOutputBufferLength < SizeNeeded) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("SetThresholdEvent: Buffer to small: Size: %d, SizeNeeded %d",
ulInputBufferLength, SizeNeeded));
*pulBytesWritten = SizeNeeded;
return(STATUS_INFO_LENGTH_MISMATCH);
}
//
// The IRP was pended so setup a cancel routine and let the
// i/o subsystem know about the pend.
//
IoMarkIrpPending(pIrp);
NdisAcquireSpinLock(&ThresholdEventQueue.Lock);
//
// Setup the structure
//
InsertTailList(&ThresholdEventQueue.List, &(pIrp->Tail.Overlay.ListEntry));
ThresholdEventQueue.ulCount++;
if (ThresholdEventQueue.ulCount > ThresholdEventQueue.ulMaxCount) {
ThresholdEventQueue.ulMaxCount = ThresholdEventQueue.ulCount;
}
IoSetCancelRoutine(pIrp, NdisWanCancelRoutine);
NdisReleaseSpinLock(&ThresholdEventQueue.Lock);
return (STATUS_PENDING);
}
#endif
NTSTATUS
FlushThresholdEvents(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("FlushThresholdEvents:"));
*pulBytesWritten = 0;
CancelThresholdEvents();
return (STATUS_SUCCESS);
}
NTSTATUS
IoSendPacket(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG SizeNeeded = sizeof(NDISWAN_IO_PACKET);
PNDISWAN_IO_PACKET In = (PNDISWAN_IO_PACKET)pInputBuffer;
PLINKCB LinkCB = NULL;
PBUNDLECB BundleCB = NULL;
NdisWanDbgOut(DBG_TRACE, DBG_SEND, ("IoSendPacket:"));
*pulBytesWritten = 0;
do {
if (ulInputBufferLength < SizeNeeded) {
NdisWanDbgOut(DBG_FAILURE, DBG_SEND, ("IoSendPacket: Buffer to small: Size: %d, SizeNeeded %d",
ulInputBufferLength, SizeNeeded));
*pulBytesWritten = SizeNeeded;
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
if (ulInputBufferLength - SizeNeeded > glLargeDataBufferSize) {
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
if ((LONG)ulInputBufferLength - FIELD_OFFSET(NDISWAN_IO_PACKET, PacketData) <
(LONG)(In->usHeaderSize + In->usPacketSize)) {
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
if (In->usHandleType == LINKHANDLE) {
if (!AreLinkAndBundleValid(In->hHandle,
TRUE,
&LinkCB,
&BundleCB)) {
NdisWanDbgOut(DBG_FAILURE, DBG_SEND, ("IoSendPacket: Invalid Handle: 0x%x, HandleType: 0x%x",
In->hHandle, In->usHandleType));
Status = NDISWAN_ERROR_INVALID_HANDLE;
break;
}
AcquireBundleLock(BundleCB);
} else {
if (!IsBundleValid(In->hHandle,
TRUE,
&BundleCB)) {
NdisWanDbgOut(DBG_FAILURE, DBG_SEND, ("IoSendPacket: Invalid Handle: 0x%x, HandleType: 0x%x",
In->hHandle, In->usHandleType));
Status = NDISWAN_ERROR_INVALID_HANDLE;
break;
}
AcquireBundleLock(BundleCB);
if (BundleCB->ulLinkCBCount == 0) {
NdisWanDbgOut(DBG_FAILURE, DBG_SEND, ("IoSendPacket: Invalid Handle: 0x%x, HandleType: 0x%x",
In->hHandle, In->usHandleType));
Status = NDISWAN_ERROR_INVALID_HANDLE;
break;
}
LinkCB = (PLINKCB)BundleCB->LinkCBList.Flink;
//
// LinkCB's lock can be acquired while BundleCB's lock
// is held
//
NdisDprAcquireSpinLock(&LinkCB->Lock);
if (LinkCB->State != LINK_UP) {
NdisWanDbgOut(DBG_FAILURE, DBG_SEND, ("IoSendPacket: Invalid Handle: 0x%x, HandleType: 0x%x",
In->hHandle, In->usHandleType));
Status = NDISWAN_ERROR_INVALID_HANDLE;
NdisDprReleaseSpinLock(&LinkCB->Lock);
LinkCB = NULL;
break;
}
REF_LINKCB(LinkCB);
NdisDprReleaseSpinLock(&LinkCB->Lock);
}
#if 0
if (LinkCB->Stats.FramesTransmitted == 0) {
if (In->PacketData[0] != 0xC0 ||
In->PacketData[1] != 0x21 ||
In->PacketData[2] != 0x01) {
DbgPrint("NDISWAN: IOSP-FirstFrame not LCP ConfigReq bcb %p, lcb %p\n",
BundleCB, LinkCB);
DbgBreakPoint();
}
}
#endif
//
// Queue an Ndis Packet for this send
//
Status =
BuildIoPacket(LinkCB, BundleCB, In, FALSE);
} while ( 0 );
//
// Derefs for the refs applied above
//
DEREF_BUNDLECB_LOCKED(BundleCB);
return (Status);
}
#ifdef NT
NTSTATUS
IoReceivePacket(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
ULONG SizeNeeded = sizeof(NDISWAN_IO_PACKET) + 1500;
PIRP Irp = (PIRP)pInputBuffer;
PIO_STACK_LOCATION IrpSp;
PNDISWAN_IO_PACKET IoPacket;
PRECV_DESC RecvDesc;
KIRQL Irql;
PLINKCB LinkCB;
NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("IoReceivePacket:"));
if (SizeNeeded > ulOutputBufferLength) {
NdisWanDbgOut(DBG_FAILURE, DBG_RECEIVE, ("IoReceivePacket: Buffer to small: Size: %d, SizeNeeded %d",
ulOutputBufferLength, SizeNeeded));
*pulBytesWritten = SizeNeeded;
return(STATUS_INFO_LENGTH_MISMATCH);
}
//
// Do we have any receive's buffered up that
// can be completed?
//
NdisAcquireSpinLock(&IoRecvList.Lock);
RecvDesc = (PRECV_DESC)IoRecvList.DescList.Flink;
while ((PVOID)RecvDesc != (PVOID)&IoRecvList.DescList) {
LinkCB = RecvDesc->LinkCB;
NdisDprAcquireSpinLock(&LinkCB->Lock);
if ((LinkCB->hLinkContext != NULL)) {
break;
}
NdisDprReleaseSpinLock(&LinkCB->Lock);
RecvDesc = (PRECV_DESC)RecvDesc->Linkage.Flink;
}
IoMarkIrpPending(Irp);
if ((PVOID)RecvDesc != (PVOID)&IoRecvList.DescList) {
LONG BufferLength, DataLength, CopySize;
RemoveEntryList(&RecvDesc->Linkage);
IoRecvList.ulDescCount--;
LinkCB->RecvDescCount--;
NdisDprReleaseSpinLock(&LinkCB->Lock);
INSERT_RECV_EVENT('s');
IrpSp = IoGetCurrentIrpStackLocation(Irp);
BufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
DataLength = BufferLength - sizeof(NDISWAN_IO_PACKET) + 1;
CopySize = (RecvDesc->CurrentLength > DataLength) ?
DataLength : RecvDesc->CurrentLength;
IoPacket = Irp->AssociatedIrp.SystemBuffer;
IoPacket->hHandle = LinkCB->hLinkContext;
IoPacket->usHandleType = LINKHANDLE;
IoPacket->usHeaderSize = 14;
IoPacket->usPacketSize = (USHORT)CopySize;
IoPacket->usPacketFlags = 0;
NdisMoveMemory(IoPacket->PacketData,
RecvDesc->CurrentBuffer,
CopySize);
#if DBG
if (gbDumpRecv) {
INT i;
for (i = 0; i < RecvDesc->CurrentLength; i++) {
if (i % 16 == 0) {
DbgPrint("\n");
}
DbgPrint("%x ", RecvDesc->CurrentBuffer[i]);
}
DbgPrint("\n");
}
#endif
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof(NDISWAN_IO_PACKET) - 1 + CopySize;
IoRecvList.LastPacketNumber = IoPacket->PacketNumber;
IoRecvList.LastIrp = Irp;
IoRecvList.LastIrpStatus = STATUS_SUCCESS;
IoRecvList.LastCopySize = (ULONG)Irp->IoStatus.Information;
ASSERT((LONG_PTR)Irp->IoStatus.Information > 0);
NdisReleaseSpinLock(&IoRecvList.Lock);
IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
NdisWanFreeRecvDesc(RecvDesc);
} else {
//
// We did not have anything buffered so lets queue
//
//
// The IRP was pended so setup a cancel routine and let the
// i/o subsystem know about the pend.
//
//
// Setup the structure
//
InsertTailList(&IoRecvList.IrpList, &(Irp->Tail.Overlay.ListEntry));
IoRecvList.ulIrpCount++;
IoSetCancelRoutine(Irp, NdisWanCancelRoutine);
INSERT_RECV_EVENT('i');
NdisReleaseSpinLock(&IoRecvList.Lock);
}
return (NDIS_STATUS_PENDING);
}
VOID
IoRecvIrpWorker(
PKDPC Dpc,
PVOID Context,
PVOID Arg1,
PVOID Arg2
)
{
PLIST_ENTRY Entry;
PNDISWAN_IO_PACKET IoPacket;
PIO_STACK_LOCATION IrpSp;
PIRP Irp;
PRECV_DESC RecvDesc;
KIRQL Irql;
LONG BufferLength, DataLength, CopySize;
PLINKCB LinkCB;
PBUNDLECB BundleCB;
NdisAcquireSpinLock(&IoRecvList.Lock);
do {
IoRecvList.TimerScheduled = FALSE;
//
// Do we have any irps that we can complete?
//
if (IoRecvList.ulIrpCount == 0) {
break;
}
//
// Do we have any receive's buffered up?
//
RecvDesc = (PRECV_DESC)IoRecvList.DescList.Flink;
while ((PVOID)RecvDesc != (PVOID)&IoRecvList.DescList) {
LinkCB = RecvDesc->LinkCB;
NdisDprAcquireSpinLock(&LinkCB->Lock);
if (LinkCB->hLinkContext != NULL) {
break;
}
NdisDprReleaseSpinLock(&LinkCB->Lock);
RecvDesc = (PRECV_DESC)RecvDesc->Linkage.Flink;
}
if ((PVOID)RecvDesc == (PVOID)&IoRecvList.DescList) {
if (!IoRecvList.TimerScheduled) {
WAN_TIME TimeOut;
IoRecvList.TimerScheduled = TRUE;
NdisWanInitWanTime(&TimeOut, 15);
KeSetTimer(&IoRecvList.Timer,
TimeOut,
&IoRecvList.Dpc);
}
break;
}
Entry = IoRecvList.IrpList.Flink;
Irp = CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry);
if (!IoSetCancelRoutine(Irp, NULL)) {
break;
}
//
// Get the recvdesc
//
RemoveEntryList(&RecvDesc->Linkage);
IoRecvList.ulDescCount--;
LinkCB->RecvDescCount--;
RemoveHeadList(&IoRecvList.IrpList);
IoRecvList.ulIrpCount--;
INSERT_RECV_EVENT('w');
IrpSp = IoGetCurrentIrpStackLocation(Irp);
BufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
DataLength = BufferLength - sizeof(NDISWAN_IO_PACKET);
CopySize = (RecvDesc->CurrentLength > DataLength) ?
DataLength : RecvDesc->CurrentLength;
IoPacket = Irp->AssociatedIrp.SystemBuffer;
IoPacket->hHandle = LinkCB->hLinkContext;
IoPacket->usHandleType = LINKHANDLE;
IoPacket->usHeaderSize = 14;
IoPacket->usPacketSize = (USHORT)CopySize;
IoPacket->usPacketFlags = 0;
NdisDprReleaseSpinLock(&LinkCB->Lock);
NdisReleaseSpinLock(&IoRecvList.Lock);
#if DBG
if (gbDumpRecv) {
INT i;
for (i = 0; i < RecvDesc->CurrentLength; i++) {
if (i % 16 == 0) {
DbgPrint("\n");
}
DbgPrint("%x ", RecvDesc->CurrentBuffer[i]);
}
DbgPrint("\n");
}
#endif
NdisMoveMemory(IoPacket->PacketData,
RecvDesc->CurrentBuffer,
CopySize);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof(NDISWAN_IO_PACKET) - 1 + CopySize;
IoRecvList.LastPacketNumber = IoPacket->PacketNumber;
IoRecvList.LastIrp = Irp;
IoRecvList.LastIrpStatus = STATUS_SUCCESS;
IoRecvList.LastCopySize = (ULONG)Irp->IoStatus.Information;
ASSERT((LONG_PTR)Irp->IoStatus.Information > 0);
IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
NdisWanFreeRecvDesc(RecvDesc);
NdisAcquireSpinLock(&IoRecvList.Lock);
} while (FALSE);
NdisReleaseSpinLock(&IoRecvList.Lock);
}
#endif
NTSTATUS
FlushReceivePacket(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("FlushReceivePacket:"));
*pulBytesWritten = 0;
CancelIoReceivePackets();
return (STATUS_SUCCESS);
}
NTSTATUS
GetStatistics(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG SizeNeeded = sizeof(NDISWAN_GET_STATS);
PNDISWAN_GET_STATS In = (PNDISWAN_GET_STATS)pInputBuffer;
PNDISWAN_GET_STATS Out = (PNDISWAN_GET_STATS)pOutputBuffer;
PBUNDLECB BundleCB = NULL;
PLINKCB LinkCB = NULL;
NdisWanDbgOut(DBG_VERBOSE, DBG_IO, ("GetStatistics:"));
*pulBytesWritten = SizeNeeded;
do {
if (ulOutputBufferLength < SizeNeeded) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetStatistics: Buffer to small: Size: %d, SizeNeeded %d",
ulOutputBufferLength, SizeNeeded));
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
NdisZeroMemory(&Out->Stats, sizeof(Out->Stats));
if (In->usHandleType == LINKHANDLE) {
//
// Looking for link stats
//
if (!AreLinkAndBundleValid(In->hHandle,
FALSE,
&LinkCB,
&BundleCB)) {
NdisWanDbgOut(DBG_INFO, DBG_IO, ("GetStatistics: Invalid LinkHandle: 0x%x",
In->hHandle));
Status = NDISWAN_ERROR_INVALID_HANDLE;
break;
}
AcquireBundleLock(BundleCB);
//
// At this point we have a valid bundlecb and linkcb
//
//
// Copy the stats over
//
NdisMoveMemory((PUCHAR)&Out->Stats.LinkStats,
(PUCHAR)&LinkCB->Stats,
sizeof(WAN_STATS));
//
// Copy the stats over
//
NdisMoveMemory((PUCHAR)&Out->Stats.BundleStats,
(PUCHAR)&BundleCB->Stats,
sizeof(WAN_STATS));
} else if (In->usHandleType == BUNDLEHANDLE) {
//
// Looking for bundle stats
//
if (!IsBundleValid(In->hHandle,
FALSE,
&BundleCB)) {
NdisWanDbgOut(DBG_INFO, DBG_IO, ("GetStatistics: Invalid BundleHandle: 0x%x",
In->hHandle));
Status = NDISWAN_ERROR_INVALID_HANDLE;
break;
}
AcquireBundleLock(BundleCB);
//
// At this point we have a valid bundlecb
//
//
// Copy the stats over
//
NdisMoveMemory((PUCHAR)&Out->Stats.BundleStats,
(PUCHAR)&BundleCB->Stats,
sizeof(WAN_STATS));
} else {
Status = NDISWAN_ERROR_INVALID_HANDLE_TYPE;
break;
}
//
// If we only have one protocol bound see if
// it is keeping stats
//
if (BundleCB->ulNumberOfRoutes == 1) {
PPROTOCOLCB ProtocolCB;
PMINIPORTCB MiniportCB;
ProtocolCB =
(PPROTOCOLCB)BundleCB->ProtocolCBList.Flink;
MiniportCB = ProtocolCB->MiniportCB;
if (MiniportCB->Flags & PROTOCOL_KEEPS_STATS) {
NDIS_WAN_GET_STATS WanStats;
ReleaseBundleLock(BundleCB);
NdisZeroMemory(&WanStats, sizeof(NDIS_WAN_GET_STATS));
ETH_COPY_NETWORK_ADDRESS(WanStats.LocalAddress, ProtocolCB->TransportAddress);
NdisMoveMemory((PUCHAR)&WanStats.BytesSent,
(PUCHAR)&Out->Stats.BundleStats,
sizeof(WAN_STATS));
NdisMIndicateStatus(MiniportCB->MiniportHandle,
NDIS_STATUS_WAN_GET_STATS,
&WanStats,
sizeof(NDIS_WAN_GET_STATS));
NdisMoveMemory((PUCHAR)&Out->Stats.LinkStats,
(PUCHAR)&WanStats.BytesSent,
sizeof(WAN_STATS));
NdisMoveMemory((PUCHAR)&Out->Stats.BundleStats,
(PUCHAR)&WanStats.BytesSent,
sizeof(WAN_STATS));
AcquireBundleLock(BundleCB);
}
}
} while ( 0 );
//
// Derefs for the refs applied above
//
DEREF_BUNDLECB_LOCKED(BundleCB);
DEREF_LINKCB(LinkCB);
return (Status);
}
NTSTATUS
SetLinkInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG SizeNeeded = sizeof(NDISWAN_SET_LINK_INFO);
WAN_REQUEST WanRequest;
PNDISWAN_SET_LINK_INFO In = (PNDISWAN_SET_LINK_INFO)pInputBuffer;
PWAN_LINK_INFO LinkInfo;
POPENCB OpenCB;
PLINKCB TempLinkCB,LinkCB = NULL;
PBUNDLECB BundleCB = NULL;
BOOLEAN MediaBroadband = FALSE;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("SetLinkInfo:"));
*pulBytesWritten = 0;
do {
if (ulInputBufferLength < SizeNeeded) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("SetLinkInfo: Buffer to small: Size: %d, SizeNeeded %d",
ulInputBufferLength, SizeNeeded));
*pulBytesWritten = SizeNeeded;
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
if (!AreLinkAndBundleValid(In->hLinkHandle,
TRUE,
&LinkCB,
&BundleCB)) {
Status = NDISWAN_ERROR_INVALID_HANDLE;
break;
}
LinkInfo = &LinkCB->LinkInfo;
OpenCB = LinkCB->OpenCB;
if (OpenCB->MediumType == NdisMediumAtm ||
(OpenCB->MediumType == NdisMediumWan &&
(OpenCB->MediumSubType == NdisWanMediumAtm ||
OpenCB->MediumSubType == NdisWanMediumPppoe)) ||
(OpenCB->MediumType == NdisMediumCoWan &&
(OpenCB->MediumSubType == NdisWanMediumAtm ||
OpenCB->MediumSubType == NdisWanMediumPppoe))) {
MediaBroadband = TRUE;
}
//
// Wait for initialization to complete
//
NdisWanWaitForNotificationEvent(&OpenCB->InitEvent);
WanRequest.Type = SYNC;
WanRequest.Origin = NDISWAN;
NdisWanInitializeNotificationEvent(&WanRequest.NotificationEvent);
WanRequest.OpenCB = OpenCB;
if (OpenCB->Flags & OPEN_LEGACY) {
NDIS_WAN_SET_LINK_INFO WanMiniportLinkInfo;
NdisZeroMemory(&WanMiniportLinkInfo, sizeof (NDIS_WAN_SET_LINK_INFO));
//
// Copy into buffer to be sent to WAN Miniport this
// skips over the LinkHandle in the NDIS_WAN_SET_LINK_INFO
// structure.
//
WanMiniportLinkInfo.NdisLinkHandle = LinkCB->NdisLinkHandle;
WanMiniportLinkInfo.MaxSendFrameSize = In->LinkInfo.MaxSendFrameSize;
WanMiniportLinkInfo.MaxRecvFrameSize = In->LinkInfo.MaxRecvFrameSize;
WanMiniportLinkInfo.SendFramingBits = In->LinkInfo.SendFramingBits;
WanMiniportLinkInfo.RecvFramingBits = In->LinkInfo.RecvFramingBits;
WanMiniportLinkInfo.SendCompressionBits = In->LinkInfo.SendCompressionBits;
WanMiniportLinkInfo.RecvCompressionBits = In->LinkInfo.RecvCompressionBits;
WanMiniportLinkInfo.SendACCM = In->LinkInfo.SendACCM;
WanMiniportLinkInfo.RecvACCM = In->LinkInfo.RecvACCM;
//
// Submit this to the WAN Miniport
//
WanRequest.NdisRequest.RequestType =
NdisRequestSetInformation;
WanRequest.NdisRequest.DATA.QUERY_INFORMATION.Oid =
OID_WAN_SET_LINK_INFO;
WanRequest.NdisRequest.DATA.QUERY_INFORMATION.InformationBuffer =
&WanMiniportLinkInfo;
WanRequest.NdisRequest.DATA.QUERY_INFORMATION.InformationBufferLength =
sizeof(NDIS_WAN_SET_LINK_INFO);
NdisWanSubmitNdisRequest(OpenCB, &WanRequest);
} else {
NDIS_WAN_CO_SET_LINK_INFO WanMiniportLinkInfo;
NdisAcquireSpinLock(&LinkCB->Lock);
if (LinkCB->ClCallState == CL_CALL_CONNECTED) {
//
// Ref so that we don't allow the
// vc to go away.
//
LinkCB->VcRefCount++;
NdisReleaseSpinLock(&LinkCB->Lock);
NdisZeroMemory(&WanMiniportLinkInfo, sizeof (NDIS_WAN_CO_SET_LINK_INFO));
//
// Copy into buffer to be sent to WAN Miniport this
// skips over the LinkHandle in the NDIS_WAN_SET_LINK_INFO
// structure.
//
WanMiniportLinkInfo.MaxSendFrameSize = In->LinkInfo.MaxSendFrameSize;
WanMiniportLinkInfo.MaxRecvFrameSize = In->LinkInfo.MaxRecvFrameSize;
WanMiniportLinkInfo.SendFramingBits = In->LinkInfo.SendFramingBits;
WanMiniportLinkInfo.RecvFramingBits = In->LinkInfo.RecvFramingBits;
WanMiniportLinkInfo.SendCompressionBits = In->LinkInfo.SendCompressionBits;
WanMiniportLinkInfo.RecvCompressionBits = In->LinkInfo.RecvCompressionBits;
WanMiniportLinkInfo.SendACCM = In->LinkInfo.SendACCM;
WanMiniportLinkInfo.RecvACCM = In->LinkInfo.RecvACCM;
//
// Submit this to the WAN Miniport
//
WanRequest.NdisRequest.RequestType =
NdisRequestSetInformation;
WanRequest.NdisRequest.DATA.QUERY_INFORMATION.Oid =
OID_WAN_CO_SET_LINK_INFO;
WanRequest.NdisRequest.DATA.QUERY_INFORMATION.InformationBuffer =
&WanMiniportLinkInfo;
WanRequest.NdisRequest.DATA.QUERY_INFORMATION.InformationBufferLength =
sizeof(NDIS_WAN_CO_SET_LINK_INFO);
WanRequest.AfHandle = NULL;
WanRequest.VcHandle = LinkCB->NdisLinkHandle;
NdisWanSubmitNdisRequest(OpenCB, &WanRequest);
NdisAcquireSpinLock(&LinkCB->Lock);
DerefVc(LinkCB);
NdisReleaseSpinLock(&LinkCB->Lock);
} else {
NdisReleaseSpinLock(&LinkCB->Lock);
}
}
//
// Copy info into our linkcb
//
AcquireBundleLock(BundleCB);
ASSERT(In->LinkInfo.SendFramingBits != 0);
ASSERT(In->LinkInfo.RecvFramingBits != 0);
//
// If we are using broadband the we must preserve the LLC and
// ADDRESS_CONTROL framing bits.
//
if (MediaBroadband) {
LinkInfo->SendFramingBits |= In->LinkInfo.SendFramingBits;
LinkInfo->RecvFramingBits |= In->LinkInfo.RecvFramingBits;
} else {
LinkInfo->SendFramingBits = In->LinkInfo.SendFramingBits;
LinkInfo->RecvFramingBits = In->LinkInfo.RecvFramingBits;
}
LinkCB->SFlowSpec.MaxSduSize =
LinkInfo->MaxSendFrameSize = In->LinkInfo.MaxSendFrameSize;
if (OpenCB->WanInfo.MaxFrameSize < LinkCB->SFlowSpec.MaxSduSize) {
LinkCB->SFlowSpec.MaxSduSize = OpenCB->WanInfo.MaxFrameSize;
}
LinkCB->RFlowSpec.MaxSduSize =
LinkInfo->MaxRecvFrameSize = In->LinkInfo.MaxRecvFrameSize;
LinkInfo->SendCompressionBits = In->LinkInfo.SendCompressionBits;
LinkInfo->RecvCompressionBits = In->LinkInfo.RecvCompressionBits;
LinkInfo->SendACCM = In->LinkInfo.SendACCM;
LinkInfo->RecvACCM = In->LinkInfo.RecvACCM;
LinkInfo->MaxRRecvFrameSize = In->LinkInfo.MaxRRecvFrameSize;
LinkInfo->MaxRSendFrameSize = In->LinkInfo.MaxRSendFrameSize;
if (LinkInfo->RecvFramingBits & LLC_ENCAPSULATION) {
LinkCB->RecvHandler = ReceiveLLC;
} else if (LinkInfo->RecvFramingBits & PPP_FRAMING) {
LinkCB->RecvHandler = ReceivePPP;
} else if (LinkInfo->RecvFramingBits & RAS_FRAMING) {
LinkCB->RecvHandler = ReceiveRAS;
} else if (LinkInfo->RecvFramingBits & SLIP_FRAMING) {
LinkCB->RecvHandler = ReceiveSLIP;
} else if (LinkInfo->RecvFramingBits & (ARAP_V1_FRAMING | ARAP_V2_FRAMING)) {
LinkCB->RecvHandler = ReceiveARAP;
} else {
if (MediaBroadband) {
LinkCB->RecvHandler = DetectBroadbandFraming;
} else {
LinkCB->RecvHandler = DetectFraming;
}
}
//
// We need to set our bundle framing based on the framing for
// each link in the bundle so we will walk the linkcb list
// and | in each link's framing bits into the bundle.
//
//
BundleCB->FramingInfo.SendFramingBits = 0;
BundleCB->FramingInfo.RecvFramingBits = 0;
for (TempLinkCB = (PLINKCB)BundleCB->LinkCBList.Flink;
(PVOID)TempLinkCB != (PVOID)&BundleCB->LinkCBList;
TempLinkCB = (PLINKCB)TempLinkCB->Linkage.Flink) {
BundleCB->FramingInfo.SendFramingBits |= TempLinkCB->LinkInfo.SendFramingBits;
BundleCB->FramingInfo.RecvFramingBits |= TempLinkCB->LinkInfo.RecvFramingBits;
}
BundleCB->FramingInfo.MaxRSendFrameSize = LinkInfo->MaxRSendFrameSize;
//
// Since I use the receive frame size for memory allocation.
//
BundleCB->FramingInfo.MaxRRecvFrameSize = (LinkInfo->MaxRRecvFrameSize) ?
LinkInfo->MaxRRecvFrameSize : glMRRU;
//
// If VJ header compression has been negotiated allocate
// and initialize resources.
//
if (BundleCB->FramingInfo.SendFramingBits & SLIP_VJ_COMPRESSION ||
BundleCB->FramingInfo.SendFramingBits & SLIP_VJ_AUTODETECT ||
BundleCB->FramingInfo.RecvFramingBits & SLIP_VJ_COMPRESSION ||
BundleCB->FramingInfo.RecvFramingBits & SLIP_VJ_AUTODETECT) {
Status = sl_compress_init(&BundleCB->VJCompress, MAX_VJ_STATES);
if (Status != NDIS_STATUS_SUCCESS) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("Error allocating VJ Info!"));
}
}
//
// Configure multilink variables if needed
//
if (BundleCB->FramingInfo.SendFramingBits & PPP_MULTILINK_FRAMING) {
if (BundleCB->FramingInfo.SendFramingBits & PPP_SHORT_SEQUENCE_HDR_FORMAT) {
BundleCB->SendSeqMask = SHORT_SEQ_MASK;
BundleCB->SendSeqTest = TEST_SHORT_SEQ;
} else {
BundleCB->SendSeqMask = LONG_SEQ_MASK;
BundleCB->SendSeqTest = TEST_LONG_SEQ;
}
}
if (BundleCB->FramingInfo.RecvFramingBits & PPP_MULTILINK_FRAMING) {
if (BundleCB->FramingInfo.RecvFramingBits & PPP_SHORT_SEQUENCE_HDR_FORMAT) {
BundleCB->RecvSeqMask = SHORT_SEQ_MASK;
BundleCB->RecvSeqTest = TEST_SHORT_SEQ;
} else {
BundleCB->RecvSeqMask = LONG_SEQ_MASK;
BundleCB->RecvSeqTest = TEST_LONG_SEQ;
}
}
SetBundleFlags(BundleCB);
UpdateBundleInfo(BundleCB);
} while ( 0 );
//
// Derefs for the refs applied by AreLinkAndBundleValid
//
DEREF_BUNDLECB_LOCKED(BundleCB);
DEREF_LINKCB(LinkCB);
return (Status);
}
NTSTATUS
GetLinkInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG SizeNeeded = sizeof(NDISWAN_GET_LINK_INFO);
PNDISWAN_GET_LINK_INFO In = (PNDISWAN_GET_LINK_INFO)pInputBuffer;
PNDISWAN_GET_LINK_INFO Out = (PNDISWAN_GET_LINK_INFO)pOutputBuffer;
PLINKCB LinkCB = NULL;
PWAN_LINK_INFO LinkInfo;
POPENCB OpenCB;
WAN_REQUEST WanRequest;
union {
NDIS_WAN_GET_LINK_INFO Mp;
NDIS_WAN_CO_GET_LINK_INFO Co;
} WanMiniportLinkInfo;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("GetLinkInfo:"));
*pulBytesWritten = SizeNeeded;
do {
if (ulOutputBufferLength < SizeNeeded) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetLinkInfo: Buffer to small: Size: %d, SizeNeeded %d",
ulOutputBufferLength, SizeNeeded));
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
if (!IsLinkValid(In->hLinkHandle,
TRUE,
&LinkCB)) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetLinkInfo: Invalid LinkHandle: 0x%x",
In->hLinkHandle));
Status = NDISWAN_ERROR_INVALID_HANDLE;
break;
}
LinkInfo = &LinkCB->LinkInfo;
OpenCB = LinkCB->OpenCB;
WanRequest.Type = SYNC;
WanRequest.Origin = NDISWAN;
NdisWanInitializeNotificationEvent(&WanRequest.NotificationEvent);
WanRequest.OpenCB = OpenCB;
NdisZeroMemory(&WanMiniportLinkInfo,
sizeof (WanMiniportLinkInfo));
if (OpenCB->Flags & OPEN_LEGACY) {
//
// Setup the link context for this request
//
WanMiniportLinkInfo.Mp.NdisLinkHandle =
LinkCB->NdisLinkHandle;
//
// Submit this to the WAN Miniport
//
WanRequest.NdisRequest.RequestType =
NdisRequestQueryInformation;
WanRequest.NdisRequest.DATA.QUERY_INFORMATION.Oid =
OID_WAN_GET_LINK_INFO;
WanRequest.NdisRequest.DATA.QUERY_INFORMATION.InformationBuffer =
&WanMiniportLinkInfo.Mp;
WanRequest.NdisRequest.DATA.QUERY_INFORMATION.InformationBufferLength =
sizeof(NDIS_WAN_GET_LINK_INFO);
Status = NdisWanSubmitNdisRequest(OpenCB, &WanRequest);
if (Status == NDIS_STATUS_SUCCESS) {
LinkInfo->MaxSendFrameSize =
WanMiniportLinkInfo.Mp.MaxSendFrameSize;
LinkInfo->MaxRecvFrameSize =
WanMiniportLinkInfo.Mp.MaxRecvFrameSize;
LinkInfo->SendFramingBits =
WanMiniportLinkInfo.Mp.SendFramingBits;
LinkInfo->RecvFramingBits =
WanMiniportLinkInfo.Mp.RecvFramingBits;
LinkInfo->SendCompressionBits =
WanMiniportLinkInfo.Mp.SendCompressionBits;
LinkInfo->RecvCompressionBits =
WanMiniportLinkInfo.Mp.RecvCompressionBits;
LinkInfo->SendACCM =
WanMiniportLinkInfo.Mp.SendACCM;
LinkInfo->RecvACCM =
WanMiniportLinkInfo.Mp.RecvACCM;
}
} else {
NdisAcquireSpinLock(&LinkCB->Lock);
if (LinkCB->ClCallState == CL_CALL_CONNECTED) {
//
// Ref so that we don't allow the
// vc to go away.
//
LinkCB->VcRefCount++;
NdisReleaseSpinLock(&LinkCB->Lock);
//
// Submit this to the WAN Miniport
//
WanRequest.NdisRequest.RequestType =
NdisRequestQueryInformation;
WanRequest.NdisRequest.DATA.QUERY_INFORMATION.Oid =
OID_WAN_CO_GET_LINK_INFO;
WanRequest.NdisRequest.DATA.QUERY_INFORMATION.InformationBuffer =
&WanMiniportLinkInfo.Co;
WanRequest.NdisRequest.DATA.QUERY_INFORMATION.InformationBufferLength =
sizeof(NDIS_WAN_CO_GET_LINK_INFO);
WanRequest.AfHandle = NULL;
WanRequest.VcHandle = LinkCB->NdisLinkHandle;
Status = NdisWanSubmitNdisRequest(OpenCB, &WanRequest);
NdisAcquireSpinLock(&LinkCB->Lock);
DerefVc(LinkCB);
NdisReleaseSpinLock(&LinkCB->Lock);
if (Status == NDIS_STATUS_SUCCESS) {
LinkInfo->MaxSendFrameSize =
WanMiniportLinkInfo.Co.MaxSendFrameSize;
LinkInfo->MaxRecvFrameSize =
WanMiniportLinkInfo.Co.MaxRecvFrameSize;
LinkInfo->SendFramingBits =
WanMiniportLinkInfo.Co.SendFramingBits;
LinkInfo->RecvFramingBits =
WanMiniportLinkInfo.Co.RecvFramingBits;
LinkInfo->SendCompressionBits =
WanMiniportLinkInfo.Co.SendCompressionBits;
LinkInfo->RecvCompressionBits =
WanMiniportLinkInfo.Co.RecvCompressionBits;
LinkInfo->SendACCM =
WanMiniportLinkInfo.Co.SendACCM;
LinkInfo->RecvACCM =
WanMiniportLinkInfo.Co.RecvACCM;
}
} else {
NdisReleaseSpinLock(&LinkCB->Lock);
}
}
Status = NDIS_STATUS_SUCCESS;
//
// Fill Recv and Send MRRU
//
LinkInfo->MaxRSendFrameSize = glMaxMTU;
LinkInfo->MaxRRecvFrameSize = glMRRU;
NdisMoveMemory(&Out->LinkInfo,
LinkInfo,
sizeof(WAN_LINK_INFO));
Out->hLinkHandle = LinkCB->hLinkHandle;
} while ( 0 );
//
// Deref for ref applied by IsLinkValid
//
DEREF_LINKCB(LinkCB);
return (Status);
}
NTSTATUS
SetCompressionInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG SizeNeeded = sizeof(NDISWAN_SET_COMPRESSION_INFO);
PNDISWAN_SET_COMPRESSION_INFO In = (PNDISWAN_SET_COMPRESSION_INFO)pInputBuffer;
PLINKCB LinkCB = NULL;
PBUNDLECB BundleCB = NULL;
POPENCB OpenCB;
WAN_REQUEST WanRequest;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("SetCompressionInfo:"));
*pulBytesWritten = 0;
do {
if (ulInputBufferLength < SizeNeeded) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("SetCompressionInfo: Buffer to small: Size: %d, SizeNeeded %d",
ulInputBufferLength, SizeNeeded));
*pulBytesWritten = SizeNeeded;
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
if (!AreLinkAndBundleValid(In->hLinkHandle,
TRUE,
&LinkCB,
&BundleCB)) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("SetCompressionInfo: Invalid LinkHandle: 0x%x",
In->hLinkHandle));
Status = NDISWAN_ERROR_INVALID_HANDLE;
break;
}
OpenCB = LinkCB->OpenCB;
#ifdef DEBUG_CCP
{
PCOMPRESS_INFO CompInfo;
PUCHAR Key;
CompInfo = &In->SendCapabilities;
DbgPrint("==>NdisWan: Set Send CompressInfo\n");
DbgPrint("MSCompType: %x\n", CompInfo->MSCompType);
DbgPrint("AuthType: %x\n", CompInfo->AuthType);
DbgPrint("Flags: %x\n", CompInfo->Flags);
CompInfo = &In->RecvCapabilities;
DbgPrint("==>NdisWan: Set Recv CompressInfo\n");
DbgPrint("MSCompType: %x\n", CompInfo->MSCompType);
DbgPrint("AuthType: %x\n", CompInfo->AuthType);
DbgPrint("Flags: %x\n", CompInfo->Flags);
}
#endif
AcquireBundleLock(BundleCB);
BundleCB->SendCompInfo.Flags =
In->SendCapabilities.Flags;
BundleCB->RecvCompInfo.Flags =
In->RecvCapabilities.Flags;
if (In->SendCapabilities.Flags & CCP_SET_KEYS) {
BundleCB->SendCompInfo.AuthType =
In->SendCapabilities.AuthType;
NdisMoveMemory(&BundleCB->SendCompInfo.LMSessionKey,
&In->SendCapabilities.LMSessionKey,
sizeof(BundleCB->SendCompInfo.LMSessionKey));
NdisMoveMemory(&BundleCB->SendCompInfo.UserSessionKey,
&In->SendCapabilities.UserSessionKey,
sizeof(BundleCB->SendCompInfo.UserSessionKey));
NdisMoveMemory(&BundleCB->SendCompInfo.Challenge,
&In->SendCapabilities.Challenge,
sizeof(BundleCB->SendCompInfo.Challenge));
NdisMoveMemory(&BundleCB->SendCompInfo.NTResponse,
&In->SendCapabilities.NTResponse,
sizeof(BundleCB->SendCompInfo.NTResponse));
#ifdef EAP_ON
NdisMoveMemory(&BundleCB->SendCompInfo.EapKey,
&In->SendCapabilities.EapKey,
sizeof(BundleCB->SendCompInfo.EapKey));
#endif
#ifdef DEBUG_CCP
{
PCOMPRESS_INFO CompInfo;
PUCHAR Key;
CompInfo = &BundleCB->SendCompInfo;
Key = CompInfo->LMSessionKey;
DbgPrint("Send KeyInfo\n");
DbgPrint("LMSession Key: %.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x\n",
Key[0],Key[1],Key[2],Key[3],
Key[4],Key[5],Key[6],Key[7]);
Key = CompInfo->UserSessionKey;
DbgPrint("UserSession Key: %.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x\n",
Key[0],Key[1],Key[2],Key[3],
Key[4],Key[5],Key[6],Key[7],
Key[8],Key[9],Key[10],Key[11],
Key[12],Key[13],Key[14],Key[15]);
Key = CompInfo->Challenge;
DbgPrint("Challenge: %.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x\n",
Key[0],Key[1],Key[2],Key[3],
Key[4],Key[5],Key[6],Key[7]);
Key = CompInfo->NTResponse;
DbgPrint("NTResponse: %.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x\n",
Key[0],Key[1],Key[2],Key[3],
Key[4],Key[5],Key[6],Key[7],
Key[8],Key[9],Key[10],Key[11],
Key[12],Key[13],Key[14],Key[15]);
DbgPrint(" %.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x\n",
Key[16],Key[17],Key[18],Key[19],
Key[20],Key[21],Key[22],Key[23]);
#ifdef EAP_ON
{
ULONG KeyLength, i;
Key = CompInfo->EapKey;
KeyLength = sizeof(CompInfo->EapKey);
i = 0;
DbgPrint("Eap Key:\n");
while (i <= KeyLength-16) {
DbgPrint("%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x\n",
Key[i],Key[i+1],Key[i+2],Key[i+3],
Key[i+4],Key[i+5],Key[i+6],Key[i+7],
Key[i+8],Key[i+9],Key[i+10],Key[i+11],
Key[i+12],Key[i+13],Key[i+14],Key[i+15]);
i += 16;
}
}
#endif
}
#endif
}
if (In->RecvCapabilities.Flags & CCP_SET_KEYS) {
BundleCB->RecvCompInfo.AuthType =
In->RecvCapabilities.AuthType;
NdisMoveMemory(&BundleCB->RecvCompInfo.LMSessionKey,
&In->RecvCapabilities.LMSessionKey,
sizeof(BundleCB->RecvCompInfo.LMSessionKey));
NdisMoveMemory(&BundleCB->RecvCompInfo.UserSessionKey,
&In->RecvCapabilities.UserSessionKey,
sizeof(BundleCB->RecvCompInfo.UserSessionKey));
NdisMoveMemory(&BundleCB->RecvCompInfo.Challenge,
&In->RecvCapabilities.Challenge,
sizeof(BundleCB->RecvCompInfo.Challenge));
NdisMoveMemory(&BundleCB->RecvCompInfo.NTResponse,
&In->RecvCapabilities.NTResponse,
sizeof(BundleCB->RecvCompInfo.NTResponse));
#ifdef EAP_ON
NdisMoveMemory(&BundleCB->RecvCompInfo.EapKey,
&In->RecvCapabilities.EapKey,
sizeof(BundleCB->RecvCompInfo.EapKey));
#endif
#ifdef DEBUG_CCP
{
PCOMPRESS_INFO CompInfo;
PUCHAR Key;
CompInfo = &BundleCB->RecvCompInfo;
Key = CompInfo->LMSessionKey;
DbgPrint("Recv KeyInfo\n");
DbgPrint("LMSession Key: %.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x\n",
Key[0],Key[1],Key[2],Key[3],
Key[4],Key[5],Key[6],Key[7]);
Key = CompInfo->UserSessionKey;
DbgPrint("UserSession Key: %.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x\n",
Key[0],Key[1],Key[2],Key[3],
Key[4],Key[5],Key[6],Key[7],
Key[8],Key[9],Key[10],Key[11],
Key[12],Key[13],Key[14],Key[15]);
Key = CompInfo->Challenge;
DbgPrint("Challenge: %.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x\n",
Key[0],Key[1],Key[2],Key[3],
Key[4],Key[5],Key[6],Key[7]);
Key = CompInfo->NTResponse;
DbgPrint("NTResponse: %.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x\n",
Key[0],Key[1],Key[2],Key[3],
Key[4],Key[5],Key[6],Key[7],
Key[8],Key[9],Key[10],Key[11],
Key[12],Key[13],Key[14],Key[15]);
DbgPrint(" %.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x\n",
Key[16],Key[17],Key[18],Key[19],
Key[20],Key[21],Key[22],Key[23]);
#ifdef EAP_ON
{
ULONG KeyLength, i;
Key = CompInfo->EapKey;
KeyLength = sizeof(CompInfo->EapKey);
i = 0;
DbgPrint("Eap Key:\n");
while (i <= KeyLength-16) {
DbgPrint("%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x\n",
Key[i],Key[i+1],Key[i+2],Key[i+3],
Key[i+4],Key[i+5],Key[i+6],Key[i+7],
Key[i+8],Key[i+9],Key[i+10],Key[i+11],
Key[i+12],Key[i+13],Key[i+14],Key[i+15]);
i += 16;
}
}
#endif
}
#endif
}
do {
if (In->SendCapabilities.Flags & CCP_SET_COMPTYPE) {
BundleCB->SendCompInfo.MSCompType =
In->SendCapabilities.MSCompType;
do {
if (!(BundleCB->Flags & SEND_CCP_ALLOCATED)) {
BundleCB->SCoherencyCounter = 0;
BundleCB->Flags |= SEND_CCP_ALLOCATED;
Status = WanAllocateCCP(BundleCB,
&BundleCB->SendCompInfo,
TRUE);
if (Status != STATUS_SUCCESS) {
break;
}
}
if (!(BundleCB->Flags & SEND_ECP_ALLOCATED)) {
BundleCB->SCoherencyCounter = 0;
BundleCB->Flags |= SEND_ECP_ALLOCATED;
Status = WanAllocateECP(BundleCB,
&BundleCB->SendCompInfo,
&BundleCB->SendCryptoInfo,
TRUE);
if (Status != STATUS_SUCCESS) {
break;
}
}
} while (FALSE);
if (Status != STATUS_SUCCESS) {
break;
}
}
if (In->RecvCapabilities.Flags & CCP_SET_COMPTYPE) {
BundleCB->RecvCompInfo.MSCompType =
In->RecvCapabilities.MSCompType;
do {
if (!(BundleCB->Flags & RECV_CCP_ALLOCATED)) {
BundleCB->RCoherencyCounter = 0;
BundleCB->LastRC4Reset = 0;
BundleCB->CCPIdentifier = 0;
BundleCB->Flags |= RECV_CCP_ALLOCATED;
Status = WanAllocateCCP(BundleCB,
&BundleCB->RecvCompInfo,
FALSE);
if (Status != STATUS_SUCCESS) {
break;
}
}
if (!(BundleCB->Flags & RECV_ECP_ALLOCATED)) {
BundleCB->RCoherencyCounter = 0;
BundleCB->LastRC4Reset = 0;
BundleCB->CCPIdentifier = 0;
BundleCB->Flags |= RECV_ECP_ALLOCATED;
Status = WanAllocateECP(BundleCB,
&BundleCB->RecvCompInfo,
&BundleCB->RecvCryptoInfo,
FALSE);
if (Status != STATUS_SUCCESS) {
break;
}
}
} while (FALSE);
if (Status != STATUS_SUCCESS) {
break;
}
}
} while (FALSE);
if (Status != STATUS_SUCCESS) {
if (BundleCB->Flags & SEND_CCP_ALLOCATED) {
BundleCB->Flags &= ~SEND_CCP_ALLOCATED;
WanDeallocateCCP(BundleCB,
&BundleCB->SendCompInfo,
TRUE);
}
if (BundleCB->Flags & RECV_CCP_ALLOCATED) {
BundleCB->Flags &= ~RECV_CCP_ALLOCATED;
WanDeallocateCCP(BundleCB,
&BundleCB->RecvCompInfo,
FALSE);
}
if (BundleCB->Flags & SEND_ECP_ALLOCATED) {
BundleCB->Flags &= ~SEND_ECP_ALLOCATED;
WanDeallocateECP(BundleCB,
&BundleCB->SendCompInfo,
&BundleCB->SendCryptoInfo);
}
if (BundleCB->Flags & RECV_ECP_ALLOCATED) {
BundleCB->Flags &= ~RECV_ECP_ALLOCATED;
WanDeallocateECP(BundleCB,
&BundleCB->RecvCompInfo,
&BundleCB->RecvCryptoInfo);
}
}
if (In->SendCapabilities.Flags & CCP_PAUSE_DATA) {
BundleCB->Flags |= PAUSE_DATA;
} else {
BundleCB->Flags &= ~PAUSE_DATA;
if (!(BundleCB->Flags & DEFERRED_WORK_QUEUED)) {
//
// Need to kick off sends again!
//
REF_BUNDLECB(BundleCB);
BundleCB->Flags |= DEFERRED_WORK_QUEUED;
InsertTailGlobalListEx(DeferredWorkList,
&BundleCB->DeferredLinkage,
15,
0);
}
}
SetBundleFlags(BundleCB);
} while ( 0 );
//
// Derefs for the refs applied in AreLinkAndBundleValid
//
DEREF_BUNDLECB_LOCKED(BundleCB);
DEREF_LINKCB(LinkCB);
return (Status);
}
NTSTATUS
GetCompressionInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG SizeNeeded = sizeof(NDISWAN_GET_COMPRESSION_INFO);
PNDISWAN_GET_COMPRESSION_INFO In = (PNDISWAN_GET_COMPRESSION_INFO)pInputBuffer;
PNDISWAN_GET_COMPRESSION_INFO Out = (PNDISWAN_GET_COMPRESSION_INFO)pOutputBuffer;
PLINKCB LinkCB = NULL;
PBUNDLECB BundleCB = NULL;
POPENCB OpenCB;
ULONG i;
WAN_REQUEST WanRequest;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("GetCompressionInfo:"));
*pulBytesWritten = SizeNeeded;
do {
if (ulInputBufferLength < SizeNeeded ||
ulOutputBufferLength < SizeNeeded) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetCompressionInfo: Buffer to small: Size: %d, SizeNeeded %d",
ulOutputBufferLength, SizeNeeded));
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
if (!AreLinkAndBundleValid(In->hLinkHandle,
TRUE,
&LinkCB,
&BundleCB)) {
Status = NDISWAN_ERROR_INVALID_HANDLE;
break;
}
OpenCB = LinkCB->OpenCB;
Out->SendCapabilities.CompType = COMPTYPE_NONE;
Out->SendCapabilities.CompLength = 0;
Out->RecvCapabilities.CompType = COMPTYPE_NONE;
Out->RecvCapabilities.CompLength = 0;
AcquireBundleLock(BundleCB);
//
// Fill in the ndiswan specific stuff
//
NdisMoveMemory(Out->SendCapabilities.LMSessionKey,
BundleCB->SendCompInfo.LMSessionKey,
sizeof(Out->SendCapabilities.LMSessionKey));
NdisMoveMemory(Out->SendCapabilities.UserSessionKey,
BundleCB->SendCompInfo.UserSessionKey,
sizeof(Out->SendCapabilities.UserSessionKey));
NdisMoveMemory(Out->SendCapabilities.Challenge,
BundleCB->SendCompInfo.Challenge,
sizeof(Out->SendCapabilities.Challenge));
NdisMoveMemory(Out->SendCapabilities.NTResponse,
BundleCB->SendCompInfo.NTResponse,
sizeof(Out->SendCapabilities.NTResponse));
#ifdef EAP_ON
NdisMoveMemory(Out->SendCapabilities.EapKey,
BundleCB->SendCompInfo.EapKey,
sizeof(Out->SendCapabilities.EapKey));
Out->SendCapabilities.EapKeyLength =
BundleCB->SendCompInfo.EapKeyLength;
#endif
NdisMoveMemory(Out->RecvCapabilities.LMSessionKey,
BundleCB->RecvCompInfo.LMSessionKey,
sizeof(Out->RecvCapabilities.LMSessionKey));
NdisMoveMemory(Out->RecvCapabilities.UserSessionKey,
BundleCB->RecvCompInfo.UserSessionKey,
sizeof(Out->RecvCapabilities.UserSessionKey));
NdisMoveMemory(Out->RecvCapabilities.Challenge,
BundleCB->RecvCompInfo.Challenge,
sizeof(Out->RecvCapabilities.Challenge));
NdisMoveMemory(Out->RecvCapabilities.NTResponse,
BundleCB->RecvCompInfo.NTResponse,
sizeof(Out->RecvCapabilities.NTResponse));
#ifdef EAP_ON
NdisMoveMemory(Out->RecvCapabilities.EapKey,
BundleCB->RecvCompInfo.EapKey,
sizeof(Out->RecvCapabilities.EapKey));
Out->RecvCapabilities.EapKeyLength =
BundleCB->RecvCompInfo.EapKeyLength;
#endif
//
// We will set encryption capabilities based on session key
// availability and auth type being used.
//
// Set send side capabilities
//
Out->SendCapabilities.MSCompType = NDISWAN_COMPRESSION;
if (BundleCB->SendCompInfo.AuthType == AUTH_USE_MSCHAPV1) {
for (i = 0; i < sizeof(Out->SendCapabilities.LMSessionKey); i++) {
if (Out->SendCapabilities.LMSessionKey[i] != 0) {
Out->SendCapabilities.MSCompType |=
(NDISWAN_ENCRYPTION |
NDISWAN_40_ENCRYPTION |
NDISWAN_56_ENCRYPTION);
break;
}
}
#ifdef ENCRYPT_128BIT
for (i = 0; i < sizeof(Out->SendCapabilities.UserSessionKey); i++) {
if (Out->SendCapabilities.UserSessionKey[i] != 0) {
Out->SendCapabilities.MSCompType |=
(NDISWAN_128_ENCRYPTION);
break;
}
}
#endif
} else if (BundleCB->SendCompInfo.AuthType == AUTH_USE_MSCHAPV2) {
for (i = 0; i < sizeof(Out->SendCapabilities.UserSessionKey); i++) {
if (Out->SendCapabilities.UserSessionKey[i] != 0) {
Out->SendCapabilities.MSCompType |=
(NDISWAN_40_ENCRYPTION |
NDISWAN_56_ENCRYPTION);
#ifdef ENCRYPT_128BIT
Out->SendCapabilities.MSCompType |=
(NDISWAN_128_ENCRYPTION);
#endif
break;
}
}
#ifdef EAP_ON
} else if (BundleCB->SendCompInfo.AuthType == AUTH_USE_EAP) {
for (i = 0; i < sizeof(Out->SendCapabilities.EapKey); i++) {
if (Out->SendCapabilities.EapKey[i] != 0) {
Out->SendCapabilities.MSCompType |=
(NDISWAN_40_ENCRYPTION |
NDISWAN_56_ENCRYPTION);
#ifdef ENCRYPT_128BIT
Out->SendCapabilities.MSCompType |=
(NDISWAN_128_ENCRYPTION);
#endif
break;
}
}
#endif
}
// Set send side capabilities
//
Out->RecvCapabilities.MSCompType = NDISWAN_COMPRESSION;
if (BundleCB->RecvCompInfo.AuthType == AUTH_USE_MSCHAPV1) {
for (i = 0; i < sizeof(Out->RecvCapabilities.LMSessionKey); i++) {
if (Out->RecvCapabilities.LMSessionKey[i] != 0) {
Out->RecvCapabilities.MSCompType |=
(NDISWAN_ENCRYPTION |
NDISWAN_40_ENCRYPTION |
NDISWAN_56_ENCRYPTION);
break;
}
}
#ifdef ENCRYPT_128BIT
for (i = 0; i < sizeof(Out->RecvCapabilities.UserSessionKey); i++) {
if (Out->RecvCapabilities.UserSessionKey[i] != 0) {
Out->RecvCapabilities.MSCompType |=
(NDISWAN_128_ENCRYPTION);
break;
}
}
#endif
} else if (BundleCB->RecvCompInfo.AuthType == AUTH_USE_MSCHAPV2) {
for (i = 0; i < sizeof(Out->RecvCapabilities.UserSessionKey); i++) {
if (Out->RecvCapabilities.UserSessionKey[i] != 0) {
Out->RecvCapabilities.MSCompType |=
(NDISWAN_40_ENCRYPTION |
NDISWAN_56_ENCRYPTION);
#ifdef ENCRYPT_128BIT
Out->RecvCapabilities.MSCompType |=
(NDISWAN_128_ENCRYPTION);
#endif
break;
}
}
#ifdef EAP_ON
} else if (BundleCB->RecvCompInfo.AuthType == AUTH_USE_EAP) {
for (i = 0; i < sizeof(Out->RecvCapabilities.EapKey); i++) {
if (Out->RecvCapabilities.EapKey[i] != 0) {
Out->RecvCapabilities.MSCompType |=
(NDISWAN_40_ENCRYPTION |
NDISWAN_56_ENCRYPTION);
#ifdef ENCRYPT_128BIT
Out->RecvCapabilities.MSCompType |=
(NDISWAN_128_ENCRYPTION);
#endif
break;
}
}
#endif
}
if (gbHistoryless &&
(OpenCB->MediumSubType == NdisWanMediumPPTP ||
OpenCB->MediumSubType == NdisWanMediumL2TP)) {
Out->SendCapabilities.MSCompType |= NDISWAN_HISTORY_LESS;
Out->RecvCapabilities.MSCompType |= NDISWAN_HISTORY_LESS;
}
#ifdef DEBUG_CCP
{
PCOMPRESS_INFO CompInfo;
PUCHAR Key;
CompInfo = &Out->SendCapabilities;
DbgPrint("NdisWan: Get Send CompressInfo\n");
DbgPrint("MSCompType: %x\n", CompInfo->MSCompType);
DbgPrint("AuthType: %x\n", CompInfo->AuthType);
DbgPrint("Flags: %x\n", CompInfo->Flags);
Key = CompInfo->LMSessionKey;
DbgPrint("LMSession Key: %.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x\n",
Key[0],Key[1],Key[2],Key[3],
Key[4],Key[5],Key[6],Key[7]);
Key = CompInfo->UserSessionKey;
DbgPrint("UserSession Key: %.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x\n",
Key[0],Key[1],Key[2],Key[3],
Key[4],Key[5],Key[6],Key[7],
Key[8],Key[9],Key[10],Key[11],
Key[12],Key[13],Key[14],Key[15]);
Key = CompInfo->Challenge;
DbgPrint("Challenge: %.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x\n",
Key[0],Key[1],Key[2],Key[3],
Key[4],Key[5],Key[6],Key[7]);
Key = CompInfo->NTResponse;
DbgPrint("NTResponse: %.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x\n",
Key[0],Key[1],Key[2],Key[3],
Key[4],Key[5],Key[6],Key[7],
Key[8],Key[9],Key[10],Key[11],
Key[12],Key[13],Key[14],Key[15]);
DbgPrint(" %.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x\n",
Key[16],Key[17],Key[18],Key[19],
Key[20],Key[21],Key[22],Key[23]);
}
#endif
#ifdef DEBUG_CCP
{
PCOMPRESS_INFO CompInfo;
PUCHAR Key;
CompInfo = &Out->RecvCapabilities;
DbgPrint("NdisWan: Get Receive CompressInfo\n");
DbgPrint("MSCompType: %x\n", CompInfo->MSCompType);
DbgPrint("AuthType: %x\n", CompInfo->AuthType);
DbgPrint("Flags: %x\n", CompInfo->Flags);
Key = CompInfo->LMSessionKey;
DbgPrint("LMSession Key: %.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x\n",
Key[0],Key[1],Key[2],Key[3],
Key[4],Key[5],Key[6],Key[7]);
Key = CompInfo->UserSessionKey;
DbgPrint("UserSession Key: %.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x\n",
Key[0],Key[1],Key[2],Key[3],
Key[4],Key[5],Key[6],Key[7],
Key[8],Key[9],Key[10],Key[11],
Key[12],Key[13],Key[14],Key[15]);
Key = CompInfo->Challenge;
DbgPrint("Challenge: %.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x\n",
Key[0],Key[1],Key[2],Key[3],
Key[4],Key[5],Key[6],Key[7]);
Key = CompInfo->NTResponse;
DbgPrint("NTResponse: %.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x\n",
Key[0],Key[1],Key[2],Key[3],
Key[4],Key[5],Key[6],Key[7],
Key[8],Key[9],Key[10],Key[11],
Key[12],Key[13],Key[14],Key[15]);
DbgPrint(" %.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x\n",
Key[16],Key[17],Key[18],Key[19],
Key[20],Key[21],Key[22],Key[23]);
}
#endif
} while ( 0 );
//
// Derefs for the refs applied in AreLinkAndBundleValid
//
DEREF_BUNDLECB_LOCKED(BundleCB);
DEREF_LINKCB(LinkCB);
return (Status);
}
NTSTATUS
SetVJInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
PLINKCB LinkCB = NULL;
PBUNDLECB BundleCB = NULL;
ULONG SizeNeeded = sizeof(NDISWAN_SET_VJ_INFO);
PNDISWAN_SET_VJ_INFO In = (PNDISWAN_SET_VJ_INFO)pInputBuffer;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("SetVJInfo:"));
*pulBytesWritten = 0;
do {
if (ulInputBufferLength < SizeNeeded) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("SetVJInfo: Buffer to small: Size: %d, SizeNeeded %d",
ulInputBufferLength, SizeNeeded));
*pulBytesWritten = SizeNeeded;
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
if (!AreLinkAndBundleValid(In->hLinkHandle,
TRUE,
&LinkCB,
&BundleCB)) {
Status = NDISWAN_ERROR_INVALID_HANDLE;
break;
}
AcquireBundleLock(BundleCB);
NdisMoveMemory(&BundleCB->RecvVJInfo,
&In->RecvCapabilities,
sizeof(VJ_INFO));
if (In->RecvCapabilities.IPCompressionProtocol == 0x2D) {
if (In->RecvCapabilities.MaxSlotID < MAX_VJ_STATES) {
Status = sl_compress_init(&BundleCB->VJCompress,
(UCHAR)(In->RecvCapabilities.MaxSlotID + 1));
if (Status != NDIS_STATUS_SUCCESS) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("Error allocating VJ Info!"));
}
}
}
NdisMoveMemory(&BundleCB->SendVJInfo,
&In->SendCapabilities,
sizeof(VJ_INFO));
if (In->SendCapabilities.IPCompressionProtocol == 0x2D) {
if (In->SendCapabilities.MaxSlotID < MAX_VJ_STATES) {
Status = sl_compress_init(&BundleCB->VJCompress,
(UCHAR)(In->SendCapabilities.MaxSlotID + 1));
if (Status != NDIS_STATUS_SUCCESS) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("Error allocating VJ Info!"));
}
}
}
SetBundleFlags(BundleCB);
} while ( 0 );
//
// Derefs for the refs applied in AreLinkAndBundleValid
//
DEREF_BUNDLECB_LOCKED(BundleCB);
DEREF_LINKCB(LinkCB);
return (Status);
}
NTSTATUS
GetVJInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
ULONG SizeNeeded = sizeof(NDISWAN_GET_VJ_INFO);
PLINKCB LinkCB = NULL;
POPENCB OpenCB = NULL;
NTSTATUS Status = STATUS_SUCCESS;
PNDISWAN_GET_VJ_INFO In = (PNDISWAN_GET_VJ_INFO)pInputBuffer;
PNDISWAN_GET_VJ_INFO Out = (PNDISWAN_GET_VJ_INFO)pOutputBuffer;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("GetVJInfo:"));
*pulBytesWritten = SizeNeeded;
do {
if (ulOutputBufferLength < SizeNeeded) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetVJInfo: Buffer to small: Size: %d, SizeNeeded %d",
ulOutputBufferLength, SizeNeeded));
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
if (!IsLinkValid(In->hLinkHandle,
TRUE,
&LinkCB)) {
Status = NDISWAN_ERROR_INVALID_HANDLE;
break;
}
OpenCB = LinkCB->OpenCB;
if (OpenCB->MediumSubType == NdisWanMediumPPTP ||
OpenCB->MediumSubType == NdisWanMediumL2TP) {
Out->SendCapabilities.IPCompressionProtocol =
Out->RecvCapabilities.IPCompressionProtocol = 0;
} else {
Out->SendCapabilities.IPCompressionProtocol =
Out->RecvCapabilities.IPCompressionProtocol = 0x2D;
}
Out->SendCapabilities.MaxSlotID =
Out->RecvCapabilities.MaxSlotID = MAX_VJ_STATES - 1;
Out->SendCapabilities.CompSlotID =
Out->RecvCapabilities.CompSlotID = 1;
} while ( 0 );
//
// Deref for ref applied by IsLinkValid
//
DEREF_LINKCB(LinkCB);
return (Status);
}
NTSTATUS
GetBandwidthUtilization(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
ULONG SizeNeeded = sizeof(NDISWAN_GET_BANDWIDTH_UTILIZATION);
PBUNDLECB BundleCB = NULL;
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
PNDISWAN_GET_BANDWIDTH_UTILIZATION In =
(PNDISWAN_GET_BANDWIDTH_UTILIZATION)pInputBuffer;
PNDISWAN_GET_BANDWIDTH_UTILIZATION Out =
(PNDISWAN_GET_BANDWIDTH_UTILIZATION)pOutputBuffer;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("GetBandwidthUtilization: Enter"));
*pulBytesWritten = 0;
if (ulInputBufferLength < sizeof(In->hBundleHandle) ||
ulOutputBufferLength < SizeNeeded) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetBandwidthUtilization: Buffer to small: Size: %d, SizeNeeded %d",
ulOutputBufferLength, SizeNeeded));
*pulBytesWritten = SizeNeeded;
return STATUS_INFO_LENGTH_MISMATCH;
}
if (!IsBundleValid(In->hBundleHandle,
FALSE,
&BundleCB)) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetBandwidthUtilization: Invalid BundleHandle: 0x%x",
In->hBundleHandle));
return NDISWAN_ERROR_INVALID_HANDLE;
}
do {
ULONGLONG MaxByteCount, temp;
AcquireBundleLock(BundleCB);
if(BundleCB->SUpperBonDInfo == NULL ||
BundleCB->RUpperBonDInfo == NULL)
{
Status = NDISWAN_ERROR_INVALID_HANDLE;
break;
}
MaxByteCount = BundleCB->SUpperBonDInfo->ulBytesInSamplePeriod;
temp = 0;
if (MaxByteCount != 0) {
temp = BundleCB->SUpperBonDInfo->SampleTable.ulCurrentSampleByteCount;
temp *= 100;
temp /= MaxByteCount;
}
Out->ulUpperXmitUtil = (ULONG)temp;
MaxByteCount = BundleCB->SLowerBonDInfo->ulBytesInSamplePeriod;
temp = 0;
if (MaxByteCount != 0) {
temp = BundleCB->SLowerBonDInfo->SampleTable.ulCurrentSampleByteCount;
temp *= 100;
temp /= MaxByteCount;
}
Out->ulLowerXmitUtil = (ULONG)temp;
MaxByteCount = BundleCB->RUpperBonDInfo->ulBytesInSamplePeriod;
temp = 0;
if (MaxByteCount != 0) {
temp = BundleCB->RUpperBonDInfo->SampleTable.ulCurrentSampleByteCount;
temp *= 100;
temp /= MaxByteCount;
}
Out->ulUpperRecvUtil = (ULONG)temp;
MaxByteCount = BundleCB->RLowerBonDInfo->ulBytesInSamplePeriod;
temp = 0;
if (MaxByteCount != 0) {
temp = BundleCB->RLowerBonDInfo->SampleTable.ulCurrentSampleByteCount;
temp *= 100;
temp /= MaxByteCount;
}
Out->ulLowerRecvUtil = (ULONG)temp;
*pulBytesWritten = SizeNeeded;
} while (FALSE);
//
// Deref for ref applied by IsBundleValid. This releases
// the BundleCB->Lock.
//
DEREF_BUNDLECB_LOCKED(BundleCB);
return (Status);
}
NTSTATUS
EnumProtocolUtilization(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
ULONG SizeNeeded = sizeof(NDISWAN_ENUM_PROTOCOL_UTILIZATION);
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("EnumProtocolUtilization:"));
*pulBytesWritten = SizeNeeded;
if (ulOutputBufferLength < SizeNeeded) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("EnumProtocolUtilization: Buffer to small: Size: %d, SizeNeeded %d",
ulOutputBufferLength, SizeNeeded));
return(STATUS_INFO_LENGTH_MISMATCH);
}
return (STATUS_NOT_IMPLEMENTED);
}
NTSTATUS
EnumActiveBundles(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
ULONG SizeNeeded = sizeof(NDISWAN_ENUM_ACTIVE_BUNDLES);
PNDISWAN_ENUM_ACTIVE_BUNDLES Out = (PNDISWAN_ENUM_ACTIVE_BUNDLES)pOutputBuffer;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("GetNumActiveBundles:"));
*pulBytesWritten = SizeNeeded;
if (ulOutputBufferLength < SizeNeeded) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetNumActiveBundles: Buffer to small: Size: %d, SizeNeeded %d",
ulOutputBufferLength, SizeNeeded));
return(STATUS_INFO_LENGTH_MISMATCH);
}
//
// Does this information need to be protected by the lock?
// I would hate to have things get slowed for this call!
//
Out->ulNumberOfActiveBundles = ConnectionTable->ulNumActiveBundles;
return (STATUS_SUCCESS);
}
NTSTATUS
GetWanInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
ULONG SizeNeeded = sizeof(NDISWAN_GET_WAN_INFO);
PNDISWAN_GET_WAN_INFO In = (PNDISWAN_GET_WAN_INFO)pInputBuffer;
PNDISWAN_GET_WAN_INFO Out = (PNDISWAN_GET_WAN_INFO)pOutputBuffer;
POPENCB OpenCB;
PLINKCB LinkCB = NULL;
NTSTATUS Status = STATUS_SUCCESS;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("GetWanInfo:"));
*pulBytesWritten = SizeNeeded;
do {
if (ulOutputBufferLength < SizeNeeded) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetWanInfo: Buffer to small: Size: %d, SizeNeeded %d",
ulOutputBufferLength, SizeNeeded));
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
if (!IsLinkValid(In->hLinkHandle,
FALSE,
&LinkCB)) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetWanInfo: Invalid LinkHandle: 0x%x",
In->hLinkHandle));
Status = NDISWAN_ERROR_INVALID_HANDLE;
break;
}
OpenCB = LinkCB->OpenCB;
Out->WanInfo.MaxFrameSize = OpenCB->WanInfo.MaxFrameSize;
Out->WanInfo.MaxTransmit = OpenCB->WanInfo.MaxTransmit;
Out->WanInfo.FramingBits = OpenCB->WanInfo.FramingBits;
Out->WanInfo.DesiredACCM = OpenCB->WanInfo.DesiredACCM;
Out->WanInfo.MaxReconstructedFrameSize = glMRRU;
Out->WanInfo.LinkSpeed = LinkCB->SFlowSpec.PeakBandwidth*8;
} while ( 0 );
//
// Deref for ref applied by IsLinkValid
//
DEREF_LINKCB(LinkCB);
return (Status);
}
NTSTATUS
SetDebugInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
PNDISWAN_SET_DEBUG_INFO pDebugInfo = (PNDISWAN_SET_DEBUG_INFO)pInputBuffer;
ULONG SizeNeeded = sizeof(NDISWAN_SET_DEBUG_INFO);
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("SetDebugInfo: OldLevel: 0x%x OldMask: 0x%x",
glDebugLevel, glDebugMask));
*pulBytesWritten = 0;
if (ulInputBufferLength < SizeNeeded) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("Buffer to small: Size: %d, SizeNeeded %d",
ulInputBufferLength, SizeNeeded));
*pulBytesWritten = SizeNeeded;
return(STATUS_INFO_LENGTH_MISMATCH);
}
glDebugLevel = pDebugInfo->ulDebugLevel;
glDebugMask = pDebugInfo->ulDebugMask;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("SetDebugInfo: NewLevel: 0x%x NewMask: 0x%x",
glDebugLevel, glDebugMask));
return (STATUS_SUCCESS);
}
NTSTATUS
SetEncryptionInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
ULONG SizeNeeded = sizeof(NDISWAN_SET_ENCRYPTION_INFO);
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("SetEncryptionInfo:"));
*pulBytesWritten = 0;
if (ulInputBufferLength < SizeNeeded) {
*pulBytesWritten = SizeNeeded;
return(STATUS_INFO_LENGTH_MISMATCH);
}
return (STATUS_NOT_IMPLEMENTED);
}
NTSTATUS
GetEncryptionInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
ULONG SizeNeeded = sizeof(NDISWAN_GET_ENCRYPTION_INFO);
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("GetEncryptionInfo:"));
*pulBytesWritten = SizeNeeded;
if (ulOutputBufferLength < SizeNeeded) {
return(STATUS_INFO_LENGTH_MISMATCH);
}
return (STATUS_NOT_IMPLEMENTED);
}
NTSTATUS
GetIdleTime(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
ULONG SizeNeeded = sizeof(NDISWAN_GET_IDLE_TIME);
PNDISWAN_GET_IDLE_TIME In = (PNDISWAN_GET_IDLE_TIME)pInputBuffer;
PNDISWAN_GET_IDLE_TIME Out = (PNDISWAN_GET_IDLE_TIME)pOutputBuffer;
PBUNDLECB BundleCB = NULL;
PPROTOCOLCB ProtocolCB = NULL;
WAN_TIME CurrentTime, Diff, OneSecond;
WAN_TIME LastNonIdleData;
NTSTATUS Status = STATUS_SUCCESS;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("GetIdleTime:"));
*pulBytesWritten = SizeNeeded;
do {
if (ulOutputBufferLength < SizeNeeded) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetIdleTime: Buffer to small: Size: %d, SizeNeeded %d",
ulInputBufferLength, SizeNeeded));
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
if (!IsBundleValid(In->hBundleHandle,
FALSE,
&BundleCB)) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetIdleTime: Invalid BundleHandle: 0x%x",
In->hBundleHandle));
Status = NDISWAN_ERROR_INVALID_HANDLE;
break;
}
AcquireBundleLock(BundleCB);
if (BundleCB->Flags & DISABLE_IDLE_DETECT) {
Out->ulSeconds = 0;
break;
}
//
// If this is for the bundle
//
if (In->usProtocolType == BUNDLE_IDLE_TIME) {
LastNonIdleData = BundleCB->LastNonIdleData;
} else {
//
// Find the protocol type
//
for (ProtocolCB = (PPROTOCOLCB)BundleCB->ProtocolCBList.Flink;
(PVOID)ProtocolCB != (PVOID)&BundleCB->ProtocolCBList;
ProtocolCB = (PPROTOCOLCB)ProtocolCB->Linkage.Flink) {
if (ProtocolCB->ProtocolType == In->usProtocolType) {
break;
}
}
if ((PVOID)ProtocolCB == (PVOID)&BundleCB->ProtocolCBList) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetIdleTime: Invalid ProtocolType: 0x%x",
In->usProtocolType));
Status = NDISWAN_ERROR_NO_ROUTE;
break;
}
LastNonIdleData = ProtocolCB->LastNonIdleData;
}
NdisWanGetSystemTime(&CurrentTime);
NdisWanCalcTimeDiff(&Diff, &CurrentTime, &LastNonIdleData);
NdisWanInitWanTime(&OneSecond, ONE_SECOND);
NdisWanDivideWanTime(&CurrentTime, &Diff, &OneSecond);
Out->ulSeconds = CurrentTime.LowPart;
} while ( 0 );
//
// Deref for ref applied by IsBundleValid. This releases the
// BundleCB->Lock.
//
DEREF_BUNDLECB_LOCKED(BundleCB);
return (Status);
}
NTSTATUS
DeactivateRoute(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
DeactivateRoute
Routine Description:
This function unroutes the protocol given by usprotocoltype
from the bundle given by hbundlehandle.
Arguments:
pInputBuffer - Pointer to the input structure that should be NDISWAN_UNROUTE
ulInputBufferLength - Length of input buffer should be sizeof(NDISWAN_UNROUTE)
pOutputBuffer - Pointer to the output structure that should be NDISWAN_UNROUTE
ulOutputBufferLength - Length of output buffer should be sizeof(NDISWAN_UNROUTE)
pulBytesWritten - Then number of bytes written to the output buffer is returned here
Return Values:
NDISWAN_ERROR_ALREADY_ROUTED
NDISWAN_ERROR_INVALID_HANDLE
STATUS_INSUFFICIENT_RESOURCES
STATUS_INFO_LENGTH_MISMATCH
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
PNDISWAN_UNROUTE In = (PNDISWAN_UNROUTE)pInputBuffer;
PNDISWAN_UNROUTE Out = (PNDISWAN_UNROUTE)pOutputBuffer;
ULONG SizeNeeded = sizeof(NDISWAN_UNROUTE);
ULONG AllocationSize, i;
PBUNDLECB BundleCB = NULL;
BOOLEAN RouteExists = FALSE;
BOOLEAN FreeBundle = FALSE;
PPROTOCOLCB ProtocolCB;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("DeactivateRoute:"));
*pulBytesWritten = 0;
do {
if (ulInputBufferLength < SizeNeeded) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("DeactivateRoute: Buffer to small: Size: %d, SizeNeeded %d",
ulInputBufferLength, SizeNeeded));
*pulBytesWritten = SizeNeeded;
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
if (!IsBundleValid(In->hBundleHandle, FALSE, &BundleCB)) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("DeactivateRoute: Invalid BundleHandle: 0x%x, ProtocolType: 0x%x",
In->hBundleHandle, In->usProtocolType));
Status = NDISWAN_ERROR_INVALID_HANDLE;
break;
}
//
// This is a call to unroute
//
AcquireBundleLock(BundleCB);
//
// Find the protocolcb for this route
//
//
for (ProtocolCB = (PPROTOCOLCB)BundleCB->ProtocolCBList.Flink;
(PVOID)ProtocolCB != (PVOID)&BundleCB->ProtocolCBList;
ProtocolCB = (PPROTOCOLCB)ProtocolCB->Linkage.Flink) {
//
// If we already have a route to this protocol type
// flag it as already existing
//
if (ProtocolCB->ProtocolType == In->usProtocolType) {
RouteExists = TRUE;
break;
}
}
if (!RouteExists) {
//
// A route already exists for this protocoltype
//
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("DeactivateRoute: Route does not exist: ProtocolType: 0x%2.2x",
In->usProtocolType));
Status = NDISWAN_ERROR_NOT_ROUTED;
break;
}
//
// If the protocol is already unrouting because
// of a halt on the protocols miniportcb we
// will just get the out!
//
if (ProtocolCB->State == PROTOCOL_UNROUTING) {
break;
}
ProtocolCB->State = PROTOCOL_UNROUTING;
BundleCB->SendMask &= ~ProtocolCB->SendMaskBit;
//
// Flush the protocol packet queues. This could cause us
// to complete frames to ndis out of order. Ndis should
// handle this.
//
FlushProtocolPacketQueue(ProtocolCB);
//
// If we have any outstanding Vc's we need to dispatch
// incoming close calls to them
//
while (!IsListEmpty(&ProtocolCB->VcList)) {
PLIST_ENTRY Entry;
PCM_VCCB CmVcCB;
Entry = RemoveHeadList(&ProtocolCB->VcList);
CmVcCB = (PCM_VCCB)CONTAINING_RECORD(Entry, CM_VCCB, Linkage);
if (CmVcCB->State == CMVC_ACTIVE) {
InterlockedExchange((PLONG)&CmVcCB->State, CMVC_CLOSE_DISPATCHED);
ReleaseBundleLock(BundleCB);
NdisCmDispatchIncomingCloseCall(NDIS_STATUS_SUCCESS,
CmVcCB->NdisVcHandle,
NULL,
0);
AcquireBundleLock(BundleCB);
}
}
DEREF_PROTOCOLCB(ProtocolCB);
ReleaseBundleLock(BundleCB);
NdisWanWaitForSyncEvent(&ProtocolCB->UnrouteEvent);
AcquireBundleLock(BundleCB);
DoLineDownToProtocol(ProtocolCB);
NdisWanFreeProtocolCB(ProtocolCB);
} while ( 0 );
//
// Deref for ref applied by IsBundleValid
//
DEREF_BUNDLECB_LOCKED(BundleCB);
return (Status);
}
NTSTATUS
GetDriverInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG SizeNeeded = sizeof(NDISWAN_DRIVER_INFO);
PNDISWAN_DRIVER_INFO Out = (PNDISWAN_DRIVER_INFO)pOutputBuffer;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("GetDriverInfo:"));
*pulBytesWritten = SizeNeeded;
do {
if (ulOutputBufferLength < SizeNeeded) {
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
NdisZeroMemory(Out, ulOutputBufferLength);
#ifdef ENCRYPT_128BIT
Out->DriverCaps = NDISWAN_128BIT_ENABLED;
#else
Out->DriverCaps = 0;
#endif
} while ( 0 );
return (Status);
}
NTSTATUS
SetProtocolEvent(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
PIRP Irp = (PIRP)pInputBuffer;
NTSTATUS Status = STATUS_PENDING;
KIRQL Irql;
NdisAcquireSpinLock(&ProtocolInfoTable->Lock);
do {
if ((ProtocolInfoTable->Flags & PROTOCOL_EVENT_OCCURRED) &&
!(ProtocolInfoTable->Flags & PROTOCOL_EVENT_SIGNALLED)) {
//
// An event occurred but we did not signal so
// signal now!
//
ProtocolInfoTable->Flags |= PROTOCOL_EVENT_SIGNALLED;
*pulBytesWritten = 0;
Status = STATUS_SUCCESS;
break;
}
if (ProtocolInfoTable->EventIrp != NULL) {
*pulBytesWritten = 0;
Status = STATUS_SUCCESS;
break;
}
ProtocolInfoTable->EventIrp = Irp;
IoMarkIrpPending(Irp);
IoSetCancelRoutine(Irp, NdisWanCancelRoutine);
Status = STATUS_PENDING;
} while (FALSE);
NdisReleaseSpinLock(&ProtocolInfoTable->Lock);
return (Status);
}
NTSTATUS
GetProtocolEvent(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
PNDISWAN_GET_PROTOCOL_EVENT Out =
(PNDISWAN_GET_PROTOCOL_EVENT)pOutputBuffer;
PPROTOCOL_INFO InfoArray;
ULONG ArraySize;
ULONG SizeNeeded = sizeof(NDISWAN_GET_PROTOCOL_EVENT);
NTSTATUS Status = STATUS_SUCCESS;
UINT i, j;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("GetProtocolEvent:"));
*pulBytesWritten = 0;
NdisAcquireSpinLock(&ProtocolInfoTable->Lock);
ArraySize = ProtocolInfoTable->ulArraySize;
do {
if (ulOutputBufferLength < SizeNeeded) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetProtocolEvent: Buffer to small: Size: %d, SizeNeeded %d",
ulInputBufferLength, SizeNeeded));
*pulBytesWritten = SizeNeeded;
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
*pulBytesWritten = sizeof(NDISWAN_GET_PROTOCOL_EVENT);
NdisZeroMemory(Out, sizeof(NDISWAN_GET_PROTOCOL_EVENT));
j = 0;
for (i = 0, InfoArray = ProtocolInfoTable->ProtocolInfo;
i < ArraySize;
i++, InfoArray++) {
if (InfoArray->Flags & PROTOCOL_EVENT_OCCURRED) {
PPROTOCOL_EVENT oevent = &Out->ProtocolEvent[j];
oevent->usProtocolType = InfoArray->ProtocolType;
if (InfoArray->Flags & PROTOCOL_REBOUND) {
//
// This means we were unbound and then
// bound again without our miniport being
// halted. We need to tell ras about two events,
// the unbind and the bind.
//
InfoArray->Flags &= ~(PROTOCOL_REBOUND |
PROTOCOL_EVENT_OCCURRED);
oevent->ulFlags = PROTOCOL_REMOVED;
Out->ulNumProtocols++;
j++;
if (j < MAX_PROTOCOLS) {
oevent = &Out->ProtocolEvent[j];
oevent->usProtocolType = InfoArray->ProtocolType;
oevent->ulFlags = PROTOCOL_ADDED;
Out->ulNumProtocols++;
j++;
}
} else {
oevent->ulFlags = (InfoArray->Flags & PROTOCOL_BOUND) ?
PROTOCOL_ADDED : PROTOCOL_REMOVED;
InfoArray->Flags &= ~PROTOCOL_EVENT_OCCURRED;
Out->ulNumProtocols++;
j++;
}
if (j == MAX_PROTOCOLS) {
break;
}
}
}
ProtocolInfoTable->Flags &=
~(PROTOCOL_EVENT_OCCURRED | PROTOCOL_EVENT_SIGNALLED);
} while (FALSE);
NdisReleaseSpinLock(&ProtocolInfoTable->Lock);
return (Status);
}
NTSTATUS
FlushProtocolEvent(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
PIRP Irp;
KIRQL Irql;
*pulBytesWritten = 0;
NdisAcquireSpinLock(&ProtocolInfoTable->Lock);
Irp = ProtocolInfoTable->EventIrp;
if ((Irp != NULL) &&
IoSetCancelRoutine(Irp, NULL)) {
ProtocolInfoTable->EventIrp = NULL;
Irp->Cancel = TRUE;
Irp->IoStatus.Status = STATUS_CANCELLED;
Irp->IoStatus.Information = 0;
NdisReleaseSpinLock(&ProtocolInfoTable->Lock);
IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
NdisAcquireSpinLock(&ProtocolInfoTable->Lock);
}
NdisReleaseSpinLock(&ProtocolInfoTable->Lock);
return (STATUS_SUCCESS);
}
NTSTATUS
IoGetProtocolInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG SizeNeeded = sizeof(NDISWAN_GET_PROTOCOL_INFO);
PNDISWAN_GET_PROTOCOL_INFO Out =
(PNDISWAN_GET_PROTOCOL_INFO)pOutputBuffer;
do {
ULONG i = 0;
ULONG j = 0;
PMINIPORTCB MiniportCB;
ULONG ArraySize;
PPROTOCOL_INFO InfoArray;
*pulBytesWritten = SizeNeeded;
if (ulOutputBufferLength < SizeNeeded) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("IoGetProtocolInfo: Buffer to small: Size: %d, SizeNeeded %d",
ulInputBufferLength, SizeNeeded));
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
NdisAcquireSpinLock(&ProtocolInfoTable->Lock);
ArraySize = ProtocolInfoTable->ulArraySize;
for (i = 0, InfoArray = ProtocolInfoTable->ProtocolInfo;
i < ArraySize;
i++, InfoArray++) {
if (InfoArray->Flags & PROTOCOL_BOUND) {
Out->ProtocolInfo[j].ProtocolType = InfoArray->ProtocolType;
Out->ProtocolInfo[j].PPPId = InfoArray->PPPId;
Out->ProtocolInfo[j].MTU = InfoArray->MTU;
Out->ProtocolInfo[j].TunnelMTU = InfoArray->TunnelMTU;
Out->ProtocolInfo[j].PacketQueueDepth = InfoArray->PacketQueueDepth;
j++;
}
}
NdisReleaseSpinLock(&ProtocolInfoTable->Lock);
Out->ulNumProtocols = j;
} while (FALSE);
return (Status);
}
NTSTATUS
SetHibernateEvent(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
PIRP Irp = (PIRP)pInputBuffer;
NTSTATUS Status = STATUS_PENDING;
KIRQL Irql;
NdisAcquireSpinLock(&NdisWanCB.Lock);
do {
if (NdisWanCB.HibernateEventIrp != NULL) {
*pulBytesWritten = 0;
Status = STATUS_SUCCESS;
break;
}
NdisWanCB.HibernateEventIrp = Irp;
IoMarkIrpPending(Irp);
IoSetCancelRoutine(Irp, NdisWanCancelRoutine);
Status = STATUS_PENDING;
} while (FALSE);
NdisReleaseSpinLock(&NdisWanCB.Lock);
return (Status);
}
NTSTATUS
FlushHibernateEvent(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
PIRP Irp;
KIRQL Irql;
*pulBytesWritten = 0;
NdisAcquireSpinLock(&NdisWanCB.Lock);
Irp = NdisWanCB.HibernateEventIrp;
if ((Irp != NULL) &&
IoSetCancelRoutine(Irp, NULL)) {
NdisWanCB.HibernateEventIrp = NULL;
Irp->Cancel = TRUE;
Irp->IoStatus.Status = STATUS_CANCELLED;
Irp->IoStatus.Information = 0;
NdisReleaseSpinLock(&NdisWanCB.Lock);
IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
NdisAcquireSpinLock(&NdisWanCB.Lock);
}
NdisReleaseSpinLock(&NdisWanCB.Lock);
return (STATUS_SUCCESS);
}
NTSTATUS
GetBundleInfo(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
ULONG SizeNeeded = sizeof(NDISWAN_GET_BUNDLE_INFO);
PNDISWAN_GET_BUNDLE_INFO In = (PNDISWAN_GET_BUNDLE_INFO)pInputBuffer;
PNDISWAN_GET_BUNDLE_INFO Out = (PNDISWAN_GET_BUNDLE_INFO)pOutputBuffer;
POPENCB OpenCB;
PBUNDLECB BundleCB = NULL;
NTSTATUS Status = STATUS_SUCCESS;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("GetWanInfo:"));
*pulBytesWritten = SizeNeeded;
do {
if (ulInputBufferLength < SizeNeeded ||
ulOutputBufferLength < SizeNeeded) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetBundleInfo: Buffer to small: Size: %d, SizeNeeded %d",
ulOutputBufferLength, SizeNeeded));
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
if (!IsBundleValid(In->hBundleHandle,
FALSE,
&BundleCB)) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetBundleInfo: Invalid Bundle Handle: 0x%x",
In->hBundleHandle));
*pulBytesWritten = 0;
Status = NDISWAN_ERROR_INVALID_HANDLE;
break;
}
AcquireBundleLock(BundleCB);
Out->BundleInfo.SendFramingBits =
BundleCB->FramingInfo.SendFramingBits;
Out->BundleInfo.SendBundleSpeed =
BundleCB->SFlowSpec.PeakBandwidth*8;
Out->BundleInfo.SendMSCompType =
BundleCB->SendCompInfo.MSCompType;
Out->BundleInfo.SendAuthType =
BundleCB->SendCompInfo.AuthType;
Out->BundleInfo.RecvFramingBits =
BundleCB->FramingInfo.RecvFramingBits;
Out->BundleInfo.RecvBundleSpeed =
BundleCB->RFlowSpec.PeakBandwidth*8;
Out->BundleInfo.RecvMSCompType =
BundleCB->RecvCompInfo.MSCompType;
Out->BundleInfo.RecvAuthType =
BundleCB->RecvCompInfo.AuthType;
} while ( 0 );
//
// Deref for ref applied by IsBundleValid. This releases
// the BundleCB->Lock
//
DEREF_BUNDLECB_LOCKED(BundleCB);
return (Status);
}
NTSTATUS
UnmapConnectionId(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
ULONG SizeNeeded = sizeof(NDISWAN_UNMAP_CONNECTION_ID);
NTSTATUS Status = STATUS_SUCCESS;
LOCK_STATE LockState;
PNDISWAN_UNMAP_CONNECTION_ID In =
(PNDISWAN_UNMAP_CONNECTION_ID)pInputBuffer;
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("UnmapConnectionId:"));
*pulBytesWritten = 0;
do {
PLINKCB LinkCB = NULL;
if (ulInputBufferLength < SizeNeeded) {
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("UnmapConnectionId: Buffer to small: Size: %d, SizeNeeded %d",
ulInputBufferLength, SizeNeeded));
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
//
// Validate the link handle
//
if (IsLinkValid(In->hLinkHandle, FALSE, &LinkCB)) {
NdisAcquireSpinLock(&LinkCB->Lock);
//
// Remove the ref applied to the link at mapconnectionid time.
// We don't have to use the full deref code as the ref applied
// in IsLinkValid will keep the link around.
//
LinkCB->RefCount--;
//
// Remove the ref applied by IsLinkValid
//
DEREF_LINKCB_LOCKED(LinkCB);
} else {
NdisWanDbgOut(DBG_FAILURE, DBG_IO,
("UnmapConnectionId: Invalid LinkHandle %x",
In->hLinkHandle));
Status = NDISWAN_ERROR_INVALID_HANDLE;
break;
}
} while (FALSE);
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("UnmapConnectionId:"));
return (Status);
}
VOID
CancelThresholdEvents(
VOID
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
#ifdef NT
KIRQL Irql;
PIRP pIrp;
PLIST_ENTRY Entry;
NdisAcquireSpinLock(&ThresholdEventQueue.Lock);
while (!IsListEmpty(&ThresholdEventQueue.List)) {
Entry = RemoveHeadList(&ThresholdEventQueue.List);
ThresholdEventQueue.ulCount--;
pIrp = CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry);
if (!IoSetCancelRoutine(pIrp, NULL)) {
//
// Irp is being canceled so let
// cancel routine handle it.
//
continue;
}
NdisReleaseSpinLock(&ThresholdEventQueue.Lock);
pIrp->Cancel = TRUE;
pIrp->IoStatus.Status = STATUS_CANCELLED;
pIrp->IoStatus.Information = 0;
IoCompleteRequest(pIrp, IO_NETWORK_INCREMENT);
NdisAcquireSpinLock(&ThresholdEventQueue.Lock);
}
NdisReleaseSpinLock(&ThresholdEventQueue.Lock);
#endif // End #ifdef NT
}
VOID
CancelIoReceivePackets(
VOID
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
#ifdef NT
PIRP pIrp;
PLIST_ENTRY Entry;
NdisAcquireSpinLock(&IoRecvList.Lock);
while (!IsListEmpty(&IoRecvList.IrpList)) {
Entry = RemoveHeadList(&IoRecvList.IrpList);
IoRecvList.ulIrpCount--;
INSERT_RECV_EVENT('c');
pIrp = CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry);
if (!IoSetCancelRoutine(pIrp, NULL)) {
//
// Irp is being canceled so let
// cancel routine complete it
//
continue;
}
pIrp->Cancel = TRUE;
pIrp->IoStatus.Status = STATUS_CANCELLED;
pIrp->IoStatus.Information = sizeof(NDISWAN_IO_PACKET);
((PNDISWAN_IO_PACKET)(pIrp->AssociatedIrp.SystemBuffer))->usHandleType = CANCELEDHANDLE;
IoRecvList.LastIrp = pIrp;
IoRecvList.LastIrpStatus = STATUS_CANCELLED;
IoRecvList.LastCopySize = (ULONG)pIrp->IoStatus.Information;
IoRecvList.LastPacketNumber =
((PNDISWAN_IO_PACKET)(pIrp->AssociatedIrp.SystemBuffer))->PacketNumber;
NdisReleaseSpinLock(&IoRecvList.Lock);
IoCompleteRequest(pIrp, IO_NETWORK_INCREMENT);
NdisAcquireSpinLock(&IoRecvList.Lock);
}
NdisReleaseSpinLock(&IoRecvList.Lock);
#endif // End #ifdef NT
}
VOID
AddProtocolCBToBundle(
PPROTOCOLCB ProtocolCB,
PBUNDLECB BundleCB
)
/*++
Routine Name:
AddProtocolCBToBundle
Routine Description:
This routine adds the protocolcb to the bundlecb protocollist and
protocoltable. It also assigns the protocolcb's handle (index into
the table) and set's the initial priority of all of the protocols
on the list.
Arguments:
ProtocolCB - Pointer to the protocol control block
BundleCB - Pointer to the bundle control block
Return Values:
None
--*/
{
ULONG i, InitialByteQuota;
ULONG InitialPriority;
AcquireBundleLock(BundleCB);
//
// Add to list
//
InsertTailList(&BundleCB->ProtocolCBList, &ProtocolCB->Linkage);
//
// Insert in table
//
ASSERT(BundleCB->ProtocolCBTable[(ULONG_PTR)ProtocolCB->ProtocolHandle] ==
(PPROTOCOLCB)RESERVED_PROTOCOLCB);
BundleCB->ProtocolCBTable[(ULONG_PTR)ProtocolCB->ProtocolHandle] =
ProtocolCB;
BundleCB->ulNumberOfRoutes++;
//
// Setup the send mask for this protocolcb
//
ProtocolCB->SendMaskBit = BundleCB->SendMask + 0x00000001;
BundleCB->SendMask = (BundleCB->SendMask << 1) | 0x00000001;
ProtocolCB->State = PROTOCOL_ROUTED;
if (BundleCB->NextProtocol == NULL) {
BundleCB->NextProtocol = ProtocolCB;
}
REF_BUNDLECB(BundleCB);
ReleaseBundleLock(BundleCB);
}
VOID
RemoveProtocolCBFromBundle(
PPROTOCOLCB ProtocolCB
)
{
PBUNDLECB BundleCB = ProtocolCB->BundleCB;
//
// If this protocolcb was not yet inserted in
// the table just return.
//
if (BundleCB->ProtocolCBTable[(ULONG_PTR)ProtocolCB->ProtocolHandle] !=
ProtocolCB) {
return;
}
RemoveEntryList(&ProtocolCB->Linkage);
BundleCB->ProtocolCBTable[(ULONG_PTR)ProtocolCB->ProtocolHandle] = NULL;
BundleCB->ulNumberOfRoutes--;
if (BundleCB->NextProtocol == ProtocolCB) {
BundleCB->NextProtocol =
(PPROTOCOLCB)ProtocolCB->Linkage.Flink;
if ((PVOID)BundleCB->NextProtocol ==
(PVOID)&BundleCB->ProtocolCBList) {
if (BundleCB->ulNumberOfRoutes != 0) {
//
// If we are back to the head of the list
// but there are still routes get the next.
//
BundleCB->NextProtocol =
(PPROTOCOLCB)BundleCB->ProtocolCBList.Flink;
} else {
//
// No more routes left...
//
BundleCB->NextProtocol = NULL;
}
}
}
//
// Deref for the ref applied when the protocolcb was
// added to the bundle. Don't need to do the entire
// bundlecb ref code here.
//
BundleCB->RefCount--;
}
VOID
SortProtocolListByPriority(
IN PBUNDLECB BundleCB
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
}
VOID
CompleteThresholdEvent(
PBUNDLECB BundleCB,
ULONG DataType,
ULONG ThresholdType
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
#ifdef NT
PLIST_ENTRY Entry;
PIRP pIrp;
PNDISWAN_SET_THRESHOLD_EVENT ThresholdEvent;
NdisAcquireSpinLock(&ThresholdEventQueue.Lock);
if (IsListEmpty(&ThresholdEventQueue.List)) {
NdisReleaseSpinLock(&ThresholdEventQueue.Lock);
return;
}
Entry = RemoveHeadList(&ThresholdEventQueue.List);
ThresholdEventQueue.ulCount--;
pIrp = CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry);
if (IoSetCancelRoutine(pIrp, NULL)) {
pIrp->IoStatus.Status = STATUS_SUCCESS;
pIrp->IoStatus.Information = sizeof(NDISWAN_SET_THRESHOLD_EVENT);
ThresholdEvent = (PNDISWAN_SET_THRESHOLD_EVENT)pIrp->AssociatedIrp.SystemBuffer;
ThresholdEvent->hBundleContext = BundleCB->hBundleContext;
ThresholdEvent->ulThreshold = ThresholdType;
ThresholdEvent->ulDataType = DataType;
NdisReleaseSpinLock(&ThresholdEventQueue.Lock);
IoCompleteRequest(pIrp, IO_NETWORK_INCREMENT);
NdisAcquireSpinLock(&ThresholdEventQueue.Lock);
}
NdisReleaseSpinLock(&ThresholdEventQueue.Lock);
#endif // End #ifdef NT
}
VOID
FlushProtocolPacketQueue(
PPROTOCOLCB ProtocolCB
)
{
ULONG Class;
PBUNDLECB BundleCB;
BundleCB = ProtocolCB->BundleCB;
for (Class = 0; Class <= MAX_MCML; Class++) {
PPACKET_QUEUE PacketQueue;
PacketQueue = &ProtocolCB->PacketQueue[Class];
while (!IsPacketQueueEmpty(PacketQueue)) {
PNDIS_PACKET NdisPacket;
NdisPacket =
RemoveHeadPacketQueue(PacketQueue);
ReleaseBundleLock(BundleCB);
//
// Complete the NdisPacket
//
CompleteNdisPacket(ProtocolCB->MiniportCB,
ProtocolCB,
NdisPacket);
AcquireBundleLock(BundleCB);
}
}
}
NDIS_HANDLE
AssignProtocolCBHandle(
PBUNDLECB BundleCB,
PPROTOCOLCB ProtocolCB
)
{
ULONG i;
//
// Find the first unused slot in the table
//
for (i = 0; i < MAX_PROTOCOLS; i++) {
if (BundleCB->ProtocolCBTable[i] == NULL) {
ProtocolCB->ProtocolHandle = (NDIS_HANDLE)ULongToPtr(i);
ProtocolCB->BundleCB = BundleCB;
BundleCB->ProtocolCBTable[i] = (PPROTOCOLCB)RESERVED_PROTOCOLCB;
break;
}
}
//
// If there is no room in the inn return
// i == MAX_PROTOCOLS which flags as an error.
//
return((NDIS_HANDLE)ULongToPtr(i));
}
VOID
FreeProtocolCBHandle(
PBUNDLECB BundleCB,
PPROTOCOLCB ProtocolCB
)
{
ASSERT(BundleCB->ProtocolCBTable[(ULONG_PTR)ProtocolCB->ProtocolHandle] ==
(PPROTOCOLCB)RESERVED_PROTOCOLCB);
ASSERT((ULONG_PTR)ProtocolCB->ProtocolHandle < MAX_PROTOCOLS);
BundleCB->ProtocolCBTable[(ULONG_PTR)ProtocolCB->ProtocolHandle] = NULL;
}
VOID
SetBundleFlags(
PBUNDLECB BundleCB
)
{
BundleCB->SendFlags = ((BundleCB->SendCompInfo.MSCompType & NDISWAN_COMPRESSION) &&
(BundleCB->SendCompressContext != NULL)) ? DO_COMPRESSION : 0;
BundleCB->SendFlags |=
(BundleCB->SendCompInfo.MSCompType & NDISWAN_HISTORY_LESS) ? DO_HISTORY_LESS : 0;
if (BundleCB->SendCryptoInfo.RC4Key != NULL) {
if (BundleCB->SendCompInfo.MSCompType & NDISWAN_ENCRYPTION) {
BundleCB->SendFlags |= (DO_ENCRYPTION | DO_LEGACY_ENCRYPTION);
} else if (BundleCB->SendCompInfo.MSCompType & NDISWAN_40_ENCRYPTION) {
BundleCB->SendFlags |= (DO_ENCRYPTION | DO_40_ENCRYPTION);
} else if (BundleCB->SendCompInfo.MSCompType & NDISWAN_56_ENCRYPTION) {
BundleCB->SendFlags |= (DO_ENCRYPTION | DO_56_ENCRYPTION);
}
#ifdef ENCRYPT_128BIT
else if (BundleCB->SendCompInfo.MSCompType & NDISWAN_128_ENCRYPTION) {
BundleCB->SendFlags |= (DO_ENCRYPTION | DO_128_ENCRYPTION);
}
#endif
}
BundleCB->SendFlags |=
(BundleCB->SendVJInfo.IPCompressionProtocol == 0x2D &&
BundleCB->VJCompress != NULL) ? DO_VJ : 0;
BundleCB->SendFlags |=
((BundleCB->FramingInfo.SendFramingBits & PPP_MULTILINK_FRAMING) &&
((BundleCB->ulLinkCBCount > 1) || (BundleCB->Flags & QOS_ENABLED))) ?
DO_MULTILINK : 0;
BundleCB->SendFlags |=
(BundleCB->FramingInfo.SendFramingBits & NBF_PRESERVE_MAC_ADDRESS) ?
SAVE_MAC_ADDRESS : 0;
BundleCB->RecvFlags = ((BundleCB->RecvCompInfo.MSCompType & NDISWAN_COMPRESSION) &&
(BundleCB->RecvCompressContext != NULL)) ? DO_COMPRESSION : 0;
BundleCB->RecvFlags |=
(BundleCB->RecvCompInfo.MSCompType & NDISWAN_HISTORY_LESS) ? DO_HISTORY_LESS : 0;
if (BundleCB->RecvCryptoInfo.RC4Key != NULL) {
if (BundleCB->RecvCompInfo.MSCompType & NDISWAN_ENCRYPTION) {
BundleCB->RecvFlags |= (DO_ENCRYPTION | DO_LEGACY_ENCRYPTION);
} else if (BundleCB->RecvCompInfo.MSCompType & NDISWAN_40_ENCRYPTION) {
BundleCB->RecvFlags |= (DO_ENCRYPTION | DO_40_ENCRYPTION);
} else if (BundleCB->RecvCompInfo.MSCompType & NDISWAN_56_ENCRYPTION) {
BundleCB->RecvFlags |= (DO_ENCRYPTION | DO_56_ENCRYPTION);
}
#ifdef ENCRYPT_128BIT
else if (BundleCB->RecvCompInfo.MSCompType & NDISWAN_128_ENCRYPTION) {
BundleCB->RecvFlags |= (DO_ENCRYPTION | DO_128_ENCRYPTION);
}
#endif
}
BundleCB->RecvFlags |=
(BundleCB->RecvVJInfo.IPCompressionProtocol == 0x2D &&
BundleCB->VJCompress != NULL) ? DO_VJ : 0;
BundleCB->RecvFlags |=
((BundleCB->FramingInfo.RecvFramingBits & PPP_MULTILINK_FRAMING) &&
((BundleCB->ulLinkCBCount > 1) || (BundleCB->Flags & QOS_ENABLED))) ?
DO_MULTILINK : 0;
BundleCB->RecvFlags |=
(BundleCB->FramingInfo.SendFramingBits & NBF_PRESERVE_MAC_ADDRESS) ?
SAVE_MAC_ADDRESS : 0;
}
NTSTATUS
NotImplemented(
IN PUCHAR pInputBuffer,
IN ULONG ulInputBufferLength,
IN PUCHAR pOutputBuffer,
IN ULONG ulOutputBufferLength,
OUT PULONG pulBytesWritten
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
return (STATUS_NOT_IMPLEMENTED);
}