4609 lines
103 KiB
C
4609 lines
103 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"
|
|
#include "tcpip.h"
|
|
#include "vjslip.h"
|
|
|
|
//
|
|
// 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
|
|
SetBridgeInfo(
|
|
IN PUCHAR pInputBuffer,
|
|
IN ULONG ulInputBufferLength,
|
|
IN PUCHAR pOutputBuffer,
|
|
IN ULONG ulOutputBufferLength,
|
|
OUT PULONG pulBytesWritten
|
|
);
|
|
|
|
|
|
NTSTATUS
|
|
GetBridgeInfo(
|
|
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
|
|
SetCIPXInfo(
|
|
IN PUCHAR pInputBuffer,
|
|
IN ULONG ulInputBufferLength,
|
|
IN PUCHAR pOutputBuffer,
|
|
IN ULONG ulOutputBufferLength,
|
|
OUT PULONG pulBytesWritten
|
|
);
|
|
|
|
|
|
NTSTATUS
|
|
GetCIPXInfo(
|
|
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
|
|
GetNdisWanCB(
|
|
IN PUCHAR pInputBuffer,
|
|
IN ULONG ulInputBufferLength,
|
|
IN PUCHAR pOutputBuffer,
|
|
IN ULONG ulOutputBufferLength,
|
|
OUT PULONG pulBytesWritten
|
|
);
|
|
|
|
NTSTATUS
|
|
EnumAdapterCB(
|
|
IN PUCHAR pInputBuffer,
|
|
IN ULONG ulInputBufferLength,
|
|
IN PUCHAR pOutputBuffer,
|
|
IN ULONG ulOutputBufferLength,
|
|
OUT PULONG pulBytesWritten
|
|
);
|
|
|
|
NTSTATUS
|
|
GetAdapterCB(
|
|
IN PUCHAR pInputBuffer,
|
|
IN ULONG ulInputBufferLength,
|
|
IN PUCHAR pOutputBuffer,
|
|
IN ULONG ulOutputBufferLength,
|
|
OUT PULONG pulBytesWritten
|
|
);
|
|
|
|
NTSTATUS
|
|
EnumWanAdapterCB(
|
|
IN PUCHAR pInputBuffer,
|
|
IN ULONG ulInputBufferLength,
|
|
IN PUCHAR pOutputBuffer,
|
|
IN ULONG ulOutputBufferLength,
|
|
OUT PULONG pulBytesWritten
|
|
);
|
|
|
|
NTSTATUS
|
|
GetWanAdapterCB(
|
|
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
|
|
);
|
|
|
|
VOID
|
|
CancelThresholdEvents(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
CancelIoReceivePackets(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
AddProtocolCBToBundle(
|
|
PPROTOCOLCB ProtocolCB,
|
|
PBUNDLECB BundleCB
|
|
);
|
|
|
|
VOID
|
|
RemoveProtocolCBFromBundle(
|
|
PPROTOCOLCB ProtocolCB,
|
|
PBUNDLECB BundleCB
|
|
);
|
|
|
|
#ifdef BANDWIDTH_ON_DEMAND
|
|
VOID
|
|
SortProtocolListByPriority(
|
|
IN PBUNDLECB BundleCB
|
|
);
|
|
#endif
|
|
|
|
VOID
|
|
FlushProtocolPacketQueue(
|
|
PPROTOCOLCB ProtocolCB
|
|
);
|
|
|
|
VOID
|
|
AssignProtocolCBHandle(
|
|
PBUNDLECB BundleCB,
|
|
PPROTOCOLCB ProtocolCB
|
|
);
|
|
|
|
VOID
|
|
FreeProtocolCBHandle(
|
|
PBUNDLECB BundleCB,
|
|
PPROTOCOLCB ProtocolCB
|
|
);
|
|
|
|
//
|
|
// End of local function prototypes
|
|
//
|
|
|
|
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 , SetBridgeInfo},
|
|
{FUNC_GET_BRIDGE_INFO , GetBridgeInfo},
|
|
{FUNC_SET_VJ_INFO , SetVJInfo},
|
|
{FUNC_GET_VJ_INFO , GetVJInfo},
|
|
{FUNC_SET_CIPX_INFO , SetCIPXInfo},
|
|
{FUNC_GET_CIPX_INFO , GetCIPXInfo},
|
|
{FUNC_SET_ENCRYPTION_INFO , SetEncryptionInfo},
|
|
{FUNC_GET_ENCRYPTION_INFO , GetEncryptionInfo},
|
|
{FUNC_SET_DEBUG_INFO , SetDebugInfo},
|
|
{FUNC_ENUM_ACTIVE_BUNDLES , EnumActiveBundles},
|
|
{FUNC_GET_NDISWANCB , GetNdisWanCB},
|
|
{FUNC_GET_ADAPTERCB , GetAdapterCB},
|
|
{FUNC_GET_WAN_ADAPTERCB , GetWanAdapterCB},
|
|
{FUNC_GET_BANDWIDTH_UTILIZATION, GetBandwidthUtilization},
|
|
{FUNC_ENUM_PROTOCOL_UTILIZATION, EnumProtocolUtilization},
|
|
{FUNC_ENUM_ADAPTERCB , EnumAdapterCB},
|
|
{FUNC_ENUM_WAN_ADAPTERCB , EnumWanAdapterCB},
|
|
{FUNC_GET_WAN_INFO , GetWanInfo},
|
|
{FUNC_GET_IDLE_TIME , GetIdleTime},
|
|
{FUNC_UNROUTE , DeactivateRoute}
|
|
};
|
|
|
|
#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;
|
|
|
|
//
|
|
// 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;
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("NdisWanIoctl: FunctionCode: 0x%8.8x, MajorFunction: 0x%8.8x, DeviceType: 0x%8.8x",
|
|
ulFuncCode, pIrpSp->MajorFunction, ulDeviceType));
|
|
//
|
|
// Make sure that this is for us
|
|
//
|
|
if ((pIrpSp->MajorFunction != IRP_MJ_DEVICE_CONTROL) ||
|
|
(ulDeviceType != FILE_DEVICE_NDISWAN) ||
|
|
(pDeviceObject != NdisWanCB.pDeviceObject)) {
|
|
|
|
return(NdisWanCB.MajorFunction[pIrpSp->MajorFunction](pDeviceObject, pIrp));
|
|
}
|
|
|
|
//
|
|
// 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)) {
|
|
|
|
pInputBuffer = (PUCHAR)pIrp;
|
|
}
|
|
|
|
Status = ExecuteIo(ulFuncCode,
|
|
pInputBuffer,
|
|
ulInputBufferLength,
|
|
pOutputBuffer,
|
|
ulOutputBufferLength,
|
|
&ulBytesWritten);
|
|
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("NdisWanIoctl: Status: 0x%8.8x, BytesWritten: %d",
|
|
Status, ulBytesWritten));
|
|
|
|
switch (Status) {
|
|
case STATUS_SUCCESS:
|
|
ReturnStatus = Status;
|
|
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);
|
|
ReturnStatus =
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
if (Status < 0xC0000000) {
|
|
Status += 0xC0100000;
|
|
}
|
|
ReturnStatus = STATUS_UNSUCCESSFUL;
|
|
break;
|
|
}
|
|
|
|
pIrp->IoStatus.Information = ulBytesWritten;
|
|
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"));
|
|
|
|
//
|
|
// Make sure that this is for us
|
|
//
|
|
if (pDeviceObject != NdisWanCB.pDeviceObject) {
|
|
|
|
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);
|
|
}
|
|
|
|
VOID
|
|
NdisWanCancelRoutine(
|
|
IN PDEVICE_OBJECT pDeviceObject,
|
|
IN PIRP pIrp
|
|
)
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Values:
|
|
|
|
--*/
|
|
{
|
|
BOOLEAN Found = FALSE;
|
|
WAN_IRQL OldIrql;
|
|
|
|
//
|
|
// Get the pointer to the AsyncEvent from the Irp.
|
|
//
|
|
PWAN_ASYNC_EVENT pAsyncEvent;
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("NdisWanCancelRoutine: Irp 0x%8.8x", pIrp));
|
|
|
|
// NdisWanRaiseIrql(&OldIrql);
|
|
|
|
//
|
|
// We need to walk the async event queue looking for
|
|
// the async event that this irp is associated with
|
|
//
|
|
NdisAcquireSpinLock(&RecvPacketQueue.Lock);
|
|
|
|
for (pAsyncEvent = (PWAN_ASYNC_EVENT)RecvPacketQueue.List.Flink;
|
|
(PVOID)pAsyncEvent != (PVOID)&RecvPacketQueue.List;
|
|
pAsyncEvent = (PWAN_ASYNC_EVENT)pAsyncEvent->Linkage.Flink) {
|
|
|
|
if (pAsyncEvent->Context == (PVOID)pIrp) {
|
|
|
|
RecvPacketQueue.ulCount--;
|
|
//
|
|
// Remove from the list
|
|
//
|
|
RemoveEntryList(&pAsyncEvent->Linkage);
|
|
|
|
Found = TRUE;
|
|
((PNDISWAN_IO_PACKET)(pIrp->AssociatedIrp.SystemBuffer))->usHandleType = CANCELEDHANDLE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
NdisReleaseSpinLock(&RecvPacketQueue.Lock);
|
|
|
|
if (!Found) {
|
|
|
|
NdisAcquireSpinLock(&ThresholdEventQueue.Lock);
|
|
|
|
for (pAsyncEvent = (PWAN_ASYNC_EVENT)ThresholdEventQueue.List.Flink;
|
|
(PVOID)pAsyncEvent != (PVOID)&ThresholdEventQueue.List;
|
|
pAsyncEvent = (PWAN_ASYNC_EVENT)pAsyncEvent->Linkage.Flink) {
|
|
|
|
if (pAsyncEvent->Context == (PVOID)pIrp) {
|
|
|
|
ThresholdEventQueue.ulCount--;
|
|
|
|
//
|
|
// Remove from the list
|
|
//
|
|
RemoveEntryList(&pAsyncEvent->Linkage);
|
|
|
|
Found = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
NdisReleaseSpinLock(&ThresholdEventQueue.Lock);
|
|
}
|
|
|
|
ASSERT(Found);
|
|
|
|
//
|
|
// Free the wan_async_event structure
|
|
//
|
|
NdisWanFreeMemory(pAsyncEvent);
|
|
|
|
// NdisWanLowerIrql(DISPATCH_LEVEL, &OldIrql);
|
|
|
|
//
|
|
// Complete the irp
|
|
//
|
|
IoSetCancelRoutine(pIrp, NULL);
|
|
pIrp->Cancel = TRUE;
|
|
pIrp->IoStatus.Status = STATUS_CANCELLED;
|
|
pIrp->IoStatus.Information = 0;
|
|
|
|
IoReleaseCancelSpinLock(pIrp->CancelIrql);
|
|
|
|
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%8.8x", ulFuncCode));
|
|
|
|
if (ulFuncCode < MAX_FUNC_CODES) {
|
|
|
|
Status = (*IoDispatchTable[ulFuncCode].Function)(pInputBuffer,
|
|
ulInputBufferLength,
|
|
pOutputBuffer,
|
|
ulOutputBufferLength,
|
|
pulBytesWritten);
|
|
}
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("ExecuteIo: Status 0x%8.8x", 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;
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("MapConnectionId:"));
|
|
|
|
*pulBytesWritten = SizeNeeded;
|
|
|
|
if ((ulInputBufferLength >= SizeNeeded) &&
|
|
(ulOutputBufferLength >= SizeNeeded)) {
|
|
|
|
NdisAcquireSpinLock(&ConnectionTable->Lock);
|
|
|
|
//
|
|
// Find the linkcb that has this connection id and return
|
|
// both the linkcb index and the bundlecb index
|
|
//
|
|
for (i = 0; i < ConnectionTable->ulArraySize; i++) {
|
|
PLINKCB pLinkCB = *(ConnectionTable->LinkArray + i);
|
|
|
|
if ((pLinkCB != NULL) &&
|
|
(pLinkCB->State == LINK_UP) &&
|
|
((pLinkCB->LineUpInfo.ConnectionWrapperID == In->hConnectionID) ||
|
|
(pLinkCB->hLinkHandle == In->hConnectionID))) {
|
|
PBUNDLECB BundleCB = pLinkCB->BundleCB;
|
|
|
|
//
|
|
// We have found the right link, return the link and bundle handles
|
|
//
|
|
Out->hLinkHandle = pLinkCB->hLinkHandle;
|
|
Out->hBundleHandle = BUNDLEH_FROM_BUNDLECB(BundleCB);
|
|
pLinkCB->hLinkContext = In->hLinkContext;
|
|
BundleCB->hBundleContext = In->hBundleContext;
|
|
|
|
//
|
|
// Copy the friendly name to the link
|
|
//
|
|
NdisMoveMemory(pLinkCB->Name,
|
|
In->szName,
|
|
(In->ulNameLength > MAX_NAME_LENGTH) ? MAX_NAME_LENGTH : In->ulNameLength);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i >= ConnectionTable->ulArraySize) {
|
|
//
|
|
// We did not find a match to the connection id
|
|
//
|
|
Status = NDISWAN_ERROR_INVALID_HANDLE;
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("MapConnectionId: ConnectionId not found! ConnectionId: 0x%8.8x",
|
|
In->hConnectionID));
|
|
}
|
|
|
|
NdisReleaseSpinLock(&ConnectionTable->Lock);
|
|
|
|
} else {
|
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
|
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("MapConnectionId: Buffer to small: Size: %d, SizeNeeded %d",
|
|
ulOutputBufferLength, SizeNeeded));
|
|
}
|
|
|
|
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);
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("GetBundleHandle:"));
|
|
|
|
*pulBytesWritten = SizeNeeded;
|
|
|
|
NdisAcquireSpinLock(&ConnectionTable->Lock);
|
|
|
|
if ((ulInputBufferLength >= SizeNeeded) &&
|
|
(ulOutputBufferLength >= SizeNeeded)) {
|
|
|
|
PLINKCB LinkCB;
|
|
PBUNDLECB BundleCB;
|
|
|
|
LINKCB_FROM_LINKH(LinkCB, In->hLinkHandle);
|
|
|
|
//
|
|
// Get the bundle handle that this link belongs to
|
|
//
|
|
if (LinkCB && LinkCB->State == LINK_UP &&
|
|
(BundleCB = LinkCB->BundleCB) != NULL) {
|
|
Out->hBundleHandle = BundleCB->hBundleHandle;
|
|
} else {
|
|
Status = NDISWAN_ERROR_INVALID_HANDLE;
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetBundleHandle: Invalid LinkHandle: 0x%8.8x",
|
|
In->hLinkHandle));
|
|
}
|
|
|
|
} else {
|
|
|
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetBundleHandle: Buffer to small: Size: %d, SizeNeeded %d",
|
|
ulOutputBufferLength, SizeNeeded));
|
|
}
|
|
|
|
NdisReleaseSpinLock(&ConnectionTable->Lock);
|
|
|
|
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;
|
|
PNDISWAN_SET_FRIENDLY_NAME In = (PNDISWAN_SET_FRIENDLY_NAME)pInputBuffer;
|
|
ULONG SizeNeeded = sizeof(NDISWAN_SET_FRIENDLY_NAME);
|
|
PLINKCB LinkCB;
|
|
PBUNDLECB BundleCB;
|
|
PUCHAR Dest;
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("SetFriendlyName:"));
|
|
|
|
*pulBytesWritten = SizeNeeded;
|
|
|
|
NdisAcquireSpinLock(&ConnectionTable->Lock);
|
|
|
|
if (ulInputBufferLength >= SizeNeeded) {
|
|
|
|
if (In->usHandleType == LINKHANDLE) {
|
|
//
|
|
// Is this a link handle
|
|
//
|
|
LINKCB_FROM_LINKH(LinkCB, In->hHandle);
|
|
|
|
if (LinkCB != NULL && LinkCB->State == LINK_UP) {
|
|
Dest = LinkCB->Name;
|
|
|
|
} else {
|
|
Status = NDISWAN_ERROR_INVALID_HANDLE;
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("SetFriendlyName: Invalid LinkHandle: 0x%8.8x",
|
|
In->hHandle));
|
|
}
|
|
|
|
} else if (In->usHandleType == BUNDLEHANDLE) {
|
|
//
|
|
// Or a bundle handle
|
|
//
|
|
BUNDLECB_FROM_BUNDLEH(BundleCB, In->hHandle);
|
|
|
|
if (BundleCB != NULL) {
|
|
Dest = BundleCB->Name;
|
|
|
|
} else {
|
|
Status = NDISWAN_ERROR_INVALID_HANDLE;
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("SetFriendlyName: Invalid BundleHandle: 0x%8.8x",
|
|
In->hHandle));
|
|
}
|
|
} else {
|
|
Status = NDISWAN_ERROR_INVALID_HANDLE_TYPE;
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("SetFriendlyName: Invalid HandleType: 0x%4.4x",
|
|
In->usHandleType));
|
|
}
|
|
|
|
if (Status == STATUS_SUCCESS) {
|
|
|
|
//
|
|
// Copy the friendly name to the link
|
|
//
|
|
NdisMoveMemory(Dest,
|
|
In->szName,
|
|
(In->ulNameLength > MAX_NAME_LENGTH) ? MAX_NAME_LENGTH : In->ulNameLength);
|
|
}
|
|
|
|
} else {
|
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("SetFriendlyName: Buffer to small: Size: %d, SizeNeeded %d",
|
|
ulInputBufferLength, SizeNeeded));
|
|
}
|
|
|
|
NdisReleaseSpinLock(&ConnectionTable->Lock);
|
|
|
|
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;
|
|
BOOLEAN RouteExists = FALSE;
|
|
PPROTOCOLCB ProtocolCB;
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("ActivateRoute:"));
|
|
|
|
*pulBytesWritten = SizeNeeded;
|
|
|
|
if (ulInputBufferLength < SizeNeeded) {
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("ActivateRoute: Buffer to small: Size: %d, SizeNeeded %d",
|
|
ulInputBufferLength, SizeNeeded));
|
|
return (STATUS_INFO_LENGTH_MISMATCH);
|
|
}
|
|
|
|
//
|
|
// If this is a valid bundle
|
|
//
|
|
BUNDLECB_FROM_BUNDLEH(BundleCB, In->hBundleHandle);
|
|
|
|
if (BundleCB == NULL) {
|
|
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("ActivateRoute: Invalid BundleHandle: 0x%8.8x, ProtocolType: 0x%4.4x",
|
|
In->hBundleHandle, In->usProtocolType));
|
|
|
|
return (NDISWAN_ERROR_INVALID_HANDLE);
|
|
}
|
|
|
|
//
|
|
// Is this a route or unroute call?
|
|
//
|
|
if (In->usProtocolType == PROTOCOL_UNROUTE) {
|
|
|
|
//
|
|
// This is a call to unroute
|
|
//
|
|
|
|
NdisAcquireSpinLock(&BundleCB->Lock);
|
|
|
|
if (!(BundleCB->Flags & BUNDLE_ROUTED)) {
|
|
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("ActivateRoute: BundleCB 0x%8.8x not routed!",
|
|
BundleCB));
|
|
NdisReleaseSpinLock(&BundleCB->Lock);
|
|
return(NDISWAN_ERROR_INVALID_HANDLE);
|
|
}
|
|
|
|
//
|
|
// Don't accept anymore sends on this bundle
|
|
//
|
|
BundleCB->Flags &= ~BUNDLE_ROUTED;
|
|
|
|
//
|
|
// Flush the protocol packet queues. This could cause us
|
|
// to complete frames to ndis out of order. Ndis should
|
|
// handle this.
|
|
//
|
|
for (ProtocolCB = (PPROTOCOLCB)BundleCB->ProtocolCBList.Flink;
|
|
(PVOID)ProtocolCB != (PVOID)&BundleCB->ProtocolCBList;
|
|
ProtocolCB = (PPROTOCOLCB)ProtocolCB->Linkage.Flink) {
|
|
|
|
FlushProtocolPacketQueue(ProtocolCB);
|
|
}
|
|
|
|
//
|
|
// Do we need to wait for any outstanding frames on the bundle?
|
|
//
|
|
if (BundleCB->OutstandingFrames != 0) {
|
|
|
|
NdisWanClearSyncEvent(&BundleCB->OutstandingFramesEvent);
|
|
|
|
BundleCB->Flags |= FRAMES_PENDING;
|
|
|
|
NdisReleaseSpinLock(&BundleCB->Lock);
|
|
|
|
NdisWanWaitForSyncEvent(&BundleCB->OutstandingFramesEvent);
|
|
|
|
NdisAcquireSpinLock(&BundleCB->Lock);
|
|
|
|
BundleCB->Flags &= ~FRAMES_PENDING;
|
|
}
|
|
|
|
//
|
|
// For each protocolcb in the bundle's protocolcb table
|
|
// (except for the i/o protocolcb)
|
|
//
|
|
for (i = 1; i < MAX_PROTOCOLS; i++) {
|
|
|
|
if (ProtocolCB = BundleCB->ProtocolCBTable[i]) {
|
|
|
|
//
|
|
// Remove the protocolcb from the bundlecb, both the table and
|
|
// the list.
|
|
//
|
|
RemoveProtocolCBFromBundle(ProtocolCB, BundleCB);
|
|
|
|
NdisReleaseSpinLock(&BundleCB->Lock);
|
|
|
|
//
|
|
// Do a linedown to the protocol
|
|
//
|
|
NdisWanClearSyncEvent(&BundleCB->IndicationEvent);
|
|
|
|
Status = DoLineDownToProtocol(ProtocolCB);
|
|
|
|
if (Status == NDIS_STATUS_PENDING) {
|
|
|
|
//
|
|
// This has been queued because we could not
|
|
// get the miniport lock. Wait for notification
|
|
// and pick up the route status.
|
|
//
|
|
NdisWanWaitForSyncEvent(&BundleCB->IndicationEvent);
|
|
|
|
Status = BundleCB->IndicationStatus;
|
|
}
|
|
|
|
//
|
|
// Return the protocolcb
|
|
//
|
|
NdisWanReturnProtocolCB(ProtocolCB);
|
|
|
|
NdisAcquireSpinLock(&BundleCB->Lock);
|
|
}
|
|
}
|
|
|
|
if (BundleCB->State == BUNDLE_GOING_DOWN) {
|
|
|
|
NdisReleaseSpinLock(&BundleCB->Lock);
|
|
|
|
//
|
|
// Clean up the connection table
|
|
//
|
|
RemoveBundleFromConnectionTable(BundleCB);
|
|
|
|
//
|
|
// Return the bundlecb
|
|
//
|
|
NdisWanReturnBundleCB(BundleCB);
|
|
|
|
} else {
|
|
NdisReleaseSpinLock(&BundleCB->Lock);
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
// This is a call to route
|
|
//
|
|
|
|
NdisAcquireSpinLock(&BundleCB->Lock);
|
|
|
|
if (BundleCB->State != BUNDLE_UP) {
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("ActivateRoute: Invalid BundleState: 0x%8.8x, BundleHandle: 0x%8.8x ProtocolType: 0x%4.4x",
|
|
BundleCB->State, In->hBundleHandle, In->usProtocolType));
|
|
|
|
NdisReleaseSpinLock(&BundleCB->Lock);
|
|
|
|
return (NDISWAN_ERROR_INVALID_HANDLE);
|
|
}
|
|
|
|
//
|
|
// First make sure that we don't already have a route to this
|
|
// protocol type
|
|
//
|
|
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->usProtocolType == In->usProtocolType) {
|
|
RouteExists = TRUE;
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
if (RouteExists) {
|
|
//
|
|
// A route already exists for this protocoltype
|
|
//
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("ActivateRoute: Route already exists: ProtocolType: 0x%2.2x",
|
|
ProtocolCB->usProtocolType));
|
|
|
|
NdisReleaseSpinLock(&BundleCB->Lock);
|
|
|
|
return (NDISWAN_ERROR_ALREADY_ROUTED);
|
|
}
|
|
|
|
//
|
|
// Create and initialize a ProtocolCB for this new route
|
|
//
|
|
NdisWanGetProtocolCB(&ProtocolCB,
|
|
In->usProtocolType,
|
|
In->usBindingNameLength,
|
|
In->BindingName,
|
|
In->ulBufferLength,
|
|
In->Buffer);
|
|
|
|
if (ProtocolCB == NULL) {
|
|
//
|
|
// Memory allocation failed
|
|
//
|
|
NdisReleaseSpinLock(&BundleCB->Lock);
|
|
|
|
return (STATUS_INSUFFICIENT_RESOURCES);
|
|
}
|
|
|
|
//
|
|
// Assign a handle for this protocolcb
|
|
//
|
|
AssignProtocolCBHandle(BundleCB, ProtocolCB);
|
|
|
|
//
|
|
// Do a new lineup to protocol
|
|
//
|
|
NdisWanClearSyncEvent(&BundleCB->IndicationEvent);
|
|
|
|
NdisReleaseSpinLock(&BundleCB->Lock);
|
|
|
|
Status = DoNewLineUpToProtocol(ProtocolCB);
|
|
|
|
if (Status == NDIS_STATUS_PENDING) {
|
|
|
|
//
|
|
// This has been queued because we could not
|
|
// get the miniport lock. Wait for notification
|
|
// and pick up the route status.
|
|
//
|
|
NdisWanWaitForSyncEvent(&BundleCB->IndicationEvent);
|
|
|
|
Status = BundleCB->IndicationStatus;
|
|
|
|
}
|
|
|
|
if (Status == NDIS_STATUS_SUCCESS) {
|
|
|
|
Out->usDeviceNameLength =
|
|
(ProtocolCB->DeviceName.Length > MAX_NAME_LENGTH) ?
|
|
MAX_NAME_LENGTH : ProtocolCB->DeviceName.Length;
|
|
|
|
NdisMoveMemory(&Out->DeviceName[0],
|
|
ProtocolCB->DeviceName.Buffer,
|
|
Out->usDeviceNameLength);
|
|
|
|
//
|
|
// Insert the protocolcb in the bundle's protocolcb table
|
|
// and list.
|
|
//
|
|
AddProtocolCBToBundle(ProtocolCB, BundleCB);
|
|
|
|
} else {
|
|
|
|
//
|
|
// Assign a handle for this protocolcb
|
|
//
|
|
FreeProtocolCBHandle(BundleCB, ProtocolCB);
|
|
|
|
NdisWanReturnProtocolCB(ProtocolCB);
|
|
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("ActivateRoute: Error during LineUp to ProtocolType: 0x%4.4x",
|
|
ProtocolCB->usProtocolType));
|
|
|
|
}
|
|
}
|
|
|
|
return (NDIS_STATUS_SUCCESS);
|
|
}
|
|
|
|
|
|
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);
|
|
PBUNDLECB OldBundleCB, NewBundleCB;
|
|
PNDISWAN_ADD_LINK_TO_BUNDLE In = (PNDISWAN_ADD_LINK_TO_BUNDLE)pInputBuffer;
|
|
PLINKCB LinkCB;
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("BundleLink:"));
|
|
|
|
*pulBytesWritten = SizeNeeded;
|
|
|
|
if (ulInputBufferLength < SizeNeeded) {
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("BundleLink: Buffer to small: Size: %d, SizeNeeded %d",
|
|
ulInputBufferLength, SizeNeeded));
|
|
|
|
return (STATUS_INFO_LENGTH_MISMATCH);
|
|
}
|
|
|
|
LINKCB_FROM_LINKH(LinkCB, In->hLinkHandle);
|
|
|
|
if (LinkCB == NULL || LinkCB->State != LINK_UP) {
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("BundleLink: Invalid LinkHandle: 0x%8.8x",
|
|
In->hLinkHandle));
|
|
return (NDISWAN_ERROR_INVALID_HANDLE);
|
|
}
|
|
|
|
BUNDLECB_FROM_BUNDLEH(NewBundleCB, In->hBundleHandle);
|
|
|
|
if (NewBundleCB == NULL) {
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("BundleLink: Invalid BundleHandle: 0x%8.8x",
|
|
In->hBundleHandle));
|
|
return (NDISWAN_ERROR_INVALID_HANDLE);
|
|
}
|
|
|
|
//
|
|
// Get the Bundle that this link currently belongs to
|
|
//
|
|
OldBundleCB = LinkCB->BundleCB;
|
|
|
|
if (OldBundleCB == NULL) {
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("BundleLink: OldBundleCB == NULL! LinkHandle: 0x%8.8x",
|
|
In->hLinkHandle));
|
|
return (NDISWAN_ERROR_INVALID_HANDLE);
|
|
|
|
}
|
|
|
|
if (OldBundleCB == NewBundleCB) {
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO,
|
|
("BundleLink: OldBundle == NewBundle! LinkHandle 0x%8.8x BundleHandle 0x%8.8x",
|
|
In->hLinkHandle, In->hBundleHandle));
|
|
return (NDISWAN_ERROR_INVALID_HANDLE);
|
|
|
|
}
|
|
|
|
NdisAcquireSpinLock(&OldBundleCB->Lock);
|
|
|
|
if (OldBundleCB->State != BUNDLE_UP) {
|
|
NdisReleaseSpinLock(&OldBundleCB->Lock);
|
|
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("BundleLink: Invalid BundleState: 0x%8.8x",
|
|
OldBundleCB->State));
|
|
return (NDISWAN_ERROR_INVALID_HANDLE);
|
|
}
|
|
|
|
NdisReleaseSpinLock(&OldBundleCB->Lock);
|
|
|
|
NdisAcquireSpinLock(&NewBundleCB->Lock);
|
|
|
|
if (NewBundleCB->State != BUNDLE_UP) {
|
|
NdisReleaseSpinLock(&NewBundleCB->Lock);
|
|
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("BundleLink: Invalid BundleState: 0x%8.8x",
|
|
NewBundleCB->State));
|
|
return (NDISWAN_ERROR_INVALID_HANDLE);
|
|
}
|
|
|
|
NdisReleaseSpinLock(&NewBundleCB->Lock);
|
|
|
|
NdisAcquireSpinLock(&OldBundleCB->Lock);
|
|
|
|
if (OldBundleCB->OutstandingFrames != 0) {
|
|
|
|
OldBundleCB->State = BUNDLE_GOING_DOWN;
|
|
|
|
NdisWanClearSyncEvent(&OldBundleCB->OutstandingFramesEvent);
|
|
|
|
OldBundleCB->Flags |= FRAMES_PENDING;
|
|
|
|
NdisReleaseSpinLock(&OldBundleCB->Lock);
|
|
|
|
NdisWanWaitForSyncEvent(&OldBundleCB->OutstandingFramesEvent);
|
|
|
|
NdisAcquireSpinLock(&OldBundleCB->Lock);
|
|
|
|
}
|
|
|
|
OldBundleCB->State = BUNDLE_DOWN;
|
|
|
|
//
|
|
// Remove the link from the old bundle
|
|
//
|
|
RemoveLinkFromBundle(OldBundleCB, LinkCB);
|
|
|
|
NdisReleaseSpinLock(&OldBundleCB->Lock);
|
|
|
|
RemoveBundleFromConnectionTable(OldBundleCB);
|
|
|
|
NdisWanReturnBundleCB(OldBundleCB);
|
|
|
|
//
|
|
// Add the link to the new bundle
|
|
//
|
|
AddLinkToBundle(NewBundleCB, LinkCB);
|
|
|
|
return (NDIS_STATUS_SUCCESS);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
EnumLinksInBundle(
|
|
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;
|
|
PNDISWAN_ENUM_LINKS_IN_BUNDLE In = (PNDISWAN_ENUM_LINKS_IN_BUNDLE)pInputBuffer;
|
|
PNDISWAN_ENUM_LINKS_IN_BUNDLE Out = (PNDISWAN_ENUM_LINKS_IN_BUNDLE)pOutputBuffer;
|
|
ULONG SizeNeeded, i;
|
|
PBUNDLECB BundleCB;
|
|
PLINKCB LinkCB;
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("EnumLinksInBundle:"));
|
|
|
|
|
|
BUNDLECB_FROM_BUNDLEH(BundleCB, In->hBundleHandle);
|
|
|
|
if (BundleCB != NULL) {
|
|
|
|
SizeNeeded = sizeof(NDISWAN_ENUM_LINKS_IN_BUNDLE) +
|
|
(sizeof(NDIS_HANDLE) * BundleCB->ulLinkCBCount);
|
|
|
|
*pulBytesWritten = SizeNeeded;
|
|
|
|
if (ulOutputBufferLength >= SizeNeeded) {
|
|
|
|
NdisAcquireSpinLock(&BundleCB->Lock);
|
|
|
|
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;
|
|
}
|
|
|
|
NdisReleaseSpinLock(&BundleCB->Lock);
|
|
|
|
} else {
|
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("EnumLinksInBundle: Buffer to small: Size: %d, SizeNeeded %d",
|
|
ulOutputBufferLength, SizeNeeded));
|
|
}
|
|
|
|
} else {
|
|
|
|
Status = NDISWAN_ERROR_INVALID_HANDLE;
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("EnumLinksInBundle: Invalid BundleHandle: 0x%8.8x",
|
|
In->hBundleHandle));
|
|
}
|
|
|
|
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;
|
|
PPROTOCOLCB ProtocolCB;
|
|
|
|
#ifdef BANDWIDTH_ON_DEMAND
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("SetProtocolPriority:"));
|
|
|
|
*pulBytesWritten = SizeNeeded;
|
|
|
|
if (ulInputBufferLength >= SizeNeeded) {
|
|
//
|
|
// If this is a valid bundle handle
|
|
//
|
|
BUNDLECB_FROM_BUNDLEH(BundleCB, In->hBundleHandle);
|
|
|
|
if (BundleCB != NULL) {
|
|
ULONG BytesPerSecond;
|
|
|
|
//
|
|
// Walk the protocolcb list looking for this protocol type
|
|
// and set it's priority level
|
|
//
|
|
NdisAcquireSpinLock(&BundleCB->Lock);
|
|
|
|
BundleCB->Flags |= PROTOCOL_PRIORITY;
|
|
|
|
BytesPerSecond = (BundleCB->LineUpInfo.BundleSpeed * 100) / 8;
|
|
|
|
for (ProtocolCB = (PPROTOCOLCB)BundleCB->ProtocolCBList.Flink;
|
|
(PVOID)ProtocolCB != (PVOID)&BundleCB->ProtocolCBList;
|
|
ProtocolCB = (PPROTOCOLCB)ProtocolCB->Linkage.Flink) {
|
|
|
|
if (ProtocolCB->usProtocolType == In->usProtocolType) {
|
|
|
|
ProtocolCB->usPriority = In->usPriority;
|
|
|
|
ProtocolCB->ulByteQuota =
|
|
(BytesPerSecond * ProtocolCB->usPriority) / 100;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Sort the list so that highest priorty protcol is at the head
|
|
//
|
|
SortProtocolListByPriority(BundleCB);
|
|
|
|
NdisReleaseSpinLock(&BundleCB->Lock);
|
|
|
|
} else {
|
|
Status = NDISWAN_ERROR_INVALID_HANDLE;
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("SetProtocolPriority: Invalid BundleHandle: 0x%8.8x",
|
|
In->hBundleHandle));
|
|
}
|
|
|
|
} else {
|
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("SetProtocolPriority: Buffer to small: Size: %d, SizeNeeded %d",
|
|
ulInputBufferLength, SizeNeeded));
|
|
}
|
|
|
|
#endif // end of BANDWIDTH_ON_DEMAND
|
|
|
|
return (Status);
|
|
}
|
|
|
|
|
|
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;
|
|
ULONG SizeNeeded = sizeof(NDISWAN_SET_BANDWIDTH_ON_DEMAND);
|
|
PNDISWAN_SET_BANDWIDTH_ON_DEMAND In = (PNDISWAN_SET_BANDWIDTH_ON_DEMAND)pInputBuffer;
|
|
|
|
#ifdef BANDWIDTH_ON_DEMAND
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("SetBandwidthOnDemand:"));
|
|
|
|
*pulBytesWritten = SizeNeeded;
|
|
|
|
if (ulInputBufferLength >= SizeNeeded) {
|
|
//
|
|
// If this is a valid bundle handle
|
|
//
|
|
BUNDLECB_FROM_BUNDLEH(BundleCB, In->hBundleHandle);
|
|
|
|
if (BundleCB != NULL) {
|
|
|
|
WAN_TIME Temp1, Temp2;
|
|
ULONG SecondsInSamplePeriod;
|
|
ULONG BytesPerSecond;
|
|
ULONG BytesInSamplePeriod;
|
|
PSAMPLE_TABLE UpperSampleTable = &BundleCB->UpperBonDInfo.SampleTable;
|
|
PSAMPLE_TABLE LowerSampleTable = &BundleCB->LowerBonDInfo.SampleTable;
|
|
|
|
|
|
NdisAcquireSpinLock(&BundleCB->Lock);
|
|
|
|
//
|
|
// We need to init the sample period in 100 nanoseconds
|
|
//
|
|
NdisWanInitWanTime(&Temp1, MILS_TO_100NANOS);
|
|
NdisWanInitWanTime(&Temp2, In->ulUpperSamplePeriod);
|
|
NdisWanMultiplyWanTime(&UpperSampleTable->SamplePeriod,
|
|
&Temp1,
|
|
&Temp2);
|
|
|
|
NdisWanInitWanTime(&Temp2, In->ulLowerSamplePeriod);
|
|
NdisWanMultiplyWanTime(&LowerSampleTable->SamplePeriod,
|
|
&Temp1,
|
|
&Temp2);
|
|
|
|
//
|
|
// The sample rate is the sample period divided by the number of
|
|
// samples in the sample array
|
|
//
|
|
NdisWanInitWanTime(&Temp1, UpperSampleTable->ulSampleArraySize);
|
|
NdisWanDivideWanTime(&UpperSampleTable->SampleRate,
|
|
&UpperSampleTable->SamplePeriod,
|
|
&Temp1);
|
|
|
|
//
|
|
// The sample rate is the sample period divided by the number of
|
|
// samples in the sample array
|
|
//
|
|
NdisWanInitWanTime(&Temp2, LowerSampleTable->ulSampleArraySize);
|
|
NdisWanDivideWanTime(&LowerSampleTable->SampleRate,
|
|
&LowerSampleTable->SamplePeriod,
|
|
&Temp2);
|
|
|
|
//
|
|
// Convert %bandwidth to Bytes/SamplePeriod
|
|
// 100bsp * 100 / 8 = BytesPerSecond
|
|
// BytesPerSecond * SecondsInSamplePeriod = BytesInSamplePeriod
|
|
// BytesInSamplePeriod * %Bandwidth / 100 = BytesInSamplePeriod
|
|
//
|
|
BundleCB->UpperBonDInfo.ulSecondsInSamplePeriod =
|
|
SecondsInSamplePeriod = In->ulUpperSamplePeriod / 1000;
|
|
|
|
BytesPerSecond = BundleCB->LineUpInfo.BundleSpeed * 100 / 8;
|
|
|
|
BytesInSamplePeriod = BytesPerSecond * SecondsInSamplePeriod;
|
|
|
|
BundleCB->UpperBonDInfo.ulBytesThreshold = BytesInSamplePeriod *
|
|
In->usUpperThreshold / 100;
|
|
|
|
BundleCB->UpperBonDInfo.usPercentBandwidth =
|
|
In->usUpperThreshold;
|
|
|
|
BundleCB->LowerBonDInfo.ulSecondsInSamplePeriod =
|
|
SecondsInSamplePeriod = In->ulLowerSamplePeriod / 1000;
|
|
|
|
BytesInSamplePeriod = BytesPerSecond * SecondsInSamplePeriod;
|
|
|
|
BundleCB->LowerBonDInfo.ulBytesThreshold = BytesInSamplePeriod *
|
|
In->usLowerThreshold / 100;
|
|
|
|
BundleCB->LowerBonDInfo.usPercentBandwidth =
|
|
In->usLowerThreshold;
|
|
|
|
BundleCB->UpperBonDInfo.State = BonDIdle;
|
|
BundleCB->LowerBonDInfo.State = BonDIdle;
|
|
|
|
NdisReleaseSpinLock(&BundleCB->Lock);
|
|
|
|
} else {
|
|
Status = NDISWAN_ERROR_INVALID_HANDLE;
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("SetBandwidthOnDemand: Invalid BundleHandle: 0x%8.8x",
|
|
In->hBundleHandle));
|
|
}
|
|
|
|
} else {
|
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("SetBandwidthOnDemand: Buffer to small: Size: %d, SizeNeeded %d",
|
|
ulInputBufferLength, SizeNeeded));
|
|
}
|
|
|
|
#endif // end of BANDWIDTH_ON_DEMAND
|
|
|
|
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:
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status = STATUS_PENDING;
|
|
ULONG SizeNeeded = sizeof(NDISWAN_SET_THRESHOLD_EVENT);
|
|
PWAN_ASYNC_EVENT pAsyncEvent;
|
|
PIRP pIrp = (PIRP)pInputBuffer;
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("SetThresholdEvent:"));
|
|
|
|
*pulBytesWritten = SizeNeeded;
|
|
|
|
if (ulInputBufferLength >= SizeNeeded) {
|
|
|
|
NdisWanAllocateMemory(&pAsyncEvent, sizeof(WAN_ASYNC_EVENT));
|
|
|
|
if (pAsyncEvent != NULL) {
|
|
KIRQL Irql;
|
|
|
|
//
|
|
// The IRP was pended so setup a cancel routine and let the
|
|
// i/o subsystem know about the pend.
|
|
//
|
|
IoAcquireCancelSpinLock(&Irql);
|
|
|
|
IoMarkIrpPending(pIrp);
|
|
|
|
//
|
|
// Setup the structure
|
|
//
|
|
pAsyncEvent->Context = (PVOID)pIrp;
|
|
|
|
InsertTailGlobalList(ThresholdEventQueue, &(pAsyncEvent->Linkage));
|
|
|
|
IoSetCancelRoutine(pIrp, NdisWanCancelRoutine);
|
|
|
|
IoReleaseCancelSpinLock(Irql);
|
|
|
|
} else {
|
|
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("SetThresholdEvent: Failed to allocate asyncevent storage"));
|
|
}
|
|
|
|
} else {
|
|
|
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("SetThresholdEvent: Buffer to small: Size: %d, SizeNeeded %d",
|
|
ulInputBufferLength, SizeNeeded));
|
|
}
|
|
|
|
return (Status);
|
|
}
|
|
#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:
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("FlushThresholdEvents:"));
|
|
|
|
CancelThresholdEvents();
|
|
|
|
return (Status);
|
|
}
|
|
|
|
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;
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("IoSendPacket:"));
|
|
|
|
*pulBytesWritten = SizeNeeded;
|
|
|
|
if (ulInputBufferLength >= SizeNeeded) {
|
|
|
|
//
|
|
// Verify the handle is a valid link or bundle handle
|
|
//
|
|
if (IsHandleValid(In->usHandleType, In->hHandle)) {
|
|
//
|
|
// Queue an Ndis Packet for this send
|
|
//
|
|
Status = BuildIoPacket(In, FALSE);
|
|
|
|
} else {
|
|
Status = NDISWAN_ERROR_INVALID_HANDLE;
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("IoSendPacket: Invalid Handle: 0x%8.8x, HandleType: 0x%4.4x",
|
|
In->hHandle, In->usHandleType));
|
|
}
|
|
|
|
} else {
|
|
|
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("IoSendPacket: Buffer to small: Size: %d, SizeNeeded %d",
|
|
ulInputBufferLength, SizeNeeded));
|
|
}
|
|
|
|
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:
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status = STATUS_PENDING;
|
|
ULONG SizeNeeded = sizeof(NDISWAN_IO_PACKET);
|
|
PWAN_ASYNC_EVENT pAsyncEvent;
|
|
PIRP pIrp = (PIRP)pInputBuffer;
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("IoReceivePacket:"));
|
|
|
|
*pulBytesWritten = SizeNeeded;
|
|
|
|
if (ulInputBufferLength >= SizeNeeded) {
|
|
|
|
NdisWanAllocateMemory(&pAsyncEvent, sizeof(WAN_ASYNC_EVENT));
|
|
|
|
if (pAsyncEvent != NULL) {
|
|
KIRQL Irql;
|
|
|
|
//
|
|
// The IRP was pended so setup a cancel routine and let the
|
|
// i/o subsystem know about the pend.
|
|
//
|
|
IoAcquireCancelSpinLock(&Irql);
|
|
|
|
IoMarkIrpPending(pIrp);
|
|
|
|
//
|
|
// Setup the structure
|
|
//
|
|
pAsyncEvent->Context = (PVOID)pIrp;
|
|
|
|
InsertTailGlobalList(RecvPacketQueue, &(pAsyncEvent->Linkage));
|
|
|
|
IoSetCancelRoutine(pIrp, NdisWanCancelRoutine);
|
|
|
|
IoReleaseCancelSpinLock(Irql);
|
|
|
|
} else {
|
|
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("IoReceivePacket: Failed to allocate asyncevent storage"));
|
|
}
|
|
|
|
} else {
|
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("IoReceivePacket: Buffer to small: Size: %d, SizeNeeded %d",
|
|
ulInputBufferLength, SizeNeeded));
|
|
}
|
|
|
|
return (Status);
|
|
}
|
|
#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:
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("FlushReceivePacket:"));
|
|
|
|
CancelIoReceivePackets();
|
|
|
|
return (Status);
|
|
}
|
|
|
|
|
|
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;
|
|
PLINKCB LinkCB;
|
|
NDIS_REQUEST NdisRequest;
|
|
NDIS_WAN_GET_STATS_INFO WanMiniportStats;
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("GetStatistics:"));
|
|
|
|
*pulBytesWritten = SizeNeeded;
|
|
|
|
if (ulOutputBufferLength < SizeNeeded) {
|
|
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetStatistics: Buffer to small: Size: %d, SizeNeeded %d",
|
|
ulOutputBufferLength, SizeNeeded));
|
|
|
|
return (STATUS_INFO_LENGTH_MISMATCH);
|
|
}
|
|
|
|
NdisZeroMemory(&Out->Stats, sizeof(Out->Stats));
|
|
|
|
if (In->usHandleType == LINKHANDLE) {
|
|
|
|
//
|
|
// Looking for link stats
|
|
//
|
|
LINKCB_FROM_LINKH(LinkCB, In->hHandle);
|
|
|
|
if (LinkCB == NULL || LinkCB->State != LINK_UP) {
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetStatistics: Invalid LinkHandle: 0x%8.8x",
|
|
In->hHandle));
|
|
|
|
return (NDISWAN_ERROR_INVALID_HANDLE);
|
|
}
|
|
|
|
BundleCB = BUNDLECB_FROM_LINKCB(LinkCB);
|
|
|
|
if (BundleCB == NULL) {
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetStatistics: Invalid BundleHandle: 0x%8.8x",
|
|
In->hHandle));
|
|
|
|
return (NDISWAN_ERROR_INVALID_HANDLE);
|
|
}
|
|
|
|
NdisAcquireSpinLock(&BundleCB->Lock);
|
|
|
|
//
|
|
// Copy the stats over
|
|
//
|
|
NdisMoveMemory((PUCHAR)&Out->Stats.LinkStats,
|
|
(PUCHAR)&LinkCB->LinkStats,
|
|
sizeof(WAN_STATS));
|
|
|
|
//
|
|
// Copy the stats over
|
|
//
|
|
NdisMoveMemory((PUCHAR)&Out->Stats.BundleStats,
|
|
(PUCHAR)&BundleCB->BundleStats,
|
|
sizeof(WAN_STATS));
|
|
|
|
//
|
|
// If the wan miniport is doing framing or compression we
|
|
// need to get stats from it.
|
|
//
|
|
if ((BundleCB->FramingInfo.SendFramingBits & PASS_THROUGH_MODE) ||
|
|
((BundleCB->SendCompInfo.MSCompType == 0 &&
|
|
BundleCB->RecvCompInfo.MSCompType == 0) &&
|
|
(BundleCB->SendCompInfo.CompType != COMPTYPE_NONE ||
|
|
BundleCB->RecvCompInfo.CompType != COMPTYPE_NONE))) {
|
|
PWAN_ADAPTERCB WanAdapterCB = LinkCB->WanAdapterCB;
|
|
|
|
NdisZeroMemory(&WanMiniportStats, sizeof(NDIS_WAN_GET_STATS_INFO));
|
|
|
|
WanMiniportStats.NdisLinkHandle = LinkCB->LineUpInfo.NdisLinkHandle;
|
|
|
|
//
|
|
// Submit this to the WAN Miniport
|
|
//
|
|
NdisRequest.RequestType = NdisRequestQueryInformation;
|
|
NdisRequest.DATA.QUERY_INFORMATION.Oid = OID_WAN_GET_STATS_INFO;
|
|
NdisRequest.DATA.QUERY_INFORMATION.InformationBuffer = &WanMiniportStats;
|
|
NdisRequest.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(NDIS_WAN_GET_STATS_INFO);
|
|
|
|
NdisReleaseSpinLock(&BundleCB->Lock);
|
|
|
|
if (NdisWanSubmitNdisRequest(WanAdapterCB,
|
|
&NdisRequest,
|
|
SYNC,
|
|
NDISWAN) == NDIS_STATUS_SUCCESS){
|
|
|
|
//
|
|
// Copy the stats over
|
|
//
|
|
NdisMoveMemory((PUCHAR)&Out->Stats.LinkStats,
|
|
(PUCHAR)&WanMiniportStats.BytesSent,
|
|
sizeof(WAN_STATS));
|
|
|
|
//
|
|
// Copy the stats over
|
|
//
|
|
NdisMoveMemory((PUCHAR)&Out->Stats.BundleStats,
|
|
(PUCHAR)&WanMiniportStats.BytesSent,
|
|
sizeof(WAN_STATS));
|
|
|
|
}
|
|
} else {
|
|
NdisReleaseSpinLock(&BundleCB->Lock);
|
|
}
|
|
|
|
} else if (In->usHandleType == BUNDLEHANDLE) {
|
|
|
|
//
|
|
// Looking for bundle stats
|
|
//
|
|
BUNDLECB_FROM_BUNDLEH(BundleCB, In->hHandle);
|
|
|
|
if (BundleCB == NULL) {
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetStatistics: Invalid BundleHandle: 0x%8.8x",
|
|
In->hHandle));
|
|
|
|
return (NDISWAN_ERROR_INVALID_HANDLE);
|
|
}
|
|
|
|
NdisAcquireSpinLock(&BundleCB->Lock);
|
|
|
|
//
|
|
// Copy the stats over
|
|
//
|
|
NdisMoveMemory((PUCHAR)&Out->Stats.BundleStats,
|
|
(PUCHAR)&BundleCB->BundleStats,
|
|
sizeof(WAN_STATS));
|
|
|
|
//
|
|
// If the wan miniport is doing framing or compression we
|
|
// need to get stats from it.
|
|
//
|
|
if ((BundleCB->LinkCBList.Flink != &BundleCB->LinkCBList) &&
|
|
((BundleCB->FramingInfo.SendFramingBits & PASS_THROUGH_MODE) ||
|
|
((BundleCB->SendCompInfo.MSCompType == 0 &&
|
|
BundleCB->RecvCompInfo.MSCompType == 0) &&
|
|
(BundleCB->SendCompInfo.CompType != COMPTYPE_NONE ||
|
|
BundleCB->RecvCompInfo.CompType != COMPTYPE_NONE)))) {
|
|
PWAN_ADAPTERCB WanAdapterCB;
|
|
|
|
LinkCB = (PLINKCB)BundleCB->LinkCBList.Flink;
|
|
|
|
NdisZeroMemory(&WanMiniportStats, sizeof(NDIS_WAN_GET_STATS_INFO));
|
|
|
|
//
|
|
// If a miniport is doing it's own compression for this release we will
|
|
// expect that multilink is not allowed on the connection so the bundle
|
|
// will only have one link.
|
|
//
|
|
|
|
WanMiniportStats.NdisLinkHandle = LinkCB->LineUpInfo.NdisLinkHandle;
|
|
WanAdapterCB = LinkCB->WanAdapterCB;
|
|
|
|
//
|
|
// Submit this to the WAN Miniport
|
|
//
|
|
NdisRequest.RequestType = NdisRequestQueryInformation;
|
|
NdisRequest.DATA.QUERY_INFORMATION.Oid = OID_WAN_GET_STATS_INFO;
|
|
NdisRequest.DATA.QUERY_INFORMATION.InformationBuffer = &WanMiniportStats;
|
|
NdisRequest.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(NDIS_WAN_GET_STATS_INFO);
|
|
|
|
NdisReleaseSpinLock(&BundleCB->Lock);
|
|
|
|
if (NdisWanSubmitNdisRequest(WanAdapterCB,
|
|
&NdisRequest,
|
|
SYNC,
|
|
NDISWAN) == NDIS_STATUS_SUCCESS){
|
|
|
|
//
|
|
// Copy the stats over
|
|
//
|
|
NdisMoveMemory((PUCHAR)&Out->Stats.BundleStats,
|
|
(PUCHAR)&WanMiniportStats.BytesSent,
|
|
sizeof(WAN_STATS));
|
|
|
|
}
|
|
} else {
|
|
NdisReleaseSpinLock(&BundleCB->Lock);
|
|
}
|
|
|
|
} else {
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetStatistics: Invalid handle type: 0x%4.4x",
|
|
In->usHandleType));
|
|
|
|
return (NDISWAN_ERROR_INVALID_HANDLE_TYPE);
|
|
}
|
|
|
|
return (STATUS_SUCCESS);
|
|
}
|
|
|
|
|
|
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);
|
|
PLINKCB LinkCB;
|
|
PBUNDLECB BundleCB;
|
|
NDIS_REQUEST NdisRequest;
|
|
PNDISWAN_SET_LINK_INFO In = (PNDISWAN_SET_LINK_INFO)pInputBuffer;
|
|
NDIS_WAN_SET_LINK_INFO WanMiniportLinkInfo;
|
|
PWAN_LINK_INFO LinkInfo;
|
|
PWAN_ADAPTERCB WanAdapterCB;
|
|
PLINKCB TempLinkCB;
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("SetLinkInfo:"));
|
|
|
|
*pulBytesWritten = SizeNeeded;
|
|
|
|
if (ulInputBufferLength >= SizeNeeded) {
|
|
|
|
LINKCB_FROM_LINKH(LinkCB, In->hLinkHandle);
|
|
|
|
if (LinkCB == NULL || LinkCB->State != LINK_UP) {
|
|
return (NDISWAN_ERROR_INVALID_HANDLE);
|
|
}
|
|
|
|
LinkInfo = &LinkCB->LinkInfo;
|
|
WanAdapterCB = LinkCB->WanAdapterCB;
|
|
|
|
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->LineUpInfo.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
|
|
//
|
|
NdisRequest.RequestType = NdisRequestSetInformation;
|
|
NdisRequest.DATA.QUERY_INFORMATION.Oid = OID_WAN_SET_LINK_INFO;
|
|
NdisRequest.DATA.QUERY_INFORMATION.InformationBuffer = &WanMiniportLinkInfo;
|
|
NdisRequest.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(NDIS_WAN_SET_LINK_INFO);
|
|
|
|
Status = NdisWanSubmitNdisRequest(LinkCB->WanAdapterCB,
|
|
&NdisRequest,
|
|
SYNC,
|
|
NDISWAN);
|
|
|
|
if (Status == NDIS_STATUS_SUCCESS) {
|
|
|
|
BundleCB = BUNDLECB_FROM_LINKCB(LinkCB);
|
|
|
|
if (BundleCB == NULL) {
|
|
return (NDISWAN_ERROR_INVALID_HANDLE);
|
|
}
|
|
|
|
//
|
|
// Copy info into our linkcb
|
|
//
|
|
NdisAcquireSpinLock(&BundleCB->Lock);
|
|
|
|
LinkInfo->MaxSendFrameSize = In->LinkInfo.MaxSendFrameSize;
|
|
LinkInfo->MaxRecvFrameSize = In->LinkInfo.MaxRecvFrameSize;
|
|
LinkInfo->SendFramingBits = In->LinkInfo.SendFramingBits;
|
|
LinkInfo->RecvFramingBits = In->LinkInfo.RecvFramingBits;
|
|
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;
|
|
|
|
//
|
|
// 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 : DEFAULT_MAX_MRRU;
|
|
|
|
//
|
|
// 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;
|
|
}
|
|
}
|
|
|
|
BundleCB->RecvDescMax = ((((BundleCB->LineUpInfo.BundleSpeed * 100) / 8) * 3) /
|
|
BundleCB->FramingInfo.MaxRRecvFrameSize) +
|
|
BundleCB->ulLinkCBCount;
|
|
|
|
NdisReleaseSpinLock(&BundleCB->Lock);
|
|
|
|
} else {
|
|
Status = STATUS_UNSUCCESSFUL;
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("SetLinkInfo: Error submitting request to Wan Miniport!"));
|
|
}
|
|
|
|
} else {
|
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("SetLinkInfo: Buffer to small: Size: %d, SizeNeeded %d",
|
|
ulInputBufferLength, SizeNeeded));
|
|
}
|
|
|
|
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;
|
|
NDIS_REQUEST NdisRequest;
|
|
NDIS_WAN_GET_LINK_INFO WanMiniportLinkInfo;
|
|
PWAN_LINK_INFO LinkInfo;
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("GetLinkInfo:"));
|
|
|
|
*pulBytesWritten = SizeNeeded;
|
|
|
|
if (ulOutputBufferLength >= SizeNeeded) {
|
|
|
|
LINKCB_FROM_LINKH(LinkCB, In->hLinkHandle);
|
|
|
|
if (LinkCB == NULL || LinkCB->State != LINK_UP) {
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetLinkInfo: Invalid LinkHandle: 0x%8.8x",
|
|
In->hLinkHandle));
|
|
return (NDISWAN_ERROR_INVALID_HANDLE);
|
|
}
|
|
|
|
LinkInfo = &LinkCB->LinkInfo;
|
|
|
|
NdisZeroMemory(&WanMiniportLinkInfo, sizeof (NDIS_WAN_GET_LINK_INFO));
|
|
|
|
//
|
|
// Setup the link context for this request
|
|
//
|
|
WanMiniportLinkInfo.NdisLinkHandle = LinkCB->LineUpInfo.NdisLinkHandle;
|
|
|
|
//
|
|
// Submit this to the WAN Miniport
|
|
//
|
|
NdisRequest.RequestType = NdisRequestQueryInformation;
|
|
NdisRequest.DATA.QUERY_INFORMATION.Oid = OID_WAN_GET_LINK_INFO;
|
|
NdisRequest.DATA.QUERY_INFORMATION.InformationBuffer = &WanMiniportLinkInfo;
|
|
NdisRequest.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(NDIS_WAN_GET_LINK_INFO);
|
|
|
|
Status = NdisWanSubmitNdisRequest(LinkCB->WanAdapterCB,
|
|
&NdisRequest,
|
|
SYNC,
|
|
NDISWAN);
|
|
|
|
if (Status == NDIS_STATUS_SUCCESS) {
|
|
|
|
LinkInfo->MaxSendFrameSize = WanMiniportLinkInfo.MaxSendFrameSize;
|
|
LinkInfo->MaxRecvFrameSize = WanMiniportLinkInfo.MaxRecvFrameSize;
|
|
LinkInfo->SendFramingBits = WanMiniportLinkInfo.SendFramingBits;
|
|
LinkInfo->RecvFramingBits = WanMiniportLinkInfo.RecvFramingBits;
|
|
LinkInfo->SendCompressionBits = WanMiniportLinkInfo.SendCompressionBits;
|
|
LinkInfo->RecvCompressionBits = WanMiniportLinkInfo.RecvCompressionBits;
|
|
LinkInfo->SendACCM = WanMiniportLinkInfo.SendACCM;
|
|
LinkInfo->RecvACCM = WanMiniportLinkInfo.RecvACCM;
|
|
|
|
//
|
|
// Fill Recv and Send MRRU
|
|
//
|
|
LinkInfo->MaxRSendFrameSize = MIN_SEND;
|
|
|
|
LinkInfo->MaxRRecvFrameSize = MAX_MRRU;
|
|
|
|
NdisMoveMemory(&Out->LinkInfo,
|
|
LinkInfo,
|
|
sizeof(WAN_LINK_INFO));
|
|
|
|
Out->hLinkHandle = LinkCB->hLinkHandle;
|
|
|
|
} else {
|
|
Status = STATUS_UNSUCCESSFUL;
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetLinkInfo: Error submitting request to Wan Miniport!"));
|
|
}
|
|
|
|
} else {
|
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetLinkInfo: Buffer to small: Size: %d, SizeNeeded %d",
|
|
ulOutputBufferLength, SizeNeeded));
|
|
}
|
|
|
|
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;
|
|
NDIS_REQUEST NdisRequest;
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("SetCompressionInfo:"));
|
|
|
|
*pulBytesWritten = SizeNeeded;
|
|
|
|
if (ulInputBufferLength >= SizeNeeded) {
|
|
PLINKCB LinkCB;
|
|
PBUNDLECB BundleCB;
|
|
NDIS_WAN_SET_COMP_INFO WanCompressionInfo;
|
|
|
|
LINKCB_FROM_LINKH(LinkCB, In->hLinkHandle);
|
|
|
|
if (LinkCB == NULL || LinkCB->State != LINK_UP) {
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("SetCompressionInfo: Invalid LinkHandle: 0x%8.8x",
|
|
In->hLinkHandle));
|
|
return (NDISWAN_ERROR_INVALID_HANDLE);
|
|
}
|
|
|
|
NdisZeroMemory(&WanCompressionInfo, sizeof(NDIS_WAN_SET_COMP_INFO));
|
|
|
|
WanCompressionInfo.NdisLinkHandle =
|
|
LinkCB->LineUpInfo.NdisLinkHandle;
|
|
|
|
WanCompressionInfo.SendCapabilities.MSCompType =
|
|
In->SendCapabilities.MSCompType;
|
|
|
|
WanCompressionInfo.SendCapabilities.CompType =
|
|
In->SendCapabilities.CompType;
|
|
|
|
WanCompressionInfo.SendCapabilities.CompLength =
|
|
In->SendCapabilities.CompLength;
|
|
|
|
if (In->SendCapabilities.CompType == 0) {
|
|
NdisMoveMemory(&WanCompressionInfo.SendCapabilities.Proprietary,
|
|
&In->SendCapabilities.Proprietary,
|
|
sizeof(In->SendCapabilities.Proprietary));
|
|
} else {
|
|
NdisMoveMemory(&WanCompressionInfo.SendCapabilities.Public,
|
|
&In->SendCapabilities.Public,
|
|
sizeof(In->SendCapabilities.Public));
|
|
}
|
|
|
|
WanCompressionInfo.RecvCapabilities.MSCompType =
|
|
In->RecvCapabilities.MSCompType;
|
|
|
|
WanCompressionInfo.RecvCapabilities.CompType =
|
|
In->RecvCapabilities.CompType;
|
|
|
|
WanCompressionInfo.RecvCapabilities.CompLength =
|
|
In->RecvCapabilities.CompLength;
|
|
|
|
if (In->RecvCapabilities.CompType == 0) {
|
|
NdisMoveMemory(&WanCompressionInfo.RecvCapabilities.Proprietary,
|
|
&In->RecvCapabilities.Proprietary,
|
|
sizeof(In->RecvCapabilities.Proprietary));
|
|
} else {
|
|
NdisMoveMemory(&WanCompressionInfo.RecvCapabilities.Public,
|
|
&In->RecvCapabilities.Public,
|
|
sizeof(In->RecvCapabilities.Public));
|
|
}
|
|
|
|
//
|
|
// Submit this to the WAN Miniport
|
|
//
|
|
NdisRequest.RequestType = NdisRequestSetInformation;
|
|
NdisRequest.DATA.QUERY_INFORMATION.Oid = OID_WAN_SET_COMP_INFO;
|
|
NdisRequest.DATA.QUERY_INFORMATION.InformationBuffer = &WanCompressionInfo;
|
|
NdisRequest.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(NDIS_WAN_SET_COMP_INFO);
|
|
|
|
NdisWanSubmitNdisRequest(LinkCB->WanAdapterCB,
|
|
&NdisRequest,
|
|
SYNC,
|
|
NDISWAN);
|
|
|
|
BundleCB = BUNDLECB_FROM_LINKCB(LinkCB);
|
|
|
|
if (BundleCB == NULL) {
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("SetCompressionInfo: Invalid LinkHandle: 0x%8.8x",
|
|
In->hLinkHandle));
|
|
return (NDISWAN_ERROR_INVALID_HANDLE);
|
|
|
|
}
|
|
|
|
NdisAcquireSpinLock(&BundleCB->Lock);
|
|
|
|
//
|
|
// Store the compression info in our bundlecb
|
|
//
|
|
NdisMoveMemory(&BundleCB->SendCompInfo,
|
|
&In->SendCapabilities,
|
|
sizeof(COMPRESS_INFO));
|
|
|
|
NdisMoveMemory(&BundleCB->RecvCompInfo,
|
|
&In->RecvCapabilities,
|
|
sizeof(COMPRESS_INFO));
|
|
|
|
WanAllocateCCP(BundleCB);
|
|
|
|
NdisReleaseSpinLock(&BundleCB->Lock);
|
|
|
|
} else {
|
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("SetCompressionInfo: Buffer to small: Size: %d, SizeNeeded %d",
|
|
ulInputBufferLength, SizeNeeded));
|
|
}
|
|
|
|
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;
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("GetCompressionInfo:"));
|
|
|
|
*pulBytesWritten = SizeNeeded;
|
|
|
|
if (ulOutputBufferLength >= SizeNeeded) {
|
|
PLINKCB LinkCB;
|
|
NDIS_REQUEST NdisRequest;
|
|
PBUNDLECB BundleCB;
|
|
NDIS_WAN_GET_COMP_INFO WanCompressionInfo;
|
|
ULONG i;
|
|
|
|
LINKCB_FROM_LINKH(LinkCB, In->hLinkHandle);
|
|
|
|
if (LinkCB == NULL || LinkCB->State != LINK_UP) {
|
|
return (NDISWAN_ERROR_INVALID_HANDLE);
|
|
}
|
|
|
|
NdisZeroMemory(&WanCompressionInfo, sizeof(NDIS_WAN_GET_COMP_INFO));
|
|
|
|
WanCompressionInfo.NdisLinkHandle = LinkCB->LineUpInfo.NdisLinkHandle;
|
|
|
|
//
|
|
// Submit this to the WAN Miniport
|
|
//
|
|
NdisRequest.RequestType = NdisRequestQueryInformation;
|
|
NdisRequest.DATA.QUERY_INFORMATION.Oid = OID_WAN_GET_COMP_INFO;
|
|
NdisRequest.DATA.QUERY_INFORMATION.InformationBuffer = &WanCompressionInfo;
|
|
NdisRequest.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(NDIS_WAN_SET_COMP_INFO);
|
|
|
|
Status = NdisWanSubmitNdisRequest(LinkCB->WanAdapterCB,
|
|
&NdisRequest,
|
|
SYNC,
|
|
NDISWAN);
|
|
|
|
if (Status == NDIS_STATUS_SUCCESS) {
|
|
|
|
//
|
|
// This miniport is doing some kind of compression!
|
|
// Fill in the miniport specific stuff
|
|
//
|
|
Out->SendCapabilities.MSCompType =
|
|
WanCompressionInfo.SendCapabilities.MSCompType;
|
|
Out->SendCapabilities.CompType =
|
|
WanCompressionInfo.SendCapabilities.CompType;
|
|
Out->SendCapabilities.CompLength =
|
|
WanCompressionInfo.SendCapabilities.CompLength;
|
|
|
|
if (Out->SendCapabilities.CompType == 0) {
|
|
NdisMoveMemory((PUCHAR)&Out->SendCapabilities.Proprietary,
|
|
(PUCHAR)&WanCompressionInfo.SendCapabilities.Proprietary,
|
|
sizeof(In->SendCapabilities.Proprietary));
|
|
} else {
|
|
NdisMoveMemory((PUCHAR)&Out->SendCapabilities.Public,
|
|
(PUCHAR)&WanCompressionInfo.SendCapabilities.Public,
|
|
sizeof(In->SendCapabilities.Public));
|
|
}
|
|
|
|
Out->RecvCapabilities.MSCompType =
|
|
WanCompressionInfo.RecvCapabilities.MSCompType;
|
|
Out->RecvCapabilities.CompType =
|
|
WanCompressionInfo.RecvCapabilities.CompType;
|
|
Out->RecvCapabilities.CompLength =
|
|
WanCompressionInfo.RecvCapabilities.CompLength;
|
|
|
|
if (Out->RecvCapabilities.CompType == 0) {
|
|
NdisMoveMemory((PUCHAR)&Out->RecvCapabilities.Proprietary,
|
|
(PUCHAR)&WanCompressionInfo.RecvCapabilities.Proprietary,
|
|
sizeof(In->SendCapabilities.Proprietary));
|
|
} else {
|
|
NdisMoveMemory((PUCHAR)&Out->RecvCapabilities.Public,
|
|
(PUCHAR)&WanCompressionInfo.RecvCapabilities.Public,
|
|
sizeof(In->SendCapabilities.Public));
|
|
}
|
|
|
|
} else {
|
|
Status = STATUS_SUCCESS;
|
|
Out->SendCapabilities.CompType = COMPTYPE_NONE;
|
|
Out->SendCapabilities.CompLength = 0;
|
|
Out->RecvCapabilities.CompType = COMPTYPE_NONE;
|
|
Out->RecvCapabilities.CompLength = 0;
|
|
}
|
|
|
|
BundleCB = BUNDLECB_FROM_LINKCB(LinkCB);
|
|
|
|
if (BundleCB == NULL) {
|
|
return (NDISWAN_ERROR_INVALID_HANDLE);
|
|
}
|
|
|
|
NdisAcquireSpinLock(&BundleCB->Lock);
|
|
|
|
//
|
|
// 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->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));
|
|
|
|
//
|
|
// We will set encryption capabilities based on session key
|
|
// availability. If the LMSessionKey is all zero's we will not
|
|
// offer 40bit encryption. If the UserSessionKey is all zero's
|
|
// we will not offer 128bit encryption.
|
|
//
|
|
Out->SendCapabilities.MSCompType = NDISWAN_COMPRESSION;
|
|
|
|
for (i = 0; i < sizeof(Out->SendCapabilities.LMSessionKey); i++) {
|
|
if (Out->SendCapabilities.LMSessionKey[i] != 0) {
|
|
Out->SendCapabilities.MSCompType |= (NDISWAN_ENCRYPTION | NDISWAN_40_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
|
|
|
|
Out->RecvCapabilities.MSCompType = NDISWAN_COMPRESSION;
|
|
|
|
for (i = 0; i < sizeof(Out->RecvCapabilities.LMSessionKey); i++) {
|
|
if (Out->RecvCapabilities.LMSessionKey[i] != 0) {
|
|
Out->RecvCapabilities.MSCompType |= (NDISWAN_ENCRYPTION | NDISWAN_40_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
|
|
|
|
NdisReleaseSpinLock(&BundleCB->Lock);
|
|
|
|
} else {
|
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetCompressionInfo: Buffer to small: Size: %d, SizeNeeded %d",
|
|
ulOutputBufferLength, SizeNeeded));
|
|
}
|
|
|
|
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;
|
|
PNDISWAN_SET_VJ_INFO In = (PNDISWAN_SET_VJ_INFO)pInputBuffer;
|
|
PLINKCB LinkCB;
|
|
PBUNDLECB BundleCB;
|
|
ULONG SizeNeeded = sizeof(NDISWAN_SET_VJ_INFO);
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("SetVJInfo:"));
|
|
|
|
*pulBytesWritten = SizeNeeded;
|
|
|
|
if (ulInputBufferLength >= SizeNeeded) {
|
|
|
|
LINKCB_FROM_LINKH(LinkCB, In->hLinkHandle);
|
|
|
|
if (LinkCB == NULL || LinkCB->State != LINK_UP) {
|
|
return (NDISWAN_ERROR_INVALID_HANDLE);
|
|
}
|
|
|
|
BundleCB = BUNDLECB_FROM_LINKCB(LinkCB);
|
|
|
|
if (BundleCB == NULL) {
|
|
return (NDISWAN_ERROR_INVALID_HANDLE);
|
|
}
|
|
|
|
NdisAcquireSpinLock(&BundleCB->Lock);
|
|
|
|
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!"));
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
NdisReleaseSpinLock(&BundleCB->Lock);
|
|
|
|
} else {
|
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("SetVJInfo: Buffer to small: Size: %d, SizeNeeded %d",
|
|
ulInputBufferLength, SizeNeeded));
|
|
}
|
|
|
|
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:
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
PNDISWAN_GET_VJ_INFO In = (PNDISWAN_GET_VJ_INFO)pInputBuffer;
|
|
PNDISWAN_GET_VJ_INFO Out = (PNDISWAN_GET_VJ_INFO)pOutputBuffer;
|
|
ULONG SizeNeeded = sizeof(NDISWAN_GET_VJ_INFO);
|
|
PLINKCB LinkCB;
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("GetVJInfo:"));
|
|
|
|
*pulBytesWritten = SizeNeeded;
|
|
|
|
if (ulOutputBufferLength >= SizeNeeded) {
|
|
|
|
LINKCB_FROM_LINKH(LinkCB, In->hLinkHandle);
|
|
|
|
if (LinkCB == NULL || LinkCB->State != LINK_UP) {
|
|
return (NDISWAN_ERROR_INVALID_HANDLE);
|
|
}
|
|
|
|
Out->SendCapabilities.IPCompressionProtocol =
|
|
Out->RecvCapabilities.IPCompressionProtocol = 0x2D;
|
|
|
|
Out->SendCapabilities.MaxSlotID =
|
|
Out->RecvCapabilities.MaxSlotID = MAX_VJ_STATES - 1;
|
|
|
|
Out->SendCapabilities.CompSlotID =
|
|
Out->RecvCapabilities.CompSlotID = 1;
|
|
|
|
} else {
|
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetVJInfo: Buffer to small: Size: %d, SizeNeeded %d",
|
|
ulOutputBufferLength, SizeNeeded));
|
|
}
|
|
|
|
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:
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
ULONG SizeNeeded = sizeof(NDISWAN_GET_BANDWIDTH_UTILIZATION);
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("GetBandwidthUtilization:"));
|
|
|
|
*pulBytesWritten = SizeNeeded;
|
|
|
|
if (ulOutputBufferLength >= SizeNeeded) {
|
|
|
|
} else {
|
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetBandwidthUtilization: Buffer to small: Size: %d, SizeNeeded %d",
|
|
ulOutputBufferLength, SizeNeeded));
|
|
}
|
|
|
|
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:
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
ULONG SizeNeeded = sizeof(NDISWAN_ENUM_PROTOCOL_UTILIZATION);
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("EnumProtocolUtilization:"));
|
|
|
|
*pulBytesWritten = SizeNeeded;
|
|
|
|
if (ulOutputBufferLength >= SizeNeeded) {
|
|
|
|
} else {
|
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("EnumProtocolUtilization: Buffer to small: Size: %d, SizeNeeded %d",
|
|
ulOutputBufferLength, SizeNeeded));
|
|
}
|
|
|
|
return (Status);
|
|
}
|
|
|
|
NTSTATUS
|
|
EnumActiveBundles(
|
|
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_ENUM_ACTIVE_BUNDLES);
|
|
PNDISWAN_ENUM_ACTIVE_BUNDLES Out = (PNDISWAN_ENUM_ACTIVE_BUNDLES)pOutputBuffer;
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("GetNumActiveBundles:"));
|
|
|
|
*pulBytesWritten = SizeNeeded;
|
|
|
|
if (ulOutputBufferLength >= SizeNeeded) {
|
|
|
|
//
|
|
// 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;
|
|
|
|
} else {
|
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetNumActiveBundles: Buffer to small: Size: %d, SizeNeeded %d",
|
|
ulOutputBufferLength, SizeNeeded));
|
|
}
|
|
|
|
return (Status);
|
|
}
|
|
|
|
NTSTATUS
|
|
GetWanInfo(
|
|
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_WAN_INFO);
|
|
PNDISWAN_GET_WAN_INFO In = (PNDISWAN_GET_WAN_INFO)pInputBuffer;
|
|
PNDISWAN_GET_WAN_INFO Out = (PNDISWAN_GET_WAN_INFO)pOutputBuffer;
|
|
PLINKCB LinkCB;
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("GetWanInfo:"));
|
|
|
|
*pulBytesWritten = SizeNeeded;
|
|
|
|
if (ulOutputBufferLength >= SizeNeeded) {
|
|
LINKCB_FROM_LINKH(LinkCB, In->hLinkHandle);
|
|
|
|
if (LinkCB != NULL) {
|
|
PWAN_ADAPTERCB WanAdapterCB = LinkCB->WanAdapterCB;
|
|
|
|
Out->WanInfo.MaxFrameSize = WanAdapterCB->WanInfo.MaxFrameSize;
|
|
Out->WanInfo.MaxTransmit = WanAdapterCB->WanInfo.MaxTransmit;
|
|
Out->WanInfo.FramingBits = WanAdapterCB->WanInfo.FramingBits;
|
|
Out->WanInfo.DesiredACCM = WanAdapterCB->WanInfo.DesiredACCM;
|
|
Out->WanInfo.MaxReconstructedFrameSize = MAX_MRRU;
|
|
Out->WanInfo.LinkSpeed = LinkCB->LineUpInfo.LinkSpeed * 100;
|
|
|
|
} else {
|
|
Status = NDISWAN_ERROR_INVALID_HANDLE;
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetWanInfo: Invalid LinkHandle: 0x%8.8x",
|
|
In->hLinkHandle));
|
|
}
|
|
|
|
} else {
|
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetWanInfo: Buffer to small: Size: %d, SizeNeeded %d",
|
|
ulOutputBufferLength, SizeNeeded));
|
|
}
|
|
|
|
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:
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
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%8.8x OldMask: 0x%8.8x",
|
|
NdisWanCB.ulTraceLevel, NdisWanCB.ulTraceMask));
|
|
|
|
*pulBytesWritten = SizeNeeded;
|
|
|
|
if (ulInputBufferLength >= SizeNeeded) {
|
|
NdisWanCB.ulTraceLevel = pDebugInfo->ulTraceLevel;
|
|
NdisWanCB.ulTraceMask = pDebugInfo->ulTraceMask;
|
|
} else {
|
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("Buffer to small: Size: %d, SizeNeeded %d",
|
|
ulInputBufferLength, SizeNeeded));
|
|
}
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("SetDebugInfo: NewLevel: 0x%8.8x NewMask: 0x%8.8x",
|
|
NdisWanCB.ulTraceLevel, NdisWanCB.ulTraceMask));
|
|
|
|
return (Status);
|
|
}
|
|
|
|
NTSTATUS
|
|
SetBridgeInfo(
|
|
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_BRIDGE_INFO);
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("SetBridgeInfo:"));
|
|
|
|
*pulBytesWritten = SizeNeeded;
|
|
|
|
if (ulInputBufferLength >= SizeNeeded) {
|
|
|
|
} else {
|
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
|
}
|
|
|
|
Status = STATUS_NOT_IMPLEMENTED;
|
|
|
|
return (Status);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
GetBridgeInfo(
|
|
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_BRIDGE_INFO);
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("GetBridgeInfo:"));
|
|
|
|
*pulBytesWritten = SizeNeeded;
|
|
|
|
if (ulOutputBufferLength >= SizeNeeded) {
|
|
|
|
} else {
|
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
|
}
|
|
|
|
Status = STATUS_NOT_IMPLEMENTED;
|
|
|
|
return (Status);
|
|
}
|
|
|
|
NTSTATUS
|
|
SetCIPXInfo(
|
|
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_CIPX_INFO);
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("SetCIPXInfo:"));
|
|
|
|
*pulBytesWritten = SizeNeeded;
|
|
|
|
if (ulInputBufferLength >= SizeNeeded) {
|
|
|
|
} else {
|
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
|
}
|
|
|
|
Status = STATUS_NOT_IMPLEMENTED;
|
|
|
|
return (Status);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
GetCIPXInfo(
|
|
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_CIPX_INFO);
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("GetCIPXInfo:"));
|
|
|
|
*pulBytesWritten = SizeNeeded;
|
|
|
|
if (ulOutputBufferLength >= SizeNeeded) {
|
|
|
|
} else {
|
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
|
}
|
|
|
|
Status = STATUS_NOT_IMPLEMENTED;
|
|
|
|
return (Status);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
SetEncryptionInfo(
|
|
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_ENCRYPTION_INFO);
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("SetEncryptionInfo:"));
|
|
|
|
*pulBytesWritten = SizeNeeded;
|
|
|
|
if (ulInputBufferLength >= SizeNeeded) {
|
|
|
|
} else {
|
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
|
}
|
|
|
|
Status = STATUS_NOT_IMPLEMENTED;
|
|
|
|
return (Status);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
GetEncryptionInfo(
|
|
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_ENCRYPTION_INFO);
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("GetEncryptionInfo:"));
|
|
|
|
*pulBytesWritten = SizeNeeded;
|
|
|
|
if (ulOutputBufferLength >= SizeNeeded) {
|
|
|
|
} else {
|
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
|
}
|
|
|
|
Status = STATUS_NOT_IMPLEMENTED;
|
|
|
|
return (Status);
|
|
}
|
|
|
|
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;
|
|
BOOLEAN Found = FALSE;
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("GetIdleTime:"));
|
|
|
|
*pulBytesWritten = SizeNeeded;
|
|
|
|
if (ulOutputBufferLength < SizeNeeded) {
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetIdleTime: Buffer to small: Size: %d, SizeNeeded %d",
|
|
ulInputBufferLength, SizeNeeded));
|
|
return (STATUS_INFO_LENGTH_MISMATCH);
|
|
}
|
|
|
|
BUNDLECB_FROM_BUNDLEH(BundleCB, In->hBundleHandle);
|
|
|
|
if (BundleCB == NULL) {
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetIdleTime: Invalid BundleHandle: 0x%8.8x",
|
|
In->hBundleHandle));
|
|
return (NDISWAN_ERROR_INVALID_HANDLE);
|
|
|
|
}
|
|
|
|
NdisAcquireSpinLock(&BundleCB->Lock);
|
|
|
|
|
|
//
|
|
// If this is for the bundle
|
|
//
|
|
if (In->usProtocolType == BUNDLE_IDLE_TIME) {
|
|
LastNonIdleData = BundleCB->LastRecvNonIdleData;
|
|
} else {
|
|
|
|
//
|
|
// Find the protocol type
|
|
//
|
|
for (ProtocolCB = (PPROTOCOLCB)BundleCB->ProtocolCBList.Flink;
|
|
(PVOID)ProtocolCB != (PVOID)&BundleCB->ProtocolCBList;
|
|
ProtocolCB = (PPROTOCOLCB)ProtocolCB->Linkage.Flink) {
|
|
|
|
if (ProtocolCB->usProtocolType == In->usProtocolType) {
|
|
Found = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!Found) {
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("GetIdleTime: Invalid ProtocolType: 0x%4.4x",
|
|
In->usProtocolType));
|
|
NdisReleaseSpinLock(&BundleCB->Lock);
|
|
return (NDISWAN_ERROR_NO_ROUTE);
|
|
}
|
|
|
|
LastNonIdleData = ProtocolCB->LastRecvNonIdleData;
|
|
}
|
|
|
|
|
|
NdisWanGetSystemTime(&CurrentTime);
|
|
NdisWanCalcTimeDiff(&Diff, &CurrentTime, &LastNonIdleData);
|
|
NdisWanInitWanTime(&OneSecond, ONE_SECOND);
|
|
NdisWanDivideWanTime(&CurrentTime, &Diff, &OneSecond);
|
|
|
|
Out->ulSeconds = CurrentTime.LowPart;
|
|
|
|
NdisReleaseSpinLock(&BundleCB->Lock);
|
|
|
|
return (STATUS_SUCCESS);
|
|
}
|
|
|
|
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;
|
|
BOOLEAN RouteExists = FALSE;
|
|
PPROTOCOLCB ProtocolCB;
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("ActivateRoute:"));
|
|
|
|
*pulBytesWritten = SizeNeeded;
|
|
|
|
if (ulInputBufferLength < SizeNeeded) {
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("DeactivateRoute: Buffer to small: Size: %d, SizeNeeded %d",
|
|
ulInputBufferLength, SizeNeeded));
|
|
return (STATUS_INFO_LENGTH_MISMATCH);
|
|
}
|
|
|
|
//
|
|
// If this is a valid bundle
|
|
//
|
|
BUNDLECB_FROM_BUNDLEH(BundleCB, In->hBundleHandle);
|
|
|
|
if (BundleCB == NULL) {
|
|
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("DeactivateRoute: Invalid BundleHandle: 0x%8.8x, ProtocolType: 0x%4.4x",
|
|
In->hBundleHandle, In->usProtocolType));
|
|
|
|
return (NDISWAN_ERROR_INVALID_HANDLE);
|
|
}
|
|
|
|
//
|
|
// If the ProtocolType is PROTOCOL_UNROUTE we will unroute all protocols
|
|
// from the bundle, otherwise we will only unroute the protocol = ProtocolType.
|
|
// If this is the only protocol on the bundle we will mark the bundle as
|
|
// being unrouted.
|
|
//
|
|
//
|
|
|
|
if (In->usProtocolType == PROTOCOL_UNROUTE) {
|
|
|
|
//
|
|
// This is a call to unroute
|
|
//
|
|
|
|
NdisAcquireSpinLock(&BundleCB->Lock);
|
|
|
|
if (!(BundleCB->Flags & BUNDLE_ROUTED)) {
|
|
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_IO, ("DeactivateRoute: BundleCB 0x%8.8x not routed!",
|
|
BundleCB));
|
|
NdisReleaseSpinLock(&BundleCB->Lock);
|
|
return(NDISWAN_ERROR_INVALID_HANDLE);
|
|
}
|
|
|
|
//
|
|
// Don't accept anymore sends on this bundle
|
|
//
|
|
BundleCB->Flags &= ~BUNDLE_ROUTED;
|
|
|
|
//
|
|
// Flush the protocol packet queues. This could cause us
|
|
// to complete frames to ndis out of order. Ndis should
|
|
// handle this.
|
|
//
|
|
for (ProtocolCB = (PPROTOCOLCB)BundleCB->ProtocolCBList.Flink;
|
|
(PVOID)ProtocolCB != (PVOID)&BundleCB->ProtocolCBList;
|
|
ProtocolCB = (PPROTOCOLCB)ProtocolCB->Linkage.Flink) {
|
|
|
|
FlushProtocolPacketQueue(ProtocolCB);
|
|
}
|
|
|
|
//
|
|
// Do we need to wait for any outstanding frames on the bundle?
|
|
//
|
|
if (BundleCB->OutstandingFrames != 0) {
|
|
|
|
NdisWanClearSyncEvent(&BundleCB->OutstandingFramesEvent);
|
|
|
|
BundleCB->Flags |= FRAMES_PENDING;
|
|
|
|
NdisReleaseSpinLock(&BundleCB->Lock);
|
|
|
|
NdisWanWaitForSyncEvent(&BundleCB->OutstandingFramesEvent);
|
|
|
|
NdisAcquireSpinLock(&BundleCB->Lock);
|
|
|
|
BundleCB->Flags &= ~FRAMES_PENDING;
|
|
}
|
|
|
|
//
|
|
// For each protocolcb in the bundle's protocolcb table
|
|
// (except for the i/o protocolcb)
|
|
//
|
|
for (i = 1; i < MAX_PROTOCOLS; i++) {
|
|
|
|
if (ProtocolCB = BundleCB->ProtocolCBTable[i]) {
|
|
|
|
//
|
|
// Remove the protocolcb from the bundlecb, both the table and
|
|
// the list.
|
|
//
|
|
RemoveProtocolCBFromBundle(ProtocolCB, BundleCB);
|
|
|
|
NdisReleaseSpinLock(&BundleCB->Lock);
|
|
|
|
//
|
|
// Do a linedown to the protocol
|
|
//
|
|
NdisWanClearSyncEvent(&BundleCB->IndicationEvent);
|
|
|
|
Status = DoLineDownToProtocol(ProtocolCB);
|
|
|
|
if (Status == NDIS_STATUS_PENDING) {
|
|
|
|
//
|
|
// This has been queued because we could not
|
|
// get the miniport lock. Wait for notification
|
|
// and pick up the route status.
|
|
//
|
|
NdisWanWaitForSyncEvent(&BundleCB->IndicationEvent);
|
|
|
|
Status = BundleCB->IndicationStatus;
|
|
}
|
|
|
|
//
|
|
// Return the protocolcb
|
|
//
|
|
NdisWanReturnProtocolCB(ProtocolCB);
|
|
|
|
NdisAcquireSpinLock(&BundleCB->Lock);
|
|
}
|
|
}
|
|
|
|
if (BundleCB->State == BUNDLE_GOING_DOWN) {
|
|
|
|
NdisReleaseSpinLock(&BundleCB->Lock);
|
|
|
|
//
|
|
// Clean up the connection table
|
|
//
|
|
RemoveBundleFromConnectionTable(BundleCB);
|
|
|
|
//
|
|
// Return the bundlecb
|
|
//
|
|
NdisWanReturnBundleCB(BundleCB);
|
|
|
|
} else {
|
|
NdisReleaseSpinLock(&BundleCB->Lock);
|
|
}
|
|
|
|
}
|
|
|
|
return (NDIS_STATUS_SUCCESS);
|
|
}
|
|
|
|
NTSTATUS
|
|
GetNdisWanCB(
|
|
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;
|
|
PNDISWAN_DUMPCB Out = (PNDISWAN_DUMPCB)pOutputBuffer;
|
|
ULONG SizeNeeded = sizeof(NDISWAN_DUMPCB) + sizeof(NDISWANCB);
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("GetNdisWanCB:"));
|
|
|
|
*pulBytesWritten = SizeNeeded;
|
|
|
|
if (ulOutputBufferLength >= SizeNeeded) {
|
|
Out->Address = (PVOID)&NdisWanCB;
|
|
NdisMoveMemory(&Out->Buffer[0],
|
|
&NdisWanCB,
|
|
sizeof(NDISWANCB));
|
|
|
|
} else {
|
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
|
}
|
|
|
|
return (Status);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
EnumAdapterCB(
|
|
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;
|
|
PNDISWAN_ENUMCB Out = (PNDISWAN_ENUMCB)pOutputBuffer;
|
|
ULONG SizeNeeded = sizeof(NDISWAN_ENUMCB) + (sizeof(PADAPTERCB) * AdapterCBList.ulCount);
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("GetAdapterCB:"));
|
|
|
|
*pulBytesWritten = SizeNeeded;
|
|
|
|
if (ulOutputBufferLength >= SizeNeeded) {
|
|
PADAPTERCB AdapterCB;
|
|
ULONG i = 0;
|
|
|
|
Out->ulNumberOfCBs = AdapterCBList.ulCount;
|
|
|
|
for (AdapterCB = (PADAPTERCB)AdapterCBList.List.Flink;
|
|
(PVOID)AdapterCB != (PVOID)&AdapterCBList.List;
|
|
AdapterCB = (PADAPTERCB)AdapterCB->Linkage.Flink) {
|
|
|
|
Out->Address[i++] = (PVOID)AdapterCB;
|
|
}
|
|
|
|
} else {
|
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
|
}
|
|
|
|
return (Status);
|
|
}
|
|
|
|
NTSTATUS
|
|
GetAdapterCB(
|
|
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;
|
|
PNDISWAN_DUMPCB Out = (PNDISWAN_DUMPCB)pOutputBuffer;
|
|
ULONG SizeNeeded = sizeof(NDISWAN_DUMPCB) + sizeof(ADAPTERCB);
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("GetAdapterCB:"));
|
|
|
|
*pulBytesWritten = SizeNeeded;
|
|
|
|
if (ulOutputBufferLength >= SizeNeeded) {
|
|
PADAPTERCB AdapterCB;
|
|
|
|
for (AdapterCB = (PADAPTERCB)AdapterCBList.List.Flink;
|
|
(PVOID)AdapterCB != (PVOID)&AdapterCBList.List;
|
|
AdapterCB = (PADAPTERCB)AdapterCB->Linkage.Flink) {
|
|
|
|
if (AdapterCB == (PADAPTERCB)Out->Address) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ((PVOID)AdapterCB != (PVOID)&AdapterCBList.List) {
|
|
|
|
NdisMoveMemory(&Out->Buffer[0],
|
|
AdapterCB,
|
|
sizeof(ADAPTERCB));
|
|
} else {
|
|
|
|
Status = NDISWAN_ERROR_INVALID_ADDRESS;
|
|
}
|
|
|
|
} else {
|
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
|
}
|
|
|
|
return (Status);
|
|
}
|
|
|
|
NTSTATUS
|
|
EnumWanAdapterCB(
|
|
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;
|
|
PNDISWAN_ENUMCB Out = (PNDISWAN_ENUMCB)pOutputBuffer;
|
|
ULONG SizeNeeded = sizeof(NDISWAN_ENUMCB) +
|
|
sizeof(PWAN_ADAPTERCB) * WanAdapterCBList.ulCount;
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("GetAdapterCB:"));
|
|
|
|
*pulBytesWritten = SizeNeeded;
|
|
|
|
if (ulOutputBufferLength >= SizeNeeded) {
|
|
PWAN_ADAPTERCB WanAdapterCB;
|
|
ULONG i = 0;
|
|
|
|
Out->ulNumberOfCBs = WanAdapterCBList.ulCount;
|
|
|
|
for (WanAdapterCB = (PWAN_ADAPTERCB)WanAdapterCBList.List.Flink;
|
|
(PVOID)WanAdapterCB != (PVOID)&WanAdapterCBList.List;
|
|
WanAdapterCB = (PWAN_ADAPTERCB)WanAdapterCB->Linkage.Flink) {
|
|
|
|
Out->Address[i] = (PVOID)WanAdapterCB;
|
|
}
|
|
|
|
} else {
|
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
|
}
|
|
|
|
return (Status);
|
|
}
|
|
|
|
NTSTATUS
|
|
GetWanAdapterCB(
|
|
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_DUMPCB) + sizeof(WAN_ADAPTERCB);
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_IO, ("GetWanAdapterCB:"));
|
|
|
|
*pulBytesWritten = SizeNeeded;
|
|
|
|
if (ulOutputBufferLength >= SizeNeeded) {
|
|
|
|
} else {
|
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
|
}
|
|
|
|
return (Status);
|
|
}
|
|
|
|
VOID
|
|
CancelThresholdEvents(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Values:
|
|
|
|
--*/
|
|
{
|
|
#ifdef NT
|
|
PWAN_ASYNC_EVENT pAsyncEvent = NULL;
|
|
KIRQL Irql;
|
|
PIRP pIrp;
|
|
|
|
|
|
for (; ;) {
|
|
|
|
NdisAcquireSpinLock(&ThresholdEventQueue.Lock);
|
|
|
|
if (!IsListEmpty(&ThresholdEventQueue.List)) {
|
|
|
|
pAsyncEvent = (PWAN_ASYNC_EVENT)RemoveHeadList(&ThresholdEventQueue.List);
|
|
ThresholdEventQueue.ulCount--;
|
|
}
|
|
|
|
NdisReleaseSpinLock(&ThresholdEventQueue.Lock);
|
|
|
|
if (pAsyncEvent != NULL) {
|
|
|
|
IoAcquireCancelSpinLock(&Irql);
|
|
|
|
pIrp = (PIRP)pAsyncEvent->Context;
|
|
|
|
pIrp->Cancel = TRUE;
|
|
pIrp->IoStatus.Status = STATUS_CANCELLED;
|
|
pIrp->IoStatus.Information = 0;
|
|
|
|
IoReleaseCancelSpinLock(Irql);
|
|
|
|
IoCompleteRequest(pIrp, IO_NETWORK_INCREMENT);
|
|
|
|
//
|
|
// Free the wan_async_event structure
|
|
//
|
|
NdisWanFreeMemory(pAsyncEvent);
|
|
|
|
pAsyncEvent = NULL;
|
|
} else
|
|
break;
|
|
}
|
|
|
|
#endif // End #ifdef NT
|
|
|
|
}
|
|
|
|
VOID
|
|
CancelIoReceivePackets(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Values:
|
|
|
|
--*/
|
|
{
|
|
#ifdef NT
|
|
PWAN_ASYNC_EVENT pAsyncEvent = NULL;
|
|
KIRQL Irql;
|
|
PIRP pIrp;
|
|
|
|
|
|
for (; ;) {
|
|
|
|
NdisAcquireSpinLock(&RecvPacketQueue.Lock);
|
|
|
|
if (!IsListEmpty(&RecvPacketQueue.List)) {
|
|
|
|
pAsyncEvent = (PWAN_ASYNC_EVENT)RemoveHeadList(&RecvPacketQueue.List);
|
|
RecvPacketQueue.ulCount--;
|
|
}
|
|
|
|
NdisReleaseSpinLock(&RecvPacketQueue.Lock);
|
|
|
|
if (pAsyncEvent != NULL) {
|
|
|
|
IoAcquireCancelSpinLock(&Irql);
|
|
|
|
pIrp = (PIRP)pAsyncEvent->Context;
|
|
|
|
pIrp->Cancel = TRUE;
|
|
pIrp->IoStatus.Status = STATUS_CANCELLED;
|
|
pIrp->IoStatus.Information = 0;
|
|
((PNDISWAN_IO_PACKET)(pIrp->AssociatedIrp.SystemBuffer))->usHandleType = CANCELEDHANDLE;
|
|
|
|
IoReleaseCancelSpinLock(Irql);
|
|
|
|
IoCompleteRequest(pIrp, IO_NETWORK_INCREMENT);
|
|
|
|
//
|
|
// Free the wan_async_event structure
|
|
//
|
|
NdisWanFreeMemory(pAsyncEvent);
|
|
|
|
pAsyncEvent = NULL;
|
|
} else
|
|
break;
|
|
}
|
|
|
|
#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;
|
|
|
|
//
|
|
// Add to list
|
|
//
|
|
InsertTailList(&BundleCB->ProtocolCBList, &ProtocolCB->Linkage);
|
|
|
|
//
|
|
// Insert in table
|
|
//
|
|
ASSERT(BundleCB->ProtocolCBTable[(ULONG)ProtocolCB->hProtocolHandle] ==
|
|
(PPROTOCOLCB)RESERVED_PROTOCOLCB);
|
|
|
|
BundleCB->ProtocolCBTable[(ULONG)ProtocolCB->hProtocolHandle] = ProtocolCB;
|
|
|
|
BundleCB->ulNumberOfRoutes++;
|
|
|
|
//
|
|
// Setup the send mask for this protocolcb
|
|
//
|
|
ProtocolCB->SendMaskBit = BundleCB->SendMask + 0x00000001;
|
|
BundleCB->SendMask = (BundleCB->SendMask << 1) | 0x00000001;
|
|
|
|
BundleCB->Flags |= BUNDLE_ROUTED;
|
|
ProtocolCB->Flags |= PROTOCOL_ROUTED;
|
|
|
|
//
|
|
// We want to walk the protocolcblist and assign the intial
|
|
// value for each protocol priority and byte quota. The
|
|
// initial value for the priority is just 100 divided by the
|
|
// number of protocols that we have routed. The initial value
|
|
// for the byte quota is the bundle speed in Bps * InitialPriority (%)
|
|
// divided by 100.
|
|
//
|
|
InitialPriority = (BundleCB->ulNumberOfRoutes - 1) ?
|
|
100 / (BundleCB->ulNumberOfRoutes - 1) : 100;
|
|
|
|
InitialByteQuota = (((BundleCB->LineUpInfo.BundleSpeed * 100) / 8) *
|
|
InitialPriority) / 100;
|
|
|
|
//
|
|
// Skip the first one on the list since it is the PrivateIo
|
|
// protocolcb and always has a priority of 100.
|
|
//
|
|
ProtocolCB = (PPROTOCOLCB)BundleCB->ProtocolCBList.Flink;
|
|
|
|
for (ProtocolCB = (PPROTOCOLCB)ProtocolCB->Linkage.Flink;
|
|
(PVOID)ProtocolCB != (PVOID)&BundleCB->ProtocolCBList;
|
|
ProtocolCB = (PPROTOCOLCB)ProtocolCB->Linkage.Flink) {
|
|
|
|
#ifdef BANDWIDTH_ON_DEMAND
|
|
ProtocolCB->usPriority = (USHORT)InitialPriority;
|
|
ProtocolCB->ulByteQuota = InitialByteQuota;
|
|
#endif // end of BANDWIDTH_ON_DEMAND
|
|
|
|
}
|
|
|
|
}
|
|
|
|
VOID
|
|
RemoveProtocolCBFromBundle(
|
|
PPROTOCOLCB ProtocolCB,
|
|
PBUNDLECB BundleCB
|
|
)
|
|
{
|
|
ProtocolCB->Flags &= ~PROTOCOL_ROUTED;
|
|
RemoveEntryList(&ProtocolCB->Linkage);
|
|
BundleCB->ProtocolCBTable[(ULONG)ProtocolCB->hProtocolHandle] = NULL;
|
|
BundleCB->ulNumberOfRoutes--;
|
|
BundleCB->SendMask &= ~ProtocolCB->SendMaskBit;
|
|
}
|
|
|
|
#ifdef BANDWIDTH_ON_DEMAND
|
|
|
|
VOID
|
|
SortProtocolListByPriority(
|
|
IN PBUNDLECB BundleCB
|
|
)
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Values:
|
|
|
|
--*/
|
|
{
|
|
PPROTOCOLCB ProtocolCB, NextProtocolCB, IoProtocolCB;
|
|
|
|
//
|
|
// First save the I/O ProtocolCB
|
|
//
|
|
IoProtocolCB = (PPROTOCOLCB)RemoveHeadList(&BundleCB->ProtocolCBList);
|
|
|
|
//
|
|
// Initial starting conditions
|
|
//
|
|
ProtocolCB = (PPROTOCOLCB)BundleCB->ProtocolCBList.Flink;
|
|
NextProtocolCB = (PPROTOCOLCB)ProtocolCB->Linkage.Flink;
|
|
|
|
//
|
|
// This is a lousy sorting algorith but it is simple and not called
|
|
// very often so we will leave it as is for now.
|
|
//
|
|
while ((PVOID)ProtocolCB != (PVOID)&BundleCB->ProtocolCBList) {
|
|
|
|
while ((PVOID)NextProtocolCB != (PVOID)&BundleCB->ProtocolCBList) {
|
|
|
|
if (NextProtocolCB->usPriority > ProtocolCB->usPriority) {
|
|
PLIST_ENTRY Prev, Next;
|
|
|
|
RemoveEntryList(&NextProtocolCB->Linkage);
|
|
|
|
Prev = (PLIST_ENTRY)ProtocolCB->Linkage.Blink;
|
|
Next = (PLIST_ENTRY)ProtocolCB->Linkage.Flink;
|
|
|
|
//
|
|
// Fix up the previous flink
|
|
//
|
|
Prev->Flink = (PLIST_ENTRY)NextProtocolCB;
|
|
|
|
//
|
|
// Fixup the new insertions flink and blink
|
|
//
|
|
NextProtocolCB->Linkage.Blink = Prev;
|
|
NextProtocolCB->Linkage.Flink = (PLIST_ENTRY)ProtocolCB;
|
|
|
|
//
|
|
// Fixup the next blink
|
|
//
|
|
ProtocolCB->Linkage.Blink = (PLIST_ENTRY)NextProtocolCB;
|
|
|
|
//
|
|
// Get the new starting point
|
|
//
|
|
ProtocolCB = NextProtocolCB;
|
|
|
|
//
|
|
// Get the next compare
|
|
//
|
|
NextProtocolCB = (PPROTOCOLCB)Next;
|
|
|
|
} else {
|
|
NextProtocolCB = (PPROTOCOLCB)NextProtocolCB->Linkage.Flink;
|
|
}
|
|
}
|
|
|
|
ProtocolCB = (PPROTOCOLCB)ProtocolCB->Linkage.Flink;
|
|
}
|
|
|
|
//
|
|
// Restore I/O ProtocolCB
|
|
//
|
|
InsertHeadList(&BundleCB->ProtocolCBList, &IoProtocolCB->Linkage);
|
|
|
|
}
|
|
|
|
#endif // end of BANDWIDTH_ON_DEMAND
|
|
|
|
VOID
|
|
CompleteThresholdEvent(
|
|
PBUNDLECB BundleCB,
|
|
ULONG ThresholdType
|
|
)
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Values:
|
|
|
|
--*/
|
|
{
|
|
#ifdef NT
|
|
KIRQL Irql;
|
|
PIRP pIrp;
|
|
PWAN_ASYNC_EVENT pAsyncEvent = NULL;
|
|
PNDISWAN_SET_THRESHOLD_EVENT ThresholdEvent;
|
|
|
|
NdisAcquireSpinLock(&ThresholdEventQueue.Lock);
|
|
|
|
if (!IsListEmpty(&ThresholdEventQueue.List)) {
|
|
|
|
pAsyncEvent = (PWAN_ASYNC_EVENT)RemoveHeadList(&ThresholdEventQueue.List);
|
|
ThresholdEventQueue.ulCount--;
|
|
}
|
|
|
|
NdisReleaseSpinLock(&ThresholdEventQueue.Lock);
|
|
|
|
if (pAsyncEvent != NULL) {
|
|
|
|
IoAcquireCancelSpinLock(&Irql);
|
|
|
|
pIrp = (PIRP)pAsyncEvent->Context;
|
|
|
|
pIrp->IoStatus.Status = STATUS_SUCCESS;
|
|
pIrp->IoStatus.Information = sizeof(NDISWAN_SET_THRESHOLD_EVENT);
|
|
|
|
ThresholdEvent = (PNDISWAN_SET_THRESHOLD_EVENT)pIrp->AssociatedIrp.SystemBuffer;
|
|
ThresholdEvent->hBundleHandle = BundleCB->hBundleHandle;
|
|
ThresholdEvent->ulThreshold = ThresholdType;
|
|
|
|
IoSetCancelRoutine(pIrp, NULL);
|
|
|
|
IoReleaseCancelSpinLock(Irql);
|
|
|
|
IoCompleteRequest(pIrp, IO_NETWORK_INCREMENT);
|
|
|
|
//
|
|
// Free the wan_async_event structure
|
|
//
|
|
NdisWanFreeMemory(pAsyncEvent);
|
|
|
|
}
|
|
|
|
#endif // End #ifdef NT
|
|
}
|
|
|
|
VOID
|
|
FlushProtocolPacketQueue(
|
|
PPROTOCOLCB ProtocolCB
|
|
)
|
|
{
|
|
ULONG MagicNumber = 0;
|
|
PADAPTERCB AdapterCB = ProtocolCB->AdapterCB;
|
|
PBUNDLECB BundleCB = ProtocolCB->BundleCB;
|
|
|
|
if (ProtocolCB->usProtocolType == PROTOCOL_PRIVATE_IO) {
|
|
MagicNumber = NDISWAN_MAGIC_NUMBER;
|
|
}
|
|
|
|
while (!IsNdisPacketQueueEmpty(ProtocolCB)) {
|
|
PNDIS_PACKET NdisPacket;
|
|
|
|
NdisPacket = RemoveHeadNdisPacketQueue(ProtocolCB);
|
|
|
|
//
|
|
// Assign the magic number
|
|
//
|
|
PMINIPORT_RESERVED_FROM_NDIS(NdisPacket)->MagicNumber = MagicNumber;
|
|
|
|
NdisReleaseSpinLock(&BundleCB->Lock);
|
|
|
|
//
|
|
// Complete the NdisPacket
|
|
//
|
|
TryToCompleteNdisPacket(AdapterCB, NdisPacket);
|
|
|
|
NdisAcquireSpinLock(&BundleCB->Lock);
|
|
}
|
|
}
|
|
|
|
VOID
|
|
AssignProtocolCBHandle(
|
|
PBUNDLECB BundleCB,
|
|
PPROTOCOLCB ProtocolCB
|
|
)
|
|
{
|
|
ULONG i;
|
|
|
|
//
|
|
// Find the first unused slot in the table
|
|
//
|
|
for (i = 1; i < MAX_PROTOCOLS; i++) {
|
|
if (BundleCB->ProtocolCBTable[i] == NULL) {
|
|
ProtocolCB->hProtocolHandle = (NDIS_HANDLE)i;
|
|
ProtocolCB->BundleCB = BundleCB;
|
|
BundleCB->ProtocolCBTable[i] = (PPROTOCOLCB)RESERVED_PROTOCOLCB;
|
|
break;
|
|
}
|
|
}
|
|
|
|
ASSERT(i < MAX_PROTOCOLS);
|
|
}
|
|
|
|
VOID
|
|
FreeProtocolCBHandle(
|
|
PBUNDLECB BundleCB,
|
|
PPROTOCOLCB ProtocolCB
|
|
)
|
|
{
|
|
|
|
ASSERT(BundleCB->ProtocolCBTable[(ULONG)ProtocolCB->hProtocolHandle] ==
|
|
(PPROTOCOLCB)RESERVED_PROTOCOLCB);
|
|
|
|
ASSERT((ULONG)ProtocolCB->hProtocolHandle < MAX_PROTOCOLS);
|
|
|
|
BundleCB->ProtocolCBTable[(ULONG)ProtocolCB->hProtocolHandle] = NULL;
|
|
}
|
|
|